| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  QEMU model of the LatticeMico32 UART block. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Copyright (c) 2010 Michael Walle <michael@walle.cc> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Specification available at: | 
					
						
							|  |  |  |  *   http://www.latticesemi.com/documents/mico32uart.pdf
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 18:16:57 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:42 +02:00
										 |  |  | #include "hw/irq.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:51 +02:00
										 |  |  | #include "hw/qdev-properties.h"
 | 
					
						
							| 
									
										
										
										
											2013-02-04 15:40:22 +01:00
										 |  |  | #include "hw/sysbus.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:45 +02:00
										 |  |  | #include "migration/vmstate.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | #include "trace.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 18:26:44 +04:00
										 |  |  | #include "chardev/char-fe.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-17 18:20:00 +01:00
										 |  |  | #include "qemu/error-report.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 16:35:07 +02:00
										 |  |  | #include "qemu/module.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     R_RXTX = 0, | 
					
						
							|  |  |  |     R_IER, | 
					
						
							|  |  |  |     R_IIR, | 
					
						
							|  |  |  |     R_LCR, | 
					
						
							|  |  |  |     R_MCR, | 
					
						
							|  |  |  |     R_LSR, | 
					
						
							|  |  |  |     R_MSR, | 
					
						
							|  |  |  |     R_DIV, | 
					
						
							|  |  |  |     R_MAX | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     IER_RBRI = (1<<0), | 
					
						
							|  |  |  |     IER_THRI = (1<<1), | 
					
						
							|  |  |  |     IER_RLSI = (1<<2), | 
					
						
							|  |  |  |     IER_MSI  = (1<<3), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     IIR_STAT = (1<<0), | 
					
						
							|  |  |  |     IIR_ID0  = (1<<1), | 
					
						
							|  |  |  |     IIR_ID1  = (1<<2), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     LCR_WLS0 = (1<<0), | 
					
						
							|  |  |  |     LCR_WLS1 = (1<<1), | 
					
						
							|  |  |  |     LCR_STB  = (1<<2), | 
					
						
							|  |  |  |     LCR_PEN  = (1<<3), | 
					
						
							|  |  |  |     LCR_EPS  = (1<<4), | 
					
						
							|  |  |  |     LCR_SP   = (1<<5), | 
					
						
							|  |  |  |     LCR_SB   = (1<<6), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     MCR_DTR  = (1<<0), | 
					
						
							|  |  |  |     MCR_RTS  = (1<<1), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     LSR_DR   = (1<<0), | 
					
						
							|  |  |  |     LSR_OE   = (1<<1), | 
					
						
							|  |  |  |     LSR_PE   = (1<<2), | 
					
						
							|  |  |  |     LSR_FE   = (1<<3), | 
					
						
							|  |  |  |     LSR_BI   = (1<<4), | 
					
						
							|  |  |  |     LSR_THRE = (1<<5), | 
					
						
							|  |  |  |     LSR_TEMT = (1<<6), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |     MSR_DCTS = (1<<0), | 
					
						
							|  |  |  |     MSR_DDSR = (1<<1), | 
					
						
							|  |  |  |     MSR_TERI = (1<<2), | 
					
						
							|  |  |  |     MSR_DDCD = (1<<3), | 
					
						
							|  |  |  |     MSR_CTS  = (1<<4), | 
					
						
							|  |  |  |     MSR_DSR  = (1<<5), | 
					
						
							|  |  |  |     MSR_RI   = (1<<6), | 
					
						
							|  |  |  |     MSR_DCD  = (1<<7), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 22:59:55 +02:00
										 |  |  | #define TYPE_LM32_UART "lm32-uart"
 | 
					
						
							|  |  |  | #define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | struct LM32UartState { | 
					
						
							| 
									
										
										
										
											2013-07-24 22:59:55 +02:00
										 |  |  |     SysBusDevice parent_obj; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-24 14:31:16 +01:00
										 |  |  |     MemoryRegion iomem; | 
					
						
							| 
									
										
										
										
											2016-10-22 12:52:51 +03:00
										 |  |  |     CharBackend chr; | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |     qemu_irq irq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     uint32_t regs[R_MAX]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | typedef struct LM32UartState LM32UartState; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void uart_update_irq(LM32UartState *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((s->regs[R_LSR] & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) | 
					
						
							|  |  |  |             && (s->regs[R_IER] & IER_RLSI)) { | 
					
						
							|  |  |  |         irq = 1; | 
					
						
							|  |  |  |         s->regs[R_IIR] = IIR_ID1 | IIR_ID0; | 
					
						
							|  |  |  |     } else if ((s->regs[R_LSR] & LSR_DR) && (s->regs[R_IER] & IER_RBRI)) { | 
					
						
							|  |  |  |         irq = 1; | 
					
						
							|  |  |  |         s->regs[R_IIR] = IIR_ID1; | 
					
						
							|  |  |  |     } else if ((s->regs[R_LSR] & LSR_THRE) && (s->regs[R_IER] & IER_THRI)) { | 
					
						
							|  |  |  |         irq = 1; | 
					
						
							|  |  |  |         s->regs[R_IIR] = IIR_ID0; | 
					
						
							|  |  |  |     } else if ((s->regs[R_MSR] & 0x0f) && (s->regs[R_IER] & IER_MSI)) { | 
					
						
							|  |  |  |         irq = 1; | 
					
						
							|  |  |  |         s->regs[R_IIR] = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         irq = 0; | 
					
						
							|  |  |  |         s->regs[R_IIR] = IIR_STAT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_lm32_uart_irq_state(irq); | 
					
						
							|  |  |  |     qemu_set_irq(s->irq, irq); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static uint64_t uart_read(void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2011-11-24 14:31:16 +01:00
										 |  |  |                           unsigned size) | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     LM32UartState *s = opaque; | 
					
						
							|  |  |  |     uint32_t r = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addr >>= 2; | 
					
						
							|  |  |  |     switch (addr) { | 
					
						
							|  |  |  |     case R_RXTX: | 
					
						
							|  |  |  |         r = s->regs[R_RXTX]; | 
					
						
							|  |  |  |         s->regs[R_LSR] &= ~LSR_DR; | 
					
						
							|  |  |  |         uart_update_irq(s); | 
					
						
							| 
									
										
										
										
											2016-10-22 12:52:55 +03:00
										 |  |  |         qemu_chr_fe_accept_input(&s->chr); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case R_IIR: | 
					
						
							|  |  |  |     case R_LSR: | 
					
						
							|  |  |  |     case R_MSR: | 
					
						
							|  |  |  |         r = s->regs[addr]; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case R_IER: | 
					
						
							|  |  |  |     case R_LCR: | 
					
						
							|  |  |  |     case R_MCR: | 
					
						
							|  |  |  |     case R_DIV: | 
					
						
							|  |  |  |         error_report("lm32_uart: read access to write only register 0x" | 
					
						
							|  |  |  |                 TARGET_FMT_plx, addr << 2); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2011-06-22 14:03:56 +02:00
										 |  |  |         error_report("lm32_uart: read access to unknown register 0x" | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |                 TARGET_FMT_plx, addr << 2); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_lm32_uart_memory_read(addr << 2, r); | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 12:30:10 +02:00
										 |  |  | static void uart_write(void *opaque, hwaddr addr, | 
					
						
							| 
									
										
										
										
											2011-11-24 14:31:16 +01:00
										 |  |  |                        uint64_t value, unsigned size) | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     LM32UartState *s = opaque; | 
					
						
							|  |  |  |     unsigned char ch = value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_lm32_uart_memory_write(addr, value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addr >>= 2; | 
					
						
							|  |  |  |     switch (addr) { | 
					
						
							|  |  |  |     case R_RXTX: | 
					
						
							| 
									
										
										
										
											2016-10-22 12:52:59 +03:00
										 |  |  |         /* XXX this blocks entire thread. Rewrite to use
 | 
					
						
							|  |  |  |          * qemu_chr_fe_write and background I/O callbacks */ | 
					
						
							|  |  |  |         qemu_chr_fe_write_all(&s->chr, &ch, 1); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case R_IER: | 
					
						
							|  |  |  |     case R_LCR: | 
					
						
							|  |  |  |     case R_MCR: | 
					
						
							|  |  |  |     case R_DIV: | 
					
						
							|  |  |  |         s->regs[addr] = value; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case R_IIR: | 
					
						
							|  |  |  |     case R_LSR: | 
					
						
							|  |  |  |     case R_MSR: | 
					
						
							|  |  |  |         error_report("lm32_uart: write access to read only register 0x" | 
					
						
							|  |  |  |                 TARGET_FMT_plx, addr << 2); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2011-06-22 14:03:56 +02:00
										 |  |  |         error_report("lm32_uart: write access to unknown register 0x" | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |                 TARGET_FMT_plx, addr << 2); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     uart_update_irq(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-24 14:31:16 +01:00
										 |  |  | static const MemoryRegionOps uart_ops = { | 
					
						
							|  |  |  |     .read = uart_read, | 
					
						
							|  |  |  |     .write = uart_write, | 
					
						
							|  |  |  |     .endianness = DEVICE_NATIVE_ENDIAN, | 
					
						
							|  |  |  |     .valid = { | 
					
						
							|  |  |  |         .min_access_size = 4, | 
					
						
							|  |  |  |         .max_access_size = 4, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void uart_rx(void *opaque, const uint8_t *buf, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     LM32UartState *s = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->regs[R_LSR] & LSR_DR) { | 
					
						
							|  |  |  |         s->regs[R_LSR] |= LSR_OE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->regs[R_LSR] |= LSR_DR; | 
					
						
							|  |  |  |     s->regs[R_RXTX] = *buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     uart_update_irq(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int uart_can_rx(void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     LM32UartState *s = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return !(s->regs[R_LSR] & LSR_DR); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void uart_event(void *opaque, int event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void uart_reset(DeviceState *d) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-07-24 22:59:55 +02:00
										 |  |  |     LM32UartState *s = LM32_UART(d); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < R_MAX; i++) { | 
					
						
							|  |  |  |         s->regs[i] = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* defaults */ | 
					
						
							|  |  |  |     s->regs[R_LSR] = LSR_THRE | LSR_TEMT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  | static void lm32_uart_init(Object *obj) | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  |     LM32UartState *s = LM32_UART(obj); | 
					
						
							|  |  |  |     SysBusDevice *dev = SYS_BUS_DEVICE(obj); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     sysbus_init_irq(dev, &s->irq); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  |     memory_region_init_io(&s->iomem, obj, &uart_ops, s, | 
					
						
							| 
									
										
										
										
											2013-06-06 21:25:08 -04:00
										 |  |  |                           "uart", R_MAX * 4); | 
					
						
							| 
									
										
										
										
											2011-11-27 11:38:10 +02:00
										 |  |  |     sysbus_init_mmio(dev, &s->iomem); | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void lm32_uart_realize(DeviceState *dev, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     LM32UartState *s = LM32_UART(dev); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-22 12:52:59 +03:00
										 |  |  |     qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, | 
					
						
							| 
									
										
										
										
											2017-07-06 15:08:49 +03:00
										 |  |  |                              uart_event, NULL, s, NULL, true); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const VMStateDescription vmstate_lm32_uart = { | 
					
						
							|  |  |  |     .name = "lm32-uart", | 
					
						
							|  |  |  |     .version_id = 1, | 
					
						
							|  |  |  |     .minimum_version_id = 1, | 
					
						
							| 
									
										
										
										
											2014-04-16 16:01:33 +02:00
										 |  |  |     .fields = (VMStateField[]) { | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  |         VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX), | 
					
						
							|  |  |  |         VMSTATE_END_OF_LIST() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  | static Property lm32_uart_properties[] = { | 
					
						
							|  |  |  |     DEFINE_PROP_CHR("chardev", LM32UartState, chr), | 
					
						
							|  |  |  |     DEFINE_PROP_END_OF_LIST(), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 13:12:29 -06:00
										 |  |  | static void lm32_uart_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							| 
									
										
										
										
											2012-01-24 13:12:29 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     dc->reset = uart_reset; | 
					
						
							|  |  |  |     dc->vmsd = &vmstate_lm32_uart; | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  |     dc->props = lm32_uart_properties; | 
					
						
							|  |  |  |     dc->realize = lm32_uart_realize; | 
					
						
							| 
									
										
										
										
											2012-01-24 13:12:29 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-10 16:19:07 +01:00
										 |  |  | static const TypeInfo lm32_uart_info = { | 
					
						
							| 
									
										
										
										
											2013-07-24 22:59:55 +02:00
										 |  |  |     .name          = TYPE_LM32_UART, | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     .parent        = TYPE_SYS_BUS_DEVICE, | 
					
						
							|  |  |  |     .instance_size = sizeof(LM32UartState), | 
					
						
							| 
									
										
										
										
											2016-05-25 14:39:03 +08:00
										 |  |  |     .instance_init = lm32_uart_init, | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     .class_init    = lm32_uart_class_init, | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-09 15:20:55 +01:00
										 |  |  | static void lm32_uart_register_types(void) | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-07 21:34:16 -06:00
										 |  |  |     type_register_static(&lm32_uart_info); | 
					
						
							| 
									
										
										
										
											2011-02-17 23:45:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-09 15:20:55 +01:00
										 |  |  | type_init(lm32_uart_register_types) |