00001
00040 #include <cfg/macros.h>
00041 #include <cpu/power.h>
00042 #include <drv/ser_p.h>
00043 #include <drv/ser.h>
00044 #include <drv/vic_lpc2.h>
00045 #include <io/lpc23xx.h>
00046 #include "cfg/cfg_ser.h"
00047 #include "ser_lpc2.h"
00048
00049
00050 #define INT_UART0 6
00051 #define INT_UART1 7
00052 #define INT_UART2 28
00053 #define INT_UART3 29
00054
00055
00056 #define RBR 0x00
00057 #define THR 0x00
00058 #define DLL 0x00
00059 #define DLM 0x04
00060 #define IER 0x04
00061 #define IIR 0x08
00062 #define FCR 0x08
00063 #define LCR 0x0c
00064 #define LSR 0x14
00065 #define SCR 0x1c
00066 #define ACR 0x20
00067 #define ICR 0x24
00068 #define FDR 0x28
00069 #define TER 0x30
00070
00071
00072 extern struct Serial *ser_handles[SER_CNT];
00073
00074 struct LPC2Serial
00075 {
00076 struct SerialHardware hw;
00077 bool sending;
00078 int irq;
00079 };
00080
00081
00082 static struct LPC2Serial UARTDesc[SER_CNT];
00083
00084 struct uart_config
00085 {
00086 uint32_t base;
00087 uint32_t pconp;
00088 uint32_t pclksel0;
00089 uint32_t pclksel0_mask;
00090 uint32_t pclksel1;
00091 uint32_t pclksel1_mask;
00092 uint32_t pinsel0;
00093 uint32_t pinsel0_mask;
00094 uint32_t pinsel4;
00095 uint32_t pinsel4_mask;
00096 };
00097
00098
00099 static const struct uart_config uart_param[] =
00100 {
00101
00102 {
00103 .base = UART0_BASE_ADDR,
00104 .pconp = BV(3),
00105
00106 .pclksel0 = BV(6),
00107 .pclksel0_mask = BV(7) | BV(6),
00108
00109 .pclksel1 = 0,
00110 .pclksel1_mask = 0,
00111
00112 .pinsel0 = BV(6) | BV(4),
00113 .pinsel0_mask = BV(7) | BV(6) | BV(5) | BV(4),
00114
00115 .pinsel4 = 0,
00116 .pinsel4_mask = 0,
00117 },
00118
00119 {
00120 .base = UART1_BASE_ADDR,
00121 .pconp = BV(4),
00122
00123 .pclksel0 = BV(8),
00124 .pclksel0_mask = BV(9) | BV(8),
00125
00126 .pclksel1 = 0,
00127 .pclksel1_mask = 0,
00128
00129 .pinsel0 = 0,
00130 .pinsel0_mask = 0,
00131
00132 .pinsel4 = BV(3) | BV(1),
00133 .pinsel4_mask = BV(3) | BV(2) | BV(1) | BV(0),
00134 },
00135
00136 {
00137 .base = UART2_BASE_ADDR,
00138 .pconp = BV(24),
00139
00140 .pclksel0 = 0,
00141 .pclksel0_mask = 0,
00142
00143 .pclksel1 = BV(16),
00144 .pclksel1_mask = BV(17) | BV(16),
00145
00146 .pinsel0 = 0,
00147 .pinsel0_mask = 0,
00148
00149 .pinsel4 = BV(19) | BV(17),
00150 .pinsel4_mask = BV(19) | BV(18) | BV(17) | BV(16),
00151 },
00152
00153 {
00154 .base = UART3_BASE_ADDR,
00155 .pconp = BV(25),
00156
00157 .pclksel0 = 0,
00158 .pclksel0_mask = 0,
00159
00160 .pclksel1 = BV(18),
00161 .pclksel1_mask = BV(19) | BV(18),
00162
00163 .pinsel0 = BV(3) | BV(1),
00164 .pinsel0_mask = BV(3) | BV(2) | BV(1) | BV(0),
00165
00166 .pinsel4 = 0,
00167 .pinsel4_mask = 0,
00168 },
00169 };
00170
00171 static void lpc2_uartSetBaudRate(int port, unsigned long baud)
00172 {
00173 cpu_flags_t flags;
00174
00175 IRQ_SAVE_DISABLE(flags);
00176
00177
00178 *(reg8_t *)(uart_param[port].base + LCR) |= 0x80;
00179
00180 *(reg8_t *)(uart_param[port].base + DLL) =
00181 DIV_ROUND(CPU_FREQ, 16 * baud) & 0xFF;
00182
00183 *(reg8_t *)(uart_param[port].base + DLM) =
00184 (DIV_ROUND(CPU_FREQ, 16 * baud) >> 8) & 0xFF;
00185 *(reg32_t *)(uart_param[port].base + LCR) &= ~0x80;
00186
00187 *(reg8_t *)(uart_param[port].base + LCR) &= ~0x80;
00188
00189 IRQ_RESTORE(flags);
00190 }
00191
00192 static void lpc2_uartSetParity(int port, int parity)
00193 {
00194
00195 uint32_t config = BV(1) | BV(0);
00196
00197 cpu_flags_t flags;
00198
00199 IRQ_SAVE_DISABLE(flags);
00200
00201 switch(parity)
00202 {
00203 case SER_PARITY_NONE:
00204 break;
00205 case SER_PARITY_ODD:
00206 config |= BV(3);
00207 break;
00208 case SER_PARITY_EVEN:
00209 config |= BV(4) | BV(3);
00210 break;
00211 default:
00212 ASSERT(0);
00213 IRQ_RESTORE(flags);
00214 return;
00215 }
00216
00217 *(reg8_t *)(uart_param[port].base + LCR) = config;
00218
00219 IRQ_RESTORE(flags);
00220 }
00221
00222 static void lpc2_uartPutChar(uint32_t base, uint8_t c)
00223 {
00224 reg8_t *lsr = (reg8_t *)base + LSR;
00225 reg8_t *thr = (reg8_t *)base + THR;
00226
00227 while (!(*lsr & BV(6)))
00228 cpu_relax();
00229 *thr = c;
00230 }
00231
00232 void lpc2_uartInit(int port)
00233 {
00234 cpu_flags_t flags;
00235
00236 IRQ_SAVE_DISABLE(flags);
00237
00238
00239 PCONP |= uart_param[port].pconp;
00240
00241 PCLKSEL0 &= ~uart_param[port].pclksel0_mask;
00242 PCLKSEL0 |= uart_param[port].pclksel0;
00243 PCLKSEL1 &= ~uart_param[port].pclksel1_mask;
00244 PCLKSEL1 |= uart_param[port].pclksel1;
00245
00246
00247 *(reg8_t *)(uart_param[port].base + LCR) = 0x83;
00248
00249 *(reg8_t *)(uart_param[port].base + DLL) =
00250 DIV_ROUND(CPU_FREQ, 16 * CONFIG_KDEBUG_BAUDRATE) & 0xFF;
00251
00252 *(reg8_t *)(uart_param[port].base + DLM) =
00253 (DIV_ROUND(CPU_FREQ, 16 * CONFIG_KDEBUG_BAUDRATE) >> 8) & 0xFF;
00254
00255 *(reg32_t *)(uart_param[port].base + FDR) = 0x10;
00256
00257
00258 PINSEL0 &= ~uart_param[port].pinsel0_mask;
00259 PINSEL0 |= uart_param[port].pinsel0;
00260 PINSEL4 &= ~uart_param[port].pinsel4_mask;
00261 PINSEL4 |= uart_param[port].pinsel4;
00262
00263 *(reg8_t *)(uart_param[port].base + LCR) = 0x03;
00264
00265
00266 *(reg8_t *)(uart_param[port].base + TER) = BV(7);
00267
00268 *(reg8_t *)(uart_param[port].base + IER) = BV(0);
00269
00270 IRQ_RESTORE(flags);
00271 }
00272
00273 static bool tx_sending(struct SerialHardware *_hw)
00274 {
00275 struct LPC2Serial *hw = (struct LPC2Serial *)_hw;
00276 return hw->sending;
00277 }
00278
00279 INLINE bool lpc2_uartRxReady(int port)
00280 {
00281
00282 return *(reg8_t *)(uart_param[port].base + LSR) & BV(0) ? true : false;
00283 }
00284
00285 static void uart_irq_rx(int port)
00286 {
00287 struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
00288 char c;
00289
00290 while (lpc2_uartRxReady(port))
00291 {
00292
00293 c = *(reg8_t *)(uart_param[port].base + RBR);
00294 if (fifo_isfull(rxfifo))
00295 ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
00296 else
00297 fifo_push(rxfifo, c);
00298 }
00299 }
00300
00301 INLINE bool lpc2_uartTxReady(int port)
00302 {
00303
00304 return *(reg8_t *)(uart_param[port].base + LSR) & BV(5) ? true : false;
00305 }
00306
00307 static void uart_irq_tx(int port)
00308 {
00309 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
00310
00311 while (lpc2_uartTxReady(port))
00312 {
00313
00314
00315
00316
00317 if (fifo_isempty(txfifo))
00318 {
00319
00320 *(reg8_t *)(uart_param[port].base + IER) &= ~BV(1);
00321 UARTDesc[port].sending = false;
00322 break;
00323 }
00324
00325 *(reg8_t *)(uart_param[port].base + THR) = fifo_pop(txfifo);
00326 }
00327 }
00328
00329 static void uart_common_irq_handler(int port)
00330 {
00331
00332 uint32_t status = *(reg32_t *)(uart_param[port].base + IIR) >> 1 & 0x7;
00333
00334
00335 if (status == 0x02)
00336 uart_irq_rx(port);
00337
00338 else if (status == 0x01)
00339 uart_irq_tx(port);
00340
00341 VICVectAddr = 0;
00342 }
00343
00344 static void lpc2_uartIRQEnable(int port, vic_handler_t handler)
00345 {
00346 vic_setVector(UARTDesc[port].irq, handler);
00347 vic_enable(UARTDesc[port].irq);
00348 }
00349
00350 static void lpc2_uartIRQDisable(int port)
00351 {
00352 vic_disable(UARTDesc[port].irq);
00353 }
00354
00355
00356 #define UART_PORT(port) \
00357 \
00358 static unsigned char \
00359 uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
00360 static unsigned char \
00361 uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE]; \
00362 \
00363 \
00364 static DECLARE_ISR(uart ## port ## _irq_handler) \
00365 { \
00366 uart_common_irq_handler(port); \
00367 } \
00368 \
00369 \
00370 static void \
00371 uart ## port ## _txStart(struct SerialHardware *_hw) \
00372 { \
00373 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo; \
00374 struct LPC2Serial *hw = (struct LPC2Serial *)_hw; \
00375 \
00376 if (hw->sending) \
00377 return; \
00378 lpc2_uartPutChar(UART ## port ## _BASE_ADDR, fifo_pop(txfifo)); \
00379 if (!fifo_isempty(txfifo)) \
00380 { \
00381 hw->sending = true; \
00382 \
00383 *(reg8_t *)(uart_param[port].base + IER) |= BV(1); \
00384 } \
00385 } \
00386 \
00387 static void \
00388 uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
00389 unsigned long baud) \
00390 { \
00391 lpc2_uartSetBaudRate(port, baud); \
00392 } \
00393 \
00394 static void \
00395 uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
00396 int parity) \
00397 { \
00398 lpc2_uartSetParity(port, parity); \
00399 } \
00400 \
00401 static void \
00402 uart ## port ## _cleanup(struct SerialHardware *_hw) \
00403 { \
00404 struct LPC2Serial *hw = (struct LPC2Serial *)_hw; \
00405 \
00406 hw->sending = false; \
00407 lpc2_uartIRQDisable(port); \
00408 } \
00409 \
00410 static void \
00411 uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw), \
00412 UNUSED_ARG(struct Serial *, ser)) \
00413 { \
00414 lpc2_uartInit(port); \
00415 lpc2_uartIRQEnable(port, uart ## port ## _irq_handler); \
00416 } \
00417 \
00418 \
00419 static const struct SerialHardwareVT UART ## port ## _VT = \
00420 { \
00421 .init = uart ## port ## _init, \
00422 .cleanup = uart ## port ## _cleanup, \
00423 .setBaudrate = uart ## port ## _setbaudrate, \
00424 .setParity = uart ## port ## _setparity, \
00425 .txStart = uart ## port ## _txStart, \
00426 .txSending = tx_sending, \
00427 };
00428
00429
00430 UART_PORT(0)
00431 UART_PORT(1)
00432 UART_PORT(2)
00433 UART_PORT(3)
00434
00435 static struct LPC2Serial UARTDesc[SER_CNT] =
00436 {
00437 {
00438 .hw = {
00439 .table = &UART0_VT,
00440 .txbuffer = uart0_txbuffer,
00441 .rxbuffer = uart0_rxbuffer,
00442 .txbuffer_size = sizeof(uart0_txbuffer),
00443 .rxbuffer_size = sizeof(uart0_rxbuffer),
00444 },
00445 .sending = false,
00446 .irq = INT_UART0,
00447 },
00448 {
00449 .hw = {
00450 .table = &UART1_VT,
00451 .txbuffer = uart1_txbuffer,
00452 .rxbuffer = uart1_rxbuffer,
00453 .txbuffer_size = sizeof(uart1_txbuffer),
00454 .rxbuffer_size = sizeof(uart1_rxbuffer),
00455 },
00456 .sending = false,
00457 .irq = INT_UART1,
00458 },
00459 {
00460 .hw = {
00461 .table = &UART2_VT,
00462 .txbuffer = uart2_txbuffer,
00463 .rxbuffer = uart2_rxbuffer,
00464 .txbuffer_size = sizeof(uart2_txbuffer),
00465 .rxbuffer_size = sizeof(uart2_rxbuffer),
00466 },
00467 .sending = false,
00468 .irq = INT_UART2,
00469 },
00470 {
00471 .hw = {
00472 .table = &UART3_VT,
00473 .txbuffer = uart3_txbuffer,
00474 .rxbuffer = uart3_rxbuffer,
00475 .txbuffer_size = sizeof(uart3_txbuffer),
00476 .rxbuffer_size = sizeof(uart3_rxbuffer),
00477 },
00478 .sending = false,
00479 .irq = INT_UART3,
00480 },
00481 };
00482
00483 struct SerialHardware *ser_hw_getdesc(int port)
00484 {
00485 ASSERT(port >= 0 && port < SER_CNT);
00486 return &UARTDesc[port].hw;
00487 }