diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2013-10-25 15:33:41 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-01-08 02:24:23 +0000 |
commit | 4cf4fcf1cb6a4332a27dd76ae19ba8852ddbaaec (patch) | |
tree | c7c60433492976a10506ec93e8fee8f7483fa44c /chip | |
parent | 375e75de27813e0f440fefc45892157972e300dc (diff) | |
download | chrome-ec-4cf4fcf1cb6a4332a27dd76ae19ba8852ddbaaec.tar.gz |
ite: Add initial support for ITE IT8380 chip
Initial support for the ITE IT8380 chip with the following peripherals :
- 8250-like UART module.
- HW timer (with a 128-us tick period).
- GPIO with pins initialization and edge interrupt support.
other functions are stubbed.
- Clock : basic fixed frequency setup only.
It also add the dev board configuration as a test vehicle.
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=none
BUG=chrome-os-partner:23575
TEST=make BOARD=it8380dev
on IT8380 dev board, use the EC serial console, use gettime from
console.
Change-Id: Id4bf37d1beb21d1a4bee404c9a0bc500025fe787
Reviewed-on: https://chromium-review.googlesource.com/175481
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Commit-Queue: Alec Berg <alecaberg@chromium.org>
Tested-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/it83xx/build.mk | 16 | ||||
-rw-r--r-- | chip/it83xx/clock.c | 92 | ||||
-rw-r--r-- | chip/it83xx/config_chip.h | 106 | ||||
-rw-r--r-- | chip/it83xx/gpio.c | 381 | ||||
-rw-r--r-- | chip/it83xx/hwtimer.c | 170 | ||||
-rw-r--r-- | chip/it83xx/irq.c | 87 | ||||
-rw-r--r-- | chip/it83xx/jtag.c | 15 | ||||
-rw-r--r-- | chip/it83xx/registers.h | 558 | ||||
-rw-r--r-- | chip/it83xx/system.c | 82 | ||||
-rw-r--r-- | chip/it83xx/uart.c | 177 |
10 files changed, 1684 insertions, 0 deletions
diff --git a/chip/it83xx/build.mk b/chip/it83xx/build.mk new file mode 100644 index 0000000000..5906cfe6de --- /dev/null +++ b/chip/it83xx/build.mk @@ -0,0 +1,16 @@ +# -*- makefile -*- +# Copyright (c) 2013 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. +# +# IT83xx chip specific files build +# + +# IT83xx SoC family has an Andes N801 core. +CORE:=nds32 + +# Required chip modules +chip-y=hwtimer.o uart.o gpio.o system.o jtag.o clock.o irq.o + +# Optional chip modules +chip-$(CONFIG_WATCHDOG)+=watchdog.o diff --git a/chip/it83xx/clock.c b/chip/it83xx/clock.c new file mode 100644 index 0000000000..f2e2a6d37b --- /dev/null +++ b/chip/it83xx/clock.c @@ -0,0 +1,92 @@ +/* Copyright (c) 2013 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. + */ + +/* Clocks and power management settings */ + +#include "clock.h" +#include "common.h" +#include "console.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* Console output macros. */ +#define CPUTS(outstr) cputs(CC_CLOCK, outstr) +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) + +static int freq; + +struct clock_gate_ctrl { + volatile uint8_t *reg; + uint8_t mask; +}; + +void clock_init(void) +{ +#if PLL_CLOCK == 48000000 + /* Set PLL frequency to 48MHz. */ + IT83XX_ECPM_PLLFREQR = 0x04; + freq = PLL_CLOCK; +#else +#error "Support only for PLL clock speed of 48MHz." +#endif + + /* Set EC Clock Frequency to PLL frequency. */ + IT83XX_ECPM_SCDCR3 &= 0xf0; + + /* Turn off auto clock gating. */ + IT83XX_ECPM_AUTOCG = 0x00; +} + +int clock_get_freq(void) +{ + return freq; +} + +/** + * Enable clock to specified peripheral + * + * @param offset Should be element of clock_gate_offsets enum. + * Bits 8-15 specify the ECPM offset of the specific clock reg. + * Bits 0-7 specify the mask for the clock register. + * @param mask Unused + * @param mode Unused + */ +void clock_enable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) +{ + volatile uint8_t *reg = (volatile uint8_t *) + (IT83XX_ECPM_BASE + (offset >> 8)); + uint8_t reg_mask = offset & 0xff; + + /* + * Note: CGCTRL3R, bit 6, must always write 1, but since there is no + * offset argument that addresses this bit, then we are guaranteed + * that this line will write a 1 to that bit. + */ + *reg &= ~reg_mask; +} + +/** + * Disable clock to specified peripheral + * + * @param offset Should be element of clock_gate_offsets enum. + * Bits 8-15 specify the ECPM offset of the specific clock reg. + * Bits 0-7 specify the mask for the clock register. + * @param mask Unused + * @param mode Unused + */ +void clock_disable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) +{ + volatile uint8_t *reg = (volatile uint8_t *) + (IT83XX_ECPM_BASE + (offset >> 8)); + uint8_t reg_mask = offset & 0xff; + uint8_t tmp_mask = 0; + + /* CGCTRL3R, bit 6, must always write a 1. */ + tmp_mask |= ((offset >> 8) == IT83XX_ECPM_CGCTRL3R_OFF) ? 0x40 : 0x00; + + *reg |= reg_mask | tmp_mask; +} diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h new file mode 100644 index 0000000000..2942dc3079 --- /dev/null +++ b/chip/it83xx/config_chip.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2013 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/nds32/config_core.h" + +/* Number of IRQ vectors on the IVIC */ +#define CONFIG_IRQ_COUNT 16 + +/* Interval between HOOK_TICK notifications */ +#define HOOK_TICK_INTERVAL (500 * MSEC) + +/* Maximum number of deferrable functions */ +#define DEFERRABLE_MAX_COUNT 8 + +/* Default PLL frequency. */ +#define PLL_CLOCK 48000000 + +/****************************************************************************/ +/* Memory mapping */ + +#define CONFIG_RAM_BASE 0x00080000 +#define CONFIG_RAM_SIZE 0x00004000 + +/* System stack size */ +#define CONFIG_STACK_SIZE 1024 + +/* non-standard task stack sizes */ +#define IDLE_TASK_STACK_SIZE 512 +#define LARGER_TASK_STACK_SIZE 640 + +/* Default task stack size */ +#define TASK_STACK_SIZE 512 + +#define CONFIG_FLASH_BASE 0x00000000 +#define CONFIG_FLASH_BANK_SIZE 0x00000800 /* protect bank size */ +#define CONFIG_FLASH_ERASE_SIZE 0x00000400 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* minimum write size */ + +/* Ideal flash write size fills the 32-entry flash write buffer */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE (32 * 4) + +/* This is the physical size of the flash on the chip. We'll reserve one bank + * in order to emulate per-bank write-protection UNTIL REBOOT. The hardware + * doesn't support a write-protect pin, and if we make the write-protection + * permanent, it can't be undone easily enough to support RMA. */ +#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000 + +/****************************************************************************/ +/* Define our flash layout. */ + +/* Size of one firmware image in flash */ +#ifndef CONFIG_FW_IMAGE_SIZE +#define CONFIG_FW_IMAGE_SIZE (CONFIG_FLASH_PHYSICAL_SIZE / 2) +#endif + +/* RO firmware must start at beginning of flash */ +#define CONFIG_FW_RO_OFF 0 + +/* + * The EC uses the one bank of flash to emulate a SPI-like write protect + * register with persistent state. + */ +#define CONFIG_FW_PSTATE_SIZE CONFIG_FLASH_BANK_SIZE + +#ifdef CONFIG_PSTATE_AT_END +/* PSTATE is at end of flash */ +#define CONFIG_FW_RO_SIZE CONFIG_FW_IMAGE_SIZE +#define CONFIG_FW_PSTATE_OFF (CONFIG_FLASH_PHYSICAL_SIZE \ + - CONFIG_FW_PSTATE_SIZE) +/* Don't claim PSTATE is part of flash */ +#define CONFIG_FLASH_SIZE CONFIG_FW_PSTATE_OFF + +#else +/* PSTATE immediately follows RO, in the first half of flash */ +#define CONFIG_FW_RO_SIZE (CONFIG_FW_IMAGE_SIZE \ + - CONFIG_FW_PSTATE_SIZE) +#define CONFIG_FW_PSTATE_OFF CONFIG_FW_RO_SIZE +#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE +#endif + +/* Either way, RW firmware is one firmware image offset from the start */ +#define CONFIG_FW_RW_OFF CONFIG_FW_IMAGE_SIZE +#define CONFIG_FW_RW_SIZE CONFIG_FW_IMAGE_SIZE + +/* TODO: why 2 sets of configs with the same numbers? */ +#define CONFIG_FW_WP_RO_OFF CONFIG_FW_RO_OFF +#define CONFIG_FW_WP_RO_SIZE CONFIG_FW_RO_SIZE + +/****************************************************************************/ +/* Customize the build */ + +/* Use hardware specific udelay() for this chip */ +#define CONFIG_HW_SPECIFIC_UDELAY + +/* Optional features present on this chip */ +#undef CONFIG_I2C +#undef CONFIG_FLASH +#undef CONFIG_WATCHDOG + +#endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/it83xx/gpio.c b/chip/it83xx/gpio.c new file mode 100644 index 0000000000..8f5f83acdd --- /dev/null +++ b/chip/it83xx/gpio.c @@ -0,0 +1,381 @@ +/* Copyright (c) 2013 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 Chrome EC */ + +#include "clock.h" +#include "common.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "switch.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* + * Converts port (ie GPIO A) to base address offset of the control register + * (GPCRx0) for that port. + */ +#define CTRL_BASE(port) ((port)*8 + 8) + +/** + * Convert wake-up controller (WUC) group to the corresponding wake-up edge + * sense register (WUESR). Return pointer to the register. + * + * @param grp WUC group. + * + * @return Pointer to corresponding WUESR register. + */ +static volatile uint8_t *wuesr(uint8_t grp) +{ + /* + * From WUESR1-WUESR4, the address increases by ones. From WUESR6 on + * the address increases by fours. + */ + return (grp <= 4) ? + (volatile uint8_t *)(IT83XX_WUC_WUESR1 + grp-1) : + (volatile uint8_t *)(IT83XX_WUC_WUESR6 + 4*(grp-6)); +} + +/** + * Convert wake-up controller (WUC) group to the corresponding wake-up edge + * mode register (WUEMR). Return pointer to the register. + * + * @param grp WUC group. + * + * @return Pointer to corresponding WUEMR register. + */ +static volatile uint8_t *wuemr(uint8_t grp) +{ + /* + * From WUEMR1-WUEMR4, the address increases by ones. From WUEMR6 on + * the address increases by fours. + */ + return (grp <= 4) ? + (volatile uint8_t *)(IT83XX_WUC_WUEMR1 + grp-1) : + (volatile uint8_t *)(IT83XX_WUC_WUEMR6 + 4*(grp-6)); +} + +/* + * Array to store the corresponding GPIO port and mask, and WUC group and mask + * for each WKO interrupt. This allows GPIO interrupts coming in through WKO + * to easily identify which pin caused the interrupt. + * Note: Using designated initializers here in addition to using the array size + * assert because many rows are purposely skipped. Not all IRQs are WKO IRQs, + * so the IRQ index skips around. But, we still want the entire array to take + * up the size of the total number of IRQs because the index to the array could + * be any IRQ number. + */ +static const struct { + uint8_t gpio_port; + uint8_t gpio_mask; + uint8_t wuc_group; + uint8_t wuc_mask; +} gpio_irqs[] = { + /* irq gpio_port,gpio_mask,wuc_group,wuc_mask */ + [IT83XX_IRQ_WKO20] = {GPIO_D, (1<<0), 2, (1<<0)}, + [IT83XX_IRQ_WKO21] = {GPIO_D, (1<<1), 2, (1<<1)}, + [IT83XX_IRQ_WKO22] = {GPIO_C, (1<<4), 2, (1<<2)}, + [IT83XX_IRQ_WKO23] = {GPIO_C, (1<<6), 2, (1<<3)}, + [IT83XX_IRQ_WKO24] = {GPIO_D, (1<<2), 2, (1<<4)}, +/* E4 is also on WKO114: this one might be a documentation error ? */ +/* [IT83XX_IRQ_WKO25] = {GPIO_E, (1<<4), 2, (1<<5)},*/ + [IT83XX_IRQ_WKO60] = {GPIO_H, (1<<0), 6, (1<<0)}, + [IT83XX_IRQ_WKO61] = {GPIO_H, (1<<1), 6, (1<<1)}, + [IT83XX_IRQ_WKO62] = {GPIO_H, (1<<2), 6, (1<<2)}, + [IT83XX_IRQ_WKO63] = {GPIO_H, (1<<3), 6, (1<<3)}, + [IT83XX_IRQ_WKO64] = {GPIO_F, (1<<4), 6, (1<<4)}, + [IT83XX_IRQ_WKO65] = {GPIO_F, (1<<5), 6, (1<<5)}, + [IT83XX_IRQ_WKO65] = {GPIO_F, (1<<6), 6, (1<<6)}, + [IT83XX_IRQ_WKO67] = {GPIO_F, (1<<7), 6, (1<<7)}, + [IT83XX_IRQ_WKO70] = {GPIO_E, (1<<0), 7, (1<<0)}, + [IT83XX_IRQ_WKO71] = {GPIO_E, (1<<1), 7, (1<<1)}, + [IT83XX_IRQ_WKO72] = {GPIO_E, (1<<2), 7, (1<<2)}, + [IT83XX_IRQ_WKO73] = {GPIO_E, (1<<3), 7, (1<<3)}, + [IT83XX_IRQ_WKO74] = {GPIO_I, (1<<4), 7, (1<<4)}, + [IT83XX_IRQ_WKO75] = {GPIO_I, (1<<5), 7, (1<<5)}, + [IT83XX_IRQ_WKO76] = {GPIO_I, (1<<6), 7, (1<<6)}, + [IT83XX_IRQ_WKO77] = {GPIO_I, (1<<7), 7, (1<<7)}, + [IT83XX_IRQ_WKO80] = {GPIO_A, (1<<3), 8, (1<<0)}, + [IT83XX_IRQ_WKO81] = {GPIO_A, (1<<4), 8, (1<<1)}, + [IT83XX_IRQ_WKO82] = {GPIO_A, (1<<5), 8, (1<<2)}, + [IT83XX_IRQ_WKO83] = {GPIO_A, (1<<6), 8, (1<<3)}, + [IT83XX_IRQ_WKO84] = {GPIO_B, (1<<2), 8, (1<<4)}, + [IT83XX_IRQ_WKO85] = {GPIO_C, (1<<0), 8, (1<<5)}, + [IT83XX_IRQ_WKO86] = {GPIO_C, (1<<7), 8, (1<<6)}, + [IT83XX_IRQ_WKO87] = {GPIO_D, (1<<7), 8, (1<<7)}, + [IT83XX_IRQ_WKO88] = {GPIO_H, (1<<4), 9, (1<<0)}, + [IT83XX_IRQ_WKO89] = {GPIO_H, (1<<5), 9, (1<<1)}, + [IT83XX_IRQ_WKO90] = {GPIO_H, (1<<6), 9, (1<<2)}, + [IT83XX_IRQ_WKO91] = {GPIO_A, (1<<0), 9, (1<<3)}, + [IT83XX_IRQ_WKO92] = {GPIO_A, (1<<1), 9, (1<<4)}, + [IT83XX_IRQ_WKO93] = {GPIO_A, (1<<2), 9, (1<<5)}, + [IT83XX_IRQ_WKO94] = {GPIO_B, (1<<4), 9, (1<<6)}, + [IT83XX_IRQ_WKO95] = {GPIO_C, (1<<2), 9, (1<<7)}, + [IT83XX_IRQ_WKO96] = {GPIO_F, (1<<0), 10, (1<<0)}, + [IT83XX_IRQ_WKO97] = {GPIO_F, (1<<1), 10, (1<<1)}, + [IT83XX_IRQ_WKO98] = {GPIO_F, (1<<2), 10, (1<<2)}, + [IT83XX_IRQ_WKO99] = {GPIO_F, (1<<3), 10, (1<<3)}, + [IT83XX_IRQ_WKO100] = {GPIO_A, (1<<7), 10, (1<<4)}, + [IT83XX_IRQ_WKO101] = {GPIO_B, (1<<0), 10, (1<<5)}, + [IT83XX_IRQ_WKO102] = {GPIO_B, (1<<1), 10, (1<<6)}, + [IT83XX_IRQ_WKO103] = {GPIO_B, (1<<3), 10, (1<<7)}, + [IT83XX_IRQ_WKO104] = {GPIO_B, (1<<5), 11, (1<<0)}, + [IT83XX_IRQ_WKO105] = {GPIO_B, (1<<6), 11, (1<<1)}, + [IT83XX_IRQ_WKO106] = {GPIO_B, (1<<7), 11, (1<<2)}, + [IT83XX_IRQ_WKO107] = {GPIO_C, (1<<1), 11, (1<<3)}, + [IT83XX_IRQ_WKO108] = {GPIO_C, (1<<3), 11, (1<<4)}, + [IT83XX_IRQ_WKO109] = {GPIO_C, (1<<5), 11, (1<<5)}, + [IT83XX_IRQ_WKO110] = {GPIO_D, (1<<3), 11, (1<<6)}, + [IT83XX_IRQ_WKO111] = {GPIO_D, (1<<4), 11, (1<<7)}, + [IT83XX_IRQ_WKO112] = {GPIO_D, (1<<5), 12, (1<<0)}, + [IT83XX_IRQ_WKO113] = {GPIO_D, (1<<6), 12, (1<<1)}, + [IT83XX_IRQ_WKO114] = {GPIO_E, (1<<4), 12, (1<<2)}, + [IT83XX_IRQ_WKO115] = {GPIO_G, (1<<0), 12, (1<<3)}, + [IT83XX_IRQ_WKO116] = {GPIO_G, (1<<1), 12, (1<<4)}, + [IT83XX_IRQ_WKO117] = {GPIO_G, (1<<2), 12, (1<<5)}, + [IT83XX_IRQ_WKO118] = {GPIO_G, (1<<6), 12, (1<<6)}, + [IT83XX_IRQ_WKO119] = {GPIO_I, (1<<0), 12, (1<<7)}, + [IT83XX_IRQ_WKO120] = {GPIO_I, (1<<1), 13, (1<<0)}, + [IT83XX_IRQ_WKO121] = {GPIO_I, (1<<2), 13, (1<<1)}, + [IT83XX_IRQ_WKO122] = {GPIO_I, (1<<3), 13, (1<<2)}, + [IT83XX_IRQ_WKO128] = {GPIO_J, (1<<0), 14, (1<<0)}, + [IT83XX_IRQ_WKO129] = {GPIO_J, (1<<1), 14, (1<<1)}, + [IT83XX_IRQ_WKO130] = {GPIO_J, (1<<2), 14, (1<<2)}, + [IT83XX_IRQ_WKO131] = {GPIO_J, (1<<3), 14, (1<<3)}, + [IT83XX_IRQ_WKO132] = {GPIO_J, (1<<4), 14, (1<<4)}, + [IT83XX_IRQ_WKO133] = {GPIO_J, (1<<5), 14, (1<<5)}, + [IT83XX_IRQ_COUNT-1] = {0, 0, 0, 0}, +}; +BUILD_ASSERT(ARRAY_SIZE(gpio_irqs) == IT83XX_IRQ_COUNT); + +/** + * Given a GPIO port and mask, find the corresponding WKO interrupt number. + * + * @param port GPIO port + * @param mask GPIO mask + * + * @return IRQ for the WKO interrupt on the corresponding input pin. + */ +static int gpio_to_irq(uint8_t port, uint8_t mask) +{ + int i; + + for (i = 0; i < IT83XX_IRQ_COUNT; i++) { + if (gpio_irqs[i].gpio_port == port && + gpio_irqs[i].gpio_mask == mask) + return i; + } + + return -1; +} + + +void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func) +{ + uint32_t pin = 0; + + /* For each bit high in the mask, set that pin to use alt. func. */ + while (mask > 0) { + /* + * If func is non-negative, set for alternate function. + * Otherwise, turn the pin into an input as it's default. + */ + if ((mask & 1) && func >= 0) + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) &= ~0xc0; + else if ((mask & 1) && func < 0) + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) = + (IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) | 0x80) & ~0x40; + + pin++; + mask >>= 1; + } +} + +test_mockable int gpio_get_level(enum gpio_signal signal) +{ + return (IT83XX_GPIO_DATA(gpio_list[signal].port) & + gpio_list[signal].mask) ? 1 : 0; +} + +void gpio_set_level(enum gpio_signal signal, int value) +{ + if (value) + IT83XX_GPIO_DATA(gpio_list[signal].port) |= + gpio_list[signal].mask; + else + IT83XX_GPIO_DATA(gpio_list[signal].port) &= + ~gpio_list[signal].mask; +} + +void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) +{ + uint32_t pin = 0; + uint32_t mask_copy = mask; + int irq; + + /* + * Select open drain first, so that we don't glitch the signal + * when changing the line to an output. + */ + if (flags & GPIO_OPEN_DRAIN) + IT83XX_GPIO_GPOT(port) |= mask; + else + IT83XX_GPIO_GPOT(port) &= ~mask; + + /* If output, set level before changing type to an output. */ + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_HIGH) + IT83XX_GPIO_DATA(port) |= mask; + else if (flags & GPIO_LOW) + IT83XX_GPIO_DATA(port) &= ~mask; + } + + /* For each bit high in the mask, set input/output and pullup/down. */ + while (mask_copy > 0) { + if (mask_copy & 1) { + /* Set input or output. */ + if (flags & GPIO_OUTPUT) + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) = + (IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) | 0x40) + & ~0x80; + else + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) = + (IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) | 0x80) + & ~0x40; + + /* Handle pullup / pulldown */ + if (flags & GPIO_PULL_UP) { + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) = + (IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) | 0x04) + & ~0x02; + } else if (flags & GPIO_PULL_DOWN) { + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) = + (IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) | 0x02) + & ~0x04; + } else { + /* No pull up/down */ + IT83XX_GPIO_CTRL(CTRL_BASE(port), pin) &= ~0x06; + } + } + + pin++; + mask_copy >>= 1; + } + + /* Set rising edge interrupt. */ + if (flags & GPIO_INT_F_RISING) { + irq = gpio_to_irq(port, mask); + + *(wuemr(gpio_irqs[irq].wuc_group)) &= ~gpio_irqs[irq].wuc_mask; + } + + /* + * Set falling edge or both edges interrupt. Note that pins in WUC + * groups 7, 10, and 12 can only declare a falling edge trigger. All + * other pins can only declare both edges as the trigger. + * + * TODO: use an assert to catch if a developer tries to declare one + * type of interrupt on a pin that doesn't support that type. + */ + if (flags & GPIO_INT_F_FALLING) { + irq = gpio_to_irq(port, mask); + + *(wuemr(gpio_irqs[irq].wuc_group)) |= gpio_irqs[irq].wuc_mask; + } +} + +int gpio_enable_interrupt(enum gpio_signal signal) +{ + int irq = gpio_to_irq(gpio_list[signal].port, gpio_list[signal].mask); + + if (irq == -1) + return EC_ERROR_UNKNOWN; + else + task_enable_irq(irq); + + return EC_SUCCESS; +} + +int gpio_disable_interrupt(enum gpio_signal signal) +{ + int irq = gpio_to_irq(gpio_list[signal].port, gpio_list[signal].mask); + + if (irq == -1) + return EC_ERROR_UNKNOWN; + else + task_disable_irq(irq); + + return EC_SUCCESS; +} + +void gpio_pre_init(void) +{ + const struct gpio_info *g = gpio_list; + int flags; + int i; + + for (i = 0; i < GPIO_COUNT; i++, g++) { + flags = g->flags; + + if (flags & GPIO_DEFAULT) + continue; + + /* Set up GPIO based on flags */ + gpio_set_flags_by_mask(g->port, g->mask, flags); + } +} + + + +/** + * Handle a GPIO interrupt by calling the pins corresponding handler if + * one exists. + * + * @param port GPIO port (GPIO_*) + * @param mask GPIO mask + */ +static void gpio_interrupt(int port, uint8_t mask) +{ + int i = 0; + const struct gpio_info *g = gpio_list; + + for (i = 0; i < GPIO_COUNT; i++, g++) { + if (port == g->port && (mask & g->mask) && g->irq_handler) { + g->irq_handler(i); + return; + } + } +} + +/** + * Define one IRQ function to handle all GPIO interrupts. The IRQ determines + * the interrupt number which was triggered, calls the master handler above, + * and clears status registers. + */ +static void __gpio_irq(void) +{ + /* Determine interrupt number. */ + int irq = IT83XX_INTC_IVCT2 - 16; + + /* Run the GPIO master handler above with corresponding port/mask. */ + gpio_interrupt(gpio_irqs[irq].gpio_port, gpio_irqs[irq].gpio_mask); + + /* + * Clear the WUC status register. Note the external pin first goes + * to the WUC module and is always edge triggered. + */ + *(wuesr(gpio_irqs[irq].wuc_group)) = gpio_irqs[irq].wuc_mask; + + /* + * Clear the interrupt controller status register. Note the interrupt + * controller is level triggered from the WUC status. + */ + task_clear_pending_irq(irq); +} + +/* Route all WKO interrupts coming from INT#2 into __gpio_irq. */ +DECLARE_IRQ(CPU_INT_2_ALL_GPIOS, __gpio_irq, 1); diff --git a/chip/it83xx/hwtimer.c b/chip/it83xx/hwtimer.c new file mode 100644 index 0000000000..cf4de26be8 --- /dev/null +++ b/chip/it83xx/hwtimer.c @@ -0,0 +1,170 @@ +/* Copyright (c) 2013 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 timers driver */ + +#include "cpu.h" +#include "common.h" +#include "hooks.h" +#include "hwtimer.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +/* 128us (2^7 us) between 2 ticks */ +#define TICK_INTERVAL_LOG2 7 + +#define TICK_INTERVAL (1 << TICK_INTERVAL_LOG2) +#define TICK_INTERVAL_MASK (TICK_INTERVAL - 1) + +/* + * Tick interval must fit in one byte, and must be greater than two + * so that the duty cycle does not equal the cycle time (IT83XX_TMR_DCR_B0 must + * be less than IT83XX_TMR_CTR_B0). + */ +BUILD_ASSERT(TICK_INTERVAL < 256 && TICK_INTERVAL > 2); + +static volatile uint32_t time_us; + +/* + * Next event time of 0 represents "no event set". But, when we actually want + * to trigger when the event time is 0, it is handled implicitly by calling + * process_timers(1) when the timer value rolls over. + */ +static uint32_t next_event_time; + +void __hw_clock_event_set(uint32_t deadline) +{ + next_event_time = deadline; +} + +uint32_t __hw_clock_event_get(void) +{ + return next_event_time; +} + +void __hw_clock_event_clear(void) +{ + next_event_time = 0; +} + +uint32_t __hw_clock_source_read(void) +{ + return time_us; +} + +void __hw_clock_source_set(uint32_t ts) +{ + time_us = ts & TICK_INTERVAL_MASK; +} + + +static void __hw_clock_source_irq(void) +{ + /* + * If this is a SW interrupt, then process the timers, but don't + * increment the time_us. + */ + if (get_itype() & 8) { + process_timers(0); + return; + } + + /* clear interrupt status */ + task_clear_pending_irq(IT83XX_IRQ_TMR_B0); + + time_us += TICK_INTERVAL; + + /* + * Find expired timers and set the new timer deadline; check the IRQ + * status to determine if the free-running counter overflowed. Note + * since each tick is greater than 1us and events can be set in + * increments of 1us, in order to find expired timers we have to + * check two conditions: the current time is exactly the next event + * time, or this tick just caused us to pass the next event time. + */ + if (time_us == next_event_time || + (time_us-TICK_INTERVAL) == + (next_event_time & ~TICK_INTERVAL_MASK)) + process_timers(0); + else if (time_us == 0) + process_timers(1); +} +DECLARE_IRQ(IT83XX_IRQ_TMR_B0, __hw_clock_source_irq, 1); + +static void setup_gpio(void) +{ + /* TMB0 enabled */ + IT83XX_GPIO_GRC2 |= 0x04; + + /* Pin muxing (TMB0) */ + IT83XX_GPIO_GPCRF0 = 0x00; +} + +static void hw_timer_enable_int(void) +{ + /* clear interrupt status */ + task_clear_pending_irq(IT83XX_IRQ_TMR_B0); + + /* enable interrupt B0 */ + task_enable_irq(IT83XX_IRQ_TMR_B0); +} + +int __hw_clock_source_init(uint32_t start_t) +{ + __hw_clock_source_set(start_t); + + /* GPIO module should do this. */ + setup_gpio(); + +#if PLL_CLOCK == 48000000 + /* Set prescaler divider value (PRSC0 = /8). */ + IT83XX_TMR_PRSC = 0x04; + + /* Tim B: 8 bit pulse mode, 8MHz clock. */ + IT83XX_TMR_GCSMS = 0x01; +#else +#error "Support only for PLL clock speed of 48MHz." +#endif + + /* Set timer B to use PRSC0. */ + IT83XX_TMR_CCGSR = 0x00; + + /* + * Set the 8-bit cycle time, duty time for timer B. Note 0 < DCR < CTR + * in order for timer interrupt to properly fire when cycle time is + * reached. + */ + IT83XX_TMR_CTR_B0 = TICK_INTERVAL - 1; + IT83XX_TMR_DCR_B0 = 0x01; + + /* Enable the cycle time interrupt for timer B0. */ + IT83XX_TMR_TMRIE |= 0x10; + + hw_timer_enable_int(); + + /* Enable TMR clock counter. */ + IT83XX_TMR_TMRCE |= 0x02; + + return IT83XX_IRQ_TMR_B0; +} + +void udelay(unsigned us) +{ + /* + * When WNCKR register is set, the CPU pauses until a low to + * high transition on an internal 65kHz clock (~15.25us). We need to + * make sure though that we don't ever delay less than the requested + * amount, so we always have to add an extra wait. + * + * TODO: This code has a few limitations, the math isn't exact so + * the larger the delay the farther off it will be, it uses a divide, + * and the resolution is only about 15us. + */ + int waits = us*4/61 + 1; + while (waits-- >= 0) + IT83XX_GCTRL_WNCKR = 0; +} diff --git a/chip/it83xx/irq.c b/chip/it83xx/irq.c new file mode 100644 index 0000000000..e65036ca22 --- /dev/null +++ b/chip/it83xx/irq.c @@ -0,0 +1,87 @@ +/* Copyright (c) 2013 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. + * + * IT83xx chip-specific part of the IRQ handling. + */ + +#include "common.h" +#include "irq_chip.h" +#include "registers.h" + +#define IRQ_GROUP(n, cpu_ints...) \ + {(uint32_t)&CONCAT2(IT83XX_INTC_ISR, n) - IT83XX_INTC_BASE, \ + (uint32_t)&CONCAT2(IT83XX_INTC_IER, n) - IT83XX_INTC_BASE, \ + ##cpu_ints} + +static const struct { + uint8_t isr_off; + uint8_t ier_off; + uint8_t cpu_int[8]; +} irq_groups[20] = { + IRQ_GROUP(0, {-1, 2, 5, 4, 6, 2, 2, 4}), + IRQ_GROUP(1, { 7, 6, 6, 5, 2, 2, 2, 8}), + IRQ_GROUP(2, { 6, 2, 8, 8, 8, 2, 12, -1}), + IRQ_GROUP(3, { 5, 4, 4, 4, 11, 11, 3, 2}), + IRQ_GROUP(4, {11, 11, 11, 11, 8, 9, 9, 9}), + IRQ_GROUP(5, {-1, -1, -1, -1, -1, -1, -1, -1}), + IRQ_GROUP(6, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(7, {10, 10, 3, -1, 3, 3, 3, 3}), + IRQ_GROUP(8, { 4, 4, 4, 4, 4, 4, 12, 12}), + IRQ_GROUP(9, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(10, { 3, 6, 12, 12, 5, 2, 2, 2}), + IRQ_GROUP(11, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(12, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(13, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(14, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(15, { 2, 2, 2, 2, 2, 2, 2, 2}), + IRQ_GROUP(16, { 2, 2, 2, 2, 2, 2, 2, -1}), + IRQ_GROUP(17, {-1, -1, -1, -1, -1, -1, -1, -1}), + IRQ_GROUP(18, { 2, 2, 2, 2, 2, 4, 4, 7}), + IRQ_GROUP(19, { 6, 6, 12, 3, 3, 3, 3, 3}), +}; + +int chip_enable_irq(int irq) +{ + int group = irq / 8; + int bit = irq % 8; + + IT83XX_INTC_REG(irq_groups[group].ier_off) |= 1 << bit; + IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)) |= 1 << bit; + + return irq_groups[group].cpu_int[bit]; +} + +int chip_disable_irq(int irq) +{ + int group = irq / 8; + int bit = irq % 8; + + IT83XX_INTC_REG(irq_groups[group].ier_off) &= ~(1 << bit); + IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)) &= ~(1 << bit); + + return -1; /* we don't want to mask other IRQs */ +} + +int chip_clear_pending_irq(int irq) +{ + int group = irq / 8; + int bit = irq % 8; + + IT83XX_INTC_REG(irq_groups[group].isr_off) |= 1 << bit; + + return -1; /* everything has been done */ +} + +int chip_trigger_irq(int irq) +{ + int group = irq / 8; + int bit = irq % 8; + + return irq_groups[group].cpu_int[bit]; +} + +void chip_init_irqs(void) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ +} diff --git a/chip/it83xx/jtag.c b/chip/it83xx/jtag.c new file mode 100644 index 0000000000..b876d7f914 --- /dev/null +++ b/chip/it83xx/jtag.c @@ -0,0 +1,15 @@ +/* Copyright (c) 2013 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 "clock.h" +#include "gpio.h" +#include "jtag.h" +#include "registers.h" +#include "system.h" + +void jtag_pre_init(void) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ +} diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h new file mode 100644 index 0000000000..e27840796d --- /dev/null +++ b/chip/it83xx/registers.h @@ -0,0 +1,558 @@ +/* Copyright (c) 2013 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 IT83xx processor + */ + +#ifndef __CROS_EC_REGISTERS_H +#define __CROS_EC_REGISTERS_H + +#include "common.h" + +/* IRQ numbers */ +#define IT83XX_IRQ_WKO20 1 +#define IT83XX_IRQ_KBC_OUT 2 +#define IT83XX_IRQ_PMC_OUT 3 +#define IT83XX_IRQ_SMB_D 4 +#define IT83XX_IRQ_WKINTAD 5 +#define IT83XX_IRQ_WKO23 6 +#define IT83XX_IRQ_PWM 7 +#define IT83XX_IRQ_ADC 8 +#define IT83XX_IRQ_SMB_A 9 +#define IT83XX_IRQ_SMB_B 10 +#define IT83XX_IRQ_KB_MATRIX 11 +#define IT83XX_IRQ_WKO26 12 +#define IT83XX_IRQ_WKINTC 13 +#define IT83XX_IRQ_WKO25 14 +#define IT83XX_IRQ_CIR 15 +#define IT83XX_IRQ_SMB_C 16 +#define IT83XX_IRQ_WKO24 17 +#define IT83XX_IRQ_PS2_2 18 +#define IT83XX_IRQ_PS2_1 19 +#define IT83XX_IRQ_PS2_0 20 +#define IT83XX_IRQ_WKO22 21 +#define IT83XX_IRQ_SMFI 22 +#define IT83XX_IRQ_KBC_IN 24 +#define IT83XX_IRQ_PMC_IN 25 +#define IT83XX_IRQ_PMC2_OUT 26 +#define IT83XX_IRQ_PMC2_IN 27 +#define IT83XX_IRQ_GINT 28 +#define IT83XX_IRQ_EGPC 29 +#define IT83XX_IRQ_EXT_TIMER1 30 +#define IT83XX_IRQ_WKO21 31 +#define IT83XX_IRQ_GPINT0 32 +#define IT83XX_IRQ_GPINT1 33 +#define IT83XX_IRQ_GPINT2 34 +#define IT83XX_IRQ_GPINT3 35 +#define IT83XX_IRQ_CIR_GPINT 36 +#define IT83XX_IRQ_SSPI 37 +#define IT83XX_IRQ_UART1 38 +#define IT83XX_IRQ_UART2 39 +#define IT83XX_IRQ_WKO60 48 +#define IT83XX_IRQ_WKO61 49 +#define IT83XX_IRQ_WKO62 50 +#define IT83XX_IRQ_WKO63 51 +#define IT83XX_IRQ_WKO64 52 +#define IT83XX_IRQ_WKO65 53 +#define IT83XX_IRQ_WKO66 54 +#define IT83XX_IRQ_WKO67 55 +#define IT83XX_IRQ_RTCT_ALARM1 56 +#define IT83XX_IRQ_RTCT_ALARM2 57 +#define IT83XX_IRQ_EXT_TIMER2 58 +#define IT83XX_IRQ_TMR_A0 60 +#define IT83XX_IRQ_TMR_A1 61 +#define IT83XX_IRQ_TMR_B0 62 +#define IT83XX_IRQ_TMR_B1 63 +#define IT83XX_IRQ_PMC2EX_OUT 64 +#define IT83XX_IRQ_PMC2EX_IN 65 +#define IT83XX_IRQ_PMC3_OUT 66 +#define IT83XX_IRQ_PMC3_IN 67 +#define IT83XX_IRQ_PMC4_OUT 68 +#define IT83XX_IRQ_PMC4_IN 69 +#define IT83XX_IRQ_I2BRAM 71 +#define IT83XX_IRQ_WKO70 72 +#define IT83XX_IRQ_WKO71 73 +#define IT83XX_IRQ_WKO72 74 +#define IT83XX_IRQ_WKO73 75 +#define IT83XX_IRQ_WKO74 76 +#define IT83XX_IRQ_WKO75 77 +#define IT83XX_IRQ_WKO76 78 +#define IT83XX_IRQ_WKO77 79 +#define IT83XX_IRQ_EXT_TMR8 80 +#define IT83XX_IRQ_SMB_CLOCK_HELD 81 +#define IT83XX_IRQ_CEC 82 +#define IT83XX_IRQ_H2RAM_LPC 83 +#define IT83XX_IRQ_WKO88 85 +#define IT83XX_IRQ_WKO89 86 +#define IT83XX_IRQ_WKO90 87 +#define IT83XX_IRQ_WKO80 88 +#define IT83XX_IRQ_WKO81 89 +#define IT83XX_IRQ_WKO82 90 +#define IT83XX_IRQ_WKO83 91 +#define IT83XX_IRQ_WKO84 92 +#define IT83XX_IRQ_WKO85 93 +#define IT83XX_IRQ_WKO86 94 +#define IT83XX_IRQ_WKO87 95 +#define IT83XX_IRQ_WKO91 96 +#define IT83XX_IRQ_WKO92 97 +#define IT83XX_IRQ_WKO93 98 +#define IT83XX_IRQ_WKO94 99 +#define IT83XX_IRQ_WKO95 100 +#define IT83XX_IRQ_WKO96 101 +#define IT83XX_IRQ_WKO97 102 +#define IT83XX_IRQ_WKO98 103 +#define IT83XX_IRQ_WKO99 104 +#define IT83XX_IRQ_WKO100 105 +#define IT83XX_IRQ_WKO101 106 +#define IT83XX_IRQ_WKO102 107 +#define IT83XX_IRQ_WKO103 108 +#define IT83XX_IRQ_WKO104 109 +#define IT83XX_IRQ_WKO105 110 +#define IT83XX_IRQ_WKO106 111 +#define IT83XX_IRQ_WKO107 112 +#define IT83XX_IRQ_WKO108 113 +#define IT83XX_IRQ_WKO109 114 +#define IT83XX_IRQ_WKO110 115 +#define IT83XX_IRQ_WKO111 116 +#define IT83XX_IRQ_WKO112 117 +#define IT83XX_IRQ_WKO113 118 +#define IT83XX_IRQ_WKO114 119 +#define IT83XX_IRQ_WKO115 120 +#define IT83XX_IRQ_WKO116 121 +#define IT83XX_IRQ_WKO117 122 +#define IT83XX_IRQ_WKO118 123 +#define IT83XX_IRQ_WKO119 124 +#define IT83XX_IRQ_WKO120 125 +#define IT83XX_IRQ_WKO121 126 +#define IT83XX_IRQ_WKO122 127 +#define IT83XX_IRQ_WKO128 128 +#define IT83XX_IRQ_WKO129 129 +#define IT83XX_IRQ_WKO130 130 +#define IT83XX_IRQ_WKO131 131 +#define IT83XX_IRQ_WKO132 132 +#define IT83XX_IRQ_WKO133 133 +#define IT83XX_IRQ_WKO134 134 +#define IT83XX_IRQ_PMC5_OUT 149 +#define IT83XX_IRQ_PMC5_IN 150 +#define IT83XX_IRQ_V_COMP 151 +#define IT83XX_IRQ_SMB_E 152 +#define IT83XX_IRQ_SMB_F 153 +#define IT83XX_IRQ_OSC_DMA 154 +#define IT83XX_IRQ_EXT_TIMER3 155 +#define IT83XX_IRQ_EXT_TIMER4 156 +#define IT83XX_IRQ_EXT_TIMER5 157 +#define IT83XX_IRQ_EXT_TIMER6 158 +#define IT83XX_IRQ_EXT_TIMER7 159 +#define IT83XX_IRQ_COUNT 160 + +/* IRQ dispatching to CPU INT vectors */ +#define IT83XX_CPU_INT_IRQ_1 2 +#define IT83XX_CPU_INT_IRQ_2 5 +#define IT83XX_CPU_INT_IRQ_3 4 +#define IT83XX_CPU_INT_IRQ_4 6 +#define IT83XX_CPU_INT_IRQ_5 2 +#define IT83XX_CPU_INT_IRQ_6 2 +#define IT83XX_CPU_INT_IRQ_7 4 +#define IT83XX_CPU_INT_IRQ_8 7 +#define IT83XX_CPU_INT_IRQ_9 6 +#define IT83XX_CPU_INT_IRQ_10 6 +#define IT83XX_CPU_INT_IRQ_11 5 +#define IT83XX_CPU_INT_IRQ_12 2 +#define IT83XX_CPU_INT_IRQ_13 2 +#define IT83XX_CPU_INT_IRQ_14 2 +#define IT83XX_CPU_INT_IRQ_15 8 +#define IT83XX_CPU_INT_IRQ_16 6 +#define IT83XX_CPU_INT_IRQ_17 2 +#define IT83XX_CPU_INT_IRQ_18 8 +#define IT83XX_CPU_INT_IRQ_19 8 +#define IT83XX_CPU_INT_IRQ_20 8 +#define IT83XX_CPU_INT_IRQ_21 2 +#define IT83XX_CPU_INT_IRQ_22 12 +#define IT83XX_CPU_INT_IRQ_24 5 +#define IT83XX_CPU_INT_IRQ_25 4 +#define IT83XX_CPU_INT_IRQ_26 4 +#define IT83XX_CPU_INT_IRQ_27 4 +#define IT83XX_CPU_INT_IRQ_28 11 +#define IT83XX_CPU_INT_IRQ_29 11 +#define IT83XX_CPU_INT_IRQ_30 3 +#define IT83XX_CPU_INT_IRQ_31 2 +#define IT83XX_CPU_INT_IRQ_32 11 +#define IT83XX_CPU_INT_IRQ_33 11 +#define IT83XX_CPU_INT_IRQ_34 11 +#define IT83XX_CPU_INT_IRQ_35 11 +#define IT83XX_CPU_INT_IRQ_36 8 +#define IT83XX_CPU_INT_IRQ_37 9 +#define IT83XX_CPU_INT_IRQ_38 9 +#define IT83XX_CPU_INT_IRQ_39 9 +#define IT83XX_CPU_INT_IRQ_48 2 +#define IT83XX_CPU_INT_IRQ_49 2 +#define IT83XX_CPU_INT_IRQ_50 2 +#define IT83XX_CPU_INT_IRQ_51 2 +#define IT83XX_CPU_INT_IRQ_52 2 +#define IT83XX_CPU_INT_IRQ_53 2 +#define IT83XX_CPU_INT_IRQ_54 2 +#define IT83XX_CPU_INT_IRQ_55 2 +#define IT83XX_CPU_INT_IRQ_56 10 +#define IT83XX_CPU_INT_IRQ_57 10 +#define IT83XX_CPU_INT_IRQ_58 3 +#define IT83XX_CPU_INT_IRQ_60 3 +#define IT83XX_CPU_INT_IRQ_61 3 +#define IT83XX_CPU_INT_IRQ_62 3 +#define IT83XX_CPU_INT_IRQ_63 3 +#define IT83XX_CPU_INT_IRQ_64 4 +#define IT83XX_CPU_INT_IRQ_65 4 +#define IT83XX_CPU_INT_IRQ_66 4 +#define IT83XX_CPU_INT_IRQ_67 4 +#define IT83XX_CPU_INT_IRQ_68 4 +#define IT83XX_CPU_INT_IRQ_69 4 +#define IT83XX_CPU_INT_IRQ_70 12 +#define IT83XX_CPU_INT_IRQ_71 12 +#define IT83XX_CPU_INT_IRQ_72 2 +#define IT83XX_CPU_INT_IRQ_73 2 +#define IT83XX_CPU_INT_IRQ_74 2 +#define IT83XX_CPU_INT_IRQ_75 2 +#define IT83XX_CPU_INT_IRQ_76 2 +#define IT83XX_CPU_INT_IRQ_77 2 +#define IT83XX_CPU_INT_IRQ_78 2 +#define IT83XX_CPU_INT_IRQ_79 2 +#define IT83XX_CPU_INT_IRQ_80 3 +#define IT83XX_CPU_INT_IRQ_81 6 +#define IT83XX_CPU_INT_IRQ_82 12 +#define IT83XX_CPU_INT_IRQ_83 12 +#define IT83XX_CPU_INT_IRQ_84 5 +#define IT83XX_CPU_INT_IRQ_85 2 +#define IT83XX_CPU_INT_IRQ_86 2 +#define IT83XX_CPU_INT_IRQ_87 2 +#define IT83XX_CPU_INT_IRQ_88 2 +#define IT83XX_CPU_INT_IRQ_89 2 +#define IT83XX_CPU_INT_IRQ_90 2 +#define IT83XX_CPU_INT_IRQ_91 2 +#define IT83XX_CPU_INT_IRQ_92 2 +#define IT83XX_CPU_INT_IRQ_93 2 +#define IT83XX_CPU_INT_IRQ_94 2 +#define IT83XX_CPU_INT_IRQ_95 2 +#define IT83XX_CPU_INT_IRQ_96 2 +#define IT83XX_CPU_INT_IRQ_97 2 +#define IT83XX_CPU_INT_IRQ_98 2 +#define IT83XX_CPU_INT_IRQ_99 2 +#define IT83XX_CPU_INT_IRQ_100 2 +#define IT83XX_CPU_INT_IRQ_101 2 +#define IT83XX_CPU_INT_IRQ_102 2 +#define IT83XX_CPU_INT_IRQ_103 2 +#define IT83XX_CPU_INT_IRQ_104 2 +#define IT83XX_CPU_INT_IRQ_105 2 +#define IT83XX_CPU_INT_IRQ_106 2 +#define IT83XX_CPU_INT_IRQ_107 2 +#define IT83XX_CPU_INT_IRQ_108 2 +#define IT83XX_CPU_INT_IRQ_109 2 +#define IT83XX_CPU_INT_IRQ_110 2 +#define IT83XX_CPU_INT_IRQ_111 2 +#define IT83XX_CPU_INT_IRQ_112 2 +#define IT83XX_CPU_INT_IRQ_113 2 +#define IT83XX_CPU_INT_IRQ_114 2 +#define IT83XX_CPU_INT_IRQ_115 2 +#define IT83XX_CPU_INT_IRQ_116 2 +#define IT83XX_CPU_INT_IRQ_117 2 +#define IT83XX_CPU_INT_IRQ_118 2 +#define IT83XX_CPU_INT_IRQ_119 2 +#define IT83XX_CPU_INT_IRQ_120 2 +#define IT83XX_CPU_INT_IRQ_121 2 +#define IT83XX_CPU_INT_IRQ_122 2 +#define IT83XX_CPU_INT_IRQ_123 2 +#define IT83XX_CPU_INT_IRQ_124 2 +#define IT83XX_CPU_INT_IRQ_125 2 +#define IT83XX_CPU_INT_IRQ_126 2 +#define IT83XX_CPU_INT_IRQ_127 2 +#define IT83XX_CPU_INT_IRQ_128 2 +#define IT83XX_CPU_INT_IRQ_129 2 +#define IT83XX_CPU_INT_IRQ_130 2 +#define IT83XX_CPU_INT_IRQ_131 2 +#define IT83XX_CPU_INT_IRQ_132 2 +#define IT83XX_CPU_INT_IRQ_133 2 +#define IT83XX_CPU_INT_IRQ_134 2 +#define IT83XX_CPU_INT_IRQ_144 2 +#define IT83XX_CPU_INT_IRQ_145 2 +#define IT83XX_CPU_INT_IRQ_146 2 +#define IT83XX_CPU_INT_IRQ_147 2 +#define IT83XX_CPU_INT_IRQ_148 2 +#define IT83XX_CPU_INT_IRQ_149 4 +#define IT83XX_CPU_INT_IRQ_150 4 +#define IT83XX_CPU_INT_IRQ_151 7 +#define IT83XX_CPU_INT_IRQ_152 6 +#define IT83XX_CPU_INT_IRQ_153 6 +#define IT83XX_CPU_INT_IRQ_154 12 +#define IT83XX_CPU_INT_IRQ_155 3 +#define IT83XX_CPU_INT_IRQ_156 3 +#define IT83XX_CPU_INT_IRQ_157 3 +#define IT83XX_CPU_INT_IRQ_158 3 +#define IT83XX_CPU_INT_IRQ_159 3 + +/* "Fake" IRQ to declare in readable fashion all WKO IRQ routed to INT#2 */ +#define CPU_INT_2_ALL_GPIOS 255 +#define IT83XX_CPU_INT_IRQ_255 2 + +#define CPU_INT(irq) CONCAT2(IT83XX_CPU_INT_IRQ_, irq) + +/* --- INTC --- */ +#define IT83XX_INTC_BASE 0x00F01100 + +#define IT83XX_INTC_REG(n) REG8(IT83XX_INTC_BASE+(n)) + +#define IT83XX_INTC_AIVCT REG8(IT83XX_INTC_BASE+0x10) + +#define IT83XX_INTC_IER0 REG8(IT83XX_INTC_BASE+0x04) +#define IT83XX_INTC_IER1 REG8(IT83XX_INTC_BASE+0x05) +#define IT83XX_INTC_IER2 REG8(IT83XX_INTC_BASE+0x06) +#define IT83XX_INTC_IER3 REG8(IT83XX_INTC_BASE+0x07) +#define IT83XX_INTC_IER4 REG8(IT83XX_INTC_BASE+0x15) +#define IT83XX_INTC_IER5 REG8(IT83XX_INTC_BASE+0x19) +#define IT83XX_INTC_IER6 REG8(IT83XX_INTC_BASE+0x1d) +#define IT83XX_INTC_IER7 REG8(IT83XX_INTC_BASE+0x21) +#define IT83XX_INTC_IER8 REG8(IT83XX_INTC_BASE+0x25) +#define IT83XX_INTC_IER9 REG8(IT83XX_INTC_BASE+0x29) +#define IT83XX_INTC_IER10 REG8(IT83XX_INTC_BASE+0x2d) +#define IT83XX_INTC_IER11 REG8(IT83XX_INTC_BASE+0x31) +#define IT83XX_INTC_IER12 REG8(IT83XX_INTC_BASE+0x35) +#define IT83XX_INTC_IER13 REG8(IT83XX_INTC_BASE+0x39) +#define IT83XX_INTC_IER14 REG8(IT83XX_INTC_BASE+0x3d) +#define IT83XX_INTC_IER15 REG8(IT83XX_INTC_BASE+0x41) +#define IT83XX_INTC_IER16 REG8(IT83XX_INTC_BASE+0x45) +#define IT83XX_INTC_IER17 REG8(IT83XX_INTC_BASE+0x49) +#define IT83XX_INTC_IER18 REG8(IT83XX_INTC_BASE+0x4d) +#define IT83XX_INTC_IER19 REG8(IT83XX_INTC_BASE+0x51) + +#define IT83XX_INTC_ISR0 REG8(IT83XX_INTC_BASE+0x00) +#define IT83XX_INTC_ISR1 REG8(IT83XX_INTC_BASE+0x01) +#define IT83XX_INTC_ISR2 REG8(IT83XX_INTC_BASE+0x02) +#define IT83XX_INTC_ISR3 REG8(IT83XX_INTC_BASE+0x03) +#define IT83XX_INTC_ISR4 REG8(IT83XX_INTC_BASE+0x14) +#define IT83XX_INTC_ISR5 REG8(IT83XX_INTC_BASE+0x18) +#define IT83XX_INTC_ISR6 REG8(IT83XX_INTC_BASE+0x1c) +#define IT83XX_INTC_ISR7 REG8(IT83XX_INTC_BASE+0x20) +#define IT83XX_INTC_ISR8 REG8(IT83XX_INTC_BASE+0x24) +#define IT83XX_INTC_ISR9 REG8(IT83XX_INTC_BASE+0x28) +#define IT83XX_INTC_ISR10 REG8(IT83XX_INTC_BASE+0x2c) +#define IT83XX_INTC_ISR11 REG8(IT83XX_INTC_BASE+0x30) +#define IT83XX_INTC_ISR12 REG8(IT83XX_INTC_BASE+0x34) +#define IT83XX_INTC_ISR13 REG8(IT83XX_INTC_BASE+0x38) +#define IT83XX_INTC_ISR14 REG8(IT83XX_INTC_BASE+0x3c) +#define IT83XX_INTC_ISR15 REG8(IT83XX_INTC_BASE+0x40) +#define IT83XX_INTC_ISR16 REG8(IT83XX_INTC_BASE+0x44) +#define IT83XX_INTC_ISR17 REG8(IT83XX_INTC_BASE+0x48) +#define IT83XX_INTC_ISR18 REG8(IT83XX_INTC_BASE+0x4c) +#define IT83XX_INTC_ISR19 REG8(IT83XX_INTC_BASE+0x50) + +#define IT83XX_INTC_EXT_IER0 REG8(IT83XX_INTC_BASE+0x60) +#define IT83XX_INTC_EXT_IER1 REG8(IT83XX_INTC_BASE+0x61) +#define IT83XX_INTC_EXT_IER2 REG8(IT83XX_INTC_BASE+0x62) +#define IT83XX_INTC_EXT_IER3 REG8(IT83XX_INTC_BASE+0x63) +#define IT83XX_INTC_EXT_IER4 REG8(IT83XX_INTC_BASE+0x64) +#define IT83XX_INTC_EXT_IER5 REG8(IT83XX_INTC_BASE+0x65) +#define IT83XX_INTC_EXT_IER6 REG8(IT83XX_INTC_BASE+0x66) +#define IT83XX_INTC_EXT_IER7 REG8(IT83XX_INTC_BASE+0x67) +#define IT83XX_INTC_EXT_IER8 REG8(IT83XX_INTC_BASE+0x68) +#define IT83XX_INTC_EXT_IER9 REG8(IT83XX_INTC_BASE+0x69) +#define IT83XX_INTC_EXT_IER10 REG8(IT83XX_INTC_BASE+0x6A) +#define IT83XX_INTC_EXT_IER11 REG8(IT83XX_INTC_BASE+0x6B) +#define IT83XX_INTC_EXT_IER12 REG8(IT83XX_INTC_BASE+0x6C) +#define IT83XX_INTC_EXT_IER13 REG8(IT83XX_INTC_BASE+0x6D) +#define IT83XX_INTC_EXT_IER14 REG8(IT83XX_INTC_BASE+0x6E) +#define IT83XX_INTC_EXT_IER15 REG8(IT83XX_INTC_BASE+0x6F) +#define IT83XX_INTC_EXT_IER16 REG8(IT83XX_INTC_BASE+0x70) +#define IT83XX_INTC_EXT_IER17 REG8(IT83XX_INTC_BASE+0x71) +#define IT83XX_INTC_EXT_IER18 REG8(IT83XX_INTC_BASE+0x72) +#define IT83XX_INTC_EXT_IER19 REG8(IT83XX_INTC_BASE+0x73) + +#define IT83XX_INTC_EXT_IER_OFF(n) (0x60 + (n)) + +#define IT83XX_INTC_IVCT0 REG8(IT83XX_INTC_BASE+0x80) +#define IT83XX_INTC_IVCT1 REG8(IT83XX_INTC_BASE+0x81) +#define IT83XX_INTC_IVCT2 REG8(IT83XX_INTC_BASE+0x82) +#define IT83XX_INTC_IVCT3 REG8(IT83XX_INTC_BASE+0x83) +#define IT83XX_INTC_IVCT4 REG8(IT83XX_INTC_BASE+0x84) +#define IT83XX_INTC_IVCT5 REG8(IT83XX_INTC_BASE+0x85) +#define IT83XX_INTC_IVCT6 REG8(IT83XX_INTC_BASE+0x86) +#define IT83XX_INTC_IVCT7 REG8(IT83XX_INTC_BASE+0x87) +#define IT83XX_INTC_IVCT8 REG8(IT83XX_INTC_BASE+0x88) +#define IT83XX_INTC_IVCT9 REG8(IT83XX_INTC_BASE+0x89) +#define IT83XX_INTC_IVCT10 REG8(IT83XX_INTC_BASE+0x8A) +#define IT83XX_INTC_IVCT11 REG8(IT83XX_INTC_BASE+0x8B) +#define IT83XX_INTC_IVCT12 REG8(IT83XX_INTC_BASE+0x8C) +#define IT83XX_INTC_IVCT13 REG8(IT83XX_INTC_BASE+0x8D) +#define IT83XX_INTC_IVCT14 REG8(IT83XX_INTC_BASE+0x8E) +#define IT83XX_INTC_IVCT15 REG8(IT83XX_INTC_BASE+0x8F) + +/* --- Wake-Up Control (WUC) --- */ +#define IT83XX_WUC_BASE 0x00F01B00 + +#define IT83XX_WUC_WUEMR1 (IT83XX_WUC_BASE+0x00) +#define IT83XX_WUC_WUEMR6 (IT83XX_WUC_BASE+0x10) +#define IT83XX_WUC_WUESR1 (IT83XX_WUC_BASE+0x04) +#define IT83XX_WUC_WUESR6 (IT83XX_WUC_BASE+0x11) + +#define IT83XX_WUC_WUESR10 REG8(IT83XX_WUC_BASE+0x21) +#define IT83XX_WUC_WUESR11 REG8(IT83XX_WUC_BASE+0x25) + +/* --- UART --- */ +#define IT83XX_UART0_BASE 0x00F02700 +#define IT83XX_UART1_BASE 0x00F02800 + +#define IT83XX_UART_BASE(n) CONCAT3(IT83XX_UART, n, _BASE) +#define IT83XX_UART_REG(n, offset) REG8(IT83XX_UART_BASE(n) + (offset)) + +#define IT83XX_UART_DLL(n) IT83XX_UART_REG(n, 0x00) +#define IT83XX_UART_DLM(n) IT83XX_UART_REG(n, 0x01) +#define IT83XX_UART_RBR(n) IT83XX_UART_REG(n, 0x00) +#define IT83XX_UART_THR(n) IT83XX_UART_REG(n, 0x00) +#define IT83XX_UART_IER(n) IT83XX_UART_REG(n, 0x01) +#define IT83XX_UART_IIR(n) IT83XX_UART_REG(n, 0x02) +#define IT83XX_UART_FCR(n) IT83XX_UART_REG(n, 0x02) +#define IT83XX_UART_LCR(n) IT83XX_UART_REG(n, 0x03) +#define IT83XX_UART_MCR(n) IT83XX_UART_REG(n, 0x04) +#define IT83XX_UART_LSR(n) IT83XX_UART_REG(n, 0x05) +#define IT83XX_UART_MSR(n) IT83XX_UART_REG(n, 0x06) +#define IT83XX_UART_SCR(n) IT83XX_UART_REG(n, 0x07) +#define IT83XX_UART_ECSMPR(n) IT83XX_UART_REG(n, 0x08) +#define IT83XX_UART_CSSR(n) IT83XX_UART_REG(n, 0x09) + +/* --- GPIO --- */ + +#define IT83XX_GPIO_BASE 0x00F01600 + +#define IT83XX_GPIO_GPCRF0 REG8(IT83XX_GPIO_BASE+0x38) + +#define IT83XX_GPIO_GRC1 REG8(IT83XX_GPIO_BASE+0xF0) +#define IT83XX_GPIO_GRC2 REG8(IT83XX_GPIO_BASE+0xF1) +#define IT83XX_GPIO_GRC3 REG8(IT83XX_GPIO_BASE+0xF2) +#define IT83XX_GPIO_GRC4 REG8(IT83XX_GPIO_BASE+0xF3) +#define IT83XX_GPIO_GRC5 REG8(IT83XX_GPIO_BASE+0xF4) +#define IT83XX_GPIO_GRC6 REG8(IT83XX_GPIO_BASE+0xF5) +#define IT83XX_GPIO_GRC7 REG8(IT83XX_GPIO_BASE+0xF6) +#define IT83XX_GPIO_GRC8 REG8(IT83XX_GPIO_BASE+0xF7) + +#define IT83XX_GPIO_DATA_BASE (IT83XX_GPIO_BASE + 0x00) +#define IT83XX_GPIO_OUTPUT_TYPE_BASE (IT83XX_GPIO_BASE + 0x70) + + +enum { + GPIO_A = 0x1, + GPIO_B = 0x2, + GPIO_C = 0x3, + GPIO_D = 0x4, + GPIO_E = 0x5, + GPIO_F = 0x6, + GPIO_G = 0x7, + GPIO_H = 0x8, + GPIO_I = 0x9, + GPIO_J = 0xa, + GPIO_M = 0xd, +}; +#define DUMMY_GPIO_BANK GPIO_A + +#define IT83XX_GPIO_DATA(port) REG8(IT83XX_GPIO_DATA_BASE + port) +#define IT83XX_GPIO_GPOT(port) REG8(IT83XX_GPIO_OUTPUT_TYPE_BASE + port) +#define IT83XX_GPIO_CTRL(port_offset, pin_offset) \ + REG8(IT83XX_GPIO_BASE + port_offset + pin_offset) + +/* --- Clock and Power Management (ECPM) --- */ + +#define IT83XX_ECPM_BASE 0x00F01E00 + +#define IT83XX_ECPM_CGCTRL1R_OFF 0x01 +#define IT83XX_ECPM_CGCTRL2R_OFF 0x02 +#define IT83XX_ECPM_CGCTRL3R_OFF 0x05 +#define IT83XX_ECPM_CGCTRL4R_OFF 0x09 + +#define IT83XX_ECPM_PLLCTRL REG8(IT83XX_ECPM_BASE+0x03) +#define IT83XX_ECPM_AUTOCG REG8(IT83XX_ECPM_BASE+0x04) +#define IT83XX_ECPM_PLLFREQR REG8(IT83XX_ECPM_BASE+0x06) +#define IT83XX_ECPM_PLLCSS REG8(IT83XX_ECPM_BASE+0x08) +#define IT83XX_ECPM_SCDCR0 REG8(IT83XX_ECPM_BASE+0x0c) +#define IT83XX_ECPM_SCDCR1 REG8(IT83XX_ECPM_BASE+0x0d) +#define IT83XX_ECPM_SCDCR2 REG8(IT83XX_ECPM_BASE+0x0e) +#define IT83XX_ECPM_SCDCR3 REG8(IT83XX_ECPM_BASE+0x0f) + +/* + * The clock gate offsets combine the register offset from ECPM_BASE and the + * mask within that register into one value. These are used for + * clock_enable_peripheral() and clock_disable_peripheral() + */ +enum clock_gate_offsets { + CGC_OFFSET_EGPC = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x40), + CGC_OFFSET_CIR = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x20), + CGC_OFFSET_SWUC = ((IT83XX_ECPM_CGCTRL2R_OFF << 8) | 0x10), + CGC_OFFSET_USB = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x20), + CGC_OFFSET_PECI = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x08), + CGC_OFFSET_UART = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x04), + CGC_OFFSET_SSPI = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x02), + CGC_OFFSET_DBGR = ((IT83XX_ECPM_CGCTRL3R_OFF << 8) | 0x01), + CGC_OFFSET_SMB = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x02), + CGC_OFFSET_CEC = ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x01) +}; + +/* --- Timer (TMR) --- */ +#define IT83XX_TMR_BASE 0x00F02900 + +#define IT83XX_TMR_PRSC REG8(IT83XX_TMR_BASE+0x00) +#define IT83XX_TMR_GCSMS REG8(IT83XX_TMR_BASE+0x01) +#define IT83XX_TMR_CTR_A0 REG8(IT83XX_TMR_BASE+0x02) +#define IT83XX_TMR_CTR_A1 REG8(IT83XX_TMR_BASE+0x03) +#define IT83XX_TMR_CTR_B0 REG8(IT83XX_TMR_BASE+0x04) +#define IT83XX_TMR_CTR_B1 REG8(IT83XX_TMR_BASE+0x05) +#define IT83XX_TMR_DCR_A0 REG8(IT83XX_TMR_BASE+0x06) +#define IT83XX_TMR_DCR_A1 REG8(IT83XX_TMR_BASE+0x07) +#define IT83XX_TMR_DCR_B0 REG8(IT83XX_TMR_BASE+0x08) +#define IT83XX_TMR_DCR_B1 REG8(IT83XX_TMR_BASE+0x09) +#define IT83XX_TMR_CCGSR REG8(IT83XX_TMR_BASE+0x0A) +#define IT83XX_TMR_TMRCE REG8(IT83XX_TMR_BASE+0x0B) +#define IT83XX_TMR_TMRIE REG8(IT83XX_TMR_BASE+0x0C) + +/* --- External Timer and Watchdog (ETWD) --- */ +#define IT83XX_ETWD_BASE 0x00F01F00 + +#define IT83XX_ETWD_ETWCFG REG8(IT83XX_ETWD_BASE+0x01) +#define IT83XX_ETWD_ET1PSR REG8(IT83XX_ETWD_BASE+0x02) +#define IT83XX_ETWD_ET1CNTLHR REG8(IT83XX_ETWD_BASE+0x03) +#define IT83XX_ETWD_ET1CNTLLR REG8(IT83XX_ETWD_BASE+0x04) +#define IT83XX_ETWD_ETWCTRL REG8(IT83XX_ETWD_BASE+0x05) +#define IT83XX_ETWD_EWDCNTLLR REG8(IT83XX_ETWD_BASE+0x06) +#define IT83XX_ETWD_EWDKEYR REG8(IT83XX_ETWD_BASE+0x07) +#define IT83XX_ETWD_EWDCNTLHR REG8(IT83XX_ETWD_BASE+0x09) +#define IT83XX_ETWD_ET3CTRL REG8(IT83XX_ETWD_BASE+0x10) +#define IT83XX_ETWD_ET3PSR REG8(IT83XX_ETWD_BASE+0x11) +#define IT83XX_ETWD_ET3CNTLLR REG8(IT83XX_ETWD_BASE+0x14) +#define IT83XX_ETWD_ET3CNTLHR REG8(IT83XX_ETWD_BASE+0x15) +#define IT83XX_ETWD_ET3CNTLH2R REG8(IT83XX_ETWD_BASE+0x16) + +/* --- General Control (GCTRL) --- */ +#define IT83XX_GCTRL_BASE 0x00F02000 + +#define IT83XX_GCTRL_WNCKR REG8(IT83XX_GCTRL_BASE+0x0B) + +/* --- MISC (not implemented yet) --- */ + +#define IT83XX_SMFI_BASE 0x00F01000 +#define IT83XX_EC2I_BASE 0x00F01200 +#define IT83XX_KBC_BASE 0x00F01300 +#define IT83XX_SWUC_BASE 0x00F01400 +#define IT83XX_PMC_BASE 0x00F01500 +#define IT83XX_PS2_BASE 0x00F01700 +#define IT83XX_PWM_BASE 0x00F01800 +#define IT83XX_ADC_BASE 0x00F01900 +#define IT83XX_DAC_BASE 0x00F01A00 +#define IT83XX_WUC_BASE 0x00F01B00 +#define IT83XX_SMB_BASE 0x00F01C00 +#define IT83XX_KBS_BASE 0x00F01D00 +#define IT83XX_EGPIO_BASE 0x00F02100 +#define IT83XX_BRAM_BASE 0x00F02200 +#define IT83XX_CIR_BASE 0x00F02300 +#define IT83XX_DBGR_BASE 0x00F02500 +#define IT83XX_SSPI_BASE 0x00F02600 +#define IT83XX_OW_BASE 0x00F02A00 +#define IT83XX_PECI_BASE 0x00F02C00 +#define IT83XX_I2C_BASE 0x00F02D00 +#define IT83XX_CEC_BASE 0x00F02E00 +#define IT83XX_USB_BASE 0x00F02F00 + +#endif /* __CROS_EC_REGISTERS_H */ diff --git a/chip/it83xx/system.c b/chip/it83xx/system.c new file mode 100644 index 0000000000..731b5d64f9 --- /dev/null +++ b/chip/it83xx/system.c @@ -0,0 +1,82 @@ +/* Copyright (c) 2013 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 Chrome EC : hardware specific implementation */ + +#include "console.h" +#include "cpu.h" +#include "flash.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "util.h" +#include "version.h" +#include "watchdog.h" + +void system_hibernate(uint32_t seconds, uint32_t microseconds) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ +} + +void system_pre_init(void) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ +} + +void system_reset(int flags) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ +} + +int system_set_scratchpad(uint32_t value) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + return 0; +} + +uint32_t system_get_scratchpad(void) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + return 0; +} + +const char *system_get_chip_vendor(void) +{ + return "ite"; +} + +const char *system_get_chip_name(void) +{ + return "it83xx"; +} + +const char *system_get_chip_revision(void) +{ + return ""; +} + +int system_get_vbnvcontext(uint8_t *block) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + return EC_SUCCESS; +} + +int system_set_vbnvcontext(const uint8_t *block) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + return EC_SUCCESS; +} + +int system_set_console_force_enabled(int val) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + return 0; +} + +int system_get_console_force_enabled(void) +{ + /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */ + return 0; +} diff --git a/chip/it83xx/uart.c b/chip/it83xx/uart.c new file mode 100644 index 0000000000..80227c34ae --- /dev/null +++ b/chip/it83xx/uart.c @@ -0,0 +1,177 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* UART module for Chrome EC */ + +#include "clock.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "util.h" + +/* Traces on UART0 */ +#define UART_PORT 0 + +static int init_done; + +int uart_init_done(void) +{ + return init_done; +} + +void uart_tx_start(void) +{ + /* If interrupt is already enabled, nothing to do */ + if (IT83XX_UART_IER(UART_PORT) & 0x02) + return; + + /* Do not allow deep sleep while transmit in progress */ + disable_sleep(SLEEP_MASK_UART); + + /* Re-enable the transmit interrupt. */ + IT83XX_UART_IER(UART_PORT) |= 0x02; +} + +void uart_tx_stop(void) +{ + IT83XX_UART_IER(UART_PORT) &= ~0x02; + + /* Re-allow deep sleep */ + enable_sleep(SLEEP_MASK_UART); +} + +void uart_tx_flush(void) +{ + /* + * Wait for transmit FIFO empty (TEMT) and transmitter holder + * register and transmitter shift registers to be empty (THRE). + */ + while ((IT83XX_UART_LSR(UART_PORT) & 0x60) != 0x60) + ; +} + +int uart_tx_ready(void) +{ + /* Transmit is ready when FIFO is empty (THRE). */ + return IT83XX_UART_LSR(UART_PORT) & 0x20; +} + +int uart_tx_in_progress(void) +{ + /* + * Transmit is in progress if transmit holding register or transmitter + * shift register are not empty (TEMT). + */ + return !(IT83XX_UART_LSR(UART_PORT) & 0x40); +} + +int uart_rx_available(void) +{ + return IT83XX_UART_LSR(UART_PORT) & 0x01; +} + +void uart_write_char(char c) +{ + /* Wait for space in transmit FIFO. */ + while (!uart_tx_ready()) + ; + + IT83XX_UART_THR(UART_PORT) = c; +} + +int uart_read_char(void) +{ + return IT83XX_UART_RBR(UART_PORT); +} + +void uart_disable_interrupt(void) +{ + task_disable_irq(IT83XX_IRQ_UART1); +} + +void uart_enable_interrupt(void) +{ + task_enable_irq(IT83XX_IRQ_UART1); +} + +static void uart_ec_interrupt(void) +{ + /* clear interrupt status */ + task_clear_pending_irq(IT83XX_IRQ_UART1); + + /* Read input FIFO until empty, then fill output FIFO */ + uart_process_input(); + uart_process_output(); +} +DECLARE_IRQ(IT83XX_IRQ_UART1, uart_ec_interrupt, 1); + +static void uart_config(void) +{ +#if PLL_CLOCK == 48000000 + /* Set CLK_UART_DIV_SEL to /2. Assumes PLL is 48 MHz. */ + IT83XX_ECPM_SCDCR1 |= 0x01; + + /* + * Specify clock source of the UART is 24MHz, + * must match CLK_UART_DIV_SEL. + */ + IT83XX_UART_CSSR(UART_PORT) = 0x01; +#else +#error "Support only for PLL clock speed of 48MHz." +#endif + + /* 8-N-1 and DLAB set to allow access to DLL and DLM registers. */ + IT83XX_UART_LCR(UART_PORT) = 0x83; + + /* Set divisor to set baud rate to 115200 */ + IT83XX_UART_DLM(UART_PORT) = 0x00; + IT83XX_UART_DLL(UART_PORT) = 0x01; + + /* + * Clear DLAB bit to exclude access to DLL and DLM and give access to + * RBR and THR. + */ + IT83XX_UART_LCR(UART_PORT) = 0x03; + + /* + * Enable TX and RX FIFOs and set RX FIFO interrupt level to the + * minimum 1 byte. + */ + IT83XX_UART_FCR(UART_PORT) = 0x07; + + /* + * set OUT2 bit to enable interrupt logic. + */ + IT83XX_UART_MCR(UART_PORT) = 0x08; +} + +void uart_init(void) +{ + /* Waiting for when we can use the GPIO module to set pin muxing */ + gpio_config_module(MODULE_UART, 1); + + /* switch UART0 on without hardware flow control */ + IT83XX_GPIO_GRC1 = 0x01; + IT83XX_GPIO_GRC6 |= 0x03; + + /* Enable clocks to UART 1 and 2. */ + clock_enable_peripheral(CGC_OFFSET_UART, 0, 0); + + /* Config UART 0 only for now. */ + uart_config(); + + /* clear interrupt status */ + task_clear_pending_irq(IT83XX_IRQ_UART1); + + /* Enable interrupts */ + IT83XX_UART_IER(UART_PORT) = 0x03; + task_enable_irq(IT83XX_IRQ_UART1); + + init_done = 1; +} |