From 5dd8aa92f274180fbbdd4dc7122eaa7bd1f9d8f9 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Wed, 15 Apr 2015 17:40:29 -0700 Subject: mec1322: i2c: Support multiple I2C ports on the same controller mec1322 I2C controller 0 has two attached ports. Modify the I2C driver so that both ports are usable. BUG=chrome-os-partner:38335,chrome-os-partner:38945 TEST=Manual on strago. Verify that i2cscan is functional. BRANCH=None Change-Id: I18d9d516984d041a38c86fd4ec1b0bfa4e885c9f Signed-off-by: Shawn Nematbakhsh Reviewed-on: https://chromium-review.googlesource.com/265951 Reviewed-by: Divya Jyothi Reviewed-by: Alec Berg --- board/cyan/board.c | 4 +- board/cyan/board.h | 16 ++-- board/glower/board.c | 4 +- board/glower/board.h | 6 +- board/mec1322_evb/board.c | 2 +- board/strago/board.c | 8 +- board/strago/board.h | 20 ++--- chip/mec1322/config_chip.h | 10 ++- chip/mec1322/i2c.c | 204 +++++++++++++++++++++++++++++---------------- chip/mec1322/registers.h | 63 ++++++++------ 10 files changed, 204 insertions(+), 133 deletions(-) diff --git a/board/cyan/board.c b/board/cyan/board.c index fae57393ba..5d6b62220b 100644 --- a/board/cyan/board.c +++ b/board/cyan/board.c @@ -47,8 +47,8 @@ const struct power_signal_info power_signal_list[] = { BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); const struct i2c_port_t i2c_ports[] = { - {"I2C0", I2C_PORT0, 100, GPIO_I2C_PORT0_SCL, GPIO_I2C_PORT0_SDA}, - {"I2C1", I2C_PORT1, 100, GPIO_I2C_PORT1_SCL, GPIO_I2C_PORT1_SDA}, + {"I2C0", MEC1322_I2C0_0, 100, GPIO_I2C_PORT0_SCL, GPIO_I2C_PORT0_SDA}, + {"I2C1", MEC1322_I2C1, 100, GPIO_I2C_PORT1_SCL, GPIO_I2C_PORT1_SDA}, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/cyan/board.h b/board/cyan/board.h index 527ab7af34..3ebd58128a 100644 --- a/board/cyan/board.h +++ b/board/cyan/board.h @@ -44,16 +44,6 @@ /* TODO: Add flash protect support for the SPI part cyan actually has */ #define CONFIG_SPI_FLASH_W25Q64 -/* I2C ports */ -#define I2C_PORT0 0 -#define I2C_PORT1 1 - -#define I2C_PORT_BATTERY I2C_PORT0 -#define I2C_PORT_CHARGER I2C_PORT0 -#define I2C_PORT_THERMAL I2C_PORT0 - -#define I2C_PORT_ACCEL I2C_PORT1 - /* Temperature sensor */ #define CONFIG_TEMP_SENSOR #define CONFIG_TEMP_SENSOR_TMP432 @@ -76,6 +66,12 @@ #ifndef __ASSEMBLER__ #include "gpio_signal.h" +#include "registers.h" + +#define I2C_PORT_BATTERY MEC1322_I2C0_0 +#define I2C_PORT_CHARGER MEC1322_I2C0_0 +#define I2C_PORT_THERMAL MEC1322_I2C0_0 +#define I2C_PORT_ACCEL MEC1322_I2C1 /* power signal definitions */ enum power_signal { diff --git a/board/glower/board.c b/board/glower/board.c index 75c2dd3d99..6198c05c31 100644 --- a/board/glower/board.c +++ b/board/glower/board.c @@ -40,8 +40,8 @@ BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"batt_chg", 1, 100}, - {"thermal", 2, 100}, + {"batt_chg", MEC1322_I2C1, 100}, + {"thermal", MEC1322_I2C2, 100}, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/glower/board.h b/board/glower/board.h index a755ddbd83..a6a120332f 100644 --- a/board/glower/board.h +++ b/board/glower/board.h @@ -71,9 +71,9 @@ #ifndef __ASSEMBLER__ /* I2C ports */ -#define I2C_PORT_BATTERY 1 -#define I2C_PORT_CHARGER 1 -#define I2C_PORT_THERMAL 2 +#define I2C_PORT_BATTERY MEC1322_I2C1 +#define I2C_PORT_CHARGER MEC1322_I2C1 +#define I2C_PORT_THERMAL MEC1322_I2C2 /* USB ports */ #define USB_PORT_COUNT 2 diff --git a/board/mec1322_evb/board.c b/board/mec1322_evb/board.c index 774abe0239..e6d4add57e 100644 --- a/board/mec1322_evb/board.c +++ b/board/mec1322_evb/board.c @@ -41,6 +41,6 @@ BUILD_ASSERT(ARRAY_SIZE(fans) == CONFIG_FANS); /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"port0", 0, 100}, + {"port0", MEC1322_I2C0_0, 100}, }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/strago/board.c b/board/strago/board.c index e175fc1f75..9f2475d040 100644 --- a/board/strago/board.c +++ b/board/strago/board.c @@ -51,10 +51,10 @@ const struct power_signal_info power_signal_list[] = { BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); const struct i2c_port_t i2c_ports[] = { - {"batt_chg", 0, 100}, - {"sensors", 1, 100}, - {"pd_mcu", 2, 100}, - {"thermal", 3, 100} + {"batt_chg", MEC1322_I2C0_0, 100}, + {"sensors", MEC1322_I2C1, 100}, + {"pd_mcu", MEC1322_I2C2, 100}, + {"thermal", MEC1322_I2C3, 100} }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); diff --git a/board/strago/board.h b/board/strago/board.h index b98b2b654f..2c354dcac2 100644 --- a/board/strago/board.h +++ b/board/strago/board.h @@ -8,7 +8,6 @@ #ifndef __BOARD_H #define __BOARD_H - /* Optional features */ #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands */ #define CONFIG_WATCHDOG_HELP @@ -49,15 +48,6 @@ #define CONFIG_I2C -/* I2C ports */ -#define I2C_PORT_BATTERY 0 -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_GYRO 1 -#define I2C_PORT_ALS 1 -#define I2C_PORT_PD_MCU 2 -#define I2C_PORT_THERMAL 3 - /* Accelerometer */ #define CONFIG_ACCEL_KXCJ9 #define CONFIG_CMD_ACCELS @@ -77,6 +67,16 @@ #ifndef __ASSEMBLER__ #include "gpio_signal.h" +#include "registers.h" + +/* I2C ports */ +#define I2C_PORT_BATTERY MEC1322_I2C0_0 +#define I2C_PORT_CHARGER MEC1322_I2C0_0 +#define I2C_PORT_ACCEL MEC1322_I2C1 +#define I2C_PORT_GYRO MEC1322_I2C1 +#define I2C_PORT_ALS MEC1322_I2C1 +#define I2C_PORT_PD_MCU MEC1322_I2C2 +#define I2C_PORT_THERMAL MEC1322_I2C3 /* power signal definitions */ enum power_signal { diff --git a/chip/mec1322/config_chip.h b/chip/mec1322/config_chip.h index 43f9974222..ecf2f5ade8 100644 --- a/chip/mec1322/config_chip.h +++ b/chip/mec1322/config_chip.h @@ -23,8 +23,14 @@ /* Maximum number of deferrable functions */ #define DEFERRABLE_MAX_COUNT 8 -/* Number of I2C ports */ -#define I2C_PORT_COUNT 4 +/* + * Number of I2C controllers. Controller 0 has 2 ports, so the chip has one + * additional port. + */ +#define CONFIG_I2C_MULTI_PORT_CONTROLLER + +#define I2C_CONTROLLER_COUNT 4 +#define I2C_PORT_COUNT 5 /****************************************************************************/ /* Memory mapping */ diff --git a/chip/mec1322/i2c.c b/chip/mec1322/i2c.c index 85a8e2a02b..e9491d31b9 100644 --- a/chip/mec1322/i2c.c +++ b/chip/mec1322/i2c.c @@ -38,9 +38,9 @@ /* Maximum transfer of a SMBUS block transfer */ #define SMBUS_MAX_BLOCK_SIZE 32 -static task_id_t task_waiting_on_port[I2C_PORT_COUNT]; +static task_id_t task_waiting_on_controller[I2C_CONTROLLER_COUNT]; -static void configure_port_speed(int port, int kbps) +static void configure_controller_speed(int controller, int kbps) { int min_t_low, min_t_high; int t_low, t_high; @@ -56,62 +56,63 @@ static void configure_port_speed(int port, int kbps) /* Fast mode plus */ min_t_low = I2C_CLOCK * 0.5 / 1000000 - 1; /* 0.5 us */ min_t_high = I2C_CLOCK * 0.26 / 1000000 - 1; /* 0.26 us */ - MEC1322_I2C_DATA_TIM(port) = 0x06060601; - MEC1322_I2C_DATA_TIM_2(port) = 0x06; + MEC1322_I2C_DATA_TIM(controller) = 0x06060601; + MEC1322_I2C_DATA_TIM_2(controller) = 0x06; } else if (kbps > 100) { /* Fast mode */ min_t_low = I2C_CLOCK * 1.3 / 1000000 - 1; /* 1.3 us */ min_t_high = I2C_CLOCK * 0.6 / 1000000 - 1; /* 0.6 us */ - MEC1322_I2C_DATA_TIM(port) = 0x040a0a01; - MEC1322_I2C_DATA_TIM_2(port) = 0x0a; + MEC1322_I2C_DATA_TIM(controller) = 0x040a0a01; + MEC1322_I2C_DATA_TIM_2(controller) = 0x0a; } else { /* Standard mode */ min_t_low = I2C_CLOCK * 4.7 / 1000000 - 1; /* 4.7 us */ min_t_high = I2C_CLOCK * 4.0 / 1000000 - 1; /* 4.0 us */ - MEC1322_I2C_DATA_TIM(port) = 0x0c4d5006; - MEC1322_I2C_DATA_TIM_2(port) = 0x4d; + MEC1322_I2C_DATA_TIM(controller) = 0x0c4d5006; + MEC1322_I2C_DATA_TIM_2(controller) = 0x4d; } t_low = MAX(min_t_low + 1, period / 2); t_high = MAX(min_t_high + 1, period - t_low); - MEC1322_I2C_BUS_CLK(port) = ((t_high & 0xff) << 8) | - (t_low & 0xff); + MEC1322_I2C_BUS_CLK(controller) = ((t_high & 0xff) << 8) | + (t_low & 0xff); } -static void configure_port(int port, int kbps) +static void configure_controller(int controller, int kbps) { - MEC1322_I2C_CTRL(port) = CTRL_PIN; - MEC1322_I2C_OWN_ADDR(port) = 0x0; - configure_port_speed(port, kbps); - MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | CTRL_ACK | CTRL_ENI; - MEC1322_I2C_CONFIG(port) |= 1 << 10; /* ENAB */ + MEC1322_I2C_CTRL(controller) = CTRL_PIN; + MEC1322_I2C_OWN_ADDR(controller) = 0x0; + configure_controller_speed(controller, kbps); + MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | + CTRL_ACK | CTRL_ENI; + MEC1322_I2C_CONFIG(controller) |= 1 << 10; /* ENAB */ /* Enable interrupt */ - MEC1322_I2C_CONFIG(port) |= 1 << 29; /* ENIDI */ - MEC1322_INT_ENABLE(12) |= (1 << port); + MEC1322_I2C_CONFIG(controller) |= 1 << 29; /* ENIDI */ + MEC1322_INT_ENABLE(12) |= (1 << controller); MEC1322_INT_BLK_EN |= 1 << 12; } -static void reset_port(int port) +static void reset_controller(int controller) { int i; - MEC1322_I2C_CONFIG(port) |= 1 << 9; + MEC1322_I2C_CONFIG(controller) |= 1 << 9; udelay(100); - MEC1322_I2C_CONFIG(port) &= ~(1 << 9); + MEC1322_I2C_CONFIG(controller) &= ~(1 << 9); for (i = 0; i < i2c_ports_used; ++i) - if (port == i2c_ports[i].port) { - configure_port(i2c_ports[i].port, i2c_ports[i].kbps); + if (controller == i2c_port_to_controller(i2c_ports[i].port)) { + configure_controller(controller, i2c_ports[i].kbps); break; } } -static int wait_for_interrupt(int port, int *event) +static int wait_for_interrupt(int controller, int *event) { - task_waiting_on_port[port] = task_get_current(); - task_enable_irq(MEC1322_IRQ_I2C_0 + port); + task_waiting_on_controller[controller] = task_get_current(); + task_enable_irq(MEC1322_IRQ_I2C_0 + controller); /* * We want to wait here quietly until the I2C interrupt comes * along, but we don't want to lose any pending events that @@ -121,7 +122,7 @@ static int wait_for_interrupt(int port, int *event) * implementation of usleep() for a similar situation. */ *event |= (task_wait_event(SECOND) & ~TASK_EVENT_I2C_IDLE); - task_waiting_on_port[port] = TASK_ID_INVALID; + task_waiting_on_controller[controller] = TASK_ID_INVALID; if (*event & TASK_EVENT_TIMER) { /* Restore any events that we saw while waiting */ task_set_event(task_get_current(), @@ -131,17 +132,17 @@ static int wait_for_interrupt(int port, int *event) return EC_SUCCESS; } -static int wait_idle(int port) +static int wait_idle(int controller) { - uint8_t sts = MEC1322_I2C_STATUS(port); + uint8_t sts = MEC1322_I2C_STATUS(controller); int rv; int event = 0; while (!(sts & STS_NBB)) { - rv = wait_for_interrupt(port, &event); + rv = wait_for_interrupt(controller, &event); if (rv) return rv; - sts = MEC1322_I2C_STATUS(port); + sts = MEC1322_I2C_STATUS(controller); } /* * Restore any events that we saw while waiting. TASK_EVENT_TIMER isn't @@ -154,17 +155,17 @@ static int wait_idle(int port) return EC_SUCCESS; } -static int wait_byte_done(int port) +static int wait_byte_done(int controller) { - uint8_t sts = MEC1322_I2C_STATUS(port); + uint8_t sts = MEC1322_I2C_STATUS(controller); int rv; int event = 0; while (sts & STS_PIN) { - rv = wait_for_interrupt(port, &event); + rv = wait_for_interrupt(controller, &event); if (rv) return rv; - sts = MEC1322_I2C_STATUS(port); + sts = MEC1322_I2C_STATUS(controller); } /* * Restore any events that we saw while waiting. TASK_EVENT_TIMER isn't @@ -185,32 +186,56 @@ static inline void fill_in_buf(uint8_t *in, int id, uint8_t val) in[id - 1] = val; } +static void select_port(int port) +{ + /* + * I2C0_1 uses port 1 of controller 0. All other I2C pin sets + * use port 0. + */ + uint8_t port_sel = (port == MEC1322_I2C0_1) ? 1 : 0; + int controller = i2c_port_to_controller(port); + + MEC1322_I2C_CONFIG(controller) &= ~0xf; + MEC1322_I2C_CONFIG(controller) |= port_sel; + +} + +static inline int get_line_level(int controller) +{ + return (MEC1322_I2C_BB_CTRL(controller) >> 5) & 0x3; +} + int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { int i; + int controller; int started = (flags & I2C_XFER_START) ? 0 : 1; uint8_t reg_sts; if (out_size == 0 && in_size == 0) return EC_SUCCESS; - wait_idle(port); + select_port(port); + controller = i2c_port_to_controller(port); + wait_idle(controller); - reg_sts = MEC1322_I2C_STATUS(port); + reg_sts = MEC1322_I2C_STATUS(controller); if (!started && (((reg_sts & (STS_BER | STS_LAB)) || !(reg_sts & STS_NBB)) || - (i2c_get_line_levels(port) != I2C_LINE_IDLE))) { + (get_line_level(controller) + != I2C_LINE_IDLE))) { CPRINTS("I2C%d bad status 0x%02x, SCL=%d, SDA=%d", port, reg_sts, - i2c_get_line_levels(port) & I2C_LINE_SCL_HIGH, - i2c_get_line_levels(port) & I2C_LINE_SDA_HIGH); + get_line_level(controller) & I2C_LINE_SCL_HIGH, + get_line_level(controller) & I2C_LINE_SDA_HIGH); - /* Attempt to unwedge the port. */ - i2c_unwedge(port); + /* Attempt to unwedge the controller. */ + i2c_unwedge(controller); - /* Bus error, bus busy, or arbitration lost. Reset port. */ - reset_port(port); + /* Bus error, bus busy, or arbitration lost. Try reset. */ + reset_controller(controller); + select_port(port); /* * We don't know what edges the slave saw, so sleep long enough @@ -220,23 +245,24 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, } if (out) { - MEC1322_I2C_DATA(port) = (uint8_t)slave_addr; + MEC1322_I2C_DATA(controller) = (uint8_t)slave_addr; /* * Clock out the slave address. Send START bit if start flag is * set. */ - MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | CTRL_ENI | - CTRL_ACK | (started ? 0 : CTRL_STA); + MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ENI | + CTRL_ACK | + (started ? 0 : CTRL_STA); if (!started) started = 1; for (i = 0; i < out_size; ++i) { - if (wait_byte_done(port)) + if (wait_byte_done(controller)) goto err_i2c_xfer; - MEC1322_I2C_DATA(port) = out[i]; + MEC1322_I2C_DATA(controller) = out[i]; } - if (wait_byte_done(port)) + if (wait_byte_done(controller)) goto err_i2c_xfer; /* @@ -244,64 +270,66 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, * doesn't expect to receive data. */ if ((flags & I2C_XFER_STOP) && in_size == 0) { - MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | - CTRL_STO | CTRL_ACK; + MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | + CTRL_STO | CTRL_ACK; } } if (in_size) { if (out_size) { /* resend start bit when change direction */ - MEC1322_I2C_CTRL(port) = CTRL_ESO | CTRL_STA | - CTRL_ACK | CTRL_ENI; + MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_STA | + CTRL_ACK | CTRL_ENI; } - MEC1322_I2C_DATA(port) = (uint8_t)slave_addr | 0x01; + MEC1322_I2C_DATA(controller) = (uint8_t)slave_addr | 0x01; if (!started) { started = 1; /* Clock out slave address with START bit */ - MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | - CTRL_STA | CTRL_ACK | CTRL_ENI; + MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | + CTRL_STA | CTRL_ACK | + CTRL_ENI; } /* On MEC1322, first byte read is dummy read (slave addr) */ in_size++; for (i = 0; i < in_size - 2; ++i) { - if (wait_byte_done(port)) + if (wait_byte_done(controller)) goto err_i2c_xfer; - fill_in_buf(in, i, MEC1322_I2C_DATA(port)); + fill_in_buf(in, i, MEC1322_I2C_DATA(controller)); } - if (wait_byte_done(port)) + if (wait_byte_done(controller)) goto err_i2c_xfer; /* * De-assert ACK bit before reading the next to last byte, * so that the last byte is NACK'ed. */ - MEC1322_I2C_CTRL(port) = CTRL_ESO | CTRL_ENI; - fill_in_buf(in, in_size - 2, MEC1322_I2C_DATA(port)); - if (wait_byte_done(port)) + MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_ENI; + fill_in_buf(in, in_size - 2, MEC1322_I2C_DATA(controller)); + if (wait_byte_done(controller)) goto err_i2c_xfer; /* Send STOP if stop flag is set */ - MEC1322_I2C_CTRL(port) = + MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ACK | ((flags & I2C_XFER_STOP) ? CTRL_STO : 0); /* Now read the last byte */ - fill_in_buf(in, in_size - 1, MEC1322_I2C_DATA(port)); + fill_in_buf(in, in_size - 1, MEC1322_I2C_DATA(controller)); } /* Check for error conditions */ - if (MEC1322_I2C_STATUS(port) & (STS_LAB | STS_BER)) + if (MEC1322_I2C_STATUS(controller) & (STS_LAB | STS_BER)) return EC_ERROR_UNKNOWN; return EC_SUCCESS; err_i2c_xfer: /* Send STOP and return error */ - MEC1322_I2C_CTRL(port) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK; + MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | + CTRL_STO | CTRL_ACK; return EC_ERROR_UNKNOWN; } @@ -329,7 +357,13 @@ int i2c_raw_get_sda(int port) int i2c_get_line_levels(int port) { - return (MEC1322_I2C_BB_CTRL(port) >> 5) & 0x3; + int rv; + + i2c_lock(port, 1); + select_port(port); + rv = get_line_level(i2c_port_to_controller(port)); + i2c_lock(port, 0); + return rv; } int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, @@ -367,32 +401,54 @@ exit: return rv; } +int i2c_port_to_controller(int port) +{ + if (port < 0 || port >= MEC1322_I2C_PORT_COUNT) + return -1; + return (port == MEC1322_I2C0_0) ? 0 : port - 1; +} static void i2c_init(void) { int i; + int controller; + int controller0_kbps = -1; /* Configure GPIOs */ gpio_config_module(MODULE_I2C, 1); - for (i = 0; i < i2c_ports_used; ++i) - configure_port(i2c_ports[i].port, i2c_ports[i].kbps); + for (i = 0; i < i2c_ports_used; ++i) { + /* + * If this controller has multiple ports, check if we already + * configured it. If so, ensure previously configured bitrate + * matches. + */ + controller = i2c_port_to_controller(i2c_ports[i].port); + if (controller == 0) { + if (controller0_kbps != -1) { + ASSERT(controller0_kbps == i2c_ports[i].kbps); + continue; + } + controller0_kbps = i2c_ports[i].kbps; + } + configure_controller(controller, i2c_ports[i].kbps); + } } DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C); -static void handle_interrupt(int port) +static void handle_interrupt(int controller) { - int id = task_waiting_on_port[port]; + int id = task_waiting_on_controller[controller]; /* Clear the interrupt status */ - MEC1322_I2C_COMPLETE(port) |= 1 << 29; + MEC1322_I2C_COMPLETE(controller) |= 1 << 29; /* * Write to control register interferes with I2C transaction. * Instead, let's disable IRQ from the core until the next time * we want to wait for STS_PIN/STS_NBB. */ - task_disable_irq(MEC1322_IRQ_I2C_0 + port); + task_disable_irq(MEC1322_IRQ_I2C_0 + controller); /* Wake up the task which was waiting on the I2C interrupt, if any. */ if (id != TASK_ID_INVALID) diff --git a/chip/mec1322/registers.h b/chip/mec1322/registers.h index ca06cb25f5..af89609dc9 100644 --- a/chip/mec1322/registers.h +++ b/chip/mec1322/registers.h @@ -245,31 +245,44 @@ static inline uintptr_t gpio_port_base(int port_id) #define MEC1322_I2C2_BASE 0x4000b000 #define MEC1322_I2C3_BASE 0x4000b400 #define MEC1322_I2C_BASESEP 0x00000400 -#define MEC1322_I2C_ADDR(port, offset) \ - (offset + (port == 0 ? MEC1322_I2C0_BASE : \ - MEC1322_I2C1_BASE + MEC1322_I2C_BASESEP * (port - 1))) - -#define MEC1322_I2C_CTRL(port) REG8(MEC1322_I2C_ADDR(port, 0x0)) -#define MEC1322_I2C_STATUS(port) REG8(MEC1322_I2C_ADDR(port, 0x0)) -#define MEC1322_I2C_OWN_ADDR(port) REG16(MEC1322_I2C_ADDR(port, 0x4)) -#define MEC1322_I2C_DATA(port) REG8(MEC1322_I2C_ADDR(port, 0x8)) -#define MEC1322_I2C_MASTER_CMD(port) REG32(MEC1322_I2C_ADDR(port, 0xc)) -#define MEC1322_I2C_SLAVE_CMD(port) REG32(MEC1322_I2C_ADDR(port, 0x10)) -#define MEC1322_I2C_PEC(port) REG8(MEC1322_I2C_ADDR(port, 0x14)) -#define MEC1322_I2C_DATA_TIM_2(port) REG8(MEC1322_I2C_ADDR(port, 0x18)) -#define MEC1322_I2C_COMPLETE(port) REG32(MEC1322_I2C_ADDR(port, 0x20)) -#define MEC1322_I2C_IDLE_SCALE(port) REG32(MEC1322_I2C_ADDR(port, 0x24)) -#define MEC1322_I2C_CONFIG(port) REG32(MEC1322_I2C_ADDR(port, 0x28)) -#define MEC1322_I2C_BUS_CLK(port) REG16(MEC1322_I2C_ADDR(port, 0x2c)) -#define MEC1322_I2C_BLK_ID(port) REG8(MEC1322_I2C_ADDR(port, 0x30)) -#define MEC1322_I2C_REV(port) REG8(MEC1322_I2C_ADDR(port, 0x34)) -#define MEC1322_I2C_BB_CTRL(port) REG8(MEC1322_I2C_ADDR(port, 0x38)) -#define MEC1322_I2C_DATA_TIM(port) REG32(MEC1322_I2C_ADDR(port, 0x40)) -#define MEC1322_I2C_TOUT_SCALE(port) REG32(MEC1322_I2C_ADDR(port, 0x44)) -#define MEC1322_I2C_SLAVE_TX_BUF(port) REG8(MEC1322_I2C_ADDR(port, 0x48)) -#define MEC1322_I2C_SLAVE_RX_BUF(port) REG8(MEC1322_I2C_ADDR(port, 0x4c)) -#define MEC1322_I2C_MASTER_TX_BUF(port) REG8(MEC1322_I2C_ADDR(port, 0x50)) -#define MEC1322_I2C_MASTER_RX_BUF(port) REG8(MEC1322_I2C_ADDR(port, 0x54)) +#define MEC1322_I2C_ADDR(controller, offset) \ + (offset + (controller == 0 ? MEC1322_I2C0_BASE : \ + MEC1322_I2C1_BASE + MEC1322_I2C_BASESEP * (controller - 1))) + +/* + * MEC1322 has five ports distributed among four controllers. Locking must + * occur by-controller (not by-port). + */ +enum mec1322_i2c_port { + MEC1322_I2C0_0 = 0, /* Controller 0, port 0 */ + MEC1322_I2C0_1 = 1, /* Controller 0, port 1 */ + MEC1322_I2C1 = 2, /* Controller 1 */ + MEC1322_I2C2 = 3, /* Controller 2 */ + MEC1322_I2C3 = 4, /* Controller 3 */ + MEC1322_I2C_PORT_COUNT, +}; + +#define MEC1322_I2C_CTRL(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x0)) +#define MEC1322_I2C_STATUS(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x0)) +#define MEC1322_I2C_OWN_ADDR(ctrl) REG16(MEC1322_I2C_ADDR(ctrl, 0x4)) +#define MEC1322_I2C_DATA(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x8)) +#define MEC1322_I2C_MASTER_CMD(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0xc)) +#define MEC1322_I2C_SLAVE_CMD(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x10)) +#define MEC1322_I2C_PEC(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x14)) +#define MEC1322_I2C_DATA_TIM_2(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x18)) +#define MEC1322_I2C_COMPLETE(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x20)) +#define MEC1322_I2C_IDLE_SCALE(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x24)) +#define MEC1322_I2C_CONFIG(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x28)) +#define MEC1322_I2C_BUS_CLK(ctrl) REG16(MEC1322_I2C_ADDR(ctrl, 0x2c)) +#define MEC1322_I2C_BLK_ID(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x30)) +#define MEC1322_I2C_REV(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x34)) +#define MEC1322_I2C_BB_CTRL(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x38)) +#define MEC1322_I2C_DATA_TIM(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x40)) +#define MEC1322_I2C_TOUT_SCALE(ctrl) REG32(MEC1322_I2C_ADDR(ctrl, 0x44)) +#define MEC1322_I2C_SLAVE_TX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x48)) +#define MEC1322_I2C_SLAVE_RX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x4c)) +#define MEC1322_I2C_MASTER_TX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x50)) +#define MEC1322_I2C_MASTER_RX_BUF(ctrl) REG8(MEC1322_I2C_ADDR(ctrl, 0x54)) /* Keyboard scan matrix */ -- cgit v1.2.1