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:
Aseda Aboagye
2017-01-30 12:56:10 -08:00
committed by chrome-bot
parent 21b47a9ee5
commit 4c06e1f963
13 changed files with 0 additions and 1821 deletions

View File

@@ -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))

View File

@@ -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. */

View File

@@ -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 */

View File

@@ -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. */
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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)
{
}

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}