mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 18:41:11 +00:00
Add npcx_evb in board folder for testing Add shared-spi arch support in common layer. Modified drivers for 1. Fan.c: console command “pwmduty”. 2. Pwm.c: for the issue when set duty to 0. 3. System.c: for hw reset only during system reset. 4. Flash.c: Fixed access denied bug of the flash driver for host command. 5. Comments from Patch Set 1 6. Comments from Patch Set 3 (except sha256.c) 7. Add openocd and flash_ec support for npcx_evb 8. Add little FW and spi-flash upload FW in chip folder 9. Add optional make rules for PROJECT_EXTRA 10.Replace CONFIG_SHRSPI_ARCH with CONFIG_CODERAM_ARCH and remove changes in common layer sources for shared-spi arch. (except sysjump) 11.Find the root cause of JTAG issue and use workaround method with SUPPORT_JTAG in clock.c 12 Execute hibernate in low power RAM for better power consumption 13 Add workaround method for version console command 14 Modified coding style issues by checkpatch.pl tool BUG=chrome-os-partner:34346 TEST=make buildall -j; test nuvoton IC specific drivers BRANCH=none Change-Id: I5e383420642de1643e2bead837a55c8c58481786 Signed-off-by: Ian Chao <mlchao@nuvoton.com> Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/233742
211 lines
4.7 KiB
C
211 lines
4.7 KiB
C
/* Copyright (c) 2014 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 "clock_chip.h"
|
|
#include "system.h"
|
|
#include "task.h"
|
|
#include "uart.h"
|
|
#include "util.h"
|
|
|
|
static int init_done;
|
|
|
|
int uart_init_done(void)
|
|
{
|
|
return init_done;
|
|
}
|
|
|
|
void uart_tx_start(void)
|
|
{
|
|
if (IS_BIT_SET(NPCX_WKEN(1, 1), 0)) {
|
|
/* disable MIWU*/
|
|
CLEAR_BIT(NPCX_WKEN(1, 1), 0);
|
|
/* go back to original setting */
|
|
task_enable_irq(NPCX_IRQ_WKINTB_1);
|
|
/* Go back CR_SIN*/
|
|
SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
|
|
/* enable uart again from MIWU mode */
|
|
task_enable_irq(NPCX_IRQ_UART);
|
|
}
|
|
|
|
/* If interrupt is already enabled, nothing to do */
|
|
if (NPCX_UICTRL & 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.
|
|
*/
|
|
NPCX_UICTRL |= 0x20;
|
|
|
|
task_trigger_irq(NPCX_IRQ_UART);
|
|
}
|
|
|
|
void uart_tx_stop(void) /* Disable TX interrupt */
|
|
{
|
|
NPCX_UICTRL &= ~0x20;
|
|
|
|
/* Re-allow deep sleep */
|
|
enable_sleep(SLEEP_MASK_UART);
|
|
}
|
|
|
|
void uart_tx_flush(void)
|
|
{
|
|
/* Wait for transmit FIFO empty */
|
|
while (!(NPCX_UICTRL & 0x01))
|
|
;
|
|
}
|
|
|
|
int uart_tx_ready(void)
|
|
{
|
|
return NPCX_UICTRL & 0x01; /*if TX FIFO is empty return 1*/
|
|
}
|
|
|
|
int uart_tx_in_progress(void)
|
|
{
|
|
/* Transmit is in progress if the TX busy bit is set. */
|
|
return NPCX_USTAT & 0x40; /*BUSY bit , if busy return 1*/
|
|
}
|
|
|
|
int uart_rx_available(void)
|
|
{
|
|
uint8_t ctrl = NPCX_UICTRL;
|
|
#ifdef CONFIG_LOW_POWER_IDLE
|
|
/*
|
|
* 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.
|
|
*/
|
|
if (ctrl & 0x02)
|
|
clock_refresh_console_in_use();
|
|
#endif
|
|
return ctrl & 0x02; /* If RX FIFO is empty return '0'*/
|
|
}
|
|
|
|
void uart_write_char(char c)
|
|
{
|
|
/* Wait for space in transmit FIFO. */
|
|
while (!uart_tx_ready())
|
|
;
|
|
|
|
NPCX_UTBUF = c;
|
|
}
|
|
|
|
int uart_read_char(void)
|
|
{
|
|
return NPCX_URBUF;
|
|
}
|
|
|
|
static void uart_clear_rx_fifo(int channel)
|
|
{
|
|
int scratch __attribute__ ((unused));
|
|
if (channel == 0) { /* suppose '0' is EC UART*/
|
|
/*if '1' that mean have a RX data on the FIFO register*/
|
|
while ((NPCX_UICTRL & 0x02))
|
|
scratch = NPCX_URBUF;
|
|
}
|
|
}
|
|
|
|
void uart_disable_interrupt(void)
|
|
{
|
|
task_disable_irq(NPCX_IRQ_UART);
|
|
}
|
|
|
|
void uart_enable_interrupt(void)
|
|
{
|
|
task_enable_irq(NPCX_IRQ_UART);
|
|
}
|
|
|
|
/**
|
|
* Interrupt handler for UART0
|
|
*/
|
|
void uart_ec_interrupt(void)
|
|
{
|
|
/* Read input FIFO until empty, then fill output FIFO */
|
|
uart_process_input();
|
|
uart_process_output();
|
|
}
|
|
DECLARE_IRQ(NPCX_IRQ_UART, uart_ec_interrupt, 1);
|
|
|
|
|
|
static void uart_config(void)
|
|
{
|
|
uint32_t div, opt_dev, min_deviation, clk, calc_baudrate, deviation;
|
|
uint8_t prescalar, opt_prescalar, i;
|
|
/* Enable the port */
|
|
/* Configure pins from GPIOs to CR_UART */
|
|
gpio_config_module(MODULE_UART, 1);
|
|
|
|
/* Calculated UART baudrate , clock source from APB2 */
|
|
opt_prescalar = opt_dev = 0;
|
|
prescalar = 10;
|
|
min_deviation = 0xFFFFFFFF;
|
|
clk = clock_get_apb2_freq();
|
|
for (i = 1; i < 31; i++) {
|
|
div = (clk * 10) / (16 * CONFIG_UART_BAUD_RATE * prescalar);
|
|
if (div != 0) {
|
|
calc_baudrate = (clk * 10) / (16 * div * prescalar);
|
|
deviation = (calc_baudrate > CONFIG_UART_BAUD_RATE) ?
|
|
(calc_baudrate - CONFIG_UART_BAUD_RATE) :
|
|
(CONFIG_UART_BAUD_RATE - calc_baudrate);
|
|
if (deviation < min_deviation) {
|
|
min_deviation = deviation;
|
|
opt_prescalar = i;
|
|
opt_dev = div;
|
|
}
|
|
}
|
|
prescalar += 5;
|
|
}
|
|
opt_dev--;
|
|
NPCX_UPSR = ((opt_prescalar<<3) & 0xF8) | ((opt_dev >> 8) & 0x7);
|
|
NPCX_UBAUD = (uint8_t)opt_dev;
|
|
/*
|
|
* 8-N-1, FIFO enabled. Must be done after setting
|
|
* the divisor for the new divisor to take effect.
|
|
*/
|
|
NPCX_UFRS = 0x00;
|
|
NPCX_UICTRL = 0x40; /* receive int enable only */
|
|
}
|
|
|
|
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 = 0x10; /* bit 4 */
|
|
clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL);
|
|
|
|
/* Set pin-mask for UART */
|
|
SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
|
|
gpio_config_module(MODULE_UART, 1);
|
|
|
|
/* Configure UARTs (identically) */
|
|
uart_config();
|
|
|
|
/*
|
|
* 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(NPCX_IRQ_UART);
|
|
|
|
init_done = 1;
|
|
}
|