diff options
-rw-r--r-- | board/it8380dev/board.c | 26 | ||||
-rw-r--r-- | board/it8380dev/board.h | 15 | ||||
-rw-r--r-- | chip/it83xx/build.mk | 1 | ||||
-rw-r--r-- | chip/it83xx/config_chip.h | 1 | ||||
-rw-r--r-- | chip/it83xx/ec2i.c | 157 | ||||
-rw-r--r-- | chip/it83xx/ec2i_chip.h | 126 | ||||
-rw-r--r-- | chip/it83xx/registers.h | 16 |
7 files changed, 340 insertions, 2 deletions
diff --git a/board/it8380dev/board.c b/board/it8380dev/board.c index 201a6c20c0..c18aa58d41 100644 --- a/board/it8380dev/board.c +++ b/board/it8380dev/board.c @@ -15,6 +15,7 @@ #include "pwm_chip.h" #include "adc.h" #include "adc_chip.h" +#include "ec2i_chip.h" /* Test GPIO interrupt function that toggles one LED. */ void test_interrupt(enum gpio_signal signal) @@ -42,6 +43,31 @@ const struct pwm_t pwm_channels[] = { BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); +/* PNPCFG settings */ +const struct ec2i_t pnpcfg_settings[] = { + /* Select logical device 06h(keyboard) */ + {HOST_INDEX_LDN, LDN_KBC_KEYBOARD}, + /* Set IRQ=01h for logical device */ + {HOST_INDEX_IRQNUMX, 0x01}, + /* Enable logical device */ + {HOST_INDEX_LDA, 0x01}, + + /* Select logical device 05h(mouse) */ + {HOST_INDEX_LDN, LDN_KBC_MOUSE}, + /* Set IRQ=0Ch for logical device */ + {HOST_INDEX_IRQNUMX, 0x0C}, + /* Enable logical device */ + {HOST_INDEX_LDA, 0x01}, + + /* Select logical device 11h(PM1 ACPI) */ + {HOST_INDEX_LDN, LDN_PMC1}, + /* Set IRQ=00h for logical device */ + {HOST_INDEX_IRQNUMX, 0x00}, + /* Enable logical device */ + {HOST_INDEX_LDA, 0x01}, +}; +BUILD_ASSERT(ARRAY_SIZE(pnpcfg_settings) == EC2I_SETTING_COUNT); + /* Initialize board. */ static void board_init(void) { diff --git a/board/it8380dev/board.h b/board/it8380dev/board.h index afadc3c40b..a1852d46a6 100644 --- a/board/it8380dev/board.h +++ b/board/it8380dev/board.h @@ -43,5 +43,20 @@ enum adc_channel { ADC_CH_COUNT }; +enum ec2i_setting { + EC2I_SET_KB_LDN, + EC2I_SET_KB_IRQ, + EC2I_SET_KB_ENABLE, + EC2I_SET_MOUSE_LDN, + EC2I_SET_MOUSE_IRQ, + EC2I_SET_MOUSE_ENABLE, + EC2I_SET_PMC1_LDN, + EC2I_SET_PMC1_IRQ, + EC2I_SET_PMC1_ENABLE, + + /* Number of EC2I settings */ + EC2I_SETTING_COUNT +}; + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/chip/it83xx/build.mk b/chip/it83xx/build.mk index 6029ee4b30..615e7832f9 100644 --- a/chip/it83xx/build.mk +++ b/chip/it83xx/build.mk @@ -16,3 +16,4 @@ chip-y=hwtimer.o uart.o gpio.o system.o jtag.o clock.o irq.o chip-$(CONFIG_WATCHDOG)+=watchdog.o chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_ADC)+=adc.o +chip-$(CONFIG_EC2I)+=ec2i.o diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h index 6032ce5e83..55e41763b4 100644 --- a/chip/it83xx/config_chip.h +++ b/chip/it83xx/config_chip.h @@ -105,5 +105,6 @@ #undef CONFIG_WATCHDOG #define CONFIG_PWM #define CONFIG_ADC +#define CONFIG_EC2I #endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/chip/it83xx/ec2i.c b/chip/it83xx/ec2i.c new file mode 100644 index 0000000000..210aad7d25 --- /dev/null +++ b/chip/it83xx/ec2i.c @@ -0,0 +1,157 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* EC2I control module for IT83xx. */ + +#include "hooks.h" +#include "ec2i_chip.h" +#include "registers.h" +#include "timer.h" + +#define EC2I_ACCESS_TIME_USEC 15 + +static int ec2i_check_status_bit(uint8_t status_bit) +{ + int num; + + for (num = 0; num < 10; num++) { + udelay(EC2I_ACCESS_TIME_USEC); + + if (!(IT83XX_EC2I_IBCTL & status_bit)) + return 0; + } + + /* Timeout */ + return -1; +} + +static void ec2i_ec_access_enable(void) +{ + /* + * bit0: Host access to the PNPCFG registers is disabled. + * bit1: Host access to the BRAM registers is disabled. + */ + IT83XX_EC2I_LSIOHA |= 0x03; + + /* bit0: EC to I-Bus access enabled. */ + IT83XX_EC2I_IBCTL |= 0x01; + + /* + * Make sure that both CRIB and CWIB bits in IBCTL register + * are cleared. + * bit1: CRIB + * bit2: CWIB + */ + if (ec2i_check_status_bit(0x06)) + IT83XX_EC2I_IBCTL &= ~0x02; + + /* Enable EC access to the PNPCFG registers */ + IT83XX_EC2I_IBMAE |= 0x01; +} + +static void ec2i_ec_access_disable(void) +{ + /* Disable EC access to the PNPCFG registers. */ + IT83XX_EC2I_IBMAE &= ~0x01; + + /* Diable EC to I-Bus access. */ + IT83XX_EC2I_IBCTL &= ~0x01; + + /* Enable host access */ + IT83XX_EC2I_LSIOHA &= ~0x03; +} + +/* EC2I write */ +enum ec2i_message ec2i_write(enum host_pnpcfg_index index, uint8_t data) +{ + /* bit1 : VCC power on */ + if (IT83XX_SWUC_SWCTL1 & 0x02) { + /* Enable EC2I EC access */ + ec2i_ec_access_enable(); + + /* Set indirect host I/O offset. (index port) */ + IT83XX_EC2I_IHIOA = 0; + IT83XX_EC2I_IHD = index; + + /* Read the CWIB bit in IBCTL until it returns 0. */ + if (ec2i_check_status_bit(0x04)) { + ec2i_ec_access_disable(); + return EC2I_WRITE_ERROR; + } + + /* Set indirect host I/O offset. (data port) */ + IT83XX_EC2I_IHIOA = 1; + IT83XX_EC2I_IHD = data; + + /* Read the CWIB bit in IBCTL until it returns 0. */ + if (ec2i_check_status_bit(0x04)) { + ec2i_ec_access_disable(); + return EC2I_WRITE_ERROR; + } + + /* Disable EC2I EC access */ + ec2i_ec_access_disable(); + + return EC2I_WRITE_SUCCESS; + } else { + return EC2I_WRITE_ERROR; + } +} + +/* EC2I read */ +enum ec2i_message ec2i_read(enum host_pnpcfg_index index) +{ + uint8_t data; + + /* bit1 : VCC power on */ + if (IT83XX_SWUC_SWCTL1 & 0x02) { + /* Enable EC2I EC access */ + ec2i_ec_access_enable(); + + /* Set indirect host I/O offset. (index port) */ + IT83XX_EC2I_IHIOA = 0; + IT83XX_EC2I_IHD = index; + + /* Read the CWIB bit in IBCTL until it returns 0. */ + if (ec2i_check_status_bit(0x04)) { + ec2i_ec_access_disable(); + return EC2I_READ_ERROR; + } + + /* Set indirect host I/O offset. (data port) */ + IT83XX_EC2I_IHIOA = 1; + + /* This access is a read-action */ + IT83XX_EC2I_IBCTL |= 0x02; + + /* Read the CRIB bit in IBCTL until it returns 0. */ + if (ec2i_check_status_bit(0x02)) { + ec2i_ec_access_disable(); + return EC2I_READ_ERROR; + } + + /* Read the data from IHD register */ + data = IT83XX_EC2I_IHD; + + /* Disable EC2I EC access */ + ec2i_ec_access_disable(); + + return EC2I_READ_SUCCESS + data; + } else { + return EC2I_READ_ERROR; + } +} + +static void pnpcfg_init(void) +{ + int table; + + for (table = 0x00; table < EC2I_SETTING_COUNT; table++) { + if (ec2i_write(pnpcfg_settings[table].index_port, + pnpcfg_settings[table].data_port) == EC2I_WRITE_ERROR) + break; + } +} +DECLARE_HOOK(HOOK_INIT, pnpcfg_init, HOOK_PRIO_DEFAULT); diff --git a/chip/it83xx/ec2i_chip.h b/chip/it83xx/ec2i_chip.h new file mode 100644 index 0000000000..d584973ef7 --- /dev/null +++ b/chip/it83xx/ec2i_chip.h @@ -0,0 +1,126 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* EC2I control module for IT83xx. */ + +#ifndef __CROS_EC_IT83XX_EC2I_H +#define __CROS_EC_IT83XX_EC2I_H + +/* Index list of the host interface registers of PNPCFG */ +enum host_pnpcfg_index { + /* Logical Device Number */ + HOST_INDEX_LDN = 0x07, + /* Chip ID Byte 1 */ + HOST_INDEX_CHIPID1 = 0x20, + /* Chip ID Byte 2 */ + HOST_INDEX_CHIPID2 = 0x21, + /* Chip Version */ + HOST_INDEX_CHIPVER = 0x22, + /* Super I/O Control */ + HOST_INDEX_SIOCTRL = 0x23, + /* Super I/O IRQ Configuration */ + HOST_INDEX_SIOIRQ = 0x25, + /* Super I/O General Purpose */ + HOST_INDEX_SIOGP = 0x26, + /* Super I/O Power Mode */ + HOST_INDEX_SIOPWR = 0x2D, + /* Depth 2 I/O Address */ + HOST_INDEX_D2ADR = 0x2E, + /* Depth 2 I/O Data */ + HOST_INDEX_D2DAT = 0x2F, + /* Logical Device Activate Register */ + HOST_INDEX_LDA = 0x30, + /* I/O Port Base Address Bits [15:8] for Descriptor 0 */ + HOST_INDEX_IOBAD0_MSB = 0x60, + /* I/O Port Base Address Bits [7:0] for Descriptor 0 */ + HOST_INDEX_IOBAD0_LSB = 0x61, + /* I/O Port Base Address Bits [15:8] for Descriptor 1 */ + HOST_INDEX_IOBAD1_MSB = 0x62, + /* I/O Port Base Address Bits [7:0] for Descriptor 1 */ + HOST_INDEX_IOBAD1_LSB = 0x63, + /* Interrupt Request Number and Wake-Up on IRQ Enabled */ + HOST_INDEX_IRQNUMX = 0x70, + /* Interrupt Request Type Select */ + HOST_INDEX_IRQTP = 0x71, + /* DMA Channel Select 0 */ + HOST_INDEX_DMAS0 = 0x74, + /* DMA Channel Select 1 */ + HOST_INDEX_DMAS1 = 0x75, + /* Device Specific Logical Device Configuration 1 to 10 */ + HOST_INDEX_DSLDC1 = 0xF0, + HOST_INDEX_DSLDC2 = 0xF1, + HOST_INDEX_DSLDC3 = 0xF2, + HOST_INDEX_DSLDC4 = 0xF3, + HOST_INDEX_DSLDC5 = 0xF4, + HOST_INDEX_DSLDC6 = 0xF5, + HOST_INDEX_DSLDC7 = 0xF6, + HOST_INDEX_DSLDC8 = 0xF7, + HOST_INDEX_DSLDC9 = 0xF8, + HOST_INDEX_DSLDC10 = 0xF9, +}; + +/* List of logical device number (LDN) assignments */ +enum logical_device_number { + /* Serial Port 1 */ + LDN_UART1 = 0x01, + /* Serial Port 2 */ + LDN_UART2 = 0x02, + /* System Wake-Up Control */ + LDN_SWUC = 0x04, + /* KBC/Mouse Interface */ + LDN_KBC_MOUSE = 0x05, + /* KBC/Keyboard Interface */ + LDN_KBC_KEYBOARD = 0x06, + /* Consumer IR */ + LDN_CIR = 0x0A, + /* Shared Memory/Flash Interface */ + LDN_SMFI = 0x0F, + /* RTC-like Timer */ + LDN_RTCT = 0x10, + /* Power Management I/F Channel 1 */ + LDN_PMC1 = 0x11, + /* Power Management I/F Channel 2 */ + LDN_PMC2 = 0x12, + /* Serial Peripheral Interface */ + LDN_SSPI = 0x13, + /* Platform Environment Control Interface */ + LDN_PECI = 0x14, + /* Power Management I/F Channel 3 */ + LDN_PMC3 = 0x17, + /* Power Management I/F Channel 4 */ + LDN_PMC4 = 0x18, + /* Power Management I/F Channel 5 */ + LDN_PMC5 = 0x19, +}; + +/* EC2I read/write message */ +enum ec2i_message { + /* EC2I write success */ + EC2I_WRITE_SUCCESS = 0x00, + /* EC2I write error */ + EC2I_WRITE_ERROR = 0x01, + /* EC2I read success */ + EC2I_READ_SUCCESS = 0x8000, + /* EC2I read error */ + EC2I_READ_ERROR = 0x8100, +}; + +/* Data structure for initializing PNPCFG via ec2i. */ +struct ec2i_t { + /* index port */ + enum host_pnpcfg_index index_port; + /* data port */ + uint8_t data_port; +}; + +extern const struct ec2i_t pnpcfg_settings[]; + +/* EC2I write */ +enum ec2i_message ec2i_write(enum host_pnpcfg_index index, uint8_t data); + +/* EC2I read */ +enum ec2i_message ec2i_read(enum host_pnpcfg_index index); + +#endif /* __CROS_EC_IT83XX_EC2I_H */ diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h index 08a3aab150..473f696a6c 100644 --- a/chip/it83xx/registers.h +++ b/chip/it83xx/registers.h @@ -383,6 +383,20 @@ #define IT83XX_INTC_IVCT14 REG8(IT83XX_INTC_BASE+0x8E) #define IT83XX_INTC_IVCT15 REG8(IT83XX_INTC_BASE+0x8F) +/* --- EC Access to the Host Controlled Modules (EC2I Bridge) --- */ +#define IT83XX_EC2I_BASE 0x00F01200 + +#define IT83XX_EC2I_IHIOA REG8(IT83XX_EC2I_BASE+0x00) +#define IT83XX_EC2I_IHD REG8(IT83XX_EC2I_BASE+0x01) +#define IT83XX_EC2I_LSIOHA REG8(IT83XX_EC2I_BASE+0x02) +#define IT83XX_EC2I_SIOLV REG8(IT83XX_EC2I_BASE+0x03) +#define IT83XX_EC2I_IBMAE REG8(IT83XX_EC2I_BASE+0x04) +#define IT83XX_EC2I_IBCTL REG8(IT83XX_EC2I_BASE+0x05) + +/* --- System Wake-UP Control (SWUC) --- */ +#define IT83XX_SWUC_BASE 0x00F01400 +#define IT83XX_SWUC_SWCTL1 REG8(IT83XX_SWUC_BASE+0x00) + /* --- Wake-Up Control (WUC) --- */ #define IT83XX_WUC_BASE 0x00F01B00 @@ -644,9 +658,7 @@ enum clock_gate_offsets { /* --- 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_DAC_BASE 0x00F01A00 |