diff options
Diffstat (limited to 'chip/npcx')
-rw-r--r-- | chip/npcx/build.mk | 2 | ||||
-rw-r--r-- | chip/npcx/i2c-npcx5.c | 47 | ||||
-rw-r--r-- | chip/npcx/i2c-npcx7.c | 70 | ||||
-rw-r--r-- | chip/npcx/i2c.c | 77 | ||||
-rw-r--r-- | chip/npcx/i2c_chip.h | 28 | ||||
-rw-r--r-- | chip/npcx/registers.h | 94 |
6 files changed, 257 insertions, 61 deletions
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk index d5047237e9..f733ab168c 100644 --- a/chip/npcx/build.mk +++ b/chip/npcx/build.mk @@ -23,7 +23,7 @@ chip-y=header.o clock.o gpio.o hwtimer.o jtag.o system.o uart.o chip-$(CONFIG_ADC)+=adc.o chip-$(CONFIG_FANS)+=fan.o chip-$(CONFIG_FLASH_PHYSICAL)+=flash.o -chip-$(CONFIG_I2C)+=i2c.o +chip-$(CONFIG_I2C)+=i2c.o i2c-$(CHIP_FAMILY).o chip-$(CONFIG_LPC)+=lpc.o chip-$(CONFIG_ESPI)+=espi.o chip-$(CONFIG_PECI)+=peci.o diff --git a/chip/npcx/i2c-npcx5.c b/chip/npcx/i2c-npcx5.c new file mode 100644 index 0000000000..6b78fd53f9 --- /dev/null +++ b/chip/npcx/i2c-npcx5.c @@ -0,0 +1,47 @@ +/* Copyright 2017 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 driver depends on chip series for Chrome EC */ + +#include "i2c.h" +#include "i2c_chip.h" +#include "registers.h" +#include "util.h" + +/*****************************************************************************/ +/* IC specific low-level driver depends on chip series */ + +int i2c_port_to_controller(int port) +{ + if (port < 0 || port >= I2C_PORT_COUNT) + return -1; + + return (port == NPCX_I2C_PORT0_0) ? 0 : port - 1; +} + +void i2c_select_port(int port) +{ + /* + * I2C0_1 uses port 1 of controller 0. All other I2C pin sets + * use port 0. + */ + if (port > NPCX_I2C_PORT0_1) + return; + + /* Select IO pins for multi-ports I2C controllers */ + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB0SEL, + (port == NPCX_I2C_PORT0_1)); +} + +int i2c_is_raw_mode(int port) +{ + int bit = (port > NPCX_I2C_PORT0_1) ? ((port - 1) * 2) : port; + + if (IS_BIT_SET(NPCX_DEVALT(2), bit)) + return 0; + else + return 1; +} + diff --git a/chip/npcx/i2c-npcx7.c b/chip/npcx/i2c-npcx7.c new file mode 100644 index 0000000000..3f27aff49e --- /dev/null +++ b/chip/npcx/i2c-npcx7.c @@ -0,0 +1,70 @@ +/* Copyright 2017 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 driver depends on chip series for Chrome EC */ + +#include "common.h" +#include "i2c.h" +#include "i2c_chip.h" +#include "registers.h" +#include "util.h" + +/*****************************************************************************/ +/* IC specific low-level driver depends on chip series */ + +int i2c_port_to_controller(int port) +{ + if (port < 0 || port >= I2C_PORT_COUNT) + return -1; + + if (port <= NPCX_I2C_PORT3_0) + return port; +#ifndef NPCX_PSL_MODE_SUPPORT + else if (port == NPCX_I2C_PORT4_0) + return 4; +#endif + else /* If port >= NPCX_I2C_PORT4_1 */ + return 4 + ((port - NPCX_I2C_PORT4_1 + 1) / 2); +} + +void i2c_select_port(int port) +{ + /* Only I2C 4/5/6 have multiple ports in series npcx7 */ + if (port <= NPCX_I2C_PORT3_0 || port >= NPCX_I2C_PORT7_0) + return; + /* Select I2C ports for the same controller */ + else if (port <= NPCX_I2C_PORT4_1) { + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB4SEL, + (port == NPCX_I2C_PORT4_1)); + } else if (port <= NPCX_I2C_PORT5_1) { + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB5SEL, + (port == NPCX_I2C_PORT5_1)); + } else { + UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB6SEL, + (port == NPCX_I2C_PORT6_1)); + } +} + +int i2c_is_raw_mode(int port) +{ + int group, bit; + + if (port == NPCX_I2C_PORT4_1 || port == NPCX_I2C_PORT5_1 || + port == NPCX_I2C_PORT6_1) { + group = 6; + bit = 7 - (port - NPCX_I2C_PORT4_1) / 2; + } else { + group = 2; + if (port <= NPCX_I2C_PORT3_0) + bit = 2 * port; + else + bit = I2C_PORT_COUNT - port; + } + + if (IS_BIT_SET(NPCX_DEVALT(group), bit)) + return 0; + else + return 1; +} diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c index 6e36b01413..4b645b7b11 100644 --- a/chip/npcx/i2c.c +++ b/chip/npcx/i2c.c @@ -12,6 +12,7 @@ #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "i2c_chip.h" #include "registers.h" #include "task.h" #include "timer.h" @@ -25,10 +26,6 @@ #define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) #endif -/* Pull-up bit for I2C */ -#define NPCX_I2C_PUBIT(controller, port) \ - ((controller*2) + port) - /* Timeout for device should be available after reset (SMBus spec. unit:ms) */ #define I2C_MAX_TIMEOUT 35 /* @@ -79,11 +76,6 @@ enum smb_oper_state_t { SMB_READ_SUSPEND, }; -/* IRQ for each port */ -static const uint32_t i2c_irqs[I2C_CONTROLLER_COUNT] = { - NPCX_IRQ_SMB1, NPCX_IRQ_SMB2, NPCX_IRQ_SMB3, NPCX_IRQ_SMB4}; -BUILD_ASSERT(ARRAY_SIZE(i2c_irqs) == I2C_CONTROLLER_COUNT); - /* I2C controller state data */ struct i2c_status { int flags; /* Flags (I2C_XFER_*) */ @@ -132,26 +124,14 @@ static const struct i2c_timing i2c_1m_timings[] = { {15, 9, 10, 10},}; const unsigned int i2c_1m_timing_used = ARRAY_SIZE(i2c_1m_timings); -int i2c_port_to_controller(int port) -{ - if (port < 0 || port >= I2C_PORT_COUNT) - return -1; - return (port == NPCX_I2C_PORT0_0) ? 0 : port - 1; -} - -static void i2c_select_port(int port) -{ - /* - * I2C0_1 uses port 1 of controller 0. All other I2C pin sets - * use port 0. - */ - if (port > NPCX_I2C_PORT0_1) - return; - - /* Select IO pins for multi-ports I2C controllers */ - UPDATE_BIT(NPCX_GLUE_SMBSEL, NPCX_SMBSEL_SMB0SEL, - (port == NPCX_I2C_PORT0_1)); -} +/* IRQ for each port */ +const uint32_t i2c_irqs[I2C_CONTROLLER_COUNT] = { + NPCX_IRQ_SMB1, NPCX_IRQ_SMB2, NPCX_IRQ_SMB3, NPCX_IRQ_SMB4, +#if defined(CHIP_FAMILY_NPCX7) + NPCX_IRQ_SMB5, NPCX_IRQ_SMB6, NPCX_IRQ_SMB7, NPCX_IRQ_SMB8, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_irqs) == I2C_CONTROLLER_COUNT); static void i2c_init_bus(int controller) { @@ -605,11 +585,23 @@ void i2c0_interrupt(void) { handle_interrupt(0); } void i2c1_interrupt(void) { handle_interrupt(1); } void i2c2_interrupt(void) { handle_interrupt(2); } void i2c3_interrupt(void) { handle_interrupt(3); } +#if defined(CHIP_FAMILY_NPCX7) +void i2c4_interrupt(void) { handle_interrupt(4); } +void i2c5_interrupt(void) { handle_interrupt(5); } +void i2c6_interrupt(void) { handle_interrupt(6); } +void i2c7_interrupt(void) { handle_interrupt(7); } +#endif DECLARE_IRQ(NPCX_IRQ_SMB1, i2c0_interrupt, 3); DECLARE_IRQ(NPCX_IRQ_SMB2, i2c1_interrupt, 3); DECLARE_IRQ(NPCX_IRQ_SMB3, i2c2_interrupt, 3); DECLARE_IRQ(NPCX_IRQ_SMB4, i2c3_interrupt, 3); +#if defined(CHIP_FAMILY_NPCX7) +DECLARE_IRQ(NPCX_IRQ_SMB5, i2c4_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_SMB6, i2c5_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_SMB7, i2c6_interrupt, 3); +DECLARE_IRQ(NPCX_IRQ_SMB8, i2c7_interrupt, 3); +#endif /*****************************************************************************/ /* IC specific low-level driver */ @@ -708,20 +700,6 @@ int i2c_get_line_levels(int port) (i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0); } -/* - * Due to we couldn't support GPIO reading when IO is selected SMBus, we need - * to distingulish which mode we used currently. - */ -int i2c_is_raw_mode(int port) -{ - int bit = (port > NPCX_I2C_PORT0_1) ? ((port - 1) * 2) : port; - - if (IS_BIT_SET(NPCX_DEVALT(2), bit)) - return 0; - else - return 1; -} - int i2c_raw_get_scl(int port) { enum gpio_signal g; @@ -774,10 +752,16 @@ static void i2c_freq_changed(void) int ctrl = i2c_port_to_controller(i2c_ports[i].port); int scl_freq; - /* SMB0/1 use core clock & SMB2/3 use apb2 clock */ if (ctrl < 2) +#if defined(CHIP_FAMILY_NPCX7) + /* SMB0/1 use APB3 clock */ + freq = clock_get_apb3_freq(); +#else + /* SMB0/1 use core clock */ freq = clock_get_freq(); +#endif else + /* Other SMB controller use APB2 clock */ freq = clock_get_apb2_freq(); /* @@ -842,12 +826,17 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_changed, HOOK_PRIO_DEFAULT); static void i2c_init(void) { int i; + /* Configure pins from GPIOs to I2Cs */ gpio_config_module(MODULE_I2C, 1); /* Enable clock for I2C peripheral */ clock_enable_peripheral(CGC_OFFSET_I2C, CGC_I2C_MASK, CGC_MODE_RUN | CGC_MODE_SLEEP); +#if defined(CHIP_FAMILY_NPCX7) + clock_enable_peripheral(CGC_OFFSET_I2C2, CGC_I2C_MASK2, + CGC_MODE_RUN | CGC_MODE_SLEEP); +#endif /* Set I2C freq */ i2c_freq_changed(); diff --git a/chip/npcx/i2c_chip.h b/chip/npcx/i2c_chip.h new file mode 100644 index 0000000000..014e6cddf2 --- /dev/null +++ b/chip/npcx/i2c_chip.h @@ -0,0 +1,28 @@ +/* Copyright 2017 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. + */ + +/* NPCX-specific I2C module for Chrome EC */ + +#ifndef __CROS_EC_I2C_CHIP_H +#define __CROS_EC_I2C_CHIP_H + +/** + * Select specific i2c port connected to i2c controller. + * + * @parm port I2C port + */ +void i2c_select_port(int port); + +/* + * Due to we couldn't support GPIO reading when IO is selected I2C, we need + * to distingulish which mode we used currently. + * + * @parm port I2C port + * + * @return 0: i2c ports are selected to pins. 1: GPIOs are selected to pins. + */ +int i2c_is_raw_mode(int port); + +#endif /* __CROS_EC_I2C_CHIP_H */ diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h index dc57852de4..7b92fea6b2 100644 --- a/chip/npcx/registers.h +++ b/chip/npcx/registers.h @@ -95,9 +95,19 @@ #define NPCX_MIWU_BASE_ADDR(mdl) (0x400BB000 + ((mdl) * 0x2000L)) #define NPCX_MFT_BASE_ADDR(mdl) (0x400E1000 + ((mdl) * 0x2000L)) #define NPCX_PM_CH_BASE_ADDR(mdl) (0x400C9000 + ((mdl) * 0x2000L)) -#define NPCX_SMB_BASE_ADDR(mdl) ((mdl < 2) ? (0x40009000 + \ - ((mdl) * 0x2000L)) : \ - (0x400C0000 + ((mdl - 2) * 0x2000L))) +#if defined(CHIP_FAMILY_NPCX7) +#define NPCX_SMB_BASE_ADDR(mdl) (((mdl) < 2) ? \ + (0x40009000 + ((mdl) * 0x2000L)) : \ + ((mdl) < 4) ? \ + (0x400C0000 + (((mdl) - 2) * 0x2000L)) : \ + ((mdl) == 4) ? \ + (0x40008000) : \ + (0x40017000 + (((mdl) - 5) * 0x1000L))) +#else +#define NPCX_SMB_BASE_ADDR(mdl) (((mdl) < 2) ? \ + (0x40009000 + ((mdl) * 0x2000L)) : \ + (0x400C0000 + (((mdl) - 2) * 0x2000L))) +#endif /* * NPCX-IRQ numbers @@ -175,7 +185,7 @@ #define NPCX_IRQ5_NOUSED NPCX_IRQ_5 #define NPCX_IRQ_PORT80 NPCX_IRQ_6 #define NPCX_IRQ_MTC_WKINTAD_0 NPCX_IRQ_7 -#define NPCX_IRQ8_NOUSED NPCX_IRQ_8 +#define NPCX_IRQ_SMB8 NPCX_IRQ_8 #define NPCX_IRQ_MFT_1 NPCX_IRQ_9 #define NPCX_IRQ_ADC NPCX_IRQ_10 #define NPCX_IRQ_WKINTEFGH_0 NPCX_IRQ_11 @@ -183,12 +193,12 @@ #define NPCX_IRQ_SMB1 NPCX_IRQ_13 #define NPCX_IRQ_SMB2 NPCX_IRQ_14 #define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15 -#define NPCX_IRQ16_NOUSED NPCX_IRQ_16 +#define NPCX_IRQ_SMB7 NPCX_IRQ_16 #define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17 #define NPCX_IRQ_SHI NPCX_IRQ_18 #define NPCX_IRQ_ESPI NPCX_IRQ_18 -#define NPCX_IRQ19_NOUSED NPCX_IRQ_19 -#define NPCX_IRQ20_NOUSED NPCX_IRQ_20 +#define NPCX_IRQ_SMB5 NPCX_IRQ_19 +#define NPCX_IRQ_SMB6 NPCX_IRQ_20 #define NPCX_IRQ_PS2 NPCX_IRQ_21 #define NPCX_IRQ22_NOUSED NPCX_IRQ_22 #define NPCX_IRQ_MFT_2 NPCX_IRQ_23 @@ -742,19 +752,46 @@ enum { #define NPCX_SMBADDR6_SAEN 7 #define NPCX_SMBADDR7_SAEN 7 #define NPCX_SMBADDR8_SAEN 7 +#if defined(CHIP_FAMILY_NPCX5) #define NPCX_SMBSEL_SMB0SEL 0 - +#elif defined(CHIP_FAMILY_NPCX7) +#define NPCX_SMBSEL_SMB4SEL 4 +#define NPCX_SMBSEL_SMB5SEL 5 +#define NPCX_SMBSEL_SMB6SEL 6 +#endif /* * SMB enumeration - * I2C Port. + * I2C port definitions. */ -enum NPCX_I2C_PORT_T { - NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0*/ - NPCX_I2C_PORT0_1 = 1, /* I2C port 0, bus 1*/ - NPCX_I2C_PORT1 = 2, /* I2C port 1 */ - NPCX_I2C_PORT2 = 3, /* I2C port 2 */ - NPCX_I2C_PORT3 = 4, /* I2C port 3 */ +#if defined(CHIP_FAMILY_NPCX5) +enum { + NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ + NPCX_I2C_PORT0_1, /* I2C port 0, bus 1 */ + NPCX_I2C_PORT1, /* I2C port 1 */ + NPCX_I2C_PORT2, /* I2C port 2 */ + NPCX_I2C_PORT3, /* I2C port 3 */ + NPCX_I2C_COUNT, }; +#elif defined(CHIP_FAMILY_NPCX7) +enum { + NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ + NPCX_I2C_PORT1_0, /* I2C port 1, bus 0 */ + NPCX_I2C_PORT2_0, /* I2C port 2, bus 0 */ + NPCX_I2C_PORT3_0, /* I2C port 3, bus 0 */ +#if !defined(NPCX_PSL_MODE_SUPPORT) + NPCX_I2C_PORT4_0, /* I2C port 4, bus 0 */ +#endif + NPCX_I2C_PORT4_1, /* I2C port 4, bus 1 */ + NPCX_I2C_PORT5_0, /* I2C port 5, bus 0 */ + NPCX_I2C_PORT5_1, /* I2C port 5, bus 1 */ + NPCX_I2C_PORT6_0, /* I2C port 6, bus 0 */ + NPCX_I2C_PORT6_1, /* I2C port 6, bus 1 */ + NPCX_I2C_PORT7_0, /* I2C port 7, bus 0 */ + NPCX_I2C_COUNT, +}; +#else +#error "Unsupported chip family for i2c ports." +#endif /******************************************************************************/ /* Power Management Controller (PMC) Registers */ @@ -763,7 +800,6 @@ enum NPCX_I2C_PORT_T { #define NPCX_DISIDL_CTL REG8(NPCX_PMC_BASE_ADDR + 0x004) #define NPCX_DISIDL_CTL1 REG8(NPCX_PMC_BASE_ADDR + 0x005) #define NPCX_PWDWN_CTL(offset) REG8(NPCX_PMC_BASE_ADDR + 0x008 + offset) -#define NPCX_PWDWN_CTL_COUNT 6 /* PMC register fields */ #define NPCX_PMCSR_DI_INSTW 0 @@ -797,6 +833,9 @@ enum NPCX_I2C_PORT_T { #define NPCX_PWDWN_CTL3_SMB1_PD 1 #define NPCX_PWDWN_CTL3_SMB2_PD 2 #define NPCX_PWDWN_CTL3_SMB3_PD 3 +#if defined(CHIP_FAMILY_NPCX7) +#define NPCX_PWDWN_CTL3_SMB4_PD 4 +#endif #define NPCX_PWDWN_CTL3_GMDA_PD 7 #define NPCX_PWDWN_CTL4_ITIM1_PD 0 #define NPCX_PWDWN_CTL4_ITIM2_PD 1 @@ -816,6 +855,11 @@ enum NPCX_I2C_PORT_T { #define NPCX_PWDWN_CTL6_ITIM5_PD 1 #define NPCX_PWDWN_CTL6_ITIM6_PD 2 #define NPCX_PWDWN_CTL6_ESPI_PD 7 +#if defined(CHIP_FAMILY_NPCX7) +#define NPCX_PWDWN_CTL7_SMB5_PD 0 +#define NPCX_PWDWN_CTL7_SMB6_PD 1 +#define NPCX_PWDWN_CTL7_SMB7_PD 2 +#endif /* * PMC enumeration @@ -834,6 +878,9 @@ enum { CGC_OFFSET_TIMER = 3, CGC_OFFSET_LPC = 4, CGC_OFFSET_ESPI = 5, +#if defined(CHIP_FAMILY_NPCX7) + CGC_OFFSET_I2C2 = 6, +#endif }; enum NPCX_PMC_PWDWN_CTL_T { @@ -843,6 +890,10 @@ enum NPCX_PMC_PWDWN_CTL_T { NPCX_PMC_PWDWN_4 = 3, NPCX_PMC_PWDWN_5 = 4, NPCX_PMC_PWDWN_6 = 5, +#if defined(CHIP_FAMILY_NPCX7) + NPCX_PMC_PWDWN_7 = 6, +#endif + NPCX_PMC_PWDWN_CNT, }; /* TODO: set PD masks based upon actual peripheral usage */ @@ -851,10 +902,21 @@ enum NPCX_PMC_PWDWN_CTL_T { #define CGC_FAN_MASK ((1 << NPCX_PWDWN_CTL1_MFT1_PD) | \ (1 << NPCX_PWDWN_CTL1_MFT2_PD)) #define CGC_FIU_MASK (1 << NPCX_PWDWN_CTL1_FIU_PD) +#if defined(CHIP_FAMILY_NPCX5) #define CGC_I2C_MASK ((1 << NPCX_PWDWN_CTL3_SMB0_PD) | \ (1 << NPCX_PWDWN_CTL3_SMB1_PD) | \ (1 << NPCX_PWDWN_CTL3_SMB2_PD) | \ (1 << NPCX_PWDWN_CTL3_SMB3_PD)) +#elif defined(CHIP_FAMILY_NPCX7) +#define CGC_I2C_MASK ((1 << NPCX_PWDWN_CTL3_SMB0_PD) | \ + (1 << NPCX_PWDWN_CTL3_SMB1_PD) | \ + (1 << NPCX_PWDWN_CTL3_SMB2_PD) | \ + (1 << NPCX_PWDWN_CTL3_SMB3_PD) | \ + (1 << NPCX_PWDWN_CTL3_SMB4_PD)) +#define CGC_I2C_MASK2 ((1 << NPCX_PWDWN_CTL7_SMB5_PD) | \ + (1 << NPCX_PWDWN_CTL7_SMB6_PD) | \ + (1 << NPCX_PWDWN_CTL7_SMB7_PD)) +#endif #define CGC_ADC_MASK (1 << NPCX_PWDWN_CTL4_ADC_PD) #define CGC_PECI_MASK (1 << NPCX_PWDWN_CTL4_PECI_PD) #define CGC_SPI_MASK (1 << NPCX_PWDWN_CTL4_SPIP_PD) |