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.c352
1 files changed, 0 insertions, 352 deletions
diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c
deleted file mode 100644
index 7ccea9eb75..0000000000
--- a/chip/lm4/uart.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* Copyright 2012 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* UART module for Chrome EC */
-
-#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "lpc.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "uart.h"
-#include "util.h"
-
-#ifdef CONFIG_UART_HOST
-#define IRQ_UART_HOST CONCAT2(LM4_IRQ_UART, CONFIG_UART_HOST)
-#endif
-
-static int init_done;
-
-int uart_init_done(void)
-{
- return init_done;
-}
-
-void uart_tx_start(void)
-{
- /* If interrupt is already enabled, nothing to do */
- if (LM4_UART_IM(0) & 0x20)
- return;
-
- /* Do not allow deep sleep while transmit in progress */
- disable_sleep(SLEEP_MASK_UART);
-
- /*
- * Re-enable the transmit interrupt, then forcibly trigger the
- * interrupt. This works around a hardware problem with the
- * UART where the FIFO only triggers the interrupt when its
- * threshold is _crossed_, not just met.
- */
- LM4_UART_IM(0) |= 0x20;
- task_trigger_irq(LM4_IRQ_UART0);
-}
-
-void uart_tx_stop(void)
-{
- LM4_UART_IM(0) &= ~0x20;
-
- /* Re-allow deep sleep */
- enable_sleep(SLEEP_MASK_UART);
-}
-
-void uart_tx_flush(void)
-{
- /* Wait for transmit FIFO empty */
- while (!(LM4_UART_FR(0) & 0x80))
- ;
-}
-
-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);
-}
-
-void uart_write_char(char c)
-{
- /* Wait for space in transmit FIFO. */
- while (!uart_tx_ready())
- ;
-
- LM4_UART_DR(0) = c;
-}
-
-int uart_read_char(void)
-{
- return LM4_UART_DR(0);
-}
-
-static void uart_clear_rx_fifo(int channel)
-{
- int scratch __attribute__ ((unused));
- while (!(LM4_UART_FR(channel) & 0x10))
- scratch = LM4_UART_DR(channel);
-}
-
-/**
- * Interrupt handler for UART0
- */
-void uart_ec_interrupt(void)
-{
- /* Clear transmit and receive interrupt status */
- LM4_UART_ICR(0) = 0x70;
-
-
- /* Read input FIFO until empty, then fill output FIFO */
- uart_process_input();
- uart_process_output();
-}
-DECLARE_IRQ(LM4_IRQ_UART0, uart_ec_interrupt, 1);
-
-#ifdef CONFIG_UART_HOST
-
-/**
- * Interrupt handler for Host UART
- */
-void uart_host_interrupt(void)
-{
- /* Clear transmit and receive interrupt status */
- LM4_UART_ICR(CONFIG_UART_HOST) = 0x70;
-
-#ifdef CONFIG_HOSTCMD_LPC
- /*
- * If we have space in our FIFO and a character is pending in LPC,
- * handle that character.
- */
- if (!(LM4_UART_FR(CONFIG_UART_HOST) & 0x20) && lpc_comx_has_char()) {
- /* Copy the next byte then disable transmit interrupt */
- LM4_UART_DR(CONFIG_UART_HOST) = lpc_comx_get_char();
- LM4_UART_IM(CONFIG_UART_HOST) &= ~0x20;
- }
-
- /*
- * Handle received character. There is no flow control on input;
- * received characters are blindly forwarded to LPC. This is ok
- * because LPC is much faster than UART, and we don't have flow control
- * on the UART receive-side either.
- */
- if (!(LM4_UART_FR(CONFIG_UART_HOST) & 0x10))
- lpc_comx_put_char(LM4_UART_DR(CONFIG_UART_HOST));
-#endif
-}
-/* Must be same prio as LPC interrupt handler so they don't preempt */
-DECLARE_IRQ(IRQ_UART_HOST, uart_host_interrupt, 2);
-
-#endif /* CONFIG_UART_HOST */
-
-static void uart_config(int port)
-{
- /* Disable the port */
- LM4_UART_CTL(port) = 0x0300;
- /* Use the internal oscillator */
- LM4_UART_CC(port) = 0x1;
- /* Set the baud rate divisor */
- LM4_UART_IBRD(port) = (INTERNAL_CLOCK / 16) / CONFIG_UART_BAUD_RATE;
- LM4_UART_FBRD(port) =
- (((INTERNAL_CLOCK / 16) % CONFIG_UART_BAUD_RATE) * 64
- + CONFIG_UART_BAUD_RATE / 2) / CONFIG_UART_BAUD_RATE;
- /*
- * 8-N-1, FIFO enabled. Must be done after setting
- * the divisor for the new divisor to take effect.
- */
- LM4_UART_LCRH(port) = 0x70;
- /*
- * Interrupt when RX fifo at minimum (>= 1/8 full), and TX fifo
- * when <= 1/4 full
- */
- LM4_UART_IFLS(port) = 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(port) = 0x50;
- /* Enable the port */
- LM4_UART_CTL(port) |= 0x0001;
-}
-
-void uart_init(void)
-{
- uint32_t mask = 0;
-
- /*
- * Enable UART0 in run, sleep, and deep sleep modes. Enable the Host
- * UART in run and sleep modes.
- */
- mask |= 1;
- clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL);
-
-#ifdef CONFIG_UART_HOST
- mask |= BIT(CONFIG_UART_HOST);
-#endif
-
- clock_enable_peripheral(CGC_OFFSET_UART, mask,
- CGC_MODE_RUN | CGC_MODE_SLEEP);
-
- gpio_config_module(MODULE_UART, 1);
-
- /* Configure UARTs (identically) */
- uart_config(0);
-
-#ifdef CONFIG_UART_HOST
- uart_config(CONFIG_UART_HOST);
-#endif
-
- /*
- * Enable interrupts for UART0 only. Host UART will have to wait
- * until the LPC bus is initialized.
- */
- uart_clear_rx_fifo(0);
- task_enable_irq(LM4_IRQ_UART0);
-
- 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_reset(GPIO_UART0_RX);
-
- /* 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 */
-
-#ifdef CONFIG_UART_HOST
-
-void uart_comx_enable(void)
-{
- uart_clear_rx_fifo(CONFIG_UART_HOST);
- task_enable_irq(IRQ_UART_HOST);
-}
-
-int uart_comx_putc_ok(void)
-{
- if (LM4_UART_FR(CONFIG_UART_HOST) & 0x20) {
- /*
- * FIFO is full, so enable transmit interrupt to let us know
- * when it empties.
- */
- LM4_UART_IM(CONFIG_UART_HOST) |= 0x20;
- return 0;
- } else {
- return 1;
- }
-}
-
-void uart_comx_putc(int c)
-{
- LM4_UART_DR(CONFIG_UART_HOST) = c;
-}
-
-#endif /* CONFIG_UART_HOST */
-
-/*****************************************************************************/
-/* Console commands */
-
-#ifdef CONFIG_CMD_COMXTEST
-
-/**
- * Write a character to COMx, waiting for space in the output buffer if
- * necessary.
- */
-static void uart_comx_putc_wait(int c)
-{
- while (!uart_comx_putc_ok())
- ;
- uart_comx_putc(c);
-}
-
-static int command_comxtest(int argc, char **argv)
-{
- /* Put characters to COMX port */
- const char *c = argc > 1 ? argv[1] : "testing comx output!";
-
- ccprintf("Writing \"%s\\r\\n\" to COMx UART...\n", c);
-
- while (*c)
- uart_comx_putc_wait(*c++);
-
- uart_comx_putc_wait('\r');
- uart_comx_putc_wait('\n');
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(comxtest, command_comxtest,
- "[string]",
- "Write test data to COMx uart");
-
-#endif /* CONFIG_CMD_COMXTEST */