Files
OpenCellular/chip/rotor/uart.c
Aseda Aboagye 5832b34148 chip: Initial support for rotor.
This commit adds initial support for rotor.

Basic drivers including:

 - hardware timer
 - GPIO
 - UART
 - watchdog

BUG=chrome-os-partner:51665
BRANCH=None
TEST=make -j buildall tests

Change-Id: I4e384fc69297f807268dcd43cf47f99ab059fd05
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/373202
Commit-Ready: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2016-09-09 12:33:48 -07:00

139 lines
2.7 KiB
C

/* Copyright 2016 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 Rotor MCU */
#include "gpio.h"
#include "registers.h"
#include "task.h"
#include "uart.h"
/* UART reference clock is 200MHz. */
#define UART_REF_CLK 200000000
static int init_done;
void uart_init(void)
{
uint16_t divisor;
/* Ungate the UART clock and the UART reference clock. */
ROTOR_MCU_UART0_CLKGEN |= (1 << 1);
ROTOR_MCU_UART0_REFCLKGEN |= (1 << 1);
/* Set DLAB = 1 */
ROTOR_MCU_UART_LCR(0) |= (1 << 7);
/* Set divisor for baud rate. */
#ifdef BOARD_REI
divisor = 1;
#else
divisor = UART_REF_CLK / (16 * CONFIG_UART_BAUD_RATE);
#endif /* !defined(BOARD_REI) */
ROTOR_MCU_UART_DLH(0) = (divisor & 0xFF00) >> 8;
ROTOR_MCU_UART_DLL(0) = divisor & 0xFF;
/* Clear DLAB bit. */
ROTOR_MCU_UART_LCR(0) &= ~(1 << 7);
/* Set data bits per character to 8. */
ROTOR_MCU_UART_LCR(0) |= (1 << 1) | (1 << 0);
/* Enable FIFOs. */
ROTOR_MCU_UART_FCR(0) |= (1 << 0);
/* Enable the pins for UART functionality. */
gpio_config_module(MODULE_UART, 1);
/* Enable Received Data Available Interrupt. */
ROTOR_MCU_UART_IER(0) |= (1 << 0);
/* Enable the interrupt. */
task_enable_irq(ROTOR_MCU_IRQ_UART_0);
init_done = 1;
}
int uart_init_done(void)
{
return init_done;
}
void uart_tx_flush(void)
{
/* Wait for TX FIFO to empty. */
while (!(ROTOR_MCU_UART_USR(0) & (1 << 2)))
;
}
int uart_tx_ready(void)
{
/* Bit set if TX FIFO is not full. */
return (ROTOR_MCU_UART_LSR(0) & (1 << 5));
}
int uart_tx_in_progress(void)
{
/* Bit set if TX FIFO is empty. */
return !(ROTOR_MCU_UART_USR(0) & (1 << 2));
}
int uart_rx_available(void)
{
/* Bit set if RX FIFO is not empty. */
return (ROTOR_MCU_UART_LSR(0) & (1 << 0));
}
void uart_write_char(char c)
{
/* Wait for space in TX FIFO. */
while (!uart_tx_ready())
;
ROTOR_MCU_UART_THR(0) = c;
}
int uart_read_char(void)
{
return ROTOR_MCU_UART_RBR(0);
}
void uart_disable_interrupt(void)
{
task_disable_irq(ROTOR_MCU_IRQ_UART_0);
}
void uart_enable_interrupt(void)
{
task_enable_irq(ROTOR_MCU_IRQ_UART_0);
}
void uart_tx_start(void)
{
/* Nothing to do if the interrupt is already enabled. */
if (ROTOR_MCU_UART_IER(0) & (1 << 1))
return;
ROTOR_MCU_UART_IER(0) |= (1 << 1);
/* Force trigger a UART interrupt. */
task_trigger_irq(ROTOR_MCU_IRQ_UART_0);
}
void uart_tx_stop(void)
{
/* Disable Transmit Holding Register Empty interrupt. */
ROTOR_MCU_UART_IER(0) &= ~(1 << 1);
}
void uart_ec_interrupt(void)
{
/* Read input FIFO until empty, then fill output FIFO */
uart_process_input();
uart_process_output();
}
DECLARE_IRQ(ROTOR_MCU_IRQ_UART_0, uart_ec_interrupt, 1);