GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / arch / mips / board / bcm963xx / src / dev_bcm63xx_uart.c
blobfdd1cedf108b89a0ba23e58326937cf040e57b30
1 #include "cfe.h"
2 #include "lib_types.h"
3 #include "lib_malloc.h"
4 #include "lib_printf.h"
5 #include "cfe_iocb.h"
6 #include "cfe_device.h"
7 #include "cfe_ioctl.h"
9 #include "sbmips.h"
12 #define XTALFREQ 25000000
14 #define WRITEREG(csr,val) *((volatile uint32_t *)(csr)) = (val)
15 #define READREG(csr) (*((volatile uint32_t *)(csr)))
17 #define UARTCTLREG_OFFSET 0x00000020
18 #define BAUDWRDREG_OFFSET 0x00000004
19 #define UARTMSCREG_OFFSET 0x00000008
20 #define UARTSTATUS_OFFSET 0x00000010
21 #define UARTDATAREG_OFFSET 0x00000014
22 #define UARTINTREG_OFFSET 0x0000000C
25 #define INTMASKREG 0xfffe000C
26 #define INT_UART0 0x00000004
27 #define INT_UART1 0x00000002
28 #define INT_TIMER 0x00000001
30 #define DEFAULTBAUD 115200
32 /* Control register */
33 #define BRGEN 0x00800000
34 #define TXEN 0x00400000
35 #define RXEN 0x00200000
37 #define BITS8SYM 0x00003000
38 #define ONESTOP 0x00000700
40 /* Miscellaneous register */
41 #define TX4 0x00004000
42 #define RX4 0x00000400
43 #define DTREN 0x00000001
44 #define RTSEN 0x00000002
46 /* Interrupt Mask / Status register */
47 #define RXBRK 0x40000000
48 #define RXPARERR 0x20000000
49 #define RXFRAMERR 0x10000000
50 #define RXOVFERR 0x00800000
51 #define RXFIFONE 0x00000800
52 #define RESETTXFIFO 0x00000080
53 #define RESETRXFIFO 0x00000040
54 #define TXFIFOEMT 0x00000020
55 #define TXUNDERR 0x00000002
56 #define TXOVFERR 0x00000004
59 static void bcm63xx_uart_probe(cfe_driver_t *drv,
60 unsigned long probe_a, unsigned long probe_b,
61 void *probe_ptr);
63 static int bcm63xx_uart_open(cfe_devctx_t *ctx);
64 static int bcm63xx_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
65 static int bcm63xx_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
66 static int bcm63xx_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
67 static int bcm63xx_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
68 static int bcm63xx_uart_close(cfe_devctx_t *ctx);
70 const static cfe_devdisp_t bcm63xx_uart_dispatch = {
71 bcm63xx_uart_open,
72 bcm63xx_uart_read,
73 bcm63xx_uart_inpstat,
74 bcm63xx_uart_write,
75 bcm63xx_uart_ioctl,
76 bcm63xx_uart_close,
77 NULL,
78 NULL
82 const cfe_driver_t bcm63xx_uart = {
83 "BCM63xx DUART",
84 "uart",
85 CFE_DEV_SERIAL,
86 &bcm63xx_uart_dispatch,
87 bcm63xx_uart_probe
91 typedef struct bcm63xx_uart_s {
92 int baudrate;
93 uint32_t uartctlreg;
94 uint32_t baudwrdreg;
95 uint32_t uartmscreg;
96 uint32_t uartintreg;
98 uint32_t uart_status;
99 uint32_t uart_tx_hold;
100 uint32_t uart_rx_hold;
101 } bcm63xx_uart_t;
104 static void bcm63xx_set_baudrate( bcm63xx_uart_t * softc )
106 uint32_t baudwd;
108 baudwd = (XTALFREQ / softc->baudrate) / 8;
109 if( baudwd & 0x1 ) {
110 baudwd = baudwd / 2 - 1;
112 WRITEREG( softc->baudwrdreg, baudwd );
116 static void bcm63xx_uart_probe(cfe_driver_t *drv,
117 unsigned long probe_a, unsigned long probe_b,
118 void *probe_ptr)
120 bcm63xx_uart_t * softc;
121 char descr[80];
123 /* enable the transmitter interrupt? */
126 * probe_a is the DUART base address.
127 * probe_b is the channel-number-within-duart (0 or 1)
128 * probe_ptr is unused.
130 softc = (bcm63xx_uart_t *) KMALLOC(sizeof(bcm63xx_uart_t),0);
131 if (softc) {
132 softc->uartctlreg = probe_a + probe_b * UARTCTLREG_OFFSET;
133 softc->baudwrdreg = softc->uartctlreg + BAUDWRDREG_OFFSET;
134 softc->uartmscreg = softc->uartctlreg + UARTMSCREG_OFFSET;
135 softc->uartintreg = softc->uartctlreg + UARTINTREG_OFFSET;
137 softc->uart_status = softc->uartctlreg + UARTSTATUS_OFFSET;
138 softc->uart_tx_hold = softc->uartctlreg + UARTDATAREG_OFFSET;
139 softc->uart_rx_hold = softc->uartctlreg + UARTDATAREG_OFFSET;
141 xsprintf( descr, "%s at 0x%X channel %d", drv->drv_description, probe_a,
142 probe_b );
143 cfe_attach( drv, softc, NULL, descr );
148 #ifdef RAW_WRITE_HACK
149 cfe_devctx_t * myctx;
151 int my_write( uint32_t length, char * msg );
152 int my_write( uint32_t length, char * msg ) {
153 iocb_buffer_t data;
155 data.buf_ptr = msg;
156 data.buf_length = length;
158 return bcm63xx_uart_write( myctx, &data );
160 #endif
163 static int bcm63xx_uart_open(cfe_devctx_t *ctx)
165 uint32_t tmpreg;
166 bcm63xx_uart_t * softc = ctx->dev_softc;
168 /* Enable the UART clock */
169 tmpreg = READREG( 0xFFFE0004 );
170 tmpreg |= 0x00000008;
171 WRITEREG( 0xFFFE0004, tmpreg );
174 softc->baudrate = DEFAULTBAUD;
175 bcm63xx_set_baudrate( softc );
177 WRITEREG( softc->uartctlreg, BRGEN | TXEN | RXEN |
178 BITS8SYM | ONESTOP |
179 RESETTXFIFO | RESETRXFIFO |
180 0x00000005 );
182 WRITEREG( softc->uartmscreg, TX4 | RX4 );
183 WRITEREG( softc->uartintreg, 0x0 );
185 #ifdef RAW_WRITE_HACK
186 myctx = ctx;
187 #endif
189 return 0;
193 static int bcm63xx_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
195 bcm63xx_uart_t * softc = ctx->dev_softc;
196 unsigned char * bptr;
197 int blen;
198 uint32_t status;
199 char inval;
200 uint32_t ctrlreg;
202 bptr = buffer->buf_ptr;
203 blen = buffer->buf_length;
205 while (blen > 0) {
206 status = READREG(softc->uart_status);
207 if(status & (RXOVFERR | RXPARERR | RXFRAMERR | RXBRK)) {
208 /* RX over flow */
209 if(status & RXOVFERR) {
210 /* reset RX FIFO to clr interrupt */
211 /* pChan->uartChannel->fifoctl |= RSTRXFIFOS; */
212 ctrlreg = READREG(softc->uartctlreg);
213 ctrlreg &= ~RESETRXFIFO;
214 WRITEREG( softc->uartctlreg, ctrlreg );
217 /* other errors just read the bad character to clear the bit */
218 inval = READREG( softc->uart_rx_hold ) & 0xFF;
220 else if(status & RXFIFONE) {
221 *bptr++ = READREG( softc->uart_rx_hold ) & 0xFF;
222 blen--;
224 else
225 break;
228 buffer->buf_retlen = buffer->buf_length - blen;
229 return 0;
233 static int bcm63xx_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
235 bcm63xx_uart_t * softc = ctx->dev_softc;
237 inpstat->inp_status = READREG(softc->uart_status) & RXFIFONE;
239 return 0;
243 static int bcm63xx_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
245 bcm63xx_uart_t * softc = ctx->dev_softc;
246 unsigned char * bptr;
247 int blen;
248 uint32_t status;
249 uint32_t control;
251 bptr = buffer->buf_ptr;
252 blen = buffer->buf_length;
254 status = 0;
255 while( (blen > 0) && !status ) {
256 /* Wait for the buffer to empty before we write the next character */
257 /* character at a time. Why doesn't it work though? */
258 do {
259 status = READREG( softc->uart_status ) & TXFIFOEMT;
260 } while( !status );
261 WRITEREG( softc->uart_tx_hold, *bptr );
262 bptr++;
263 blen--;
265 status = READREG( softc->uart_status ) & (TXOVFERR|TXUNDERR);
268 if( status ) {
269 /* Reset TX FIFO */
270 control = READREG( softc->uartctlreg );
271 control |= RESETTXFIFO;
272 WRITEREG( softc->uartctlreg, control );
273 blen++;
276 buffer->buf_retlen = buffer->buf_length - blen;
277 return 0;
281 static int bcm63xx_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
283 uint32_t tmpreg;
284 bcm63xx_uart_t * softc = ctx->dev_softc;
285 unsigned int * info = (unsigned int *) buffer->buf_ptr;
287 switch ((int)buffer->buf_ioctlcmd) {
288 case IOCTL_SERIAL_GETSPEED:
289 *info = softc->baudrate;
290 break;
291 case IOCTL_SERIAL_SETSPEED:
292 softc->baudrate = *info;
293 bcm63xx_set_baudrate( softc );
294 break;
295 case IOCTL_SERIAL_GETFLOW:
296 tmpreg = READREG( softc->uartmscreg );
297 if( tmpreg & (DTREN | RTSEN) ) {
298 *info = SERIAL_FLOW_HARDWARE;
299 } else {
300 *info = SERIAL_FLOW_SOFTWARE;
302 break;
303 case IOCTL_SERIAL_SETFLOW:
304 tmpreg = READREG( softc->uartmscreg );
305 switch( *info ) {
306 case SERIAL_FLOW_NONE:
307 case SERIAL_FLOW_SOFTWARE:
308 tmpreg &= ~(DTREN | RTSEN);
309 break;
310 case SERIAL_FLOW_HARDWARE:
311 tmpreg |= DTREN | RTSEN;
312 break;
314 WRITEREG( softc->uartmscreg, tmpreg );
315 break;
316 default:
317 return -1;
320 return 0;
324 static int bcm63xx_uart_close(cfe_devctx_t *ctx)
326 uint32_t tmpreg;
327 bcm63xx_uart_t * softc = ctx->dev_softc;
330 /* Turn off the UART clock. */
331 tmpreg = READREG( 0xFFFE0004 );
332 tmpreg &= ~( 0x00000008 );
333 WRITEREG( 0xFFFE0004, tmpreg );
335 /* Restore the Interrupt Status Register to its default state. */
336 tmpreg = READREG( INTMASKREG );
337 tmpreg |= ( INT_UART1 | INT_UART0 );
338 WRITEREG( INTMASKREG, tmpreg );
340 /*****************************/
342 /* Restore the baudword register */
343 WRITEREG( softc->baudwrdreg, 0x0 );
345 /* Restore the UART control register */
346 WRITEREG( softc->uartctlreg, 0x00003704 );
348 /* Restore the UART Miscellaneous Control Register */
349 WRITEREG( softc->uartmscreg, 0x00008800 );
351 /* Restore the UART Interrupt Mask / Status Register */
352 WRITEREG( softc->uartintreg, 0x0 );
354 return 0;