1 #include <rthw.h>
2 #include <rtthread.h>
3
4 #include "io.h"
5 #include <asm/ppc4xx-intvec.h>
6
7 #define UART0_BASE 0xef600300
8 #define UART1_BASE 0xef600400
9 #define UCR0_MASK 0x0000007f
10 #define UCR1_MASK 0x00007f00
11 #define UCR0_UDIV_POS 0
12 #define UCR1_UDIV_POS 8
13 #define UDIV_MAX 127
14
15 #define UART_RBR 0x00
16 #define UART_THR 0x00
17 #define UART_IER 0x01
18 #define UART_IIR 0x02
19 #define UART_FCR 0x02
20 #define UART_LCR 0x03
21 #define UART_MCR 0x04
22 #define UART_LSR 0x05
23 #define UART_MSR 0x06
24 #define UART_SCR 0x07
25 #define UART_DLL 0x00
26 #define UART_DLM 0x01
27
28 /*-----------------------------------------------------------------------------+
29 | Line Status Register.
30 +-----------------------------------------------------------------------------*/
31 #define asyncLSRDataReady1 0x01
32 #define asyncLSROverrunError1 0x02
33 #define asyncLSRParityError1 0x04
34 #define asyncLSRFramingError1 0x08
35 #define asyncLSRBreakInterrupt1 0x10
36 #define asyncLSRTxHoldEmpty1 0x20
37 #define asyncLSRTxShiftEmpty1 0x40
38 #define asyncLSRRxFifoError1 0x80
39
40 /* PPC405 serial device */
41 struct rt_ppc405_serial
42 {
43 /* inherit from device */
44 struct rt_device parent;
45
46 rt_uint32_t hw_base;
47 rt_uint32_t irqno;
48 rt_uint32_t baudrate;
49
50 /* reception field */
51 rt_uint16_t save_index, read_index;
52 rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
53 };
54 struct rt_ppc405_serial ppc405_serial;
55
56 /* serial character device */
rt_serial_init(rt_device_t dev)57 static rt_err_t rt_serial_init (rt_device_t dev)
58 {
59 return RT_EOK;
60 }
61
rt_serial_open(rt_device_t dev,rt_uint16_t oflag)62 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
63 {
64 struct rt_ppc405_serial* device;
65 device = (struct rt_ppc405_serial*) dev;
66
67 RT_ASSERT(device != RT_NULL);
68 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
69 {
70 /* Enable "RX Data Available" Interrupt on UART */
71 out_8((rt_uint8_t*)device->hw_base + UART_IER, 0x01);
72 /* Setup UART FIFO: RX trigger level: 1 byte, Enable FIFO */
73 out_8((rt_uint8_t*)device->hw_base + UART_FCR, 1);
74
75 /* init UART rx interrupt */
76 rt_hw_interrupt_unmask(device->irqno);
77 }
78
79 return RT_EOK;
80 }
81
rt_serial_close(rt_device_t dev)82 static rt_err_t rt_serial_close(rt_device_t dev)
83 {
84 struct rt_ppc405_serial* device;
85 device = (struct rt_ppc405_serial*) dev;
86
87 RT_ASSERT(device != RT_NULL);
88 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
89 {
90 /* mask UART rx interrupt */
91 rt_hw_interrupt_mask(device->irqno);
92 }
93
94 return RT_EOK;
95 }
96
rt_serial_control(rt_device_t dev,int cmd,void * args)97 static rt_err_t rt_serial_control(rt_device_t dev, int cmd, void *args)
98 {
99 return RT_EOK;
100 }
101
rt_serial_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)102 static rt_size_t rt_serial_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
103 {
104 rt_uint8_t* ptr;
105 struct rt_ppc405_serial* device;
106
107 device = (struct rt_ppc405_serial*) dev;
108 RT_ASSERT(device != RT_NULL);
109
110 /* point to buffer */
111 ptr = (rt_uint8_t*) buffer;
112
113 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
114 {
115 while (size)
116 {
117 /* interrupt receive */
118 rt_base_t level;
119
120 /* disable interrupt */
121 level = rt_hw_interrupt_disable();
122 if (device->read_index != device->save_index)
123 {
124 *ptr = device->rx_buffer[device->read_index];
125
126 device->read_index ++;
127 if (device->read_index >= RT_UART_RX_BUFFER_SIZE)
128 device->read_index = 0;
129 }
130 else
131 {
132 /* no data in rx buffer */
133
134 /* enable interrupt */
135 rt_hw_interrupt_enable(level);
136 break;
137 }
138
139 /* enable interrupt */
140 rt_hw_interrupt_enable(level);
141
142 ptr ++; size --;
143 }
144
145 return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
146 }
147 else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
148 {
149 /* not support right now */
150 RT_ASSERT(0);
151 }
152
153 /* polling mode */
154 RT_ASSERT(0);
155
156 return (rt_size_t)ptr - (rt_size_t)buffer;
157 }
158
rt_serial_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)159 static rt_size_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
160 {
161 char *ptr;
162 struct rt_ppc405_serial* device;
163
164 device = (struct rt_ppc405_serial*) dev;
165 RT_ASSERT(device != RT_NULL);
166
167 if (dev->flag & RT_DEVICE_FLAG_INT_TX)
168 {
169 /* not support */
170 RT_ASSERT(0);
171 }
172 else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
173 {
174 /* not support */
175 RT_ASSERT(0);
176 }
177
178 /* polling write */
179 ptr = (char *)buffer;
180
181 if (dev->flag & RT_DEVICE_FLAG_STREAM)
182 {
183 /* stream mode */
184 while (size)
185 {
186 if (*ptr == '\n')
187 {
188 while ((in_8((rt_uint8_t*)device->hw_base + UART_LSR) & 0x20) != 0x20);
189 out_8((rt_uint8_t*)device->hw_base + UART_THR, '\r');
190 }
191
192 while ((in_8((rt_uint8_t*)device->hw_base + UART_LSR) & 0x20) != 0x20);
193 out_8((rt_uint8_t*)device->hw_base + UART_THR, *ptr);
194
195 ptr ++;
196 size --;
197 }
198 }
199 else
200 {
201 while (size)
202 {
203 while ((in_8((rt_uint8_t*)device->hw_base + UART_LSR) & 0x20) != 0x20);
204 out_8((rt_uint8_t*)device->hw_base + UART_THR, *ptr);
205
206 ptr ++;
207 size --;
208 }
209 }
210
211 return (rt_size_t) ptr - (rt_size_t) buffer;
212 }
213
rt_serial_set_baudrate(struct rt_ppc405_serial * device)214 void rt_serial_set_baudrate(struct rt_ppc405_serial* device)
215 {
216 rt_uint32_t bdiv;
217
218 bdiv = 115200;
219 out_8((rt_uint8_t *)device->hw_base + UART_DLL, bdiv); /* set baudrate divisor */
220 out_8((rt_uint8_t *)device->hw_base + UART_DLM, bdiv >> 8); /* set baudrate divisor */
221 }
222
rt_serial_isr(int irqno,void * param)223 void rt_serial_isr(int irqno, void* param)
224 {
225 unsigned char status;
226 struct rt_ppc405_serial *device;
227
228 device = (struct rt_ppc405_serial*) param;
229 status = in_8((rt_uint8_t *)device->hw_base + UART_LSR);
230
231 if (status & 0x01)
232 {
233 rt_base_t level;
234
235 while (status & 0x01)
236 {
237 /* disable interrupt */
238 level = rt_hw_interrupt_disable();
239
240 /* read character */
241 device->rx_buffer[device->save_index] = (0xff & (int) in_8((rt_uint8_t *)device->hw_base));
242 device->save_index ++;
243 if (device->save_index >= RT_UART_RX_BUFFER_SIZE)
244 device->save_index = 0;
245
246 /* if the next position is read index, discard this 'read char' */
247 if (device->save_index == device->read_index)
248 {
249 device->read_index ++;
250 if (device->read_index >= RT_UART_RX_BUFFER_SIZE)
251 device->read_index = 0;
252 }
253
254 /* enable interrupt */
255 rt_hw_interrupt_enable(level);
256
257 /* check error */
258 if ((status & ( asyncLSRFramingError1 |
259 asyncLSROverrunError1 |
260 asyncLSRParityError1 |
261 asyncLSRBreakInterrupt1 )) != 0)
262 {
263 out_8((rt_uint8_t *)device->hw_base + UART_LSR,
264 asyncLSRFramingError1 |
265 asyncLSROverrunError1 |
266 asyncLSRParityError1 |
267 asyncLSRBreakInterrupt1);
268 }
269
270 status = in_8((rt_uint8_t *)device->hw_base + UART_LSR);
271 }
272
273 /* invoke callback */
274 if(device->parent.rx_indicate != RT_NULL)
275 {
276 device->parent.rx_indicate(&device->parent, 1);
277 }
278 }
279 }
280
rt_hw_serial_init(void)281 void rt_hw_serial_init(void)
282 {
283 volatile rt_uint8_t val;
284 struct rt_ppc405_serial* device;
285
286 device = (struct rt_ppc405_serial*) &ppc405_serial;
287 device->parent.type = RT_Device_Class_Char;
288
289 device->hw_base = UART0_BASE;
290 device->baudrate = 115200;
291 device->irqno = VECNUM_U0;
292 rt_hw_interrupt_install(device->irqno, rt_serial_isr, device, "serial"); /* install isr */
293
294 rt_memset(device->rx_buffer, 0, sizeof(device->rx_buffer));
295 device->read_index = device->save_index = 0;
296
297 out_8((rt_uint8_t *)device->hw_base + UART_LCR, 0x80); /* set DLAB bit */
298 /* setup baudrate */
299 rt_serial_set_baudrate(device);
300 out_8((rt_uint8_t *)device->hw_base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */
301 out_8((rt_uint8_t *)device->hw_base + UART_FCR, 0x00); /* disable FIFO */
302 out_8((rt_uint8_t *)device->hw_base + UART_MCR, 0x00); /* no modem control DTR RTS */
303 val = in_8((rt_uint8_t *)device->hw_base + UART_LSR); /* clear line status */
304 val = in_8((rt_uint8_t *)device->hw_base + UART_RBR); /* read receive buffer */
305 out_8((rt_uint8_t *)device->hw_base + UART_SCR, 0x00); /* set scratchpad */
306 out_8((rt_uint8_t *)device->hw_base + UART_IER, 0x00); /* set interrupt enable reg */
307
308 device->parent.type = RT_Device_Class_Char;
309 device->parent.init = rt_serial_init;
310 device->parent.open = rt_serial_open;
311 device->parent.close = rt_serial_close;
312 device->parent.read = rt_serial_read;
313 device->parent.write = rt_serial_write;
314 device->parent.control = rt_serial_control;
315 device->parent.user_data = RT_NULL;
316
317 rt_device_register(&device->parent,
318 "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM);
319 }
320