diff options
-rw-r--r-- | chip/lm4/lpc.c | 54 | ||||
-rw-r--r-- | chip/lm4/registers.h | 7 | ||||
-rw-r--r-- | chip/lm4/uart.c | 123 | ||||
-rw-r--r-- | include/lpc.h | 6 | ||||
-rw-r--r-- | include/uart.h | 9 |
5 files changed, 101 insertions, 98 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index a74ebaaf95..962b4f07ba 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -109,32 +109,9 @@ int lpc_init(void) /* TODO: could configure IRQSELs and set IRQEN2/CX, and then the host * can enable IRQs on its own. */ LM4_LPC_CTL(LPC_CH_COMX) = 0x0004 | (LPC_POOL_OFFS_COMX << (5 - 1)); - -#ifdef USE_LPC_COMx_DMA - /* TODO: haven't been able to get this to work yet */ - /* COMx UART DMA mode */ - LM4_LPC_LPCDMACX = 0x00070000; - - /* TODO: set up DMA */ - LM4_SYSTEM_RCGCDMA = 1; - /* Wait 3 clocks before accessing other DMA regs */ - LM4_SYSTEM_RCGCDMA = 1; - LM4_SYSTEM_RCGCDMA = 1; - LM4_SYSTEM_RCGCDMA = 1; - /* Enable master */ - LM4_DMA_DMACFG = 1; - /* TODO: hope we don't need the channel control structs; we're just - * throwing this somewhere in memory. Shouldn't need it if we leave - * all the channel disabled, though. */ - LM4_DMA_DMACTLBASE = 0x20004000; - /* Map UART and LPC DMA functions to channels */ - LM4_DMA_DMACHMAP0 = 0x00003000; /* Channel 3 encoding 3 = LPC0 Ch3 */ - LM4_DMA_DMACHMAP1 = 0x00000011; /* Channels 8,9 encoding 1 = UART1 */ -#else /* Use our LPC interrupt handler to notify COMxIM on write-from-host */ LM4_LPC_LPCDMACX = 0x00110000; LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_COMX, 2); -#endif /* Enable LPC channels */ LM4_LPC_LPCCTL = @@ -174,6 +151,23 @@ void lpc_send_host_response(int slot, int status) } +int lpc_comx_has_char(void) +{ + return LM4_LPC_ST(LPC_CH_COMX) & 0x02; +} + + +int lpc_comx_get_char(void) +{ + /* TODO: this clears the receive-ready interrupt too, which will be ok + * once we're handing output to COMx as well. But we're not yet. */ + LM4_LPC_LPCDMACX = LM4_LPC_LPCDMACX; + /* Copy the next byte */ + return LPC_POOL_COMX[0]; +} + + + /* LPC interrupt handler */ static void lpc_interrupt(void) { @@ -229,16 +223,10 @@ static void lpc_interrupt(void) LM4_LPC_LPCDMACX = cis; /* Handle host writes */ - if (LM4_LPC_ST(LPC_CH_COMX) & 0x02) { - if (LM4_UART_FR(1) & 0x20) { - /* FIFO is full, so enable transmit - * interrupt to let us know when it - * empties */ - LM4_UART_IM(1) |= 0x20; - } else { - /* Space in FIFO, so copy byte */ - LM4_UART_DR(1) = LPC_POOL_COMX[0]; - } + if (lpc_comx_has_char()) { + /* Copy a character to the UART if there's space */ + if (uart_comx_putc_ok()) + uart_comx_putc(lpc_comx_get_char()); } /* TODO: handle UART input to host - if host read the diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h index 3ac924c64f..91fc2f90be 100644 --- a/chip/lm4/registers.h +++ b/chip/lm4/registers.h @@ -16,7 +16,12 @@ #define LM4_UART_CH0_BASE 0x4000c000 #define LM4_UART_CH1_BASE 0x4000d000 -#define LM4UARTREG(ch, offset) LM4REG(LM4_UART_CH##ch##_BASE + (offset)) +#define LM4_UART_CH_SEP 0x00001000 +static inline int lm4_uart_addr(int ch, int offset) +{ + return offset + LM4_UART_CH0_BASE + LM4_UART_CH_SEP * ch; +} +#define LM4UARTREG(ch, offset) LM4REG(lm4_uart_addr(ch, offset)) #define LM4_UART_DR(ch) LM4UARTREG(ch, 0x000) #define LM4_UART_FR(ch) LM4UARTREG(ch, 0x018) #define LM4_UART_IBRD(ch) LM4UARTREG(ch, 0x024) diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c index d7177e0f96..f7f785301d 100644 --- a/chip/lm4/uart.c +++ b/chip/lm4/uart.c @@ -9,6 +9,7 @@ #include "board.h" #include "console.h" +#include "lpc.h" #include "registers.h" #include "task.h" #include "uart.h" @@ -85,11 +86,10 @@ static void uart_0_interrupt(void) last_rx_was_cr = 0; } - /* Echo characters directly to the transmit - * FIFO so we don't interfere with the - * transmit buffer. This means that if a lot - * of output is happening, input characters - * won't always be properly echoed. */ + /* Echo characters directly to the transmit FIFO so we + * don't interfere with the transmit buffer. This + * means that if a lot of output is happening, input + * characters won't always be properly echoed. */ if (console_mode && c == '\n') LM4_UART_DR(0) = '\r'; LM4_UART_DR(0) = c; @@ -97,9 +97,8 @@ static void uart_0_interrupt(void) /* Handle backspace if we can */ if (c == '\b') { if (rx_buf_head != rx_buf_tail) { - /* Delete the previous - * character (and space over - * it on the output) */ + /* Delete the previous character (and + * space over it on the output) */ LM4_UART_DR(0) = ' '; LM4_UART_DR(0) = '\b'; rx_buf_head = RX_BUF_PREV(rx_buf_head); @@ -141,17 +140,10 @@ static void uart_1_interrupt(void) /* TODO: handle input */ /* If we have space in our FIFO and a character is pending in LPC, - * grab it. - * - * TODO: move UART1 interrupt to the LPC module? */ - if (!(LM4_UART_FR(1) & 0x20) && (LM4_LPC_ST(LPC_CH_COMX) & 0x02)) { - /* TODO: this clears the receive-ready interrupt too, - * which will be ok once we're handing input as well. - * But we're not yet. */ - LM4_LPC_LPCDMACX = LM4_LPC_LPCDMACX; - /* Copy the next byte */ - LM4_UART_DR(1) = LPC_POOL_COMX[0]; - /* Disable transmit interrupt */ + * handle that character. */ + if (!(LM4_UART_FR(1) & 0x20) && lpc_comx_has_char()) { + /* Copy the next byte then disable transmit interrupt */ + LM4_UART_DR(1) = lpc_comx_get_char(); LM4_UART_IM(1) &= ~0x20; } } @@ -189,6 +181,7 @@ static void configure_gpio(void) int uart_init(void) { volatile uint32_t scratch __attribute__((unused)); + int ch; /* Enable UART0 and UART1 and delay a few clocks */ LM4_SYSTEM_RCGCUART |= 0x03; @@ -197,58 +190,36 @@ int uart_init(void) /* Configure GPIOs */ configure_gpio(); - /* UART0 setup */ - /* Disable the port via UARTCTL */ - LM4_UART_CTL(0) = 0x0300; - /* Set the baud rate divisor */ - LM4_UART_IBRD(0) = (CPU_CLOCK / 16) / BAUD_RATE; - LM4_UART_FBRD(0) = + /* Configure UART0 and UART1 (identically) */ + for (ch = 0; ch < 2; ch++) { + /* Disable the port */ + LM4_UART_CTL(ch) = 0x0300; + /* Set the baud rate divisor */ + LM4_UART_IBRD(ch) = (CPU_CLOCK / 16) / BAUD_RATE; + LM4_UART_FBRD(ch) = (((CPU_CLOCK / 16) % BAUD_RATE) * 64 + BAUD_RATE / 2) / BAUD_RATE; - /* Set UARTLCRH to 8-N-1, FIFO enabled. Must be done after setting - * the divisor for the new divisor to take effect. */ - LM4_UART_LCRH(0) = 0x70; - /* Interrupt when RX fifo at minimum (>= 1/8 full), and TX fifo when - * <= 1/4 full */ - LM4_UART_IFLS(0) = 0x01; - /* Unmask receive-FIFO, receive-timeout. We need - * receive-timeout because the minimum RX FIFO depth is 1/8 = - * 2 bytes; without the receive-timeout we'd never be notified - * about single received characters. */ - LM4_UART_IM(0) = 0x50; - /* Enable the port */ - LM4_UART_CTL(0) |= 0x0001; - - /* UART1 setup */ - /* Disable the port via UARTCTL */ - LM4_UART_CTL(1) = 0x0300; - /* Set the baud rate divisor */ - LM4_UART_IBRD(1) = (CPU_CLOCK / 16) / BAUD_RATE; - LM4_UART_FBRD(1) = - (((CPU_CLOCK / 16) % BAUD_RATE) * 64 + BAUD_RATE / 2) / - BAUD_RATE; - /* Set UARTLCRH to 8-N-1, FIFO enabled. Must be done after setting - * the divisor for the new divisor to take effect. */ - LM4_UART_LCRH(1) = 0x70; - /* Unmask receive-FIFO, receive-timeout. We need - * receive-timeout because the minimum RX FIFO depth is 1/8 = - * 2 bytes; without the receive-timeout we'd never be notified - * about single received characters. */ - LM4_UART_IM(1) = 0x50; -#ifdef USE_UART_DMA - /* No interrupts on UART1 */ - LM4_UART_IM(1) = 0x00; - /* Enable RX and TX DMA */ - LM4_UART_DMACTL(1) = 0x03; -#endif - /* Enable the port */ - LM4_UART_CTL(1) |= 0x0001; + /* 8-N-1, FIFO enabled. Must be done after setting + * the divisor for the new divisor to take effect. */ + LM4_UART_LCRH(ch) = 0x70; + /* Interrupt when RX fifo at minimum (>= 1/8 full), and TX fifo + * when <= 1/4 full */ + LM4_UART_IFLS(ch) = 0x01; + /* Unmask receive-FIFO, receive-timeout. We need + * receive-timeout because the minimum RX FIFO depth is 1/8 = 2 + * bytes; without the receive-timeout we'd never be notified + * about single received characters. */ + LM4_UART_IM(ch) = 0x50; + /* Enable the port */ + LM4_UART_CTL(ch) |= 0x0001; + } /* Print hello on UART1 for debugging */ + /* TODO: remove in production */ { const char *c = "Hello on UART1\r\n"; while (*c) - LM4_UART_DR(1) = *c++; + uart_comx_putc(*c++); } return EC_SUCCESS; @@ -462,6 +433,7 @@ void uart_emergency_flush(void) } while (tx_buf_head != tx_buf_tail); } + void uart_flush_input(void) { /* Disable interrupts */ @@ -561,3 +533,26 @@ int uart_gets(char *dest, int size) /* Return the length we got */ return got; } + + +/*****************************************************************************/ +/* COMx functions */ + + +int uart_comx_putc_ok(void) +{ + if (LM4_UART_FR(1) & 0x20) { + /* FIFO is full, so enable transmit interrupt to let us know + * when it empties. */ + LM4_UART_IM(1) |= 0x20; + return 0; + } else { + return 1; + } +} + + +void uart_comx_putc(int c) +{ + LM4_UART_DR(1) = c; +} diff --git a/include/lpc.h b/include/lpc.h index 9fa68381a3..8cf87668f6 100644 --- a/include/lpc.h +++ b/include/lpc.h @@ -25,4 +25,10 @@ uint8_t *lpc_get_host_range(int slot); * commands, 1 for usermode-originated commands. */ void lpc_send_host_response(int slot, int status); +/* Returns non-zero if the COMx interface has received a character. */ +int lpc_comx_has_char(void); + +/* Returns the next character pending on the COMx interface. */ +int lpc_comx_get_char(void); + #endif /* __CROS_EC_LPC_H */ diff --git a/include/uart.h b/include/uart.h index 12ecf7a1a6..75ff43e9e7 100644 --- a/include/uart.h +++ b/include/uart.h @@ -109,4 +109,13 @@ int uart_gets(char *dest, int size); /* TODO: getc(), putc() equivalents? */ +/*****************************************************************************/ +/* COMx functions */ + +/* Returns non-zero if ok to put a character via uart_comx_putc(). */ +int uart_comx_putc_ok(void); + +/* Puts a character to the COMx interface. */ +void uart_comx_putc(int c); + #endif /* __CROS_EC_UART_H */ |