summaryrefslogtreecommitdiff
path: root/chip/lm4/uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/lm4/uart.c')
-rw-r--r--chip/lm4/uart.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c
index 7fd7101b70..8e593f7c65 100644
--- a/chip/lm4/uart.c
+++ b/chip/lm4/uart.c
@@ -69,6 +69,12 @@ int uart_tx_ready(void)
return !(LM4_UART_FR(0) & 0x20);
}
+int uart_tx_in_progress(void)
+{
+ /* Transmit is in progress if the TX busy bit is set. */
+ return LM4_UART_FR(0) & 0x08;
+}
+
int uart_rx_available(void)
{
return !(LM4_UART_FR(0) & 0x10);
@@ -192,7 +198,7 @@ void uart_init(void)
* UART in run and sleep modes.
*/
mask |= 1;
- clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_DSLEEP);
+ clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL);
#ifdef CONFIG_UART_HOST
mask |= (1 << CONFIG_UART_HOST);
@@ -217,6 +223,71 @@ void uart_init(void)
init_done = 1;
}
+#ifdef CONFIG_LOW_POWER_IDLE
+void uart_enter_dsleep(void)
+{
+ const struct gpio_info g = gpio_list[GPIO_UART0_RX];
+
+ /* Disable the UART0 module interrupt. */
+ task_disable_irq(LM4_IRQ_UART0);
+
+ /* Disable UART0 peripheral in deep sleep. */
+ clock_disable_peripheral(CGC_OFFSET_UART, 0x1, CGC_MODE_DSLEEP);
+
+ /*
+ * Set the UART0 RX pin to be a generic GPIO with the flags defined
+ * in the board.c file.
+ */
+ gpio_set_flags_by_mask(g.port, g.mask, g.flags);
+ gpio_set_alternate_function(g.port, g.mask, -1);
+
+ /* Clear any pending GPIO interrupts on the UART0 RX pin. */
+ LM4_GPIO_ICR(g.port) = g.mask;
+
+ /* Enable GPIO interrupts on the UART0 RX pin. */
+ gpio_enable_interrupt(GPIO_UART0_RX);
+}
+
+void uart_exit_dsleep(void)
+{
+ const struct gpio_info g = gpio_list[GPIO_UART0_RX];
+
+ /*
+ * If the UART0 RX GPIO interrupt has not fired, then no edge has been
+ * detected. Disable the GPIO interrupt so that switching the pin over
+ * to a UART pin doesn't inadvertently cause a GPIO edge interrupt.
+ * Note: we can't disable this interrupt if it has already fired
+ * because then the IRQ will not get called.
+ */
+ if (!(LM4_GPIO_MIS(g.port) & g.mask))
+ gpio_disable_interrupt(GPIO_UART0_RX);
+
+ /* Configure UART0 pins for use in UART peripheral. */
+ gpio_config_module(MODULE_UART, 1);
+
+ /* Clear pending interrupts on UART peripheral and enable interrupts. */
+ uart_clear_rx_fifo(0);
+ task_enable_irq(LM4_IRQ_UART0);
+
+ /* Enable UART0 peripheral in deep sleep */
+ clock_enable_peripheral(CGC_OFFSET_UART, 0x1, CGC_MODE_DSLEEP);
+}
+
+void uart_deepsleep_interrupt(enum gpio_signal signal)
+{
+ /*
+ * Activity seen on UART RX pin while UART was disabled for deep sleep.
+ * The console won't see that character because the UART is disabled,
+ * so we need to inform the clock module of UART activity ourselves.
+ */
+ clock_refresh_console_in_use();
+
+ /* Disable interrupts on UART0 RX pin to avoid repeated interrupts. */
+ gpio_disable_interrupt(GPIO_UART0_RX);
+}
+#endif /* CONFIG_LOW_POWER_IDLE */
+
+
/*****************************************************************************/
/* COMx functions */