diff options
-rw-r--r-- | board/npcx_evb/board.c | 7 | ||||
-rw-r--r-- | board/npcx_evb/board.h | 3 | ||||
-rw-r--r-- | board/npcx_evb/gpio.inc | 19 | ||||
-rw-r--r-- | board/npcx_evb_arm/board.c | 7 | ||||
-rw-r--r-- | board/npcx_evb_arm/board.h | 3 | ||||
-rw-r--r-- | board/npcx_evb_arm/gpio.inc | 20 | ||||
-rw-r--r-- | chip/npcx/config_chip.h | 10 | ||||
-rw-r--r-- | chip/npcx/gpio.c | 13 | ||||
-rw-r--r-- | chip/npcx/i2c.c | 310 | ||||
-rw-r--r-- | chip/npcx/lpc.c | 4 | ||||
-rw-r--r-- | chip/npcx/registers.h | 19 | ||||
-rw-r--r-- | chip/npcx/system.c | 6 |
12 files changed, 261 insertions, 160 deletions
diff --git a/board/npcx_evb/board.c b/board/npcx_evb/board.c index 8b3a72304d..3e438bb6b0 100644 --- a/board/npcx_evb/board.c +++ b/board/npcx_evb/board.c @@ -110,8 +110,11 @@ BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + {"master0-0", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL0, GPIO_I2C0_SDA0}, + {"master0-1", NPCX_I2C_PORT0_1, 100, GPIO_I2C0_SCL1, GPIO_I2C0_SDA1}, + {"master1", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, + {"master2", NPCX_I2C_PORT2, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + {"master3", NPCX_I2C_PORT3, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/npcx_evb/board.h b/board/npcx_evb/board.h index 1553edba3f..7f1b3529a4 100644 --- a/board/npcx_evb/board.h +++ b/board/npcx_evb/board.h @@ -46,7 +46,6 @@ /* Optional feature - used by nuvoton */ #define NPCX_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */ #define NPCX_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */ -#define NPCX_I2C0_BUS2 0 /* 0:GPIOB4/B5 1:GPIOB2/B3 as I2C0 */ #define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */ #define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ #define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */ @@ -56,7 +55,7 @@ #undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ /* Single I2C port, where the EC is the master. */ -#define I2C_PORT_MASTER 0 +#define I2C_PORT_MASTER NPCX_I2C_PORT0_0 #define I2C_PORT_HOST 0 #ifndef __ASSEMBLER__ diff --git a/board/npcx_evb/gpio.inc b/board/npcx_evb/gpio.inc index 149b045a7a..7c7ae2f10d 100644 --- a/board/npcx_evb/gpio.inc +++ b/board/npcx_evb/gpio.inc @@ -27,8 +27,16 @@ GPIO(SPI_CS_L, PIN(A, 5), GPIO_OUT_HIGH) * I2C pins should be configured as inputs until I2C module is * initialized. This will avoid driving the lines unintentionally. */ -GPIO(MASTER_I2C_SCL, PIN(B, 5), GPIO_INPUT) -GPIO(MASTER_I2C_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(I2C0_SCL0, PIN(B, 5), GPIO_ODR_HIGH) +GPIO(I2C0_SDA0, PIN(B, 4), GPIO_ODR_HIGH) +GPIO(I2C0_SCL1, PIN(B, 3), GPIO_ODR_HIGH) +GPIO(I2C0_SDA1, PIN(B, 2), GPIO_ODR_HIGH) +GPIO(I2C1_SCL, PIN(9, 0), GPIO_ODR_HIGH) +GPIO(I2C1_SDA, PIN(8, 7), GPIO_ODR_HIGH) +GPIO(I2C2_SCL, PIN(9, 2), GPIO_ODR_HIGH) +GPIO(I2C2_SDA, PIN(9, 1), GPIO_ODR_HIGH) +GPIO(I2C3_SCL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(I2C3_SDA, PIN(D, 0), GPIO_ODR_HIGH) /* Used for board version command */ GPIO(BOARD_VERSION1, PIN(6, 4), GPIO_INPUT) /* Board version stuffing resistor 1 */ @@ -45,11 +53,8 @@ ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT #else ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */ #endif -#if NPCX_I2C0_BUS2 -ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB2/B3 */ -#else -ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */ -#endif +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA1/I2C0SCL1 GPIOB2/B3 */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA0/I2C0SCL0 GPIOB4/B5 */ ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1SDA GPIO87 */ ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO90/91/92 */ ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* I2C3SDA/I2C3SCL GPIOD0/D1 */ diff --git a/board/npcx_evb_arm/board.c b/board/npcx_evb_arm/board.c index 56eb9b5635..6661ff6e11 100644 --- a/board/npcx_evb_arm/board.c +++ b/board/npcx_evb_arm/board.c @@ -110,8 +110,11 @@ BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT); /******************************************************************************/ /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"master", I2C_PORT_MASTER, 100, - GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + {"master0-0", NPCX_I2C_PORT0_0, 100, GPIO_I2C0_SCL0, GPIO_I2C0_SDA0}, + {"master0-1", NPCX_I2C_PORT0_1, 100, GPIO_I2C0_SCL1, GPIO_I2C0_SDA1}, + {"master1", NPCX_I2C_PORT1, 100, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, + {"master2", NPCX_I2C_PORT2, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA}, + {"master3", NPCX_I2C_PORT3, 100, GPIO_I2C3_SCL, GPIO_I2C3_SDA}, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/npcx_evb_arm/board.h b/board/npcx_evb_arm/board.h index 62856cda56..4c795059ac 100644 --- a/board/npcx_evb_arm/board.h +++ b/board/npcx_evb_arm/board.h @@ -42,7 +42,6 @@ /* Optional feature - used by nuvoton */ #define NPCX_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */ #define NPCX_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */ -#define NPCX_I2C0_BUS2 0 /* 0:GPIOB4/B5 1:GPIOB2/B3 as I2C0 */ #define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */ #define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/ #define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */ @@ -52,7 +51,7 @@ #undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */ /* Single I2C port, where the EC is the master. */ -#define I2C_PORT_MASTER 0 +#define I2C_PORT_MASTER NPCX_I2C_PORT0_0 #define I2C_PORT_HOST 0 #ifndef __ASSEMBLER__ diff --git a/board/npcx_evb_arm/gpio.inc b/board/npcx_evb_arm/gpio.inc index 30e19ef1a9..995c68a3d8 100644 --- a/board/npcx_evb_arm/gpio.inc +++ b/board/npcx_evb_arm/gpio.inc @@ -28,8 +28,17 @@ GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Goo * I2C pins should be configured as inputs until I2C module is * initialized. This will avoid driving the lines unintentionally. */ -GPIO(MASTER_I2C_SCL, PIN(B, 5), GPIO_INPUT) -GPIO(MASTER_I2C_SDA, PIN(B, 4), GPIO_INPUT) +GPIO(I2C0_SCL0, PIN(B, 5), GPIO_ODR_HIGH) +GPIO(I2C0_SDA0, PIN(B, 4), GPIO_ODR_HIGH) +GPIO(I2C0_SCL1, PIN(B, 3), GPIO_ODR_HIGH) +GPIO(I2C0_SDA1, PIN(B, 2), GPIO_ODR_HIGH) +GPIO(I2C1_SCL, PIN(9, 0), GPIO_ODR_HIGH) +GPIO(I2C1_SDA, PIN(8, 7), GPIO_ODR_HIGH) +GPIO(I2C2_SCL, PIN(9, 2), GPIO_ODR_HIGH) +GPIO(I2C2_SDA, PIN(9, 1), GPIO_ODR_HIGH) +GPIO(I2C3_SCL, PIN(D, 1), GPIO_ODR_HIGH) +GPIO(I2C3_SDA, PIN(D, 0), GPIO_ODR_HIGH) + /* Used for board version command */ GPIO(BOARD_VERSION1, PIN(6, 4), GPIO_INPUT) /* Board version stuffing resistor 1 */ GPIO(BOARD_VERSION2, PIN(6, 5), GPIO_INPUT) /* Board version stuffing resistor 2 */ @@ -45,11 +54,8 @@ ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT #else ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */ #endif -#if NPCX_I2C0_BUS2 -ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB2/B3 */ -#else -ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */ -#endif +ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA1/I2C0SCL1 GPIOB2/B3 */ +ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA0/I2C0SCL0 GPIOB4/B5 */ ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1SDA GPIO87 */ ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO90/91/92 */ ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* I2C3SDA/I2C3SCL GPIOD0/D1 */ diff --git a/chip/npcx/config_chip.h b/chip/npcx/config_chip.h index f8314f6282..3b39065220 100644 --- a/chip/npcx/config_chip.h +++ b/chip/npcx/config_chip.h @@ -29,8 +29,16 @@ /* Maximum number of deferrable functions */ #define DEFERRABLE_MAX_COUNT 8 +/* + * Number of I2C controllers. Controller 0 has 2 ports, so the chip has one + * additional port. + */ +#define CONFIG_I2C_MULTI_PORT_CONTROLLER +/* Number of I2C controllers */ +#define I2C_CONTROLLER_COUNT 4 /* Number of I2C ports */ -#define I2C_PORT_COUNT 4 +#define I2C_PORT_COUNT 5 + /* Number of PWM ports */ #define PWM_COUNT 8 diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c index cb8e7348a6..1173338716 100644 --- a/chip/npcx/gpio.c +++ b/chip/npcx/gpio.c @@ -219,13 +219,10 @@ struct gpio_alt_map { const struct gpio_alt_map gpio_alt_table[] = { /* I2C Module */ -#if NPCX_I2C0_BUS2 - { NPCX_GPIO(B, 2), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SDA */ - { NPCX_GPIO(B, 3), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SCL */ -#else - { NPCX_GPIO(B, 4), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SDA */ - { NPCX_GPIO(B, 5), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SCL */ -#endif + { NPCX_GPIO(B, 2), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SDA1 */ + { NPCX_GPIO(B, 3), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SCL1 */ + { NPCX_GPIO(B, 4), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SDA0 */ + { NPCX_GPIO(B, 5), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SCL0 */ { NPCX_GPIO(8, 7), NPCX_ALT(2, I2C1_0_SL)}, /* SMB1SDA */ { NPCX_GPIO(9, 0), NPCX_ALT(2, I2C1_0_SL)}, /* SMB1SCL */ { NPCX_GPIO(9, 1), NPCX_ALT(2, I2C2_0_SL)}, /* SMB2SDA */ @@ -328,7 +325,7 @@ void gpio_pwm_io_type_sel(uint8_t alt_mask, uint8_t func) CLEAR_BIT(NPCX_PWMCTLEX(chan), NPCX_PWMCTLEX_OD_OUT); } -int gpio_alt_sel(uint8_t port, uint8_t mask, uint8_t func) +int gpio_alt_sel(uint8_t port, uint8_t mask, int8_t func) { int i; const struct gpio_alt_map *map = gpio_alt_table; diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c index d9940b688a..77788525e4 100644 --- a/chip/npcx/i2c.c +++ b/chip/npcx/i2c.c @@ -26,19 +26,17 @@ #endif /* Pull-up bit for I2C */ -#define NPCX_I2C_PUBIT(port, bus) \ - ((port*2) + bus) +#define NPCX_I2C_PUBIT(controller, port) \ + ((controller*2) + port) /* Data abort timeout unit:ms*/ #define I2C_ABORT_TIMEOUT 35 -/* Maximum time we allow for an I2C transfer (SMB stardard is 25 ms) */ -#define I2C_TIMEOUT_US (100*MSEC) /* Marco functions of I2C */ -#define I2C_START(port) SET_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_START) -#define I2C_STOP(port) SET_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_STOP) -#define I2C_NACK(port) SET_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_ACK) -#define I2C_WRITE_BYTE(port, data) (NPCX_SMBSDA(port) = data) -#define I2C_READ_BYTE(port, data) (data = NPCX_SMBSDA(port)) +#define I2C_START(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_START) +#define I2C_STOP(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_STOP) +#define I2C_NACK(ctrl) SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_ACK) +#define I2C_WRITE_BYTE(ctrl, data) (NPCX_SMBSDA(ctrl) = data) +#define I2C_READ_BYTE(ctrl, data) (data = NPCX_SMBSDA(ctrl)) /* Error values that functions can return */ enum smb_error { @@ -73,11 +71,11 @@ enum smb_oper_state_t { /* IRQ for each port */ -static const uint32_t i2c_irqs[I2C_PORT_COUNT] = { +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_PORT_COUNT); +BUILD_ASSERT(ARRAY_SIZE(i2c_irqs) == I2C_CONTROLLER_COUNT); -/* I2C port state data */ +/* I2C controller state data */ struct i2c_status { int flags; /* Flags (I2C_XFER_*) */ const uint8_t *tx_buf; /* Entry pointer of transmit buffer */ @@ -85,83 +83,105 @@ struct i2c_status { uint16_t sz_txbuf; /* Size of Tx buffer in bytes */ uint16_t sz_rxbuf; /* Size of rx buffer in bytes */ uint16_t idx_buf; /* Current index of Tx/Rx buffer */ - uint8_t slave_addr;/* target slave address */ - enum smb_oper_state_t oper_state;/* smbus operation state */ + uint8_t slave_addr;/* Target slave address */ + enum smb_oper_state_t oper_state;/* Smbus operation state */ enum smb_error err_code; /* Error code */ - int task_waiting; /* Task waiting on port */ + int task_waiting; /* Task waiting on controller */ + uint32_t timeout_us;/* Transaction timeout */ }; -/* I2C port state data array */ -static struct i2c_status i2c_stsobjs[I2C_PORT_COUNT]; +/* I2C controller state data array */ +static struct i2c_status i2c_stsobjs[I2C_CONTROLLER_COUNT]; -int i2c_bus_busy(int port) +int i2c_port_to_controller(int port) { - return IS_BIT_SET(NPCX_SMBCST(port), NPCX_SMBCST_BB) ? 1 : 0; + if (port < 0 || port >= I2C_PORT_COUNT) + return -1; + return (port == NPCX_I2C_PORT0_0) ? 0 : port - 1; } -int i2c_abort_data(int port) +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)); +} + +int i2c_bus_busy(int controller) +{ + return IS_BIT_SET(NPCX_SMBCST(controller), NPCX_SMBCST_BB) ? 1 : 0; +} + +int i2c_abort_data(int controller) { uint16_t timeout = I2C_ABORT_TIMEOUT; /* Clear NEGACK, STASTR and BER bits */ - SET_BIT(NPCX_SMBST(port), NPCX_SMBST_BER); - SET_BIT(NPCX_SMBST(port), NPCX_SMBST_STASTR); - SET_BIT(NPCX_SMBST(port), NPCX_SMBST_NEGACK); + SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_BER); + SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_STASTR); + SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_NEGACK); /* Wait till STOP condition is generated */ while (--timeout) { - if (!IS_BIT_SET(NPCX_SMBCTL1(port), NPCX_SMBCTL1_STOP)) + if (!IS_BIT_SET(NPCX_SMBCTL1(controller), NPCX_SMBCTL1_STOP)) break; msleep(1); } /* Clear BB (BUS BUSY) bit */ - SET_BIT(NPCX_SMBCST(port), NPCX_SMBCST_BB); + SET_BIT(NPCX_SMBCST(controller), NPCX_SMBCST_BB); if (timeout == 0) { - cprints(CC_I2C, "Abort i2c %02x fail!", port); + cprints(CC_I2C, "Abort i2c %02x fail!", controller); return 0; } else return 1; } -void i2c_reset(int port) +void i2c_reset(int controller) { uint16_t timeout = I2C_ABORT_TIMEOUT; /* Disable the SMB module */ - CLEAR_BIT(NPCX_SMBCTL2(port), NPCX_SMBCTL2_ENABLE); + CLEAR_BIT(NPCX_SMBCTL2(controller), NPCX_SMBCTL2_ENABLE); while (--timeout) { /* WAIT FOR SCL & SDA IS HIGH */ - if (IS_BIT_SET(NPCX_SMBCTL3(port), NPCX_SMBCTL3_SCL_LVL) && - IS_BIT_SET(NPCX_SMBCTL3(port), NPCX_SMBCTL3_SDA_LVL)) + if (IS_BIT_SET(NPCX_SMBCTL3(controller), NPCX_SMBCTL3_SCL_LVL) + && IS_BIT_SET(NPCX_SMBCTL3(controller), NPCX_SMBCTL3_SDA_LVL)) break; msleep(1); } if (timeout == 0) - cprints(CC_I2C, "Reset i2c %02x fail!", port); + cprints(CC_I2C, "Reset i2c %02x fail!", controller); /* Enable the SMB module */ - SET_BIT(NPCX_SMBCTL2(port), NPCX_SMBCTL2_ENABLE); + SET_BIT(NPCX_SMBCTL2(controller), NPCX_SMBCTL2_ENABLE); } -void i2c_recovery(int port) +void i2c_recovery(int controller) { CPUTS("RECOVERY\r\n"); /* Abort data, generating STOP condition */ - if (i2c_abort_data(port) == 1 && - i2c_stsobjs[port].err_code == SMB_MASTER_NO_ADDRESS_MATCH) + if (i2c_abort_data(controller) == 1 && + i2c_stsobjs[controller].err_code == SMB_MASTER_NO_ADDRESS_MATCH) return; - /* Reset i2c port by re-enable i2c port*/ - i2c_reset(port); + /* Reset i2c controller by re-enable i2c controller*/ + i2c_reset(controller); } -enum smb_error i2c_master_transaction(int port) +enum smb_error i2c_master_transaction(int controller) { /* Set i2c mode to object */ int events = 0; - volatile struct i2c_status *p_status = i2c_stsobjs + port; + volatile struct i2c_status *p_status = i2c_stsobjs + controller; if (p_status->oper_state == SMB_IDLE) { p_status->oper_state = SMB_MASTER_START; @@ -171,15 +191,16 @@ enum smb_error i2c_master_transaction(int port) } /* Generate a START condition */ - I2C_START(port); + I2C_START(controller); CPUTS("ST"); /* Wait for transfer complete or timeout */ - events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, I2C_TIMEOUT_US); + events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, + p_status->timeout_us); /* Handle timeout */ if ((events & TASK_EVENT_I2C_IDLE) == 0) { - /* Recovery I2C port */ - i2c_recovery(port); + /* Recovery I2C controller */ + i2c_recovery(controller); p_status->err_code = SMB_TIMEOUT_ERROR; } @@ -188,15 +209,15 @@ enum smb_error i2c_master_transaction(int port) */ else if (p_status->err_code == SMB_BUS_ERROR || p_status->err_code == SMB_MASTER_NO_ADDRESS_MATCH){ - i2c_recovery(port); + i2c_recovery(controller); } return p_status->err_code; } -inline void i2c_handle_sda_irq(int port) +inline void i2c_handle_sda_irq(int controller) { - volatile struct i2c_status *p_status = i2c_stsobjs + port; + volatile struct i2c_status *p_status = i2c_stsobjs + controller; /* 1 Issue Start is successful ie. write address byte */ if (p_status->oper_state == SMB_MASTER_START || p_status->oper_state == SMB_REPEAT_START) { @@ -209,15 +230,15 @@ inline void i2c_handle_sda_irq(int port) * before writing address byte */ if (p_status->sz_rxbuf == 1) - I2C_NACK(port); + I2C_NACK(controller); /* Write the address to the bus R bit*/ - I2C_WRITE_BYTE(port, (addr | 0x1)); + I2C_WRITE_BYTE(controller, (addr | 0x1)); CPRINTS("-ARR-0x%02x", addr); } else {/* Transmit mode */ p_status->oper_state = SMB_WRITE_OPER; /* Write the address to the bus W bit*/ - I2C_WRITE_BYTE(port, addr); + I2C_WRITE_BYTE(controller, addr); CPRINTS("-ARW-0x%02x", addr); } /* Completed handling START condition */ @@ -232,11 +253,11 @@ inline void i2c_handle_sda_irq(int port) /* need to STOP or not */ if (p_status->flags & I2C_XFER_STOP) { /* Issue a STOP condition on the bus */ - I2C_STOP(port); + I2C_STOP(controller); CPUTS("-SP"); } /* Clear SDA Status bit by writing dummy byte */ - I2C_WRITE_BYTE(port, 0xFF); + I2C_WRITE_BYTE(controller, 0xFF); /* Set error code */ p_status->err_code = SMB_OK; /* Notify upper layer */ @@ -262,24 +283,24 @@ inline void i2c_handle_sda_irq(int port) * Generate (Repeated) Start * upon next write to SDA */ - I2C_START(port); + I2C_START(controller); CPUTS("-RST"); /* * Receiving one byte only - set nack just * before writing address byte */ if (p_status->sz_rxbuf == 1) { - I2C_NACK(port); + I2C_NACK(controller); CPUTS("-GNA"); } /* Write the address to the bus R bit*/ - I2C_WRITE_BYTE(port, (addr_byte | 0x1)); + I2C_WRITE_BYTE(controller, (addr_byte | 0x1)); CPUTS("-ARR"); } } /* write next byte (not last byte and not slave address */ else { - I2C_WRITE_BYTE(port, + I2C_WRITE_BYTE(controller, p_status->tx_buf[p_status->idx_buf++]); CPRINTS("-W(%02x)", p_status->tx_buf[p_status->idx_buf-1]); @@ -293,7 +314,7 @@ inline void i2c_handle_sda_irq(int port) /* need to STOP or not */ if (p_status->flags & I2C_XFER_STOP) { /* Stop should set before reading last byte */ - I2C_STOP(port); + I2C_STOP(controller); CPUTS("-SP"); } } @@ -304,12 +325,12 @@ inline void i2c_handle_sda_irq(int port) * so that nack will be generated after receive * of last byte */ - I2C_NACK(port); + I2C_NACK(controller); CPUTS("-GNA"); } /* Read data for SMBSDA */ - I2C_READ_BYTE(port, data); + I2C_READ_BYTE(controller, data); CPRINTS("-R(%02x)", data); /* Read to buffer */ p_status->rx_buf[p_status->idx_buf++] = data; @@ -328,16 +349,16 @@ inline void i2c_handle_sda_irq(int port) } } -void i2c_master_int_handler (int port) +void i2c_master_int_handler (int controller) { - volatile struct i2c_status *p_status = i2c_stsobjs + port; + volatile struct i2c_status *p_status = i2c_stsobjs + controller; /* Condition 1 : A Bus Error has been identified */ - if (IS_BIT_SET(NPCX_SMBST(port), NPCX_SMBST_BER)) { + if (IS_BIT_SET(NPCX_SMBST(controller), NPCX_SMBST_BER)) { /* Generate a STOP condition */ - I2C_STOP(port); + I2C_STOP(controller); CPUTS("-SP"); /* Clear BER Bit */ - SET_BIT(NPCX_SMBST(port), NPCX_SMBST_BER); + SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_BER); /* Set error code */ p_status->err_code = SMB_BUS_ERROR; /* Notify upper layer */ @@ -347,12 +368,12 @@ void i2c_master_int_handler (int port) } /* Condition 2: A negative acknowledge has occurred */ - if (IS_BIT_SET(NPCX_SMBST(port), NPCX_SMBST_NEGACK)) { + if (IS_BIT_SET(NPCX_SMBST(controller), NPCX_SMBST_NEGACK)) { /* Generate a STOP condition */ - I2C_STOP(port); + I2C_STOP(controller); CPUTS("-SP"); /* Clear NEGACK Bit */ - SET_BIT(NPCX_SMBST(port), NPCX_SMBST_NEGACK); + SET_BIT(NPCX_SMBST(controller), NPCX_SMBST_NEGACK); /* Set error code */ p_status->err_code = SMB_MASTER_NO_ADDRESS_MATCH; /* Notify upper layer */ @@ -362,18 +383,18 @@ void i2c_master_int_handler (int port) } /* Condition 3: SDA status is set - transmit or receive */ - if (IS_BIT_SET(NPCX_SMBST(port), NPCX_SMBST_SDAST)) - i2c_handle_sda_irq(port); + if (IS_BIT_SET(NPCX_SMBST(controller), NPCX_SMBST_SDAST)) + i2c_handle_sda_irq(controller); } /** - * Handle an interrupt on the specified port. + * Handle an interrupt on the specified controller. * - * @param port I2C port generating interrupt + * @param controller I2C controller generating interrupt */ -void handle_interrupt(int port) +void handle_interrupt(int controller) { - i2c_master_int_handler(port); + i2c_master_int_handler(controller); } void i2c0_interrupt(void) { handle_interrupt(0); } @@ -389,10 +410,19 @@ DECLARE_IRQ(NPCX_IRQ_SMB4, i2c3_interrupt, 2); /*****************************************************************************/ /* IC specific low-level driver */ +void i2c_set_timeout(int port, uint32_t timeout) +{ + int ctrl = i2c_port_to_controller(port); + /* Param is port, but timeout is stored by-controller. */ + i2c_stsobjs[ctrl].timeout_us = + timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; +} + int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { - volatile struct i2c_status *p_status = i2c_stsobjs + port; + int ctrl = i2c_port_to_controller(port); + volatile struct i2c_status *p_status = i2c_stsobjs + ctrl; if (out_size == 0 && in_size == 0) return EC_SUCCESS; @@ -408,7 +438,10 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, p_status->task_waiting = task_get_current(); interrupt_enable(); - /* Copy data to port struct */ + /* Select port for multi-ports i2c controller */ + i2c_select_port(port); + + /* Copy data to controller struct */ p_status->flags = flags; p_status->tx_buf = out; p_status->sz_txbuf = out_size; @@ -426,30 +459,32 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, p_status->err_code = SMB_OK; /* Make sure we're in a good state to start */ - if ((flags & I2C_XFER_START) && (i2c_bus_busy(port) + if ((flags & I2C_XFER_START) && (i2c_bus_busy(ctrl) || (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { - /* Attempt to unwedge the port. */ - i2c_unwedge(port); - /* recovery i2c port */ - i2c_recovery(port); + /* Attempt to unwedge the controller. */ + i2c_unwedge(ctrl); + /* recovery i2c controller */ + i2c_recovery(ctrl); + /* Select port again for recovery */ + i2c_select_port(port); } /* Enable SMB interrupt and New Address Match interrupt source */ - SET_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_NMINTE); - SET_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_INTEN); + SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_NMINTE); + SET_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_INTEN); CPUTS("\n"); /* Start master transaction */ - i2c_master_transaction(port); + i2c_master_transaction(ctrl); /* Reset task ID */ p_status->task_waiting = TASK_ID_INVALID; /* Disable SMB interrupt and New Address Match interrupt source */ - CLEAR_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_NMINTE); - CLEAR_BIT(NPCX_SMBCTL1(port), NPCX_SMBCTL1_INTEN); + CLEAR_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_NMINTE); + CLEAR_BIT(NPCX_SMBCTL1(ctrl), NPCX_SMBCTL1_INTEN); CPRINTS("-Err:0x%02x\n", p_status->err_code); @@ -460,8 +495,8 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, * Return raw I/O line levels (I2C_LINE_*) for a port when port is in alternate * function mode. * - * @param port Port to check - * @return State of SCL/SDA bit 0/1 + * @param port Port to check + * @return State of SCL/SDA bit 0/1 */ int i2c_get_line_levels(int port) { @@ -469,17 +504,35 @@ 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 * 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; - /* Check do we support this port of i2c and return gpio number of scl */ - if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) -#if !(I2C_LEVEL_SUPPORT) - return gpio_get_level(g); -#else - return IS_BIT_SET(NPCX_SMBCTL3(port), NPCX_SMBCTL3_SCL_LVL); -#endif + /* + * Check do we support this port of i2c and return gpio number of scl. + * Please notice we cannot read voltage level from GPIO in M4 EC + */ + if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS) { + if (i2c_is_raw_mode(port)) + return gpio_get_level(g); + else + return IS_BIT_SET(NPCX_SMBCTL3( + i2c_port_to_controller(port)), NPCX_SMBCTL3_SCL_LVL); + } /* If no SCL pin defined for this port, then return 1 to appear idle */ return 1; @@ -488,13 +541,19 @@ int i2c_raw_get_scl(int port) int i2c_raw_get_sda(int port) { enum gpio_signal g; - /* Check do we support this port of i2c and return gpio number of scl */ - if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) -#if !(I2C_LEVEL_SUPPORT) - return gpio_get_level(g); -#else - return IS_BIT_SET(NPCX_SMBCTL3(port), NPCX_SMBCTL3_SDA_LVL); -#endif + + /* + * Check do we support this port of i2c and return gpio number of scl. + * Please notice we cannot read voltage level from GPIO in M4 EC + */ + if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS) { + if (i2c_is_raw_mode(port)) + return gpio_get_level(g); + else + return IS_BIT_SET(NPCX_SMBCTL3( + i2c_port_to_controller(port)), NPCX_SMBCTL3_SDA_LVL); + } + /* If no SDA pin defined for this port, then return 1 to appear idle */ return 1; @@ -508,17 +567,17 @@ static void i2c_freq_changed(void) for (i = 0; i < i2c_ports_used; i++) { int bus_freq = i2c_ports[i].kbps; - int port = i2c_ports[i].port; + int ctrl = i2c_port_to_controller(i2c_ports[i].port); int scl_time; /* SMB0/1 use core clock & SMB2/3 use apb2 clock */ - if (port < 2) + if (ctrl < 2) freq = clock_get_freq(); else freq = clock_get_apb2_freq(); /* use Fast Mode */ - SET_BIT(NPCX_SMBCTL3(port) , NPCX_SMBCTL3_400K); + SET_BIT(NPCX_SMBCTL3(ctrl) , NPCX_SMBCTL3_400K); /* * Set SCLLT/SCLHT: @@ -530,8 +589,8 @@ static void i2c_freq_changed(void) scl_time = (freq/1000) / (bus_freq * 4); /* bus_freq is KHz */ /* set SCL High/Low time */ - NPCX_SMBSCLLT(port) = scl_time; - NPCX_SMBSCLHT(port) = scl_time; + NPCX_SMBSCLLT(ctrl) = scl_time; + NPCX_SMBSCLHT(ctrl) = scl_time; } } DECLARE_HOOK(HOOK_FREQ_CHANGE, i2c_freq_changed, HOOK_PRIO_DEFAULT); @@ -553,38 +612,50 @@ static void i2c_init(void) */ for (i = 0; i < i2c_ports_used; i++) { int port = i2c_ports[i].port; - volatile struct i2c_status *p_status = i2c_stsobjs + port; + int ctrl = i2c_port_to_controller(port); + volatile struct i2c_status *p_status = i2c_stsobjs + ctrl; /* Configure pull-up for SMB interface pins */ /* Enable 3.3V pull-up or turn to 1.8V support */ - if (port == NPCX_I2C_PORT0) { -#if NPCX_I2C0_BUS2 - SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(port, 1)); + if (port == NPCX_I2C_PORT0_0) { +#ifdef NPCX_I2C0_0_1P8V + SET_BIT(NPCX_LV_GPIO_CTL0, NPCX_LV_GPIO_CTL0_SC0_0_LV); + SET_BIT(NPCX_LV_GPIO_CTL0, NPCX_LV_GPIO_CTL0_SD0_0_LV); +#else + SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(ctrl, 0)); +#endif + } else if (port == NPCX_I2C_PORT0_1) { +#ifdef NPCX_I2C0_1_1P8V + SET_BIT(NPCX_LV_GPIO_CTL1, NPCX_LV_GPIO_CTL0_SC0_1_LV); + SET_BIT(NPCX_LV_GPIO_CTL1, NPCX_LV_GPIO_CTL0_SD0_1_LV); +#else + SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(ctrl, 1)); +#endif + } else if (port == NPCX_I2C_PORT1) { +#ifdef NPCX_I2C1_1P8V + SET_BIT(NPCX_LV_GPIO_CTL0, NPCX_LV_GPIO_CTL0_SC1_0_LV); + SET_BIT(NPCX_LV_GPIO_CTL0, NPCX_LV_GPIO_CTL0_SD1_0_LV); #else - SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(port, 0)); + SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(ctrl, 0)); #endif } else if (port == NPCX_I2C_PORT2) { #ifdef NPCX_I2C2_1P8V SET_BIT(NPCX_LV_GPIO_CTL1, NPCX_LV_GPIO_CTL1_SC2_0_LV); SET_BIT(NPCX_LV_GPIO_CTL1, NPCX_LV_GPIO_CTL1_SD2_0_LV); #else - SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(port, 0)); + SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(ctrl, 0)); #endif } else if (port == NPCX_I2C_PORT3) { #ifdef NPCX_I2C3_1P8V SET_BIT(NPCX_LV_GPIO_CTL1, NPCX_LV_GPIO_CTL1_SC3_0_LV); SET_BIT(NPCX_LV_GPIO_CTL1, NPCX_LV_GPIO_CTL1_SD3_0_LV); #else - SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(port, 0)); + SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(ctrl, 0)); #endif - - SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(port, 0)); - } else { - SET_BIT(NPCX_DEVPU0, NPCX_I2C_PUBIT(port, 0)); } /* Enable module - before configuring CTL1 */ - SET_BIT(NPCX_SMBCTL2(port), NPCX_SMBCTL2_ENABLE); + SET_BIT(NPCX_SMBCTL2(ctrl), NPCX_SMBCTL2_ENABLE); /* status init */ p_status->oper_state = SMB_IDLE; @@ -593,7 +664,10 @@ static void i2c_init(void) p_status->task_waiting = TASK_ID_INVALID; /* Enable event and error interrupts */ - task_enable_irq(i2c_irqs[port]); + task_enable_irq(i2c_irqs[ctrl]); + + /* Use default timeout. */ + i2c_set_timeout(port, 0); } } DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C); diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c index 03aa36f55a..e135fabaa6 100644 --- a/chip/npcx/lpc.c +++ b/chip/npcx/lpc.c @@ -546,10 +546,10 @@ void lpc_pmc_obe_interrupt(void) } DECLARE_IRQ(NPCX_IRQ_PM_CHAN_OBE, lpc_pmc_obe_interrupt, 2); - void lpc_port80_interrupt(void) { - port_80_write((NPCX_GLUE_SDPD0<<0) | (NPCX_GLUE_SDPD1<<8)); + port_80_write(NPCX_DP80BUF); + /* No matter what , just clear error status bit */ SET_BIT(NPCX_DP80STS, 7); SET_BIT(NPCX_DP80STS, 5); diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h index d981540bb6..fbcf7991dc 100644 --- a/chip/npcx/registers.h +++ b/chip/npcx/registers.h @@ -29,7 +29,6 @@ /* Global Definition */ #define CHIP_VERSION 3 /* A3 version */ #define I2C_7BITS_ADDR 0 -#define I2C_LEVEL_SUPPORT 1 /* Switcher of features */ #define SUPPORT_LCT 1 #define SUPPORT_WDG 1 @@ -283,6 +282,7 @@ #define NPCX_GLUE_SDPD0 REG8(NPCX_GLUE_REGS_BASE + 0x010) #define NPCX_GLUE_SDPD1 REG8(NPCX_GLUE_REGS_BASE + 0x012) #define NPCX_GLUE_SDP_CTS REG8(NPCX_GLUE_REGS_BASE + 0x014) +#define NPCX_GLUE_SMBSEL REG8(NPCX_GLUE_REGS_BASE + 0x021) /******************************************************************************/ /* MIWU registers */ @@ -569,6 +569,13 @@ enum { /* Others bit definitions */ #define NPCX_LFCGCALCNT_LPREG_CTL_EN 1 +#define NPCX_LV_GPIO_CTL0_SC0_0_LV 0 +#define NPCX_LV_GPIO_CTL0_SD0_0_LV 1 +#define NPCX_LV_GPIO_CTL0_SC0_1_LV 2 +#define NPCX_LV_GPIO_CTL0_SD0_1_LV 3 +#define NPCX_LV_GPIO_CTL0_SC1_0_LV 4 +#define NPCX_LV_GPIO_CTL0_SD1_0_LV 5 + #define NPCX_LV_GPIO_CTL1_SC2_0_LV 0 #define NPCX_LV_GPIO_CTL1_SD2_0_LV 1 #define NPCX_LV_GPIO_CTL1_SC3_0_LV 2 @@ -657,16 +664,18 @@ enum { #define NPCX_SMBADDR6_SAEN 7 #define NPCX_SMBADDR7_SAEN 7 #define NPCX_SMBADDR8_SAEN 7 +#define NPCX_SMBSEL_SMB0SEL 0 /* * SMB enumeration * I2C Port. */ enum NPCX_I2C_PORT_T { - NPCX_I2C_PORT0 = 0, /* I2C port 0, bus 0/1*/ - NPCX_I2C_PORT1 = 1, /* I2C port 1 */ - NPCX_I2C_PORT2 = 2, /* I2C port 2 */ - NPCX_I2C_PORT3 = 3, /* I2C port 3 */ + 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 */ }; /******************************************************************************/ diff --git a/chip/npcx/system.c b/chip/npcx/system.c index 973cb84c0c..525049acba 100644 --- a/chip/npcx/system.c +++ b/chip/npcx/system.c @@ -482,11 +482,9 @@ void system_reset(int flags) /* Save reset flag */ if (flags & SYSTEM_RESET_HARD) save_flags |= RESET_FLAG_HARD; - else { + else save_flags |= RESET_FLAG_SOFT; - /* Use SYSRESETREQ to trigger a soft reboot */ - CPU_NVIC_APINT = 0x05fa0004; - } + /* Store flags to battery backed RAM. */ bbram_data_write(BBRM_DATA_INDEX_SAVED_RESET_FLAGS, save_flags); |