diff options
Diffstat (limited to 'chip/lm4/uart.c')
-rw-r--r-- | chip/lm4/uart.c | 73 |
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 */ |