diff options
author | Scott Worley <scott.worley@microchip.corp-partner.google.com> | 2020-12-19 09:10:00 -0500 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-02-10 02:27:37 +0000 |
commit | b5e1a901f31c2900a93de67db16573b3c832ff81 (patch) | |
tree | 79dd7d86b83c5c3fb52f351cfa532c568410812c | |
parent | afa970e21552678c83beb55238f5e8be697a0520 (diff) | |
download | chrome-ec-b5e1a901f31c2900a93de67db16573b3c832ff81.tar.gz |
mchp: MEC152x increase number of I2C controllers
Microchip MEC152x has eight I2C controllers. The first five include
network layer DMA options the remaining three do not. The current I2C
driver does not use network layer therefore we updated the driver to
support all I2C controllers available.
BRANCH=none
BUG=b:177463787
TEST=Booted skylake RVP to Chrome OS
Signed-off-by: Scott Worley <scott.worley@microchip.corp-partner.google.com>
Change-Id: I30ebfa55faf8e3bdc02373726ad6ca5f696e77e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2601203
Reviewed-by: Ravin Kumar <ravin.kumar@microchip.com>
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Ravin Kumar <ravin.kumar@microchip.com>
-rw-r--r-- | chip/mchp/i2c.c | 418 |
1 files changed, 259 insertions, 159 deletions
diff --git a/chip/mchp/i2c.c b/chip/mchp/i2c.c index 606e931a13..fc032e138a 100644 --- a/chip/mchp/i2c.c +++ b/chip/mchp/i2c.c @@ -3,9 +3,7 @@ * found in the LICENSE file. */ -/* I2C port module for MCHP MEC - * TODO handle chip variants - */ +/* I2C port module for MCHP MEC */ #include "common.h" #include "console.h" @@ -14,69 +12,75 @@ #include "i2c.h" #include "registers.h" #include "task.h" +#include "tfdp_chip.h" #include "timer.h" #include "util.h" -#include "tfdp_chip.h" #define CPUTS(outstr) cputs(CC_I2C, outstr) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) +#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) /* * MCHP I2C BAUD clock source is 16 MHz. */ -#define I2C_CLOCK 16000000 /* 16 MHz */ +#define I2C_CLOCK 16000000UL +#define MCHP_I2C_SUPPORTED_BUS_CLOCKS 6 /* SMBus Timing values for 1MHz Speed */ -#define SPEED_1MHZ_BUS_CLOCK 0x0509 -#define SPEED_1MHZ_DATA_TIMING 0x06060601 -#define SPEED_1MHZ_DATA_TIMING_2 0x06 -#define SPEED_1MHZ_IDLE_SCALING 0x01000050 -#define SPEED_1MHZ_TIMEOUT_SCALING 0x149CC2C7 +#define SPEED_1MHZ_BUS_CLOCK 0x0509ul +#define SPEED_1MHZ_DATA_TIMING 0x06060601ul +#define SPEED_1MHZ_DATA_TIMING_2 0x06ul +#define SPEED_1MHZ_IDLE_SCALING 0x01000050ul +#define SPEED_1MHZ_TIMEOUT_SCALING 0x149CC2C7ul /* SMBus Timing values for 400kHz speed */ -#define SPEED_400KHZ_BUS_CLOCK 0x0F17 -#define SPEED_400KHZ_DATA_TIMING 0x040A0F01 -#define SPEED_400KHZ_DATA_TIMING_2 0x0A -#define SPEED_400KHZ_IDLE_SCALING 0x01000050 -#define SPEED_400KHZ_TIMEOUT_SCALING 0x149CC2C7 +#define SPEED_400KHZ_BUS_CLOCK 0x0F17ul +#define SPEED_400KHZ_DATA_TIMING 0x040A0F01ul +#define SPEED_400KHZ_DATA_TIMING_2 0x0Aul +#define SPEED_400KHZ_IDLE_SCALING 0x01000050ul +#define SPEED_400KHZ_TIMEOUT_SCALING 0x149CC2C7ul /* SMBus Timing values for 100kHz speed */ #define SPEED_100KHZ_BUS_CLOCK 0x4F4Ful #define SPEED_100KHZ_DATA_TIMING 0x0C4D4306ul #define SPEED_100KHZ_DATA_TIMING_2 0x4Dul #define SPEED_100KHZ_IDLE_SCALING 0x01FC01EDul #define SPEED_100KHZ_TIMEOUT_SCALING 0x4B9CC2C7ul +/* Bus clock dividers for 333, 80, and 40 kHz */ +#define SPEED_333KHZ_BUS_CLOCK 0x0F1Ful +#define SPEED_80KHZ_BUS_CLOCK 0x6363ul +#define SPEED_40KHZ_BUS_CLOCK 0xC7C7ul + /* Status */ -#define STS_NBB BIT(0) /* Bus busy */ -#define STS_LAB BIT(1) /* Arbitration lost */ -#define STS_LRB BIT(3) /* Last received bit */ -#define STS_BER BIT(4) /* Bus error */ -#define STS_PIN BIT(7) /* Pending interrupt */ +#define STS_NBB BIT(0) /* Bus busy */ +#define STS_LAB BIT(1) /* Arbitration lost */ +#define STS_LRB BIT(3) /* Last received bit */ +#define STS_BER BIT(4) /* Bus error */ +#define STS_PIN BIT(7) /* Pending interrupt */ /* Control */ -#define CTRL_ACK BIT(0) /* Acknowledge */ -#define CTRL_STO BIT(1) /* STOP */ -#define CTRL_STA BIT(2) /* START */ -#define CTRL_ENI BIT(3) /* Enable interrupt */ -#define CTRL_ESO BIT(6) /* Enable serial output */ -#define CTRL_PIN BIT(7) /* Pending interrupt not */ +#define CTRL_ACK BIT(0) /* Acknowledge */ +#define CTRL_STO BIT(1) /* STOP */ +#define CTRL_STA BIT(2) /* START */ +#define CTRL_ENI BIT(3) /* Enable interrupt */ +#define CTRL_ESO BIT(6) /* Enable serial output */ +#define CTRL_PIN BIT(7) /* Pending interrupt not */ /* Completion */ -#define COMP_DTEN BIT(2) /* enable device timeouts */ -#define COMP_MCEN BIT(3) /* enable master cumulative timeouts */ -#define COMP_SCEN BIT(4) /* enable slave cumulative timeouts */ -#define COMP_BIDEN BIT(5) /* enable Bus idle timeouts */ -#define COMP_IDLE BIT(29) /* i2c bus is idle */ -#define COMP_RW_BITS_MASK 0x3C /* R/W bits mask */ +#define COMP_DTEN BIT(2) /* enable device timeouts */ +#define COMP_MCEN BIT(3) /* enable master cumulative timeouts */ +#define COMP_SCEN BIT(4) /* enable slave cumulative timeouts */ +#define COMP_BIDEN BIT(5) /* enable Bus idle timeouts */ +#define COMP_IDLE BIT(29) /* i2c bus is idle */ +#define COMP_RW_BITS_MASK 0x3C /* R/W bits mask */ /* Configuration */ -#define CFG_PORT_MASK (0x0F) /* port selection field */ -#define CFG_TCEN BIT(4) /* Enable HW bus timeouts */ -#define CFG_FEN BIT(8) /* enable input filtering */ -#define CFG_RESET BIT(9) /* reset controller */ -#define CFG_ENABLE BIT(10) /* enable controller */ -#define CFG_GC_DIS BIT(14) /* disable general call address */ -#define CFG_ENIDI BIT(29) /* Enable I2C idle interrupt */ +#define CFG_PORT_MASK (0x0F) /* port selection field */ +#define CFG_TCEN BIT(4) /* Enable HW bus timeouts */ +#define CFG_FEN BIT(8) /* enable input filtering */ +#define CFG_RESET BIT(9) /* reset controller */ +#define CFG_ENABLE BIT(10) /* enable controller */ +#define CFG_GC_DIS BIT(14) /* disable general call address */ +#define CFG_ENIDI BIT(29) /* Enable I2C idle interrupt */ /* Enable network layer master done interrupt */ -#define CFG_ENMI BIT(30) +#define CFG_ENMI BIT(30) /* Enable network layer slave done interrupt */ -#define CFG_ENSI BIT(31) +#define CFG_ENSI BIT(31) /* Master Command */ #define MCMD_MRUN BIT(0) #define MCMD_MPROCEED BIT(1) @@ -141,18 +145,53 @@ static struct { uint8_t lines; } cdata[I2C_CONTROLLER_COUNT]; -static const uint16_t i2c_controller_pcr[MCHP_I2C_CTRL_MAX] = { - MCHP_PCR_I2C0, - MCHP_PCR_I2C1, - MCHP_PCR_I2C2, - MCHP_PCR_I2C3 +static const uint16_t i2c_ctrl_nvic_id[] = { + MCHP_IRQ_I2C_0, MCHP_IRQ_I2C_1, MCHP_IRQ_I2C_2, MCHP_IRQ_I2C_3, +#if defined(CHIP_FAMILY_MEC152X) + MCHP_IRQ_I2C_4, MCHP_IRQ_I2C_5, MCHP_IRQ_I2C_6, MCHP_IRQ_I2C_7 +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_ctrl_nvic_id) == MCHP_I2C_CTRL_MAX); + +static const uint16_t i2c_controller_pcr[] = { + MCHP_PCR_I2C0, MCHP_PCR_I2C1, MCHP_PCR_I2C2, MCHP_PCR_I2C3, +#if defined(CHIP_FAMILY_MEC152X) + MCHP_PCR_I2C4, MCHP_PCR_I2C5, MCHP_PCR_I2C6, MCHP_PCR_I2C7, +#endif +}; +BUILD_ASSERT(ARRAY_SIZE(i2c_controller_pcr) == MCHP_I2C_CTRL_MAX); + +static uintptr_t i2c_ctrl_base_addr[] = { + MCHP_I2C0_BASE, MCHP_I2C1_BASE, MCHP_I2C2_BASE, MCHP_I2C3_BASE, +#if defined(CHIP_FAMILY_MEC152X) + MCHP_I2C4_BASE, + /* NOTE: 5-7 do not implement network layer hardware */ + MCHP_I2C5_BASE, MCHP_I2C6_BASE, MCHP_I2C7_BASE +#endif }; +BUILD_ASSERT(ARRAY_SIZE(i2c_ctrl_base_addr) == MCHP_I2C_CTRL_MAX); -static int chip_i2c_is_controller_valid(int controller) +static bool chip_i2c_is_controller_valid(int controller) { if ((controller < 0) || (controller >= MCHP_I2C_CTRL_MAX)) + return false; + return true; +} + +static uintptr_t chip_i2c_ctrl_base(int controller) +{ + if (!chip_i2c_is_controller_valid(controller)) + return 0; + + return i2c_ctrl_base_addr[controller]; +} + +static uint32_t chip_i2c_ctrl_nvic_id(int controller) +{ + if (!chip_i2c_is_controller_valid(controller)) return 0; - return 1; + + return (uint32_t)i2c_ctrl_nvic_id[controller]; } static void i2c_ctrl_slp_en(int controller, int sleep_en) @@ -184,39 +223,35 @@ struct i2c_bus_clk { }; const struct i2c_bus_clk i2c_freq_tbl[] = { - { 40, 0xC7C7 }, - { 80, 0x6363 }, - { 100, 0x4F4F }, - { 333, 0x0F1F }, - { 400, 0x0F17 }, - { 1000, 0x0509 }, + { 40, SPEED_40KHZ_BUS_CLOCK }, { 80, SPEED_80KHZ_BUS_CLOCK }, + { 100, SPEED_100KHZ_BUS_CLOCK }, { 333, SPEED_333KHZ_BUS_CLOCK }, + { 400, SPEED_400KHZ_BUS_CLOCK }, { 1000, SPEED_1MHZ_BUS_CLOCK }, }; +BUILD_ASSERT(ARRAY_SIZE(i2c_freq_tbl) == MCHP_I2C_SUPPORTED_BUS_CLOCKS); static int get_closest(int lesser, int greater, int target) { if (target - i2c_freq_tbl[lesser].freq_khz >= - i2c_freq_tbl[greater].freq_khz - target) + i2c_freq_tbl[greater].freq_khz - target) return greater; else return lesser; } /* - * Return index in i2c_freq_tbl of supported frequeny + * Return index in i2c_freq_tbl of supported frequencies * closest to requested frequency. */ static const struct i2c_bus_clk *get_supported_speed_idx(int req_kbps) { int i, limit, m, imax; - ASSERT(ARRAY_SIZE(i2c_freq_tbl) != 0); - if (req_kbps <= i2c_freq_tbl[0].freq_khz) return &i2c_freq_tbl[0]; imax = ARRAY_SIZE(i2c_freq_tbl); - if (req_kbps >= i2c_freq_tbl[imax-1].freq_khz) - return &i2c_freq_tbl[imax-1]; + if (req_kbps >= i2c_freq_tbl[imax - 1].freq_khz) + return &i2c_freq_tbl[imax - 1]; /* we only get here if ARRAY_SIZE(...) > 1 * and req_kbps is in range. @@ -229,15 +264,15 @@ static const struct i2c_bus_clk *get_supported_speed_idx(int req_kbps) break; if (req_kbps < i2c_freq_tbl[m].freq_khz) { - if (m > 0 && req_kbps > i2c_freq_tbl[m-1].freq_khz) { - m = get_closest(m-1, m, req_kbps); + if (m > 0 && req_kbps > i2c_freq_tbl[m - 1].freq_khz) { + m = get_closest(m - 1, m, req_kbps); break; } limit = m; } else { - if (m < imax-1 && - req_kbps < i2c_freq_tbl[m+1].freq_khz) { - m = get_closest(m, m+1, req_kbps); + if (m < imax - 1 && + req_kbps < i2c_freq_tbl[m + 1].freq_khz) { + m = get_closest(m, m + 1, req_kbps); break; } i = m + 1; @@ -258,25 +293,28 @@ static const struct i2c_bus_clk *get_supported_speed_idx(int req_kbps) static void configure_controller_speed(int controller, int kbps) { const struct i2c_bus_clk *p; + uintptr_t raddr; + + raddr = chip_i2c_ctrl_base(controller); p = get_supported_speed_idx(kbps); - MCHP_I2C_BUS_CLK(controller) = p->bus_clk; + MCHP_I2C_BUS_CLK(raddr) = p->bus_clk; if (p->freq_khz > 400) { /* Fast mode plus */ - MCHP_I2C_DATA_TIM(controller) = SPEED_1MHZ_DATA_TIMING; - MCHP_I2C_DATA_TIM_2(controller) = SPEED_1MHZ_DATA_TIMING_2; - MCHP_I2C_IDLE_SCALE(controller) = SPEED_1MHZ_IDLE_SCALING; - MCHP_I2C_TOUT_SCALE(controller) = SPEED_1MHZ_TIMEOUT_SCALING; + MCHP_I2C_DATA_TIM(raddr) = SPEED_1MHZ_DATA_TIMING; + MCHP_I2C_DATA_TIM_2(raddr) = SPEED_1MHZ_DATA_TIMING_2; + MCHP_I2C_IDLE_SCALE(raddr) = SPEED_1MHZ_IDLE_SCALING; + MCHP_I2C_TOUT_SCALE(raddr) = SPEED_1MHZ_TIMEOUT_SCALING; } else if (p->freq_khz > 100) { /* Fast mode */ - MCHP_I2C_DATA_TIM(controller) = SPEED_400KHZ_DATA_TIMING; - MCHP_I2C_DATA_TIM_2(controller) = SPEED_400KHZ_DATA_TIMING_2; - MCHP_I2C_IDLE_SCALE(controller) = SPEED_400KHZ_IDLE_SCALING; - MCHP_I2C_TOUT_SCALE(controller) = SPEED_400KHZ_TIMEOUT_SCALING; + MCHP_I2C_DATA_TIM(raddr) = SPEED_400KHZ_DATA_TIMING; + MCHP_I2C_DATA_TIM_2(raddr) = SPEED_400KHZ_DATA_TIMING_2; + MCHP_I2C_IDLE_SCALE(raddr) = SPEED_400KHZ_IDLE_SCALING; + MCHP_I2C_TOUT_SCALE(raddr) = SPEED_400KHZ_TIMEOUT_SCALING; } else { /* Standard mode */ - MCHP_I2C_DATA_TIM(controller) = SPEED_100KHZ_DATA_TIMING; - MCHP_I2C_DATA_TIM_2(controller) = SPEED_100KHZ_DATA_TIMING_2; - MCHP_I2C_IDLE_SCALE(controller) = SPEED_100KHZ_IDLE_SCALING; - MCHP_I2C_TOUT_SCALE(controller) = SPEED_100KHZ_TIMEOUT_SCALING; + MCHP_I2C_DATA_TIM(raddr) = SPEED_100KHZ_DATA_TIMING; + MCHP_I2C_DATA_TIM_2(raddr) = SPEED_100KHZ_DATA_TIMING_2; + MCHP_I2C_IDLE_SCALE(raddr) = SPEED_100KHZ_IDLE_SCALING; + MCHP_I2C_TOUT_SCALE(raddr) = SPEED_100KHZ_TIMEOUT_SCALING; } } @@ -286,19 +324,21 @@ static void configure_controller_speed(int controller, int kbps) */ static void enable_controller_irq(int controller) { - MCHP_INT_ENABLE(MCHP_I2C_GIRQ) = - MCHP_I2C_GIRQ_BIT(controller); - task_enable_irq(MCHP_IRQ_I2C_0 + controller); + uint32_t nvic_id = chip_i2c_ctrl_nvic_id(controller); + + MCHP_INT_ENABLE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); + task_enable_irq(nvic_id); } static void disable_controller_irq(int controller) { - MCHP_INT_DISABLE(MCHP_I2C_GIRQ) = - MCHP_I2C_GIRQ_BIT(controller); + uint32_t nvic_id = chip_i2c_ctrl_nvic_id(controller); + + MCHP_INT_DISABLE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); /* read back into read-only reg. to insure disable takes effect */ MCHP_INT_BLK_IRQ = MCHP_INT_DISABLE(MCHP_I2C_GIRQ); - task_disable_irq(MCHP_IRQ_I2C_0 + controller); - task_clear_pending_irq(MCHP_IRQ_I2C_0 + controller); + task_disable_irq(nvic_id); + task_clear_pending_irq(nvic_id); } /* @@ -307,49 +347,55 @@ static void disable_controller_irq(int controller) */ static void configure_controller(int controller, int port, int kbps) { - if (!chip_i2c_is_controller_valid(controller)) + uintptr_t raddr = chip_i2c_ctrl_base(controller); + + if (raddr == 0) return; disable_controller_irq(controller); - MCHP_INT_SOURCE(MCHP_I2C_GIRQ) = - MCHP_I2C_GIRQ_BIT(controller); + MCHP_INT_SOURCE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); /* set to default except for port select field b[3:0] */ - MCHP_I2C_CONFIG(controller) = (uint32_t)(port & 0xf); - MCHP_I2C_CTRL(controller) = CTRL_PIN; + MCHP_I2C_CONFIG(raddr) = (uint32_t)(port & 0xf); + MCHP_I2C_CTRL(raddr) = CTRL_PIN; /* Set both controller slave addresses to 0 the * general call address. We disable general call * below. */ - MCHP_I2C_OWN_ADDR(controller) = 0; + MCHP_I2C_OWN_ADDR(raddr) = 0; configure_controller_speed(controller, kbps); /* Controller timings done, clear RO status, enable * output, and ACK generation. */ - MCHP_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_ACK; /* filter enable, disable General Call */ - MCHP_I2C_CONFIG(controller) |= CFG_FEN + CFG_GC_DIS; + MCHP_I2C_CONFIG(raddr) |= CFG_FEN + CFG_GC_DIS; /* enable controller */ - MCHP_I2C_CONFIG(controller) |= CFG_ENABLE; + MCHP_I2C_CONFIG(raddr) |= CFG_ENABLE; } static void reset_controller(int controller) { int i; + uintptr_t raddr; + + raddr = chip_i2c_ctrl_base(controller); + if (raddr == 0) + return; /* Reset asserted for at least one AHB clock */ - MCHP_I2C_CONFIG(controller) |= BIT(9); + MCHP_I2C_CONFIG(raddr) |= BIT(9); MCHP_EC_ID_RO = 0; - MCHP_I2C_CONFIG(controller) &= ~BIT(9); + MCHP_I2C_CONFIG(raddr) &= ~BIT(9); for (i = 0; i < i2c_ports_used; ++i) if (controller == i2c_port_to_controller(i2c_ports[i].port)) { configure_controller(controller, i2c_ports[i].port, - i2c_ports[i].kbps); + i2c_ports[i].kbps); cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; break; @@ -383,18 +429,19 @@ static int wait_for_interrupt(int controller, int timeout) static int wait_idle(int controller) { - uint8_t sts = MCHP_I2C_STATUS(controller); + uintptr_t raddr = chip_i2c_ctrl_base(controller); uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; int rv = 0; + uint8_t sts = MCHP_I2C_STATUS(raddr); while (!(sts & STS_NBB)) { if (rv) return rv; if (get_time().val > block_timeout) rv = wait_for_interrupt(controller, - task_timeout - get_time().val); - sts = MCHP_I2C_STATUS(controller); + task_timeout - get_time().val); + sts = MCHP_I2C_STATUS(raddr); } if (sts & (STS_BER | STS_LAB)) @@ -423,22 +470,24 @@ static int wait_byte_done(int controller, uint8_t mask, uint8_t expected) { uint64_t block_timeout; uint64_t task_timeout; + uintptr_t raddr; int rv; uint8_t sts; rv = 0; + raddr = chip_i2c_ctrl_base(controller); block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; task_timeout = block_timeout + cdata[controller].timeout_us; - sts = MCHP_I2C_STATUS(controller); + sts = MCHP_I2C_STATUS(raddr); cdata[controller].hwsts = sts; while (sts & STS_PIN) { if (rv) return rv; if (get_time().val > block_timeout) { rv = wait_for_interrupt(controller, - task_timeout - get_time().val); + task_timeout - get_time().val); } - sts = MCHP_I2C_STATUS(controller); + sts = MCHP_I2C_STATUS(raddr); cdata[controller].hwsts = sts; } @@ -459,14 +508,16 @@ static int wait_byte_done(int controller, uint8_t mask, uint8_t expected) static void select_port(int port, int controller) { uint32_t port_sel; + uintptr_t raddr; + raddr = chip_i2c_ctrl_base(controller); port_sel = (uint32_t)(port & 0x0f); - if ((MCHP_I2C_CONFIG(controller) & 0x0f) == port_sel) + if ((MCHP_I2C_CONFIG(raddr) & 0x0f) == port_sel) return; - MCHP_I2C_CONFIG(controller) |= BIT(9); + MCHP_I2C_CONFIG(raddr) |= BIT(9); MCHP_EC_ID_RO = 0; /* extra write to read-only as delay */ - MCHP_I2C_CONFIG(controller) &= ~BIT(9); + MCHP_I2C_CONFIG(raddr) &= ~BIT(9); configure_controller(controller, port_sel, i2c_ports[port].kbps); } @@ -493,13 +544,16 @@ static uint32_t get_line_level(int port) */ static int i2c_check_recover(int port, int controller) { + uintptr_t raddr; uint32_t lines; uint8_t reg; + + raddr = chip_i2c_ctrl_base(controller); lines = get_line_level(port); - reg = MCHP_I2C_STATUS(controller); + reg = MCHP_I2C_STATUS(raddr); if ((((reg & (STS_BER | STS_LAB)) || !(reg & STS_NBB)) || - (lines != I2C_LINE_IDLE))) { + (lines != I2C_LINE_IDLE))) { cdata[controller].flags |= (1ul << 16); CPRINTS("I2C%d port%d recov status 0x%02x, SDA:SCL=0x%0x", controller, port, reg, lines); @@ -516,10 +570,10 @@ static int i2c_check_recover(int port, int controller) * that the slave will see the new start condition below. */ usleep(1000); - reg = MCHP_I2C_STATUS(controller); + reg = MCHP_I2C_STATUS(raddr); lines = get_line_level(port); if ((reg & (STS_BER | STS_LAB)) || !(reg & STS_NBB) || - (lines != I2C_LINE_IDLE)) + (lines != I2C_LINE_IDLE)) return EC_ERROR_UNKNOWN; } return EC_SUCCESS; @@ -539,16 +593,18 @@ static inline void push_in_buf(uint8_t **in, uint8_t val, int skip) */ static int i2c_mtx(int ctrl) { + uintptr_t raddr; int i, rv; + raddr = chip_i2c_ctrl_base(ctrl); rv = EC_SUCCESS; cdata[ctrl].flags |= (1ul << 1); if (cdata[ctrl].xflags & I2C_XFER_START) { cdata[ctrl].flags |= (1ul << 2); - MCHP_I2C_DATA(ctrl) = cdata[ctrl].slv_addr_8bit; + MCHP_I2C_DATA(raddr) = cdata[ctrl].slv_addr_8bit; /* Clock out the slave address, sending START bit */ - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI | - CTRL_ACK | CTRL_STA; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_ACK | CTRL_STA; cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN; } @@ -556,19 +612,19 @@ static int i2c_mtx(int ctrl) rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 17); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_ENI | CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_STO | CTRL_ACK; return rv; } cdata[ctrl].flags |= (1ul << 15); - MCHP_I2C_DATA(ctrl) = cdata[ctrl].outp[i]; + MCHP_I2C_DATA(raddr) = cdata[ctrl].outp[i]; } rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 18); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_STO | CTRL_ACK; return rv; } @@ -577,10 +633,10 @@ static int i2c_mtx(int ctrl) * doesn't expect to receive data. */ if ((cdata[ctrl].xflags & I2C_XFER_STOP) && - (cdata[ctrl].in_size == 0)) { + (cdata[ctrl].in_size == 0)) { cdata[ctrl].flags |= (1ul << 3); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | + CTRL_ACK; cdata[ctrl].transaction_state = I2C_TRANSACTION_STOPPED; } return rv; @@ -619,21 +675,24 @@ static int i2c_mtx(int ctrl) */ static int i2c_mrx_start(int ctrl) { - uint8_t u8; + uintptr_t raddr; int rv; + uint8_t u8; + + raddr = chip_i2c_ctrl_base(ctrl); cdata[ctrl].flags |= (1ul << 4); u8 = CTRL_ESO | CTRL_ENI | CTRL_STA | CTRL_ACK; if (cdata[ctrl].transaction_state == I2C_TRANSACTION_OPEN) { cdata[ctrl].flags |= (1ul << 5); /* Repeated-START then address */ - MCHP_I2C_CTRL(ctrl) = u8; + MCHP_I2C_CTRL(raddr) = u8; } - MCHP_I2C_DATA(ctrl) = cdata[ctrl].slv_addr_8bit | 0x01; + MCHP_I2C_DATA(raddr) = cdata[ctrl].slv_addr_8bit | 0x01; if (cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) { cdata[ctrl].flags |= (1ul << 6); /* address then START */ - MCHP_I2C_CTRL(ctrl) = u8 | CTRL_PIN; + MCHP_I2C_CTRL(raddr) = u8 | CTRL_PIN; } cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN; /* Controller generates START, transmits data(address) capturing @@ -646,8 +705,8 @@ static int i2c_mrx_start(int ctrl) rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 19); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | + CTRL_ACK; return rv; } /* if STOP requested and last 1 or 2 bytes prepare controller @@ -655,17 +714,16 @@ static int i2c_mrx_start(int ctrl) * controller is setup to NACK last byte. */ cdata[ctrl].flags |= (1ul << 8); - if (cdata[ctrl].xflags & I2C_XFER_STOP && - (cdata[ctrl].in_size < 2)) { + if (cdata[ctrl].xflags & I2C_XFER_STOP && (cdata[ctrl].in_size < 2)) { cdata[ctrl].flags |= (1ul << 9); - MCHP_I2C_CTRL(ctrl) = CTRL_ESO | CTRL_ENI; + MCHP_I2C_CTRL(raddr) = CTRL_ESO | CTRL_ENI; } /* * Read & discard slave address. * Generates clocks for next data */ cdata[ctrl].flags |= (1ul << 10); - u8 = MCHP_I2C_DATA(ctrl); + u8 = MCHP_I2C_DATA(raddr); return rv; } /* @@ -686,27 +744,30 @@ static int i2c_mrx_data(int ctrl) uint32_t stop = (uint32_t)cdata[ctrl].xflags & I2C_XFER_STOP; uint8_t *pdest = cdata[ctrl].inp; int rv; + uintptr_t raddr; + + raddr = chip_i2c_ctrl_base(ctrl); cdata[ctrl].flags |= (1ul << 11); while (nrx) { rv = wait_byte_done(ctrl, 0xff, 0x00); if (rv) { cdata[ctrl].flags |= (1ul << 20); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | + CTRL_ACK; return rv; } if (stop) { if (nrx == 2) { cdata[ctrl].flags |= (1ul << 12); - MCHP_I2C_CTRL(ctrl) = CTRL_ESO | CTRL_ENI; + MCHP_I2C_CTRL(raddr) = CTRL_ESO | CTRL_ENI; } else if (nrx == 1) { cdata[ctrl].flags |= (1ul << 13); - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | + CTRL_STO | CTRL_ACK; } } - *pdest++ = MCHP_I2C_DATA(ctrl); + *pdest++ = MCHP_I2C_DATA(raddr); nrx--; } cdata[ctrl].flags |= (1ul << 14); @@ -716,12 +777,12 @@ static int i2c_mrx_data(int ctrl) /* * Called from common/i2c_master */ -int chip_i2c_xfer(int port, uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +int chip_i2c_xfer(int port, uint16_t slave_addr_flags, const uint8_t *out, + int out_size, uint8_t *in, int in_size, int flags) { int ctrl; int ret_done; + uintptr_t raddr; if (out_size == 0 && in_size == 0) return EC_SUCCESS; @@ -730,6 +791,10 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, if (ctrl < 0) return EC_ERROR_INVAL; + raddr = chip_i2c_ctrl_base(ctrl); + if (raddr == 0) + return EC_ERROR_INVAL; + cdata[ctrl].flags = (1ul << 0); disable_controller_irq(ctrl); select_port(port, ctrl); @@ -749,7 +814,7 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, cdata[ctrl].xflags = flags; if ((flags & I2C_XFER_START) && - cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) { + cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) { wait_idle(ctrl); ret_done = i2c_check_recover(port, ctrl); if (ret_done) @@ -780,7 +845,7 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, wait_idle(ctrl); /* Check for error conditions */ - if (MCHP_I2C_STATUS(ctrl) & (STS_LAB | STS_BER)) { + if (MCHP_I2C_STATUS(raddr) & (STS_LAB | STS_BER)) { cdata[ctrl].flags |= (1ul << 21); goto err_chip_i2c_xfer; } @@ -789,15 +854,14 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags, err_chip_i2c_xfer: cdata[ctrl].flags |= (1ul << 22); - cdata[ctrl].hwsts2 = MCHP_I2C_STATUS(ctrl); /* record status */ + cdata[ctrl].hwsts2 = MCHP_I2C_STATUS(raddr); /* record status */ /* NOTE: writing I2C.Ctrl.PIN=1 will clear all bits * except NBB in I2C.Status */ - MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MCHP_I2C_CTRL(raddr) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK; cdata[ctrl].transaction_state = I2C_TRANSACTION_STOPPED; /* record status after STOP */ - cdata[ctrl].hwsts4 = MCHP_I2C_STATUS(ctrl); + cdata[ctrl].hwsts4 = MCHP_I2C_STATUS(raddr); /* record line levels. * Note line levels may reflect STOP condition @@ -900,10 +964,9 @@ void i2c_init(void) i2c_ctrl_slp_en(controller, 0); if (controller_kbps[controller] && - (controller_kbps[controller] != kbps)) { + (controller_kbps[controller] != kbps)) { CPRINTF("I2C[%d] init speed conflict: %d != %d\n", - controller, kbps, - controller_kbps[controller]); + controller, kbps, controller_kbps[controller]); kbps = MIN(kbps, controller_kbps[controller]); } @@ -916,7 +979,7 @@ void i2c_init(void) controller_kbps[controller] = pbc->freq_khz; configure_controller(controller, i2c_ports[i].port, - controller_kbps[controller]); + controller_kbps[controller]); cdata[controller].task_waiting = TASK_ID_INVALID; cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; /* Use default timeout. */ @@ -934,6 +997,7 @@ static void handle_interrupt(int controller) { uint32_t r; int id = cdata[controller].task_waiting; + uintptr_t raddr = chip_i2c_ctrl_base(controller); /* * Write to control register interferes with I2C transaction. @@ -941,10 +1005,10 @@ static void handle_interrupt(int controller) * we want to wait for STS_PIN/STS_NBB. */ disable_controller_irq(controller); - cdata[controller].hwsts3 = MCHP_I2C_STATUS(controller); + cdata[controller].hwsts3 = MCHP_I2C_STATUS(raddr); /* Clear all interrupt status */ - r = MCHP_I2C_COMPLETE(controller); - MCHP_I2C_COMPLETE(controller) = r; + r = MCHP_I2C_COMPLETE(raddr); + MCHP_I2C_COMPLETE(raddr) = r; cdata[controller].i2c_complete = r; MCHP_INT_SOURCE(MCHP_I2C_GIRQ) = MCHP_I2C_GIRQ_BIT(controller); @@ -953,12 +1017,48 @@ static void handle_interrupt(int controller) task_set_event(id, TASK_EVENT_I2C_IDLE); } -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); } +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_MEC152X) +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(MCHP_IRQ_I2C_0, i2c0_interrupt, 2); DECLARE_IRQ(MCHP_IRQ_I2C_1, i2c1_interrupt, 2); DECLARE_IRQ(MCHP_IRQ_I2C_2, i2c2_interrupt, 2); DECLARE_IRQ(MCHP_IRQ_I2C_3, i2c3_interrupt, 2); +#if defined(CHIP_FAMILY_MEC152X) +DECLARE_IRQ(MCHP_IRQ_I2C_4, i2c4_interrupt, 2); +DECLARE_IRQ(MCHP_IRQ_I2C_5, i2c5_interrupt, 2); +DECLARE_IRQ(MCHP_IRQ_I2C_6, i2c6_interrupt, 2); +DECLARE_IRQ(MCHP_IRQ_I2C_7, i2c7_interrupt, 2); +#endif |