summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-12-09 13:55:27 -0800
committerRandall Spangler <rspangler@chromium.org>2011-12-12 14:12:09 -0800
commit70c3e30b633b530acb913a99d7cb602c9e8baf99 (patch)
treec431e759327c7740d9e2f2d7307a186305887652
parent6995d4771f7c07b08948c867f4ec0de309ed925e (diff)
downloadchrome-ec-70c3e30b633b530acb913a99d7cb602c9e8baf99.tar.gz
Clean up UART code
LPC module no longer directly talks to UART registers, and vice-versa. Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=none TEST='ectool sertest' on target system Change-Id: Id070c0d849bdfe91c752e0af651d357b695d2648 (cherry picked from commit ab8c3c2b8e3b08a4bf5573cda3a12dd3a384e67d)
-rw-r--r--chip/lm4/lpc.c54
-rw-r--r--chip/lm4/registers.h7
-rw-r--r--chip/lm4/uart.c123
-rw-r--r--include/lpc.h6
-rw-r--r--include/uart.h9
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 */