mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-01 12:52:26 +00:00
chip: Remove rotor.
It's unused. BUG=None BRANCH=None TEST=make -j buildall Change-Id: I91f9ec3ed4d3d632b75217fbf0254a9733e668a0 Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/434110 Commit-Ready: Aseda Aboagye <aaboagye@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
21b47a9ee5
commit
4c06e1f963
@@ -1,21 +0,0 @@
|
||||
# -*- makefile -*-
|
||||
# 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.
|
||||
#
|
||||
# Rotor chip specific files build
|
||||
#
|
||||
|
||||
# Rotor has a Cortex-M4F ARM core
|
||||
CORE:=cortex-m
|
||||
# Allow the full Cortex-M4 instruction set
|
||||
CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4
|
||||
|
||||
# Required chip modules
|
||||
chip-y=clock.o gpio.o hwtimer.o jtag.o system.o uart.o
|
||||
chip-$(CONFIG_I2C)+=i2c.o
|
||||
chip-$(CONFIG_SPI_MASTER)+=spi_master.o
|
||||
chip-$(CONFIG_WATCHDOG)+=watchdog.o
|
||||
|
||||
# Rotor MCU only supports one image, so only build RW.
|
||||
all_deps=$(patsubst ro,,$(def_all_deps))
|
||||
@@ -1,21 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Clock and power management settings */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
void clock_init(void)
|
||||
{
|
||||
/* Clocks should already be initialized for us. */
|
||||
}
|
||||
|
||||
int clock_get_freq(void)
|
||||
{
|
||||
return CPU_CLOCK;
|
||||
}
|
||||
|
||||
/* TODO(aaboagye): Add support for changing sysclock frequency. */
|
||||
@@ -1,73 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_CONFIG_CHIP_H
|
||||
#define __CROS_EC_CONFIG_CHIP_H
|
||||
|
||||
/* CPU core BFD configuration */
|
||||
#include "core/cortex-m/config_core.h"
|
||||
|
||||
/* Interval between HOOK_TICK notifications */
|
||||
#define HOOK_TICK_INTERVAL_MS 250
|
||||
#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC)
|
||||
|
||||
/****************************************************************************/
|
||||
/* Memory mapping */
|
||||
|
||||
/*
|
||||
* The memory region for RAM is 0x20000000-0x20060000. (384 KB)
|
||||
* - Only 1 image is loaded directly into SRAM.
|
||||
* - The lower 128KB is reserved for the image.
|
||||
* - The next 128KB is reserved for RAM.
|
||||
* - The last 128KB is reserved.
|
||||
*/
|
||||
|
||||
/****************************************************************************/
|
||||
#define ROTOR_MCU_SRAM_BASE 0x20000000
|
||||
#define ROTOR_MCU_SRAM_END (ROTOR_MCU_SRAM_BASE + (3 * 0x20000))
|
||||
#define CONFIG_RAM_BASE (ROTOR_MCU_SRAM_BASE + CONFIG_RW_SIZE)
|
||||
#define CONFIG_RAM_SIZE (1 * 0x20000)
|
||||
|
||||
/* Default task stack size. */
|
||||
#define TASK_STACK_SIZE 512
|
||||
|
||||
/* System stack size */
|
||||
#define CONFIG_STACK_SIZE 1024
|
||||
|
||||
/* non-standard task stack sizes */
|
||||
#define IDLE_TASK_STACK_SIZE 512
|
||||
#define LARGER_TASK_STACK_SIZE 768
|
||||
|
||||
#define CONFIG_PROGRAM_MEMORY_BASE ROTOR_MCU_SRAM_BASE
|
||||
#define CONFIG_MAPPED_STORAGE_BASE CONFIG_PROGRAM_MEMORY_BASE
|
||||
|
||||
/* There's only 1 image. */
|
||||
#undef CONFIG_FW_INCLUDE_RO
|
||||
#define CONFIG_RO_MEM_OFF 0
|
||||
#define CONFIG_RO_SIZE 0
|
||||
|
||||
#define CONFIG_RW_MEM_OFF 0
|
||||
#define CONFIG_RW_SIZE (1 * 0x20000)
|
||||
|
||||
/* There's no concept of protected storage for the MCU. */
|
||||
#define CONFIG_EC_PROTECTED_STORAGE_OFF 0
|
||||
#define CONFIG_EC_PROTECTED_STORAGE_SIZE 0
|
||||
#define CONFIG_EC_WRITABLE_STORAGE_OFF 0
|
||||
#define CONFIG_EC_WRITABLE_STORAGE_SIZE 0
|
||||
#define CONFIG_RO_STORAGE_OFF 0
|
||||
#define CONFIG_RW_STORAGE_OFF 0
|
||||
|
||||
#define CONFIG_FLASH_SIZE CONFIG_RW_SIZE
|
||||
#define CONFIG_FLASH_BANK_SIZE 0
|
||||
|
||||
/* Number of IRQ vectors on the NVIC */
|
||||
#define CONFIG_IRQ_COUNT 96
|
||||
|
||||
#define GPIO_PIN(port, index) GPIO_##port, (1 << index)
|
||||
#define GPIO_PIN_MASK(port, mask) GPIO_##port, (mask)
|
||||
|
||||
#define I2C_PORT_COUNT 6
|
||||
|
||||
#endif /* __CROS_EC_CONFIG_CHIP_H */
|
||||
@@ -1,25 +0,0 @@
|
||||
/* 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.
|
||||
*
|
||||
* DMA driver for Rotor MCU
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "dma.h"
|
||||
#include "registers.h"
|
||||
|
||||
rotor_mcu_dma_chan_t *dma_get_channel(enum dma_channel channel)
|
||||
{
|
||||
rotor_mcu_dma_regs_t *dma = ROTOR_MCU_DMA_REGS;
|
||||
|
||||
return &dma->chan[channel];
|
||||
}
|
||||
|
||||
void dma_prepare_tx(const struct dma_option *option, unsigned count,
|
||||
const void *memory)
|
||||
{
|
||||
rotor_mcu_dma_chan_t *chan = dma_get_channel(option->channel);
|
||||
|
||||
/* TODO(aaboagye): Actually set up a transaction. */
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* GPIO module for Rotor MCU */
|
||||
|
||||
#include "gpio.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
|
||||
test_mockable int gpio_get_level(enum gpio_signal signal)
|
||||
{
|
||||
uint32_t mask = gpio_list[signal].mask;
|
||||
uint32_t val;
|
||||
|
||||
if (mask == 0)
|
||||
return 0;
|
||||
|
||||
val = ROTOR_MCU_GPIO_PLR(gpio_list[signal].port);
|
||||
return (val & mask) ? 1 : 0;
|
||||
}
|
||||
|
||||
void gpio_set_level(enum gpio_signal signal, int value)
|
||||
{
|
||||
uint32_t mask = gpio_list[signal].mask;
|
||||
|
||||
if (mask == 0)
|
||||
return;
|
||||
|
||||
/* Enable direct writes to take effect. */
|
||||
ROTOR_MCU_GPIO_DWER(gpio_list[signal].port) |= mask;
|
||||
|
||||
if (value)
|
||||
ROTOR_MCU_GPIO_OLR(gpio_list[signal].port) |= mask;
|
||||
else
|
||||
ROTOR_MCU_GPIO_OLR(gpio_list[signal].port) &= ~mask;
|
||||
}
|
||||
|
||||
void gpio_pre_init(void)
|
||||
{
|
||||
int i;
|
||||
const struct gpio_info *g = gpio_list;
|
||||
|
||||
/* Set all GPIOs to their defaults. */
|
||||
for (i = 0; i < GPIO_COUNT; i++, g++) {
|
||||
int flags = g->flags;
|
||||
|
||||
if (flags & GPIO_DEFAULT)
|
||||
continue;
|
||||
|
||||
gpio_set_flags_by_mask(g->port, g->mask, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
|
||||
{
|
||||
while (mask) {
|
||||
int i = GPIO_MASK_TO_NUM(mask);
|
||||
const uint32_t this_mask = (1 << i);
|
||||
mask &= ~this_mask;
|
||||
|
||||
/* Enable direct writes to take effect. */
|
||||
ROTOR_MCU_GPIO_DWER(port) |= this_mask;
|
||||
|
||||
/* Input/Output */
|
||||
if (flags & GPIO_OUTPUT)
|
||||
ROTOR_MCU_GPIO_PDR(port) |= this_mask;
|
||||
else
|
||||
ROTOR_MCU_GPIO_PDR(port) &= ~this_mask;
|
||||
|
||||
/* Pull Up / Pull Down */
|
||||
if (flags & GPIO_PULL_UP) {
|
||||
ROTOR_MCU_GPIO_PCFG(port, i) |= (1 << 14);
|
||||
} else if (flags & GPIO_PULL_DOWN) {
|
||||
ROTOR_MCU_GPIO_PCFG(port, i) |= (1 << 13);
|
||||
} else {
|
||||
/* No pull up/down */
|
||||
ROTOR_MCU_GPIO_PCFG(port, i) &= ~(3 << 14);
|
||||
}
|
||||
|
||||
/* Edge vs. Level Interrupts */
|
||||
if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING))
|
||||
ROTOR_MCU_GPIO_IMR(port) &= this_mask;
|
||||
else
|
||||
ROTOR_MCU_GPIO_IMR(port) |= this_mask;
|
||||
|
||||
/* Interrupt polarity */
|
||||
if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_HIGH))
|
||||
ROTOR_MCU_GPIO_HRIPR(port) |= this_mask;
|
||||
else
|
||||
ROTOR_MCU_GPIO_HRIPR(port) &= ~this_mask;
|
||||
|
||||
if (flags & (GPIO_INT_F_FALLING | GPIO_INT_F_LOW))
|
||||
ROTOR_MCU_GPIO_LFIPR(port) |= this_mask;
|
||||
else
|
||||
ROTOR_MCU_GPIO_LFIPR(port) &= this_mask;
|
||||
|
||||
/* Set level */
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
if (flags & GPIO_HIGH)
|
||||
ROTOR_MCU_GPIO_OLR(port) |= this_mask;
|
||||
else if (flags & GPIO_LOW)
|
||||
ROTOR_MCU_GPIO_OLR(port) &= ~this_mask;
|
||||
}
|
||||
|
||||
/* No analog support. */
|
||||
};
|
||||
}
|
||||
|
||||
void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (mask) {
|
||||
i = GPIO_MASK_TO_NUM(mask);
|
||||
mask &= ~(1 << i);
|
||||
|
||||
ROTOR_MCU_GPIO_PCFG(port, i) &= ~0x7;
|
||||
if (func > 0)
|
||||
ROTOR_MCU_GPIO_PCFG(port, i) |= (func & 0x7);
|
||||
};
|
||||
}
|
||||
|
||||
int gpio_enable_interrupt(enum gpio_signal signal)
|
||||
{
|
||||
const struct gpio_info *g = gpio_list + signal;
|
||||
|
||||
if ((g->mask == 0) || (signal >= GPIO_IH_COUNT))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
ROTOR_MCU_GPIO_ITER(g->port) |= g->mask;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int gpio_disable_interrupt(enum gpio_signal signal)
|
||||
{
|
||||
const struct gpio_info *g = gpio_list + signal;
|
||||
|
||||
if ((g->mask == 0) || (signal >= GPIO_IH_COUNT))
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
ROTOR_MCU_GPIO_ITER(g->port) &= ~g->mask;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* GPIO IRQ handler.
|
||||
*
|
||||
* @param port GPIO port (GPIO_[ABCDE])
|
||||
* @param int_status interrupt status for the port.
|
||||
*/
|
||||
static void gpio_interrupt(int port, uint32_t int_status)
|
||||
{
|
||||
int i = 0;
|
||||
const struct gpio_info *g = gpio_list;
|
||||
|
||||
/* Search for the right IRQ handler. */
|
||||
for (i = 0; i < GPIO_IH_COUNT && int_status; i++, g++) {
|
||||
if (port == g->port && (int_status & g->mask)) {
|
||||
gpio_irq_handlers[i](i);
|
||||
int_status &= ~g->mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handlers for each GPIO port. These read and clear the interrupt bits for
|
||||
* the port, then call the master handler above.
|
||||
*/
|
||||
#define GPIO_IRQ_FUNC(irqfunc, port) \
|
||||
void irqfunc(void) \
|
||||
{ \
|
||||
uint32_t int_status = ROTOR_MCU_GPIO_ISR(port); \
|
||||
ROTOR_MCU_GPIO_ISR(port) = int_status; \
|
||||
gpio_interrupt(port, int_status); \
|
||||
}
|
||||
|
||||
GPIO_IRQ_FUNC(__gpio_a_interrupt, GPIO_A);
|
||||
GPIO_IRQ_FUNC(__gpio_b_interrupt, GPIO_B);
|
||||
GPIO_IRQ_FUNC(__gpio_c_interrupt, GPIO_C);
|
||||
GPIO_IRQ_FUNC(__gpio_d_interrupt, GPIO_D);
|
||||
GPIO_IRQ_FUNC(__gpio_e_interrupt, GPIO_E);
|
||||
|
||||
/* Declare per-bank GPIO IRQs. */
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_GPIO_0, __gpio_a_interrupt, 1);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_GPIO_1, __gpio_b_interrupt, 1);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_GPIO_2, __gpio_c_interrupt, 1);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_GPIO_3, __gpio_d_interrupt, 1);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_GPIO_4, __gpio_e_interrupt, 1);
|
||||
@@ -1,201 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Hardware timer driver for Rotor MCU */
|
||||
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "hwtimer.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* Timer 0 is the clock timer.
|
||||
* Timer 1 is the event timer.
|
||||
*/
|
||||
|
||||
#ifdef BOARD_REI
|
||||
/* static uint32_t reload_val; */
|
||||
#else
|
||||
static uint32_t rollover_cnt;
|
||||
#endif /* defined(BOARD_REI) */
|
||||
|
||||
|
||||
void __hw_clock_event_set(uint32_t deadline)
|
||||
{
|
||||
uint32_t ticks;
|
||||
uint32_t delta;
|
||||
|
||||
__hw_clock_event_clear();
|
||||
|
||||
delta = deadline - __hw_clock_source_read();
|
||||
|
||||
/* Convert the delta to ticks. */
|
||||
ticks = delta * (clock_get_freq() / SECOND);
|
||||
|
||||
/* Set the timer load count to the deadline. */
|
||||
ROTOR_MCU_TMR_TNLC(1) = ticks;
|
||||
|
||||
/* Enable the timer. */
|
||||
ROTOR_MCU_TMR_TNCR(1) |= (1 << 0);
|
||||
}
|
||||
|
||||
uint32_t __hw_clock_event_get(void)
|
||||
{
|
||||
uint32_t ticks;
|
||||
/* Get the time of the next programmed deadline. */
|
||||
ticks = ROTOR_MCU_TMR_TNCV(1);
|
||||
return __hw_clock_source_read() + ((ticks * SECOND) / clock_get_freq());
|
||||
}
|
||||
|
||||
void __hw_clock_event_clear(void)
|
||||
{
|
||||
/* Disable the event timer. This also clears any pending interrupt. */
|
||||
ROTOR_MCU_TMR_TNCR(1) &= ~(1 << 0);
|
||||
}
|
||||
|
||||
/* Triggered when Timer 1 reaches 0. */
|
||||
void __hw_clock_event_irq(void)
|
||||
{
|
||||
/*
|
||||
* Clear the event which disables the timer and clears the pending
|
||||
* interrupt.
|
||||
*/
|
||||
__hw_clock_event_clear();
|
||||
|
||||
/* Process timers now. */
|
||||
process_timers(0);
|
||||
}
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_TIMER_1, __hw_clock_event_irq, 1);
|
||||
|
||||
uint32_t __hw_clock_source_read(void)
|
||||
{
|
||||
#ifdef BOARD_REI
|
||||
/* uint32_t ticks = reload_val - ROTOR_MCU_TMR_TNCV(0); */
|
||||
uint32_t ticks = 0xFFFFFFFF - ROTOR_MCU_TMR_TNCV(0);
|
||||
/* Convert the ticks into microseconds. */
|
||||
/* return ticks * (SECOND / clock_get_freq()); */
|
||||
|
||||
return (ticks * (clock_get_freq() / SECOND));
|
||||
#else
|
||||
/* Convert ticks to microseconds and account for the rollovers. */
|
||||
uint32_t ticks = 0xFFFFFFFF - ROTOR_MCU_TMR_TNCV(0);
|
||||
uint32_t us = (0xFFFFFFFF / clock_get_freq()) * rollover_cnt * SECOND;
|
||||
return us + ((ticks * SECOND) / clock_get_freq());
|
||||
#endif /* defined(BOARD_REI) */
|
||||
}
|
||||
|
||||
void __hw_clock_source_set(uint32_t ts)
|
||||
{
|
||||
/* Convert microseconds to ticks. */
|
||||
uint32_t ticks;
|
||||
|
||||
/* Disable the timer. */
|
||||
ROTOR_MCU_TMR_TNCR(0) &= ~1;
|
||||
#ifdef BOARD_REI
|
||||
/* ticks = (ts / SECOND) * clock_get_freq(); */
|
||||
ticks = (clock_get_freq() / SECOND) * ts;
|
||||
/* Set the load count. */
|
||||
/* ROTOR_MCU_TMR_TNLC(0) = reload_val - ticks; */
|
||||
ROTOR_MCU_TMR_TNLC(0) = 0xFFFFFFFF - ticks;
|
||||
|
||||
/* Re-enable the timer block. */
|
||||
ROTOR_MCU_TMR_TNCR(0) |= 1;
|
||||
|
||||
/*
|
||||
* Restore the behaviour of counting down from the reload value after
|
||||
* the next reload.
|
||||
*/
|
||||
/* ROTOR_MCU_TMR_TNLC(0) = reload_val; */
|
||||
#else
|
||||
/* Determine the rollover count and set the load count */
|
||||
rollover_cnt = ts / ((0xFFFFFFFF / clock_get_freq()) * SECOND);
|
||||
ticks = (ts % (0xFFFFFFFF / clock_get_freq()) * SECOND);
|
||||
ROTOR_MCU_TMR_TNLC(0) = 0xFFFFFFFF - ticks;
|
||||
|
||||
/* Re-enable the timer block. */
|
||||
ROTOR_MCU_TMR_TNCR(0) |= 1;
|
||||
#endif /* defined(BOARD_REI) */
|
||||
}
|
||||
|
||||
/* Triggered when Timer 0 reaches 0. */
|
||||
void __hw_clock_source_irq(void)
|
||||
{
|
||||
/* Make sure that the interrupt actually fired. */
|
||||
if (!(ROTOR_MCU_TMR_TNIS(0) & (1 << 0)))
|
||||
return;
|
||||
/*
|
||||
* Clear the interrupt by reading the TNEOI register. Reading from this
|
||||
* register returns all zeroes.
|
||||
*/
|
||||
if (ROTOR_MCU_TMR_TNEOI(0))
|
||||
;
|
||||
|
||||
#ifdef BOARD_REI
|
||||
/* Process timers indicating the overflow event. */
|
||||
process_timers(1);
|
||||
#else
|
||||
rollover_cnt++;
|
||||
if (rollover_cnt >= (clock_get_freq() / 1000000)) {
|
||||
/* Process timers indicating the overflow event. */
|
||||
process_timers(1);
|
||||
rollover_cnt = 0;
|
||||
} else {
|
||||
process_timers(0);
|
||||
}
|
||||
#endif /* defined(BOARD_REI) */
|
||||
}
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_TIMER_0, __hw_clock_source_irq, 1);
|
||||
|
||||
void __hw_timer_enable_clock(int n, int enable)
|
||||
{
|
||||
/* Should be already be configured. */
|
||||
}
|
||||
|
||||
int __hw_clock_source_init(uint32_t start_t)
|
||||
{
|
||||
#ifdef BOARD_REI
|
||||
/* reload_val = (0xFFFFFFFF / SECOND) * clock_get_freq(); */
|
||||
/* reload_val = 0xFFFFFFFF; */
|
||||
#endif /* defined(BOARD_REI) */
|
||||
/*
|
||||
* Use Timer 0 as the clock. The clock source for the timer block
|
||||
* cannot be prescaled down to 1MHz, therefore, we'll have to handle the
|
||||
* rollovers.
|
||||
*
|
||||
* There's also no match functionality, so set up an additional timer,
|
||||
* Timer 1, to handle events.
|
||||
*/
|
||||
|
||||
/* Disable the timers. */
|
||||
ROTOR_MCU_TMR_TNCR(0) &= ~(1 << 0);
|
||||
ROTOR_MCU_TMR_TNCR(1) &= ~(1 << 0);
|
||||
|
||||
/*
|
||||
* Timer 0
|
||||
*
|
||||
* Unmask interrupt, set user-defined count mode, and disable PWM.
|
||||
*/
|
||||
ROTOR_MCU_TMR_TNCR(0) = (1 << 1);
|
||||
|
||||
/* Use the specified start timer value and start the timer. */
|
||||
__hw_clock_source_set(start_t);
|
||||
|
||||
/*
|
||||
* Timer 1
|
||||
*
|
||||
* Unmask interrupt, set user-defined count mode, and disable PWM.
|
||||
*/
|
||||
ROTOR_MCU_TMR_TNCR(1) = (1 << 1);
|
||||
|
||||
/* Enable interrupts. */
|
||||
task_enable_irq(ROTOR_MCU_IRQ_TIMER_0);
|
||||
task_enable_irq(ROTOR_MCU_IRQ_TIMER_1);
|
||||
|
||||
/* Return event timer IRQ number. */
|
||||
return ROTOR_MCU_IRQ_TIMER_1;
|
||||
}
|
||||
597
chip/rotor/i2c.c
597
chip/rotor/i2c.c
@@ -1,597 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "i2c.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
/* I2C driver for Rotor MCU */
|
||||
|
||||
/* Console output macros */
|
||||
#define CPUTS(outstr) cputs(CC_I2C, outstr)
|
||||
#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
|
||||
|
||||
/* Timing table. */
|
||||
/* TODO(aaboagye): Add entries once you figure out the APLL0 src frequency. */
|
||||
enum i2c_input_clk {
|
||||
I2C_CLK_SRC_25MHZ,
|
||||
I2C_CLK_SRC_8MHZ, /* TODO(aaboagye): This is the ANA_GRP DRO,
|
||||
* but I'm not sure of the exact frequency.
|
||||
* Clock diagram shows a range from 8-24MHz
|
||||
*/
|
||||
I2C_CLK_SRC_32KHZ,
|
||||
NUM_I2C_SRC_CLKS
|
||||
};
|
||||
|
||||
struct i2c_timing_t {
|
||||
uint16_t t_high;
|
||||
uint16_t t_low;
|
||||
};
|
||||
|
||||
struct i2c_timing_map_t {
|
||||
const struct i2c_timing_t *times;
|
||||
};
|
||||
|
||||
/*
|
||||
* Standard mode Minimum times according to spec:
|
||||
* t_high = 4.0 us
|
||||
* t_low = 4.7 us
|
||||
*/
|
||||
static const struct i2c_timing_t standard_mode_timings[NUM_I2C_SRC_CLKS] = {
|
||||
/* 25MHz */
|
||||
{
|
||||
.t_high = 100,
|
||||
.t_low = 118,
|
||||
},
|
||||
|
||||
/* 8MHz */
|
||||
{
|
||||
.t_high = 32,
|
||||
.t_low = 38,
|
||||
},
|
||||
|
||||
/* 32KHz */
|
||||
{
|
||||
.t_high = 1,
|
||||
.t_low = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Fast mode minimum times according to spec:
|
||||
* t_high = 0.6 us
|
||||
* t_low = 1.3 us
|
||||
*/
|
||||
static const struct i2c_timing_t fast_mode_timings[NUM_I2C_SRC_CLKS] = {
|
||||
/* 25MHz */
|
||||
{
|
||||
.t_high = 15,
|
||||
.t_low = 33,
|
||||
},
|
||||
|
||||
/* 8MHz */
|
||||
{
|
||||
.t_high = 5,
|
||||
.t_low = 11,
|
||||
},
|
||||
|
||||
/* 32KHz */
|
||||
{
|
||||
.t_high = 1,
|
||||
.t_low = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Fast mode plus minimum times according to spec:
|
||||
* t_high = 0.26 us
|
||||
* t_low = 0.5 us
|
||||
*/
|
||||
static const struct i2c_timing_t fast_mode_plus_timings[NUM_I2C_SRC_CLKS] = {
|
||||
/* 25MHz */
|
||||
{
|
||||
.t_high = 7,
|
||||
.t_low = 13,
|
||||
},
|
||||
|
||||
/* 8MHz */
|
||||
{
|
||||
.t_high = 3,
|
||||
.t_low = 4,
|
||||
},
|
||||
|
||||
/* 32KHz */
|
||||
{
|
||||
.t_high = 1,
|
||||
.t_low = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct i2c_timing_map_t timing_settings[I2C_FREQ_COUNT] = {
|
||||
{
|
||||
.times = fast_mode_plus_timings,
|
||||
},
|
||||
|
||||
{
|
||||
.times = fast_mode_timings,
|
||||
},
|
||||
|
||||
{
|
||||
.times = standard_mode_timings,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* Task waiting on port, or TASK_ID_INVALID if none. */
|
||||
static volatile int task_waiting[I2C_PORT_COUNT] = { TASK_ID_INVALID };
|
||||
|
||||
/**
|
||||
* Dumps some i2c regs for debugging.
|
||||
*
|
||||
* @params port The port for which regs to dump.
|
||||
*/
|
||||
static void dump_regs(int port)
|
||||
{
|
||||
CPRINTS("I2C%d regs", port);
|
||||
CPRINTS("IC_TAR: %08X", ROTOR_MCU_I2C_TAR(port));
|
||||
CPRINTS("IC_INTR_MASK: %08X", ROTOR_MCU_I2C_INTR_MASK(port));
|
||||
CPRINTS("IC_INTR_STAT: %08X", ROTOR_MCU_I2C_INTR_STAT(port));
|
||||
CPRINTS("IC_RAW_INTR_STAT: %08X",
|
||||
ROTOR_MCU_I2C_RAW_INTR_STAT(port));
|
||||
CPRINTS("IC_STATUS: %08X", ROTOR_MCU_I2C_STATUS(port));
|
||||
CPRINTS("IC_TX_ABRT_SRC: %08X", ROTOR_MCU_I2C_TX_ABRT_SRC(port));
|
||||
}
|
||||
|
||||
static int command_i2cdump(int argc, char **argv)
|
||||
{
|
||||
int port;
|
||||
char *e;
|
||||
|
||||
if (argc < 2)
|
||||
return EC_ERROR_PARAM_COUNT;
|
||||
|
||||
port = strtoi(argv[1], &e, 0);
|
||||
if (*e)
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
if ((port < 0) || (port >= I2C_PORT_COUNT))
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
dump_regs(port);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(i2cdump, command_i2cdump, NULL, NULL, NULL);
|
||||
|
||||
/*
|
||||
* TODO(aaboagye): Resurrect this once you figure out the clock issues.
|
||||
*
|
||||
* I was running into transfer aborts because the transactions were taking much
|
||||
* longer than expected. Hacked this out so I could make progress.
|
||||
*/
|
||||
#if 0
|
||||
/**
|
||||
* Abort the current transaction.
|
||||
*
|
||||
* The controller will send a STOP condition and flush the TX FIFO.
|
||||
*
|
||||
* @param port The port where you wish to abort the transaction.
|
||||
*/
|
||||
static void abort_transfer(int port)
|
||||
{
|
||||
int evt;
|
||||
|
||||
/* Unmask the M_TX_ABRT interrupt. */
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) = ROTOR_MCU_I2C_M_TX_ABRT;
|
||||
|
||||
/* Issue the abort. */
|
||||
ROTOR_MCU_I2C_ENABLE(port) |= ROTOR_MCU_I2C_ABORT;
|
||||
|
||||
/* Wait for the interrupt to fire. */
|
||||
evt = task_wait_event_mask(TASK_EVENT_I2C_IDLE, 500);
|
||||
if (evt & TASK_EVENT_TIMER)
|
||||
CPRINTS("i2c: timed out waiting for abort interrupt.");
|
||||
else
|
||||
CPRINTS("i2c xfer abort.");
|
||||
|
||||
/* Mask the M_TX_ABRT interrupt. */
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) = 0;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/**
|
||||
* Disable the I2C port.
|
||||
*
|
||||
* @param port The port which you wish to disable.
|
||||
* @return EC_SUCCESS on successfully disabling the port, non-zero otherwise.
|
||||
*/
|
||||
static int disable_i2c(int port)
|
||||
{
|
||||
uint8_t timeout = 50;
|
||||
|
||||
/* Check if the hardware is already shutdown. */
|
||||
if (!(ROTOR_MCU_I2C_ENABLE_STATUS(port) & ROTOR_MCU_I2C_IC_EN))
|
||||
return EC_SUCCESS;
|
||||
|
||||
/* Try disabling the port. */
|
||||
ROTOR_MCU_I2C_ENABLE(port) &= ~ROTOR_MCU_I2C_EN;
|
||||
|
||||
/* Check to see that the hardware actually shuts down. */
|
||||
while (ROTOR_MCU_I2C_ENABLE_STATUS(port) & ROTOR_MCU_I2C_IC_EN) {
|
||||
usleep(10);
|
||||
timeout--;
|
||||
|
||||
if (timeout == 0)
|
||||
return EC_ERROR_TIMEOUT;
|
||||
};
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the byte has been popped from the TX FIFO.
|
||||
*
|
||||
* This interrupt is automatically cleared by hardware when the buffer level
|
||||
* goes above the threshold (set to one element).
|
||||
*
|
||||
* @param port The i2c port to wait for.
|
||||
* @param timeout The timeout in microseconds.
|
||||
*/
|
||||
static int wait_byte_done(int port, int timeout)
|
||||
{
|
||||
uint32_t events;
|
||||
|
||||
/* Unmask the TX_EMPTY interrupt. */
|
||||
task_waiting[port] = task_get_current();
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) |= ROTOR_MCU_I2C_M_TX_EMPTY;
|
||||
|
||||
/* Wait until the interrupt fires. */
|
||||
events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, timeout);
|
||||
task_waiting[port] = TASK_ID_INVALID;
|
||||
|
||||
return (events & TASK_EVENT_I2C_IDLE) ? EC_SUCCESS : EC_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the byte has been inserted to the RX FIFO.
|
||||
*
|
||||
* Since the RX transmission level is set to only 1 element, the RX_FULL
|
||||
* interrupt should fire when there's at least 1 new byte to read. This
|
||||
* interrupt is automatically cleared by hardware when the buffer level goes
|
||||
* below the threshold (set to one element).
|
||||
*
|
||||
* @param port The i2c port to wait for.
|
||||
* @param timeout The timeout in microseconds.
|
||||
*/
|
||||
static int wait_byte_ready(int port, int timeout)
|
||||
{
|
||||
uint32_t events;
|
||||
|
||||
/* Unmask the RX_FULL interrupt. */
|
||||
task_waiting[port] = task_get_current();
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) |= ROTOR_MCU_I2C_M_RX_FULL;
|
||||
|
||||
/* Wait until the interrupt fires. */
|
||||
events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, timeout);
|
||||
task_waiting[port] = TASK_ID_INVALID;
|
||||
|
||||
return (events & TASK_EVENT_I2C_IDLE) ? EC_SUCCESS : EC_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
|
||||
uint8_t *in, int in_size, int flags)
|
||||
{
|
||||
int i;
|
||||
int rv;
|
||||
int val;
|
||||
uint64_t task_timeout = get_time().val + I2C_TIMEOUT_DEFAULT_US;
|
||||
/* Check if there's anything we actually have to do. */
|
||||
if (!in_size && !out_size)
|
||||
return EC_SUCCESS;
|
||||
|
||||
/* Make sure we're in a good state to start. */
|
||||
if ((flags & I2C_XFER_START) &&
|
||||
i2c_get_line_levels(port) != I2C_LINE_IDLE) {
|
||||
CPRINTS("I2C%d Addr:%02X bad status SCL=%d, SDA=%d",
|
||||
port,
|
||||
slave_addr,
|
||||
i2c_get_line_levels(port) & I2C_LINE_SCL_HIGH,
|
||||
i2c_get_line_levels(port) & I2C_LINE_SDA_HIGH ? 1 : 0);
|
||||
|
||||
/* Attempt to unwedge the port. */
|
||||
i2c_unwedge(port);
|
||||
}
|
||||
|
||||
/* Set the slave address. */
|
||||
ROTOR_MCU_I2C_TAR(port) = (slave_addr >> 1) & 0xFF;
|
||||
|
||||
/*
|
||||
* Placing data into the TX FIFO causes the i2c block to generate a
|
||||
* START condition on the bus.
|
||||
*/
|
||||
for (i = 0; i < out_size; i++) {
|
||||
/* Issue a STOP bit if this is the last byte. */
|
||||
if ((i == (out_size-1)) && (flags & I2C_XFER_STOP))
|
||||
ROTOR_MCU_I2C_DATA_CMD(port) |=
|
||||
(ROTOR_MCU_I2C_STOP | out[i]);
|
||||
else
|
||||
ROTOR_MCU_I2C_DATA_CMD(port) = out[i];
|
||||
|
||||
/* Wait until byte popped from TX FIFO. */
|
||||
rv = wait_byte_done(port, task_timeout - get_time().val);
|
||||
if (rv != EC_SUCCESS) {
|
||||
/* Abort the transaction. */
|
||||
/* dump_regs(port); */
|
||||
return EC_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < in_size; i++) {
|
||||
/*
|
||||
* In order for the i2c block to continue acknowledging reads, a
|
||||
* read command must be written for every byte that is to be
|
||||
* received.
|
||||
*/
|
||||
val = ROTOR_MCU_I2C_RD_CMD;
|
||||
|
||||
/* Issue a RESTART since direction is changing. */
|
||||
if (i == 0)
|
||||
val |= ROTOR_MCU_I2C_RESTART;
|
||||
|
||||
|
||||
/* Issue a STOP if this is the last byte. */
|
||||
if ((i == (in_size-1)) && (flags & I2C_XFER_STOP))
|
||||
val |= ROTOR_MCU_I2C_STOP;
|
||||
|
||||
ROTOR_MCU_I2C_DATA_CMD(port) = val;
|
||||
|
||||
/* Wait for RX_FULL interrupt. */
|
||||
rv = wait_byte_ready(port, task_timeout - get_time().val);
|
||||
if (rv != EC_SUCCESS)
|
||||
return EC_ERROR_TIMEOUT;
|
||||
|
||||
/* Retrieve the byte from the RX FIFO. */
|
||||
in[i] = (ROTOR_MCU_I2C_DATA_CMD(port) & 0xFF);
|
||||
}
|
||||
|
||||
task_waiting[port] = TASK_ID_INVALID;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the port with the requested speeds.
|
||||
*
|
||||
* @param port I2C port being configured.
|
||||
* @param freq The desired operation speed of the port.
|
||||
*/
|
||||
static void set_port_speed(int port, enum i2c_freq freq)
|
||||
{
|
||||
enum i2c_input_clk src_clk;
|
||||
const struct i2c_timing_t *timings;
|
||||
|
||||
/* Determine the current i2c clock source .*/
|
||||
switch ((ROTOR_MCU_I2C_REFCLKGEN(port) >> 24) & 0x3) {
|
||||
case 0: /* ANA_GRP XTAL */
|
||||
src_clk = I2C_CLK_SRC_25MHZ;
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C clk src: 25MHz");
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
case 1: /* EXT 32KHz CLK */
|
||||
src_clk = I2C_CLK_SRC_32KHZ;
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C clk src: 32KHz");
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
case 2: /* ANA_GRP DRO CLK */
|
||||
src_clk = I2C_CLK_SRC_8MHZ;
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C clk src: 8MHz");
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
case 3: /* APLL0 CLK */
|
||||
/* Something like 589MHz?? */
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C clk src: APLL0");
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the count registers for the appropriate timing. */
|
||||
timings = &timing_settings[freq].times[src_clk];
|
||||
|
||||
switch (freq) {
|
||||
case I2C_FREQ_100KHZ: /* Standard Mode */
|
||||
ROTOR_MCU_I2C_CON(port) = ROTOR_MCU_I2C_SPEED_STD_MODE;
|
||||
ROTOR_MCU_I2C_SS_SCL_HCNT(port) = (timings->t_high & 0xFFFF);
|
||||
ROTOR_MCU_I2C_SS_SCL_LCNT(port) = (timings->t_low & 0xFFFF);
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C%d speed 100KHz", port);
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
|
||||
case I2C_FREQ_400KHZ: /* Fast Mode */
|
||||
ROTOR_MCU_I2C_CON(port) = ROTOR_MCU_I2C_SPEED_FAST_MODE;
|
||||
ROTOR_MCU_I2C_FS_SCL_HCNT(port) = (timings->t_high & 0xFFFF);
|
||||
ROTOR_MCU_I2C_FS_SCL_LCNT(port) = (timings->t_low & 0xFFFF);
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C%d speed 400KHz", port);
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
|
||||
case I2C_FREQ_1000KHZ: /* Fast Mode Plus */
|
||||
ROTOR_MCU_I2C_CON(port) = ROTOR_MCU_I2C_SPEED_HISPD_MODE;
|
||||
ROTOR_MCU_I2C_HS_SCL_HCNT(port) = (timings->t_high & 0xFFFF);
|
||||
ROTOR_MCU_I2C_HS_SCL_LCNT(port) = (timings->t_low & 0xFFFF);
|
||||
#ifdef CONFIG_BRINGUP
|
||||
CPRINTS("I2C%d speed 1MHz", port);
|
||||
#endif /* defined(CONFIG_BRINGUP) */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the specified I2C port.
|
||||
*
|
||||
* @param p the I2C port.
|
||||
*/
|
||||
static void i2c_init_port(const struct i2c_port_t *p)
|
||||
{
|
||||
int port = p->port;
|
||||
enum i2c_freq freq;
|
||||
|
||||
/* Enable the clock for the port if necessary. */
|
||||
if (!(ROTOR_MCU_I2C_REFCLKGEN(port) & ROTOR_MCU_M4_BIST_CLKEN))
|
||||
ROTOR_MCU_I2C_REFCLKGEN(port) |= ROTOR_MCU_M4_BIST_CLKEN;
|
||||
|
||||
/* Disable the I2C block to allow changes to certain registers. */
|
||||
disable_i2c(port);
|
||||
|
||||
/*
|
||||
* Mask all interrupts right now except for aborts so we can clear them.
|
||||
* We'll unmask the ones we need as we go.
|
||||
*/
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) = ROTOR_MCU_I2C_M_TX_ABRT;
|
||||
|
||||
/* Set operation speed. */
|
||||
switch (p->kbps) {
|
||||
case 1000: /* Fast-mode Plus */
|
||||
freq = I2C_FREQ_1000KHZ;
|
||||
break;
|
||||
case 400: /* Fast-mode */
|
||||
freq = I2C_FREQ_400KHZ;
|
||||
break;
|
||||
case 100: /* Standard-mode */
|
||||
freq = I2C_FREQ_100KHZ;
|
||||
break;
|
||||
default: /* unknown speed, defaults to 100kBps */
|
||||
CPRINTS("I2C bad speed %d kBps. Defaulting to 100kbps.",
|
||||
p->kbps);
|
||||
freq = I2C_FREQ_100KHZ;
|
||||
}
|
||||
/* TODO(aaboagye): Verify that the frequency is set correctly. */
|
||||
set_port_speed(port, freq);
|
||||
|
||||
/*
|
||||
* Configure as I2C master allowing RESTART conditions and using 7-bit
|
||||
* addressing. I2C_CON is initialized by the call to set_port_speed()
|
||||
* above.
|
||||
*/
|
||||
ROTOR_MCU_I2C_CON(port) |= ROTOR_MCU_I2C_MASTER_MODE |
|
||||
ROTOR_MCU_I2C_IC_SLAVE_DISABLE |
|
||||
ROTOR_MCU_I2C_IC_RESTART_EN;
|
||||
|
||||
/* Enable interrupts for the port. */
|
||||
task_enable_irq(ROTOR_MCU_IRQ_I2C_0 + port);
|
||||
|
||||
/* Enable the port. */
|
||||
ROTOR_MCU_I2C_ENABLE(port) |= ROTOR_MCU_I2C_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the i2c module for all supported ports.
|
||||
*/
|
||||
static void i2c_init(void)
|
||||
{
|
||||
const struct i2c_port_t *p = i2c_ports;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < i2c_ports_used; i++, p++)
|
||||
i2c_init_port(p);
|
||||
|
||||
/* Configure the GPIO pins for I2C usage. */
|
||||
gpio_config_module(MODULE_I2C, 1);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C);
|
||||
|
||||
int i2c_get_line_levels(int port)
|
||||
{
|
||||
return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) |
|
||||
(i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0);
|
||||
}
|
||||
|
||||
int i2c_raw_get_scl(int port)
|
||||
{
|
||||
enum gpio_signal pin;
|
||||
|
||||
if (get_scl_from_i2c_port(port, &pin) == EC_SUCCESS)
|
||||
return gpio_get_level(pin);
|
||||
|
||||
/* If no SCL pin defined for this port, then return 1 to appear idle. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i2c_raw_get_sda(int port)
|
||||
{
|
||||
enum gpio_signal pin;
|
||||
|
||||
if (get_sda_from_i2c_port(port, &pin) == EC_SUCCESS)
|
||||
return gpio_get_level(pin);
|
||||
|
||||
/* If no SDA pin defined for this port, then return 1 to appear idle. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an interrupt on the specified port.
|
||||
*
|
||||
* @param port I2C port generating interrupt
|
||||
*/
|
||||
static void handle_interrupt(int port)
|
||||
{
|
||||
int waiting_task = task_waiting[port];
|
||||
|
||||
/* Clear software clearable interrupt status. */
|
||||
if (ROTOR_MCU_I2C_CLR_INTR(port))
|
||||
;
|
||||
|
||||
/* Clear TX aborts. */
|
||||
if (ROTOR_MCU_I2C_CLR_TX_ABRT(port))
|
||||
;
|
||||
|
||||
/* If no task is waiting, just return. */
|
||||
if (waiting_task == TASK_ID_INVALID)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the TX_EMPTY is unmasked, let's mask it so we don't keep
|
||||
* re-entering this IRQ handler.
|
||||
*/
|
||||
if ((ROTOR_MCU_I2C_INTR_MASK(port) & ROTOR_MCU_I2C_M_TX_EMPTY) &
|
||||
(ROTOR_MCU_I2C_INTR_STAT(port) & ROTOR_MCU_I2C_M_TX_EMPTY))
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) &= ~ROTOR_MCU_I2C_M_TX_EMPTY;
|
||||
|
||||
/* Same for RX_FULL */
|
||||
if ((ROTOR_MCU_I2C_INTR_MASK(port) & ROTOR_MCU_I2C_M_RX_FULL) &
|
||||
(ROTOR_MCU_I2C_INTR_STAT(port) & ROTOR_MCU_I2C_M_RX_FULL))
|
||||
ROTOR_MCU_I2C_INTR_MASK(port) &= ~ROTOR_MCU_I2C_M_RX_FULL;
|
||||
|
||||
/* Wake up the task which was waiting for the interrupt. */
|
||||
task_set_event(waiting_task, TASK_EVENT_I2C_IDLE, 0);
|
||||
}
|
||||
|
||||
void i2c0_interrupt(void) { handle_interrupt(0); }
|
||||
void i2c1_interrupt(void) { handle_interrupt(1); }
|
||||
void i2c2_interrupt(void) { handle_interrupt(2); }
|
||||
void i2c3_interrupt(void) { handle_interrupt(3); }
|
||||
void i2c4_interrupt(void) { handle_interrupt(4); }
|
||||
void i2c5_interrupt(void) { handle_interrupt(5); }
|
||||
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_I2C_0, i2c0_interrupt, 2);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_I2C_1, i2c1_interrupt, 2);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_I2C_2, i2c2_interrupt, 2);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_I2C_3, i2c3_interrupt, 2);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_I2C_4, i2c4_interrupt, 2);
|
||||
DECLARE_IRQ(ROTOR_MCU_IRQ_I2C_5, i2c5_interrupt, 2);
|
||||
@@ -1,10 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* JTAG module for Rotor MCU */
|
||||
|
||||
void jtag_pre_init(void)
|
||||
{
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
/* 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.
|
||||
*
|
||||
* Register map for Rotor MCU
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_REGISTERS_H
|
||||
#define __CROS_EC_REGISTERS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Master clocks and resets. */
|
||||
#define ROTOR_MCU_CLKRSTGEN_BASE 0xEF000800
|
||||
#define ROTOR_MCU_RESETAP REG32(ROTOR_MCU_CLKRSTGEN_BASE + 0x000)
|
||||
#define ROTOR_MCU_AP_NRESET (1 << 0)
|
||||
#define ROTOR_MCU_M4_BIST_CLKCFG REG32(ROTOR_MCU_CLKRSTGEN_BASE + 0x140)
|
||||
#define ROTOR_MCU_M4_BIST_CLKEN (1 << 1)
|
||||
|
||||
/* GPIO */
|
||||
#define DUMMY_GPIO_BANK 0
|
||||
|
||||
#define GPIO_A 0xEF022000
|
||||
#define GPIO_B 0xEF022100
|
||||
#define GPIO_C 0xEF022200
|
||||
#define GPIO_D 0xEF022300
|
||||
#define GPIO_E 0xEF022400
|
||||
|
||||
#define ROTOR_MCU_GPIO_PLR(b) REG32((b) + 0x0)
|
||||
#define ROTOR_MCU_GPIO_PDR(b) REG32((b) + 0x4)
|
||||
#define ROTOR_MCU_GPIO_PSR(b) REG32((b) + 0xC)
|
||||
#define ROTOR_MCU_GPIO_HRIPR(b) REG32((b) + 0x10)
|
||||
#define ROTOR_MCU_GPIO_LFIPR(b) REG32((b) + 0x14)
|
||||
#define ROTOR_MCU_GPIO_ISR(b) REG32((b) + 0x18)
|
||||
#define ROTOR_MCU_GPIO_SDR(b) REG32((b) + 0x1C)
|
||||
#define ROTOR_MCU_GPIO_CDR(b) REG32((b) + 0x20)
|
||||
#define ROTOR_MCU_GPIO_SHRIPR(b) REG32((b) + 0x24)
|
||||
#define ROTOR_MCU_GPIO_CHRIPR(b) REG32((b) + 0x28)
|
||||
#define ROTOR_MCU_GPIO_SLFIPR(b) REG32((b) + 0x2C)
|
||||
#define ROTOR_MCU_GPIO_CLFIPR(b) REG32((b) + 0x30)
|
||||
#define ROTOR_MCU_GPIO_OLR(b) REG32((b) + 0x34)
|
||||
#define ROTOR_MCU_GPIO_DWER(b) REG32((b) + 0x38)
|
||||
#define ROTOR_MCU_GPIO_IMR(b) REG32((b) + 0x3C)
|
||||
#define ROTOR_MCU_GPIO_SIMR(b) REG32((b) + 0x48)
|
||||
#define ROTOR_MCU_GPIO_CIMR(b) REG32((b) + 0x4C)
|
||||
/* Interrupt Target Enable regs for MCU are instances 24-31. */
|
||||
#define ROTOR_MCU_GPIO_ITER(b) REG32((b) + 0xB0 + \
|
||||
4*(((b) - GPIO_A) >> 8))
|
||||
|
||||
|
||||
/* MCU Pad Wrap */
|
||||
#define ROTOR_MCU_PAD_WRAP_BASE 0xEF020000
|
||||
#define ROTOR_MCU_IO_PAD_CFG(n) REG32(ROTOR_MCU_PAD_WRAP_BASE + 0x8 + \
|
||||
((n) * 0x4))
|
||||
|
||||
#define GPIO_PAD_CFG_IDX(port, pin) (((((port) % 0x2000) / 0x100) * 32) + \
|
||||
(pin))
|
||||
#define GPIO_PAD_CFG_ADDR(port, pin) ((GPIO_PAD_CFG_IDX(port, pin) * 4) + \
|
||||
ROTOR_MCU_PAD_WRAP_BASE + 8)
|
||||
#define ROTOR_MCU_GPIO_PCFG(port, pin) REG32(GPIO_PAD_CFG_ADDR(port, pin))
|
||||
|
||||
/* I2C */
|
||||
#define ROTOR_MCU_I2C_BASE 0xED080000
|
||||
#define ROTOR_MCU_I2C_CFG_BASE(n) (ROTOR_MCU_I2C_BASE + (n)*0x1000)
|
||||
#define ROTOR_MCU_I2C_CON(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x00)
|
||||
#define ROTOR_MCU_I2C_TAR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x04)
|
||||
#define ROTOR_MCU_I2C_SAR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x08)
|
||||
#define ROTOR_MCU_I2C_HS_MADDR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x0C)
|
||||
#define ROTOR_MCU_I2C_DATA_CMD(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x10)
|
||||
#define ROTOR_MCU_I2C_SS_SCL_HCNT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x14)
|
||||
#define ROTOR_MCU_I2C_SS_SCL_LCNT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x18)
|
||||
#define ROTOR_MCU_I2C_FS_SCL_HCNT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x1C)
|
||||
#define ROTOR_MCU_I2C_FS_SCL_LCNT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x20)
|
||||
#define ROTOR_MCU_I2C_HS_SCL_HCNT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x24)
|
||||
#define ROTOR_MCU_I2C_HS_SCL_LCNT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x28)
|
||||
#define ROTOR_MCU_I2C_INTR_STAT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x2C)
|
||||
#define ROTOR_MCU_I2C_INTR_MASK(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x30)
|
||||
#define ROTOR_MCU_I2C_RAW_INTR_STAT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x34)
|
||||
#define ROTOR_MCU_I2C_RX_TL(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x38)
|
||||
#define ROTOR_MCU_I2C_TX_TL(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x3C)
|
||||
#define ROTOR_MCU_I2C_CLR_INTR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x40)
|
||||
#define ROTOR_MCU_I2C_CLR_RX_UNDER(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x44)
|
||||
#define ROTOR_MCU_I2C_CLR_RX_OVER(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x48)
|
||||
#define ROTOR_MCU_I2C_CLR_TX_OVER(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x4C)
|
||||
#define ROTOR_MCU_I2C_CLR_RD_REQ(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x50)
|
||||
#define ROTOR_MCU_I2C_CLR_TX_ABRT(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x54)
|
||||
#define ROTOR_MCU_I2C_CLR_RX_DONE(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x58)
|
||||
#define ROTOR_MCU_I2C_CLR_ACTIVITY(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x5C)
|
||||
#define ROTOR_MCU_I2C_CLR_STOP_DET(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x60)
|
||||
#define ROTOR_MCU_I2C_CLR_START_DET(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x64)
|
||||
#define ROTOR_MCU_I2C_CLR_GEN_CALL(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x68)
|
||||
#define ROTOR_MCU_I2C_ENABLE(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x6C)
|
||||
#define ROTOR_MCU_I2C_STATUS(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x70)
|
||||
#define ROTOR_MCU_I2C_TXFLR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x74)
|
||||
#define ROTOR_MCU_I2C_RXFLR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x78)
|
||||
#define ROTOR_MCU_I2C_SDA_HOLD(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x7C)
|
||||
#define ROTOR_MCU_I2C_TX_ABRT_SRC(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x80)
|
||||
#define ROTOR_MCU_I2C_DMA_CR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x88)
|
||||
#define ROTOR_MCU_I2C_DMA_TDLR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x8C)
|
||||
#define ROTOR_MCU_I2C_DMA_RDLR(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x90)
|
||||
#define ROTOR_MCU_I2C_SDA_SETUP(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x94)
|
||||
#define ROTOR_MCU_I2C_ACK_GEN_CALL(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x98)
|
||||
#define ROTOR_MCU_I2C_ENABLE_STATUS(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0x9C)
|
||||
#define ROTOR_MCU_I2C_FS_SPKLEN(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0xA0)
|
||||
#define ROTOR_MCU_I2C_HS_SPKLEN(n) REG32(ROTOR_MCU_I2C_CFG_BASE(n) + 0xA4)
|
||||
#define ROTOR_MCU_I2C_REFCLKGEN(n) REG32((ROTOR_MCU_CLKRSTGEN_BASE + \
|
||||
+ 0x3D0 + (0x10 * (n))))
|
||||
/* bit definitions */
|
||||
#define ROTOR_MCU_I2C_M_TX_ABRT (1 << 6)
|
||||
#define ROTOR_MCU_I2C_M_TX_EMPTY (1 << 4)
|
||||
#define ROTOR_MCU_I2C_M_RX_FULL (1 << 2)
|
||||
#define ROTOR_MCU_I2C_ABORT (1 << 1)
|
||||
#define ROTOR_MCU_I2C_EN (1 << 0)
|
||||
#define ROTOR_MCU_I2C_IC_EN (1 << 0)
|
||||
#define ROTOR_MCU_I2C_STOP (1 << 9)
|
||||
#define ROTOR_MCU_I2C_RD_CMD (1 << 8)
|
||||
#define ROTOR_MCU_I2C_RESTART (1 << 10)
|
||||
#define ROTOR_MCU_I2C_SPEED_STD_MODE (1 << 1)
|
||||
#define ROTOR_MCU_I2C_SPEED_FAST_MODE (2 << 1)
|
||||
#define ROTOR_MCU_I2C_SPEED_HISPD_MODE (3 << 1)
|
||||
#define ROTOR_MCU_I2C_IC_SLAVE_DISABLE (1 << 6)
|
||||
#define ROTOR_MCU_I2C_IC_RESTART_EN (1 << 5)
|
||||
#define ROTOR_MCU_I2C_MASTER_MODE (1 << 0)
|
||||
|
||||
|
||||
/* UART */
|
||||
#define ROTOR_MCU_UART0_CLKGEN REG32(ROTOR_MCU_CLKRSTGEN_BASE + 0x240)
|
||||
#define ROTOR_MCU_UART0_REFCLKGEN REG32(ROTOR_MCU_CLKRSTGEN_BASE + 0x3B0)
|
||||
#define ROTOR_MCU_UART_CFG_BASE(n) (0xED060000 + (n)*0x1000)
|
||||
/* DLAB = 0 */
|
||||
#define ROTOR_MCU_UART_RBR(n) /* R */ REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x0)
|
||||
#define ROTOR_MCU_UART_THR(n) /* W */ REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x0)
|
||||
#define ROTOR_MCU_UART_IER(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x4)
|
||||
/* DLAB = 1 */
|
||||
#define ROTOR_MCU_UART_DLL(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x0)
|
||||
#define ROTOR_MCU_UART_DLH(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x4)
|
||||
|
||||
#define ROTOR_MCU_UART_IIR(n) /* R */ REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x8)
|
||||
#define ROTOR_MCU_UART_FCR(n) /* W */ REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x8)
|
||||
#define ROTOR_MCU_UART_LCR(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0xC)
|
||||
#define ROTOR_MCU_UART_MCR(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x10)
|
||||
#define ROTOR_MCU_UART_LSR(n) /* R */ REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x14)
|
||||
#define ROTOR_MCU_UART_MSR(n) /* R */ REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x18)
|
||||
#define ROTOR_MCU_UART_SCR(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x1C)
|
||||
#define ROTOR_MCU_UART_USR(n) REG32(ROTOR_MCU_UART_CFG_BASE(n) + 0x7C)
|
||||
|
||||
/* Timers */
|
||||
#define ROTOR_MCU_TMR_CFG_BASE(n) (0xED020000 + (n)*0x1000)
|
||||
#define ROTOR_MCU_TMR_TNLC(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0x0)
|
||||
#define ROTOR_MCU_TMR_TNCV(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0x4)
|
||||
#define ROTOR_MCU_TMR_TNCR(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0x8)
|
||||
#define ROTOR_MCU_TMR_TNEOI(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0xC)
|
||||
#define ROTOR_MCU_TMR_TNIS(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0x10)
|
||||
#define ROTOR_MCU_TMR_TIS(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0xA0)
|
||||
#define ROTOR_MCU_TMR_TEOI(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0xA4)
|
||||
#define ROTOR_MCU_TMR_TRIS(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0xA8)
|
||||
#define ROTOR_MCU_TMR_TNLC2(n) REG32(ROTOR_MCU_TMR_CFG_BASE(n) + 0xB0)
|
||||
|
||||
/* Watchdog */
|
||||
#define ROTOR_MCU_WDT_BASE 0xED010000
|
||||
#define ROTOR_MCU_WDT_CR REG32(ROTOR_MCU_WDT_BASE + 0x00)
|
||||
#define ROTOR_MCU_WDT_TORR REG32(ROTOR_MCU_WDT_BASE + 0x04)
|
||||
#define ROTOR_MCU_WDT_CCVR REG32(ROTOR_MCU_WDT_BASE + 0x08)
|
||||
#define ROTOR_MCU_WDT_CRR REG32(ROTOR_MCU_WDT_BASE + 0x0C)
|
||||
#define ROTOR_MCU_WDT_STAT REG32(ROTOR_MCU_WDT_BASE + 0x10)
|
||||
#define ROTOR_MCU_WDT_EOI REG32(ROTOR_MCU_WDT_BASE + 0x14)
|
||||
/* To prevent accidental restarts, this magic value must be written to CRR. */
|
||||
#define ROTOR_MCU_WDT_KICK 0x76
|
||||
|
||||
/* SSI */
|
||||
#define ROTOR_MCU_SSI_BASE(port) (0xED070000 + ((port) * 0x1000))
|
||||
#define ROTOR_MCU_SSI_CTRLR0(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x00)
|
||||
#define ROTOR_MCU_SSI_CTRLR1(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x04)
|
||||
#define ROTOR_MCU_SSI_SSIENR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x08)
|
||||
#define ROTOR_MCU_SSI_BAUDR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x14)
|
||||
#define ROTOR_MCU_SSI_TXFTLR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x18)
|
||||
#define ROTOR_MCU_SSI_RXFTLR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x1C)
|
||||
#define ROTOR_MCU_SSI_TXFLR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x20)
|
||||
#define ROTOR_MCU_SSI_RXFLR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x24)
|
||||
#define ROTOR_MCU_SSI_SR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x28)
|
||||
#define ROTOR_MCU_SSI_IMR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x2C)
|
||||
#define ROTOR_MCU_SSI_ISR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x30)
|
||||
#define ROTOR_MCU_SSI_RISR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x34)
|
||||
#define ROTOR_MCU_SSI_TXOICR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x38)
|
||||
#define ROTOR_MCU_SSI_RXOICR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x3C)
|
||||
#define ROTOR_MCU_SSI_RXUICR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x40)
|
||||
#define ROTOR_MCU_SSI_ICR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x48)
|
||||
#define ROTOR_MCU_SSI_DMACR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x4C)
|
||||
#define ROTOR_MCU_SSI_DMATDLR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x50)
|
||||
#define ROTOR_MCU_SSI_DMARDLR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x54)
|
||||
#define ROTOR_MCU_SSI_IDR(port) REG32(ROTOR_MCU_SSI_BASE(port) + 0x58)
|
||||
#define ROTOR_MCU_SSI_DR(port, idx) REG32(ROTOR_MCU_SSI_BASE(port) + \
|
||||
(0x60 + ((idx) * 0x04)))
|
||||
#define ROTOR_MCU_MAX_SSI_PORTS 2
|
||||
|
||||
/* DMA */
|
||||
#define ROTOR_MCU_DMA_BASE 0xED200000
|
||||
|
||||
enum dma_channel {
|
||||
/* Channel numbers */
|
||||
ROTOR_MCU_DMAC_SPI0_TX = 0,
|
||||
ROTOR_MCU_DMAC_SPI0_RX = 1,
|
||||
ROTOR_MCU_DMAC_SPI1_TX = 2,
|
||||
ROTOR_MCU_DMAC_SPI1_RX = 3,
|
||||
|
||||
/* Channel count */
|
||||
ROTOR_MCU_DMAC_COUNT = 8,
|
||||
};
|
||||
|
||||
/* Registers for a single channel of the DMA controller. */
|
||||
struct rotor_mcu_dma_chan {
|
||||
uint32_t cfg; /* Config */
|
||||
uint32_t ctrl; /* Control */
|
||||
uint32_t status; /* Status */
|
||||
uint32_t pad0;
|
||||
uint32_t cpr; /* Parameter */
|
||||
uint32_t cdr; /* Descriptor */
|
||||
uint32_t cndar; /* Next descriptor address */
|
||||
uint32_t fill_value; /* Fill value */
|
||||
uint32_t int_en; /* Interrupt enable */
|
||||
uint32_t int_pend; /* Interrupt pending */
|
||||
uint32_t int_ack; /* Interrupt acknowledge */
|
||||
uint32_t int_force; /* Interrupt force */
|
||||
uint32_t tmr_ctrl; /* Timer control */
|
||||
uint32_t timeout_cnt_stat; /* Timeout Count Status */
|
||||
uint32_t crbar; /* Read burst address */
|
||||
uint32_t crblr; /* Read burst length */
|
||||
uint32_t cwbar; /* Write burst address */
|
||||
uint32_t cwblr; /* Write burst length */
|
||||
uint32_t cwbrr; /* Write burst remain */
|
||||
uint32_t csrr; /* Save/restore control */
|
||||
uint32_t csrli; /* Save/restore lower DMA ID */
|
||||
uint32_t csrui; /* Save/restore upper DMA ID */
|
||||
uint32_t crsl; /* Lower request status */
|
||||
uint32_t crsu; /* Upper request status */
|
||||
uint32_t cafr; /* ACK force */
|
||||
uint32_t pad1[0x27]; /* pad to offset 0x100 */
|
||||
};
|
||||
|
||||
/* Always use rotor_mcu_dma_chan_t so volatile keyword is included! */
|
||||
typedef volatile struct rotor_mcu_dma_chan rotor_mcu_dma_chan_t;
|
||||
|
||||
/* Common code and header file must use this */
|
||||
typedef rotor_mcu_dma_chan_t dma_chan_t;
|
||||
|
||||
struct rotor_mcu_dma_regs {
|
||||
uint32_t top_int_status;
|
||||
uint32_t top_soft_reset;
|
||||
uint32_t params;
|
||||
uint32_t pad[0x3D]; /* Pad to offset 0x100 */
|
||||
rotor_mcu_dma_chan_t chan[ROTOR_MCU_DMAC_COUNT];
|
||||
};
|
||||
|
||||
/* Always use rotor_mcu_dma_regs_t so volatile keyword is included! */
|
||||
typedef volatile struct rotor_mcu_dma_regs rotor_mcu_dma_regs_t;
|
||||
|
||||
#define ROTOR_MCU_DMA_REGS ((rotor_mcu_dma_regs_t *)ROTOR_MCU_DMA_BASE)
|
||||
|
||||
/* IRQ Numbers */
|
||||
#define ROTOR_MCU_IRQ_TIMER_0 6
|
||||
#define ROTOR_MCU_IRQ_TIMER_1 7
|
||||
#define ROTOR_MCU_IRQ_WDT 14
|
||||
#define ROTOR_MCU_IRQ_UART_0 16
|
||||
#define ROTOR_MCU_IRQ_SPI_0 18
|
||||
#define ROTOR_MCU_IRQ_SPI_1 19
|
||||
#define ROTOR_MCU_IRQ_I2C_0 20
|
||||
#define ROTOR_MCU_IRQ_I2C_1 21
|
||||
#define ROTOR_MCU_IRQ_I2C_2 22
|
||||
#define ROTOR_MCU_IRQ_I2C_3 23
|
||||
#define ROTOR_MCU_IRQ_I2C_4 24
|
||||
#define ROTOR_MCU_IRQ_I2C_5 25
|
||||
#define ROTOR_MCU_IRQ_DMAC_0 44
|
||||
#define ROTOR_MCU_IRQ_DMAC_1 45
|
||||
#define ROTOR_MCU_IRQ_DMAC_2 46
|
||||
#define ROTOR_MCU_IRQ_DMAC_3 47
|
||||
#define ROTOR_MCU_IRQ_DMAC_4 48
|
||||
#define ROTOR_MCU_IRQ_DMAC_5 49
|
||||
#define ROTOR_MCU_IRQ_DMAC_6 50
|
||||
#define ROTOR_MCU_IRQ_DMAC_7 51
|
||||
#define ROTOR_MCU_IRQ_DMATOP 52
|
||||
#define ROTOR_MCU_IRQ_GPIO_0 79
|
||||
#define ROTOR_MCU_IRQ_GPIO_1 80
|
||||
#define ROTOR_MCU_IRQ_GPIO_2 81
|
||||
#define ROTOR_MCU_IRQ_GPIO_3 82
|
||||
#define ROTOR_MCU_IRQ_GPIO_4 83
|
||||
#define ROTOR_MCU_IRQ_GPIO_5 84
|
||||
#define ROTOR_MCU_IRQ_GPIO_6 85
|
||||
#define ROTOR_MCU_IRQ_GPIO_7 86
|
||||
|
||||
#endif /* __CROS_EC_REGISTERS_H */
|
||||
@@ -1,103 +0,0 @@
|
||||
/* 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.
|
||||
*
|
||||
* Standard SPI master driver for Rotor MCU
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "dma.h"
|
||||
#include "registers.h"
|
||||
#include "spi.h"
|
||||
#include "task.h"
|
||||
|
||||
static struct mutex spi_mutex[ROTOR_MCU_MAX_SSI_PORTS];
|
||||
|
||||
/* Default DMA channel options */
|
||||
static struct dma_option dma_tx_option[] = {
|
||||
{
|
||||
.channel = ROTOR_MCU_DMAC_SPI0_TX,
|
||||
.periph = (void *)&ROTOR_MCU_SSI_DR(0, 0),
|
||||
.flags = 0, /* TODO(aaboagye): Create some flags. */
|
||||
},
|
||||
|
||||
{
|
||||
.channel = ROTOR_MCU_DMAC_SPI1_TX,
|
||||
.periph = (void *)&ROTOR_MCU_SSI_DR(1, 0),
|
||||
.flags = 0, /* TODO(aaboagye): Create some flags. */
|
||||
},
|
||||
};
|
||||
|
||||
static struct dma_option dma_rx_option[] = {
|
||||
{
|
||||
.channel = ROTOR_MCU_DMAC_SPI0_RX,
|
||||
.periph = (void *)&ROTOR_MCU_SSI_DR(0, 0),
|
||||
.flags = 0, /* TODO(aaboagye): Create some flags. */
|
||||
},
|
||||
|
||||
{
|
||||
.channel = ROTOR_MCU_DMAC_SPI1_RX,
|
||||
.periph = (void *)&ROTOR_MCU_SSI_DR(1, 0),
|
||||
.flags = 0, /* TODO(aaboagye): Create some flags. */
|
||||
},
|
||||
};
|
||||
|
||||
int spi_enable(int port, int enable)
|
||||
{
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
int spi_transaction(const struct spi_device_t *spi_device,
|
||||
const uint8_t *txdata, int txlen,
|
||||
uint8_t *rxdata, int rxlen)
|
||||
{
|
||||
int rv, port;
|
||||
|
||||
port = spi_device->port;
|
||||
mutex_lock(spi_mutex + port);
|
||||
rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen);
|
||||
mutex_unlock(spi_mutex + port);
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
int spi_transaction_async(const struct spi_device_t *spi_device,
|
||||
const uint8_t *txdata, int txlen,
|
||||
uint8_t *rxdata, int rxlen)
|
||||
{
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
int spi_transaction_flush(const struct spi_device_t *spi_device)
|
||||
{
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a SPI port.
|
||||
*
|
||||
* @param port SPI port to initialize.
|
||||
* @return EC_SUCCESS
|
||||
*/
|
||||
static int spi_master_initialize(int port)
|
||||
{
|
||||
int i, div;
|
||||
|
||||
/* Make sure port is valid. */
|
||||
ASSERT((port >= 0) && (port < ROTOR_MCU_MAX_SSI_PORTS));
|
||||
|
||||
/* Disable the SSI module in order to make changes. */
|
||||
ROTOR_MCU_SSI_SSIENR(port) = 0;
|
||||
|
||||
/* Find the greatest divisor for this port and set it. */
|
||||
div = 0;
|
||||
for (i = 0; i < spi_devices_used; i++)
|
||||
if ((spi_devices[i].port == port) &&
|
||||
(div < spi_devices[i].div))
|
||||
div = spi_devices[i].div;
|
||||
ROTOR_MCU_SSI_BAUDR(port) = (div & 0xFFFF);
|
||||
|
||||
/* Set 8-bit serial data transfer, SPI mode, and SPI_CLOCK_MODE0. */
|
||||
ROTOR_MCU_SSI_CTRLR0(port) = (0x7 << 16);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* System module for Rotor MCU */
|
||||
|
||||
#include "common.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
void system_pre_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void system_reset(int flags)
|
||||
{
|
||||
/* Disable interrupts to avoid task swaps during reboot. */
|
||||
interrupt_disable();
|
||||
|
||||
/* TODO: Implement flags and stuff. */
|
||||
|
||||
/*
|
||||
* Try to trigger a watchdog reset, by setting the smallest timeout
|
||||
* period we can.
|
||||
*/
|
||||
ROTOR_MCU_WDT_TORR = 0;
|
||||
watchdog_reload();
|
||||
|
||||
/* Wait for system reset. */
|
||||
while (1)
|
||||
asm("wfi");
|
||||
}
|
||||
|
||||
const char *system_get_chip_name(void)
|
||||
{
|
||||
return "rotor";
|
||||
}
|
||||
|
||||
const char *system_get_chip_vendor(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *system_get_chip_revision(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int system_get_vbnvcontext(uint8_t *block)
|
||||
{
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
int system_set_vbnvcontext(const uint8_t *block)
|
||||
{
|
||||
return EC_ERROR_UNIMPLEMENTED;
|
||||
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/* 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);
|
||||
@@ -1,88 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Watchdog driver */
|
||||
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "hooks.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
void IRQ_HANDLER(ROTOR_MCU_IRQ_WDT)(void) __attribute__((naked));
|
||||
void IRQ_HANDLER(ROTOR_MCU_IRQ_WDT)(void)
|
||||
{
|
||||
/* Naked call so we can extract raw LR and SP */
|
||||
asm volatile("mov r0, lr\n"
|
||||
"mov r1, sp\n"
|
||||
/*
|
||||
* Must push registers in pairs to keep 64-bit aligned
|
||||
* stack for ARM EABI. This also conveninently saves
|
||||
* R0=LR so we can pass it to task_resched_if_needed.
|
||||
*/
|
||||
"push {r0, lr}\n"
|
||||
"bl watchdog_trace\n"
|
||||
/*
|
||||
* Do NOT reset the watchdog interrupt here; it will
|
||||
* be done in watchdog_reload(), or reset will be
|
||||
* triggered if we don't call that by the next watchdog
|
||||
* period. Instead, de-activate the interrupt in the
|
||||
* NVIC, so the watchdog trace will only be printed
|
||||
* once.
|
||||
*/
|
||||
"mov r0, %[irq]\n"
|
||||
"bl task_disable_irq\n"
|
||||
"pop {r0, lr}\n"
|
||||
"b task_resched_if_needed\n"
|
||||
: : [irq] "i" (ROTOR_MCU_IRQ_WDT));
|
||||
}
|
||||
const struct irq_priority IRQ_PRIORITY(ROTOR_MCU_IRQ_WDT)
|
||||
__attribute__((section(".rodata.irqprio")))
|
||||
= {ROTOR_MCU_IRQ_WDT, 0}; /*
|
||||
* put the watchdog at the highest
|
||||
* priority.
|
||||
*/
|
||||
|
||||
void watchdog_reload(void)
|
||||
{
|
||||
/* Kick the watchdog. */
|
||||
ROTOR_MCU_WDT_CRR = ROTOR_MCU_WDT_KICK;
|
||||
}
|
||||
DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT);
|
||||
|
||||
int watchdog_init(void)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
* Set timeout period.
|
||||
*
|
||||
* The watchdog timer only allows you to set a timeout period that's a
|
||||
* power of two. So find the most significant bit. The TOP field only
|
||||
* takes a nibble which is then added to 16. Unfortunately, there will
|
||||
* be some error.
|
||||
*/
|
||||
i = __fls(CONFIG_WATCHDOG_PERIOD_MS * (clock_get_freq() / 1000)) - 16;
|
||||
if (i > 0)
|
||||
ROTOR_MCU_WDT_TORR = (i & 0x0f);
|
||||
else
|
||||
ROTOR_MCU_WDT_TORR = 0;
|
||||
|
||||
/*
|
||||
* Reset after 2 timeouts. Reset pulse of 2 pclk cycles, and enable
|
||||
* the WDT.
|
||||
*/
|
||||
ROTOR_MCU_WDT_CR = (5 << 2) | 0x3;
|
||||
|
||||
/* Kick */
|
||||
watchdog_reload();
|
||||
|
||||
/* Enable WDT interrupt. */
|
||||
task_enable_irq(ROTOR_MCU_IRQ_WDT);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user