diff --git a/board/it8380dev/board.c b/board/it8380dev/board.c index 4179dfce19..56fe4d4bcc 100644 --- a/board/it8380dev/board.c +++ b/board/it8380dev/board.c @@ -23,6 +23,7 @@ #include "lpc.h" #include "intc.h" #include "fan.h" +#include "i2c.h" /* Test GPIO interrupt function that toggles one LED. */ void test_interrupt(enum gpio_signal signal) @@ -181,6 +182,21 @@ struct keyboard_scan_config keyscan_config = { }, }; +/* + * I2C channels (A, B, and C) are using the same timing registers (00h~07h) + * at default. + * In order to set frequency independently for each channels, + * We use timing registers 09h~0Bh, and the supported frequency will be: + * 50KHz, 100KHz, 400KHz, or 1MHz. + */ +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + {"battery", 2, 100, GPIO_I2C_C_SCL, GPIO_I2C_C_SDA}, + {"evb-1", 0, 100, GPIO_I2C_A_SCL, GPIO_I2C_A_SDA}, + {"evb-2", 1, 100, GPIO_I2C_B_SCL, GPIO_I2C_B_SDA}, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + /*****************************************************************************/ /* Console commands */ diff --git a/board/it8380dev/board.h b/board/it8380dev/board.h index 4e13c58b86..3207cd0d90 100644 --- a/board/it8380dev/board.h +++ b/board/it8380dev/board.h @@ -9,17 +9,18 @@ #define __CROS_EC_BOARD_H /* Optional features */ -#define CONFIG_POWER_BUTTON -#define CONFIG_KEYBOARD_PROTOCOL_8042 -#define CONFIG_KEYBOARD_BOARD_CONFIG -#undef CONFIG_KEYBOARD_KSI_WUC_INT -#undef CONFIG_SPI_USE_CS1 -#define CONFIG_PECI_TJMAX 100 -/* For IT839X series and IT838X DX only. */ -#define CONFIG_PECI_WITH_INTERRUPT -#define CONFIG_FANS 1 #undef CHIP_FAMILY_IT839X +#define CONFIG_FANS 1 +#undef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT +#define CONFIG_IT83XX_PECI_WITH_INTERRUPT +#define CONFIG_IT83XX_SMCLK2_ON_GPC7 +#undef CONFIG_IT83XX_SPI_USE_CS1 +#define CONFIG_KEYBOARD_BOARD_CONFIG +#define CONFIG_KEYBOARD_PROTOCOL_8042 +#define CONFIG_PECI_TJMAX 100 +#define CONFIG_POWER_BUTTON + /* Debug */ #undef CONFIG_KEYBOARD_DEBUG #undef CONFIG_UART_TX_BUF_SIZE diff --git a/board/it8380dev/gpio.inc b/board/it8380dev/gpio.inc index 4a443c67eb..0e4be968ec 100644 --- a/board/it8380dev/gpio.inc +++ b/board/it8380dev/gpio.inc @@ -33,16 +33,35 @@ GPIO(PCH_RCIN_L, PIN(B, 6), GPIO_OUT_HIGH) GPIO(LPC_CLKRUN_L, PIN(H, 0), GPIO_OUT_LOW) GPIO(PCH_WAKE_L, PIN(B, 7), GPIO_ODR_HIGH) /* Wake signal from EC to PCH */ +GPIO(I2C_A_SCL, PIN(B, 3), GPIO_INPUT) +GPIO(I2C_A_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(I2C_B_SCL, PIN(C, 1), GPIO_INPUT) +GPIO(I2C_B_SDA, PIN(C, 2), GPIO_INPUT) +#ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 +GPIO(I2C_C_SCL, PIN(C, 7), GPIO_INPUT) +#else +GPIO(I2C_C_SCL, PIN(F, 6), GPIO_INPUT) +#endif +GPIO(I2C_C_SDA, PIN(F, 7), GPIO_INPUT) + /* Unimplemented signals which we need to emulate for now */ UNIMPLEMENTED(ENTERING_RW) ALTERNATE(PIN_MASK(B, 0x03), 1, MODULE_UART, GPIO_PULL_UP) /* UART0 */ ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_SPI, 0) /* SSCK of SPI */ ALTERNATE(PIN_MASK(C, 0x28), 3, MODULE_SPI, 0) /* SMOSI/SMISO of SPI */ -#ifdef CONFIG_SPI_USE_CS1 +#ifdef CONFIG_IT83XX_SPI_USE_CS1 ALTERNATE(PIN_MASK(G, 0x01), 3, MODULE_SPI, 0) /* SSCE1# of SPI */ #else ALTERNATE(PIN_MASK(G, 0x04), 3, MODULE_SPI, 0) /* SSCE0# of SPI */ #endif ALTERNATE(PIN_MASK(A, 0x80), 1, MODULE_PWM_FAN, 0) /* PWM7 for FAN1 */ ALTERNATE(PIN_MASK(D, 0x40), 3, MODULE_PWM_FAN, 0) /* TACH0A for FAN1 */ +ALTERNATE(PIN_MASK(B, 0x18), 1, MODULE_I2C, 0) /* I2C A SCL/SDA */ +#ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 +ALTERNATE(PIN_MASK(C, 0x86), 1, MODULE_I2C, 0) /* I2C B SCL/SDA, C SCL */ +ALTERNATE(PIN_MASK(F, 0x80), 1, MODULE_I2C, 0) /* I2C C SDA */ +#else +ALTERNATE(PIN_MASK(C, 0x06), 1, MODULE_I2C, 0) /* I2C B SCL/SDA */ +ALTERNATE(PIN_MASK(F, 0xC0), 1, MODULE_I2C, 0) /* I2C C SCL/SDA */ +#endif diff --git a/chip/it83xx/build.mk b/chip/it83xx/build.mk index 280c6c5de8..d8e75f0726 100644 --- a/chip/it83xx/build.mk +++ b/chip/it83xx/build.mk @@ -24,3 +24,4 @@ chip-$(CONFIG_LPC)+=lpc.o chip-$(CONFIG_SPI)+=spi.o chip-$(CONFIG_PECI)+=peci.o chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o +chip-$(CONFIG_I2C)+=i2c.o diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h index 6ec6fbee4c..b38decefdc 100644 --- a/chip/it83xx/config_chip.h +++ b/chip/it83xx/config_chip.h @@ -22,6 +22,9 @@ /* Default PLL frequency. */ #define PLL_CLOCK 48000000 +/* Number of I2C ports */ +#define I2C_PORT_COUNT 3 + /****************************************************************************/ /* Memory mapping */ @@ -76,15 +79,15 @@ #define CONFIG_HW_SPECIFIC_UDELAY /* Optional features present on this chip */ -#undef CONFIG_I2C -#undef CONFIG_FLASH -#undef CONFIG_WATCHDOG -#define CONFIG_PWM #define CONFIG_ADC #define CONFIG_EC2I +#undef CONFIG_FLASH +#define CONFIG_I2C #define CONFIG_LPC -#define CONFIG_SPI #define CONFIG_PECI +#define CONFIG_PWM +#define CONFIG_SPI +#undef CONFIG_WATCHDOG #define GPIO_PIN(port, index) GPIO_##port, (1 << index) #define GPIO_PIN_MASK(port, mask) GPIO_##port, (mask) diff --git a/chip/it83xx/gpio.c b/chip/it83xx/gpio.c index 49c31fb871..24ef6ac78d 100644 --- a/chip/it83xx/gpio.c +++ b/chip/it83xx/gpio.c @@ -360,7 +360,7 @@ static void __gpio_irq(void) /* Determine interrupt number. */ int irq = IT83XX_INTC_IVCT2 - 16; -#if defined(HAS_TASK_KEYSCAN) && defined(CONFIG_KEYBOARD_KSI_WUC_INT) +#if defined(HAS_TASK_KEYSCAN) && defined(CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT) if (irq == IT83XX_IRQ_WKINTC) { keyboard_raw_interrupt(); return; diff --git a/chip/it83xx/i2c.c b/chip/it83xx/i2c.c new file mode 100644 index 0000000000..e76228f428 --- /dev/null +++ b/chip/it83xx/i2c.c @@ -0,0 +1,468 @@ +/* Copyright 2015 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. + */ + +/* I2C module for Chrome EC */ + +#include "clock.h" +#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" + +#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) + +/* + * The count number of the counter for 25 ms register. + * The 25 ms register is calculated by (count number *1.024 kHz). + */ +#define I2C_CLK_LOW_TIMEOUT 25 /* ~= 25ms */ + +#define I2C_LOOP_DELAY_US 16 + +/* Default maximum time we allow for an I2C transfer */ +#define I2C_TIMEOUT_DEFAULT_US (100 * MSEC) + +enum i2c_host_status { + /* Host busy */ + HOSTA_HOBY = 0x01, + /* Finish Interrupt */ + HOSTA_FINTR = 0x02, + /* Device error */ + HOSTA_DVER = 0x04, + /* Bus error */ + HOSTA_BSER = 0x08, + /* Fail */ + HOSTA_FAIL = 0x10, + /* Not response ACK */ + HOSTA_NACK = 0x20, + /* Time-out error */ + HOSTA_TMOE = 0x40, + /* Byte done status */ + HOSTA_BDS = 0x80, + + HOSTA_NO_FINISH = 0xFF, +}; + +enum i2c_host_status_mask { + HOSTA_ANY_ERROR = (HOSTA_DVER | HOSTA_BSER | + HOSTA_FAIL | HOSTA_NACK | HOSTA_TMOE), + HOSTA_NEXT_BYTE = HOSTA_BDS, + HOSTA_ALL_WC_BIT = (HOSTA_FINTR | HOSTA_ANY_ERROR | HOSTA_BDS), +}; + +enum i2c_reset_cause { + I2C_RC_NO_IDLE_FOR_START = 1, + I2C_RC_READ_NO_FINISH, + I2C_RC_WRITE_NO_FINISH, +}; + +struct i2c_ch_freq { + int kpbs; + uint8_t freq_set; +}; + +static const struct i2c_ch_freq i2c_freq_select[] = { + { 50, 1}, + { 100, 2}, + { 400, 3}, + { 1000, 4}, +}; + +struct i2c_pin { + volatile uint8_t *pin_clk; + volatile uint8_t *pin_data; + volatile uint8_t *pin_clk_ctrl; + volatile uint8_t *pin_data_ctrl; + volatile uint8_t *mirror_clk; + volatile uint8_t *mirror_data; + uint8_t clk_mask; + uint8_t data_mask; +}; + +static const struct i2c_pin i2c_pin_regs[] = { + { &IT83XX_GPIO_GPCRB3, &IT83XX_GPIO_GPCRB4, + &IT83XX_GPIO_GPDRB, &IT83XX_GPIO_GPDRB, + &IT83XX_GPIO_GPDMRB, &IT83XX_GPIO_GPDMRB, + 0x08, 0x10}, + { &IT83XX_GPIO_GPCRC1, &IT83XX_GPIO_GPCRC2, + &IT83XX_GPIO_GPDRC, &IT83XX_GPIO_GPDRC, + &IT83XX_GPIO_GPDMRC, &IT83XX_GPIO_GPDMRC, + 0x02, 0x04}, +#ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 + { &IT83XX_GPIO_GPCRC7, &IT83XX_GPIO_GPCRF7, + &IT83XX_GPIO_GPDRC, &IT83XX_GPIO_GPDRF, + &IT83XX_GPIO_GPDMRC, &IT83XX_GPIO_GPDMRF, + 0x80, 0x80}, +#else + { &IT83XX_GPIO_GPCRF6, &IT83XX_GPIO_GPCRF7, + &IT83XX_GPIO_GPDRF, &IT83XX_GPIO_GPDRF, + &IT83XX_GPIO_GPDMRF, &IT83XX_GPIO_GPDMRF, + 0x40, 0x80}, +#endif +}; + +/* I2C port state data */ +struct i2c_port_data { + const uint8_t *out; /* Output data pointer */ + int out_size; /* Output data to transfer, in bytes */ + uint8_t *in; /* Input data pointer */ + int in_size; /* Input data to transfer, in bytes */ + int flags; /* Flags (I2C_XFER_*) */ + int widx; /* Index into output data */ + int ridx; /* Index into input data */ + int err; /* Error code, if any */ + uint8_t addr; /* address of device */ + uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ +}; +static struct i2c_port_data pdata[I2C_PORT_COUNT]; + +static void i2c_reset(int p, int cause) +{ + /* bit1, kill current transaction. */ + IT83XX_SMB_HOCTL(p) |= 0x02; + IT83XX_SMB_HOCTL(p) &= ~0x02; + + /* Disable the SMBus host interface */ + IT83XX_SMB_HOCTL2(p) = 0x00; + + /* clk pin output high */ + *i2c_pin_regs[p].pin_clk = 0x40; + *i2c_pin_regs[p].pin_clk_ctrl |= i2c_pin_regs[p].clk_mask; + + udelay(16); + + /* data pin output high */ + *i2c_pin_regs[p].pin_data = 0x40; + *i2c_pin_regs[p].pin_data_ctrl |= i2c_pin_regs[p].data_mask; + + udelay(500); + /* start condition */ + *i2c_pin_regs[p].pin_data_ctrl &= ~i2c_pin_regs[p].data_mask; + udelay(1000); + /* stop condition */ + *i2c_pin_regs[p].pin_data_ctrl |= i2c_pin_regs[p].data_mask; + udelay(500); + + /* I2C function */ + *i2c_pin_regs[p].pin_clk = 0x00; + *i2c_pin_regs[p].pin_data = 0x00; + + /* Enable the SMBus host interface */ + IT83XX_SMB_HOCTL2(p) = 0x11; + + /* W/C host status register */ + IT83XX_SMB_HOSTA(p) = HOSTA_ALL_WC_BIT; + + CPRINTS("I2C ch%d reset cause %d", p, cause); +} + +static void i2c_r_last_byte(int p) +{ + struct i2c_port_data *pd = pdata + p; + + /* + * bit5, The firmware shall write 1 to this bit + * when the next byte will be the last byte for i2c read. + */ + if ((pd->flags & I2C_XFER_STOP) && (pd->ridx == pd->in_size - 1)) + IT83XX_SMB_HOCTL(p) |= 0x20; +} + +static void i2c_w2r_change_direction(int p) +{ + /* I2C switch direction */ + if (IT83XX_SMB_HOCTL2(p) & 0x08) { + i2c_r_last_byte(p); + IT83XX_SMB_HOSTA(p) = HOSTA_NEXT_BYTE; + } else { + /* + * bit2, I2C switch direction wait. + * bit3, I2C switch direction enable. + */ + IT83XX_SMB_HOCTL2(p) |= 0x0C; + IT83XX_SMB_HOSTA(p) = HOSTA_NEXT_BYTE; + i2c_r_last_byte(p); + IT83XX_SMB_HOCTL2(p) &= ~0x04; + } +} + +static int i2c_transaction(int p) +{ + uint32_t num; + struct i2c_port_data *pd = pdata + p; + + /* i2c write */ + if (pd->out_size) { + if (pd->flags & I2C_XFER_START) { + /* i2c enable */ + IT83XX_SMB_HOCTL2(p) = 0x13; + /* + * bit0, Direction of the host transfer. + * bit[1:7}, Address of the targeted slave. + */ + IT83XX_SMB_TRASLA(p) = pd->addr; + /* Send first byte */ + IT83XX_SMB_HOBDB(p) = *(pd->out++); + pd->widx++; + /* + * bit0, Host interrupt enable. + * bit[2:4}, Extend command. + * bit6, start. + */ + IT83XX_SMB_HOCTL(p) = 0x5D; + } + + for (num = 0; num < pd->timeout_us; num += I2C_LOOP_DELAY_US) { + /* Host has completed the transmission of a byte */ + if (IT83XX_SMB_HOSTA(p) & HOSTA_BDS) { + if (pd->widx < pd->out_size) { + /* Send next byte */ + IT83XX_SMB_HOBDB(p) = *(pd->out++); + pd->widx++; + } else { + if (pd->in_size > 0) { + i2c_w2r_change_direction(p); + goto write_to_read; + } + + if (pd->flags & I2C_XFER_STOP) + IT83XX_SMB_HOCTL2(p) = 0x11; + else + break; + } + /* W/C byte done for next byte or finish */ + IT83XX_SMB_HOSTA(p) = HOSTA_NEXT_BYTE; + /* This bit will be set by termination of a command */ + } else if (IT83XX_SMB_HOSTA(p) & HOSTA_FINTR) { + break; + } + /* - 1 since some time was used in the code above */ + udelay(I2C_LOOP_DELAY_US - 1); + } + + pd->err = IT83XX_SMB_HOSTA(p) & HOSTA_ANY_ERROR; + + if (num > pd->timeout_us) { + pd->err = HOSTA_NO_FINISH; + i2c_reset(p, I2C_RC_WRITE_NO_FINISH); + } + + if (pd->flags & I2C_XFER_STOP) { + IT83XX_SMB_HOCTL2(p) = 0x00; + /* W/C */ + IT83XX_SMB_HOSTA(p) = HOSTA_ALL_WC_BIT; + } + return pd->err; + /* i2c read */ + } else if (pd->in_size) { + if (pd->flags & I2C_XFER_START) { + /* i2c enable */ + IT83XX_SMB_HOCTL2(p) = 0x13; + /* + * bit0, Direction of the host transfer. + * bit[1:7}, Address of the targeted slave. + */ + IT83XX_SMB_TRASLA(p) = pd->addr | 0x01; + /* + * bit0, Host interrupt enable. + * bit[2:4}, Extend command. + * bit5, The firmware shall write 1 to this bit + * when the next byte will be the last byte. + * bit6, start. + */ + if ((1 == pd->in_size) && (pd->flags & I2C_XFER_STOP)) + IT83XX_SMB_HOCTL(p) = 0x7D; + else + IT83XX_SMB_HOCTL(p) = 0x5D; + } else { + i2c_w2r_change_direction(p); + } + +write_to_read: + for (num = 0; num < pd->timeout_us; num += I2C_LOOP_DELAY_US) { + /* when the host controller has received a byte */ + if (IT83XX_SMB_HOSTA(p) & HOSTA_BDS) { + if (pd->ridx < pd->in_size) { + /* To get received data. */ + *(pd->in++) = IT83XX_SMB_HOBDB(p); + pd->ridx++; + /* For last byte */ + i2c_r_last_byte(p); + } + + if ((pd->ridx == pd->in_size) && + (!(pd->flags & I2C_XFER_STOP))) + break; + + /* W/C for next byte or finish */ + IT83XX_SMB_HOSTA(p) = HOSTA_NEXT_BYTE; + /* This bit will be set by termination of a command */ + } else if (IT83XX_SMB_HOSTA(p) & HOSTA_FINTR) { + break; + } + + /* - 1 since some time was used in the code above */ + udelay(I2C_LOOP_DELAY_US - 1); + } + + pd->err = IT83XX_SMB_HOSTA(p) & HOSTA_ANY_ERROR; + + if (num > pd->timeout_us) { + pd->err = HOSTA_NO_FINISH; + i2c_reset(p, I2C_RC_READ_NO_FINISH); + } + + if (pd->flags & I2C_XFER_STOP) { + IT83XX_SMB_HOCTL2(p) = 0x00; + /* W/C */ + IT83XX_SMB_HOSTA(p) = HOSTA_ALL_WC_BIT; + } + return pd->err; + } + return 0; +} + +int i2c_is_busy(int port) +{ + return IT83XX_SMB_HOSTA(port) & HOSTA_HOBY; +} + +int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, + uint8_t *in, int in_size, int flags) +{ + struct i2c_port_data *pd = pdata + port; + + if (out_size == 0 && in_size == 0) + return EC_SUCCESS; + + /* Copy data to port struct */ + pd->out = out; + pd->out_size = out_size; + pd->in = in; + pd->in_size = in_size; + pd->flags = flags; + pd->widx = 0; + pd->ridx = 0; + pd->err = 0; + pd->addr = slave_addr; + + /* Make sure we're in a good state to start */ + if ((flags & I2C_XFER_START) && (i2c_is_busy(port) + || (IT83XX_SMB_HOSTA(port) & HOSTA_ALL_WC_BIT) + || (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { + /* Attempt to unwedge the port. */ + i2c_unwedge(port); + /* reset i2c port */ + i2c_reset(port, I2C_RC_NO_IDLE_FOR_START); + } + /* Start transaction */ + i2c_transaction(port); + + return pd->err; +} + +int i2c_raw_get_scl(int port) +{ + enum gpio_signal g; + + if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) + return !!(*i2c_pin_regs[port].mirror_clk & + i2c_pin_regs[port].clk_mask); + + /* 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 g; + + if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) + return !!(*i2c_pin_regs[port].mirror_data & + i2c_pin_regs[port].data_mask); + + /* If no SDA pin defined for this port, then return 1 to appear idle */ + return 1; +} + +int i2c_get_line_levels(int port) +{ + return IT83XX_SMB_SMBPCTL(port) & 0x03; +} + +void i2c_set_timeout(int port, uint32_t timeout) +{ + pdata[port].timeout_us = timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; +} + +static void i2c_freq_changed(void) +{ + int i, f; + + for (i = 0; i < i2c_ports_used; i++) { + for (f = ARRAY_SIZE(i2c_freq_select) - 1; f >= 0; f--) { + if (i2c_ports[i].kbps >= i2c_freq_select[f].kpbs) { + IT83XX_SMB_SCLKTS(i2c_ports[i].port) = + i2c_freq_select[f].freq_set; + break; + } + } + } + + /* This field defines the SMCLK0/1/2 clock/data low timeout. */ + IT83XX_SMB_25MS = I2C_CLK_LOW_TIMEOUT; +} +DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_changed, HOOK_PRIO_DEFAULT); + +static void i2c_init(void) +{ + int i, p; + + /* Configure GPIOs */ + gpio_config_module(MODULE_I2C, 1); + +#ifdef CONFIG_IT83XX_SMCLK2_ON_GPC7 + /* bit7, 0: SMCLK2 is located on GPF6, 1: SMCLK2 is located on GPC7 */ + IT83XX_GPIO_GRC7 |= 0x80; +#endif + + /* Enable I2C function. */ + for (i = 0; i < i2c_ports_used; i++) { + /* I2c port mapping. */ + p = i2c_ports[i].port; + /* + * bit0, The SMBus host interface is enabled. + * bit1, Enable to communicate with I2C device and + * support I2C-compatible cycles. + * bit4, This bit controls the reset mechanism of SMBus master + * to handle the SMDAT line low if 25ms reg timeout. + */ + IT83XX_SMB_HOCTL2(p) = 0x11; + /* + * bit1, Kill SMBus host transaction. + * bit0, Enable the interrupt for the master interface. + */ + IT83XX_SMB_HOCTL(p) = 0x03; + IT83XX_SMB_HOCTL(p) = 0x01; + /* W/C host status register */ + IT83XX_SMB_HOSTA(p) = HOSTA_ALL_WC_BIT; + + IT83XX_SMB_HOCTL2(p) = 0x00; + } + + i2c_freq_changed(); + + for (i = 0; i < I2C_PORT_COUNT; i++) { + + /* Use default timeout */ + i2c_set_timeout(i, 0); + } +} +DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C); diff --git a/chip/it83xx/intc.c b/chip/it83xx/intc.c index b4f42b0ab4..ebccb043d1 100644 --- a/chip/it83xx/intc.c +++ b/chip/it83xx/intc.c @@ -24,7 +24,7 @@ void intc_cpu_int_group_5(void) lpc_kbc_ibf_interrupt(); break; #endif -#if defined(HAS_TASK_KEYSCAN) && !defined(CONFIG_KEYBOARD_KSI_WUC_INT) +#if defined(HAS_TASK_KEYSCAN) && !defined(CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT) case IT83XX_IRQ_KB_MATRIX: keyboard_raw_interrupt(); break; diff --git a/chip/it83xx/keyboard_raw.c b/chip/it83xx/keyboard_raw.c index 48749008d2..ddaa4974e2 100644 --- a/chip/it83xx/keyboard_raw.c +++ b/chip/it83xx/keyboard_raw.c @@ -35,7 +35,7 @@ void keyboard_raw_init(void) /* KSO[15:8] pins low. */ IT83XX_KBS_KSOH1 = 0x00; -#ifdef CONFIG_KEYBOARD_KSI_WUC_INT +#ifdef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT /* KSI[0-7] falling-edge triggered is selected */ IT83XX_WUC_WUEMR3 = 0xFF; @@ -58,7 +58,7 @@ void keyboard_raw_init(void) */ void keyboard_raw_task_start(void) { -#ifdef CONFIG_KEYBOARD_KSI_WUC_INT +#ifdef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT IT83XX_WUC_WUESR3 = 0xFF; task_clear_pending_irq(IT83XX_IRQ_WKINTC); task_enable_irq(IT83XX_IRQ_WKINTC); @@ -105,7 +105,7 @@ test_mockable int keyboard_raw_read_rows(void) void keyboard_raw_enable_interrupt(int enable) { if (enable) { -#ifdef CONFIG_KEYBOARD_KSI_WUC_INT +#ifdef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT IT83XX_WUC_WUESR3 = 0xFF; task_clear_pending_irq(IT83XX_IRQ_WKINTC); task_enable_irq(IT83XX_IRQ_WKINTC); @@ -114,7 +114,7 @@ void keyboard_raw_enable_interrupt(int enable) task_enable_irq(IT83XX_IRQ_KB_MATRIX); #endif } else { -#ifdef CONFIG_KEYBOARD_KSI_WUC_INT +#ifdef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT task_disable_irq(IT83XX_IRQ_WKINTC); #else task_disable_irq(IT83XX_IRQ_KB_MATRIX); @@ -127,7 +127,7 @@ void keyboard_raw_enable_interrupt(int enable) */ void keyboard_raw_interrupt(void) { -#ifdef CONFIG_KEYBOARD_KSI_WUC_INT +#ifdef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT task_disable_irq(IT83XX_IRQ_WKINTC); #else task_disable_irq(IT83XX_IRQ_KB_MATRIX); diff --git a/chip/it83xx/peci.c b/chip/it83xx/peci.c index b613fa7971..1f167b3f43 100644 --- a/chip/it83xx/peci.c +++ b/chip/it83xx/peci.c @@ -182,7 +182,7 @@ static enum peci_status peci_transaction(uint8_t addr, IT83XX_PECI_HOWRDR = w_buf[index]; peci_current_task = task_get_current(); -#ifdef CONFIG_PECI_WITH_INTERRUPT +#ifdef CONFIG_IT83XX_PECI_WITH_INTERRUPT task_clear_pending_irq(IT83XX_IRQ_PECI); task_enable_irq(IT83XX_IRQ_PECI); diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h index bc7ddeee44..47113ecd12 100644 --- a/chip/it83xx/registers.h +++ b/chip/it83xx/registers.h @@ -461,6 +461,10 @@ #define IT83XX_GPIO_GCR REG8(IT83XX_GPIO_BASE+0x00) +#define IT83XX_GPIO_GPDRB REG8(IT83XX_GPIO_BASE+0x02) +#define IT83XX_GPIO_GPDRC REG8(IT83XX_GPIO_BASE+0x03) +#define IT83XX_GPIO_GPDRF REG8(IT83XX_GPIO_BASE+0x06) + #define IT83XX_GPIO_GPCRA0 REG8(IT83XX_GPIO_BASE+0x10) #define IT83XX_GPIO_GPCRA1 REG8(IT83XX_GPIO_BASE+0x11) #define IT83XX_GPIO_GPCRA2 REG8(IT83XX_GPIO_BASE+0x12) @@ -470,6 +474,33 @@ #define IT83XX_GPIO_GPCRA6 REG8(IT83XX_GPIO_BASE+0x16) #define IT83XX_GPIO_GPCRA7 REG8(IT83XX_GPIO_BASE+0x17) +#define IT83XX_GPIO_GPCRB0 REG8(IT83XX_GPIO_BASE+0x18) +#define IT83XX_GPIO_GPCRB1 REG8(IT83XX_GPIO_BASE+0x19) +#define IT83XX_GPIO_GPCRB2 REG8(IT83XX_GPIO_BASE+0x1A) +#define IT83XX_GPIO_GPCRB3 REG8(IT83XX_GPIO_BASE+0x1B) +#define IT83XX_GPIO_GPCRB4 REG8(IT83XX_GPIO_BASE+0x1C) +#define IT83XX_GPIO_GPCRB5 REG8(IT83XX_GPIO_BASE+0x1D) +#define IT83XX_GPIO_GPCRB6 REG8(IT83XX_GPIO_BASE+0x1E) +#define IT83XX_GPIO_GPCRB7 REG8(IT83XX_GPIO_BASE+0x1F) + +#define IT83XX_GPIO_GPCRC0 REG8(IT83XX_GPIO_BASE+0x20) +#define IT83XX_GPIO_GPCRC1 REG8(IT83XX_GPIO_BASE+0x21) +#define IT83XX_GPIO_GPCRC2 REG8(IT83XX_GPIO_BASE+0x22) +#define IT83XX_GPIO_GPCRC3 REG8(IT83XX_GPIO_BASE+0x23) +#define IT83XX_GPIO_GPCRC4 REG8(IT83XX_GPIO_BASE+0x24) +#define IT83XX_GPIO_GPCRC5 REG8(IT83XX_GPIO_BASE+0x25) +#define IT83XX_GPIO_GPCRC6 REG8(IT83XX_GPIO_BASE+0x26) +#define IT83XX_GPIO_GPCRC7 REG8(IT83XX_GPIO_BASE+0x27) + +#define IT83XX_GPIO_GPCRF0 REG8(IT83XX_GPIO_BASE+0x38) +#define IT83XX_GPIO_GPCRF1 REG8(IT83XX_GPIO_BASE+0x39) +#define IT83XX_GPIO_GPCRF2 REG8(IT83XX_GPIO_BASE+0x3A) +#define IT83XX_GPIO_GPCRF3 REG8(IT83XX_GPIO_BASE+0x3B) +#define IT83XX_GPIO_GPCRF4 REG8(IT83XX_GPIO_BASE+0x3C) +#define IT83XX_GPIO_GPCRF5 REG8(IT83XX_GPIO_BASE+0x3D) +#define IT83XX_GPIO_GPCRF6 REG8(IT83XX_GPIO_BASE+0x3E) +#define IT83XX_GPIO_GPCRF7 REG8(IT83XX_GPIO_BASE+0x3F) + #define IT83XX_GPIO_GPCRF0 REG8(IT83XX_GPIO_BASE+0x38) #define IT83XX_GPIO_GPCRF1 REG8(IT83XX_GPIO_BASE+0x39) #define IT83XX_GPIO_GPCRF2 REG8(IT83XX_GPIO_BASE+0x3A) @@ -488,6 +519,10 @@ #define IT83XX_GPIO_GPCRI6 REG8(IT83XX_GPIO_BASE+0x56) #define IT83XX_GPIO_GPCRI7 REG8(IT83XX_GPIO_BASE+0x57) +#define IT83XX_GPIO_GPDMRB REG8(IT83XX_GPIO_BASE+0x62) +#define IT83XX_GPIO_GPDMRC REG8(IT83XX_GPIO_BASE+0x63) +#define IT83XX_GPIO_GPDMRF REG8(IT83XX_GPIO_BASE+0x66) + #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) @@ -856,12 +891,34 @@ REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 3 : 6) + (ch << 4)) #define IT83XX_PECI_AWFCSV REG8(IT83XX_PECI_BASE+0x0D) #define IT83XX_PECI_PADCTLR REG8(IT83XX_PECI_BASE+0x0E) +/* SMBus/I2C Interface (SMB/I2C) */ +#define IT83XX_SMB_BASE 0x00F01C00 + +#define IT83XX_SMB_4P7USL REG8(IT83XX_SMB_BASE+0x00) +#define IT83XX_SMB_4P0USL REG8(IT83XX_SMB_BASE+0x01) +#define IT83XX_SMB_300NS REG8(IT83XX_SMB_BASE+0x02) +#define IT83XX_SMB_250NS REG8(IT83XX_SMB_BASE+0x03) +#define IT83XX_SMB_25MS REG8(IT83XX_SMB_BASE+0x04) +#define IT83XX_SMB_45P3USL REG8(IT83XX_SMB_BASE+0x05) +#define IT83XX_SMB_45P3USH REG8(IT83XX_SMB_BASE+0x06) +#define IT83XX_SMB_4P7A4P0H REG8(IT83XX_SMB_BASE+0x07) +#define IT83XX_SMB_SCLKTS(ch) REG8(IT83XX_SMB_BASE+0x09+ch) +#define IT83XX_SMB_HOSTA(ch) REG8(IT83XX_SMB_BASE+0x40+(ch << 6)) +#define IT83XX_SMB_HOCTL(ch) REG8(IT83XX_SMB_BASE+0x41+(ch << 6)) +#define IT83XX_SMB_HOCMD(ch) REG8(IT83XX_SMB_BASE+0x42+(ch << 6)) +#define IT83XX_SMB_TRASLA(ch) REG8(IT83XX_SMB_BASE+0x43+(ch << 6)) +#define IT83XX_SMB_D0REG(ch) REG8(IT83XX_SMB_BASE+0x44+(ch << 6)) +#define IT83XX_SMB_D1REG(ch) REG8(IT83XX_SMB_BASE+0x45+(ch << 6)) +#define IT83XX_SMB_HOBDB(ch) REG8(IT83XX_SMB_BASE+0x46+(ch << 6)) +#define IT83XX_SMB_PECERC(ch) REG8(IT83XX_SMB_BASE+0x47+(ch << 6)) +#define IT83XX_SMB_SMBPCTL(ch) REG8(IT83XX_SMB_BASE+0x4A+(ch << 6)) +#define IT83XX_SMB_HOCTL2(ch) REG8(IT83XX_SMB_BASE+0x50+(ch << 6)) + /* --- MISC (not implemented yet) --- */ #define IT83XX_PS2_BASE 0x00F01700 #define IT83XX_DAC_BASE 0x00F01A00 #define IT83XX_WUC_BASE 0x00F01B00 -#define IT83XX_SMB_BASE 0x00F01C00 #define IT83XX_EGPIO_BASE 0x00F02100 #define IT83XX_BRAM_BASE 0x00F02200 #define IT83XX_CIR_BASE 0x00F02300 diff --git a/chip/it83xx/spi.c b/chip/it83xx/spi.c index 503e4a8d41..12955c80e3 100644 --- a/chip/it83xx/spi.c +++ b/chip/it83xx/spi.c @@ -82,7 +82,7 @@ int spi_enable(int enable) * 01b: SSCK/SMOSI/SMISO/SSCE0# are enabled. * 11b: SSCK/SMOSI/SMISO/SSCE1#/SSCE0# are enabled. */ -#ifdef CONFIG_SPI_USE_CS1 +#ifdef CONFIG_IT83XX_SPI_USE_CS1 IT83XX_GPIO_GRC1 |= 0x20; #else IT83XX_GPIO_GRC1 |= 0x10; @@ -105,7 +105,7 @@ int spi_transaction(const uint8_t *txdata, int txlen, IT83XX_SSPI_SPICTRL2 &= ~0x04; for (idx = 0x00; idx < txlen; idx++) { IT83XX_SSPI_SPIDATA = txdata[idx]; -#ifdef CONFIG_SPI_USE_CS1 +#ifdef CONFIG_IT83XX_SPI_USE_CS1 /* Write 1 to start the data transmission of CS1 */ IT83XX_SSPI_SPISTS |= 0x08; #else @@ -117,7 +117,7 @@ int spi_transaction(const uint8_t *txdata, int txlen, /* bit[1]: Read cycle */ IT83XX_SSPI_SPICTRL2 |= 0x04; for (idx = 0x00; idx < rxlen; idx++) { -#ifdef CONFIG_SPI_USE_CS1 +#ifdef CONFIG_IT83XX_SPI_USE_CS1 /* Write 1 to start the data transmission of CS1 */ IT83XX_SSPI_SPISTS |= 0x08; #else diff --git a/include/config.h b/include/config.h index be4d59127c..f7af2ba28b 100644 --- a/include/config.h +++ b/include/config.h @@ -935,6 +935,18 @@ /* Number of IRQs supported on the EC chip */ #undef CONFIG_IRQ_COUNT +/* Enable Wake-up control interrupt from KSI */ +#undef CONFIG_IT83XX_KEYBOARD_KSI_WUC_INT + +/* Interrupt for PECI module. (IT839X series and IT838X DX only) */ +#undef CONFIG_IT83XX_PECI_WITH_INTERRUPT + +/* To define it, if I2C channel C and PECI used at the same time. */ +#undef CONFIG_IT83XX_SMCLK2_ON_GPC7 + +/* Use SSPI Chip Enable 1. */ +#undef CONFIG_IT83XX_SPI_USE_CS1 + /*****************************************************************************/ /* Keyboard config */ @@ -955,9 +967,6 @@ /* Enable extra debugging output from keyboard modules */ #undef CONFIG_KEYBOARD_DEBUG -/* Enable Wake-up control interrupt from KSI */ -#undef CONFIG_KEYBOARD_KSI_WUC_INT - /* The board uses a negative edge-triggered GPIO for keyboard interrupts. */ #undef CONFIG_KEYBOARD_IRQ_GPIO @@ -1287,9 +1296,6 @@ /* SPI module port. */ #undef CONFIG_SPI_PORT -/* Use SSPI Chip Enable 1. */ -#undef CONFIG_SPI_USE_CS1 - /* Support testing SPI slave controller driver. */ #undef CONFIG_SPS_TEST