From 7bfcb41d2cad36c220eee89576e41dacea870adb Mon Sep 17 00:00:00 2001 From: Scott Date: Tue, 4 Oct 2016 12:52:31 -0700 Subject: [PATCH] Cr50: I2CM: Enable i2c master for accessing INA chips On both Reef and Gru there are INA (shunt bus voltage monitor) ICs connected to the Cr50 I2C master bus. The use case for these chips is in a lab setting using case closed debugging. Power to the INA chips is controlled by a separate Cr50 gpio signal. By default, the INAs are powered off and the I2C master bus is not connected. A function ina_connect() is provided which needs to be called prior to attempting to access the INAs via I2C. BRANCH=none BUG=chrome-os-partner:57059 TEST=manual Tested both Reef and Gru. Verified that console command 'ccd ina on|off' works as expected and that can repeatedly read registers on the INA using the following command "i2cxfer r16 0 0x40 0". Read 0x2771 [10097] which is the default value. In addition wrote register 14 (bits 15:1 are writeable) and verified the value was able to read the value back which was written. Change-Id: I670f7897555dae29642264531599dc4471c52bbd Signed-off-by: Scott Reviewed-on: https://chromium-review.googlesource.com/394168 Commit-Ready: Scott Collyer Tested-by: Scott Collyer Reviewed-by: Bill Richardson --- board/cr50/board.c | 13 +++++++++++ board/cr50/board.h | 3 +++ board/cr50/gpio.inc | 12 ++++++---- board/cr50/rdd.c | 53 ++++++++++++++++++++++++++++++++++++++++++++- chip/g/rdd.h | 6 +++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/board/cr50/board.c b/board/cr50/board.c index 9a1be332b4..ed34fa3000 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -12,9 +12,11 @@ #include "flash_config.h" #include "gpio.h" #include "hooks.h" +#include "i2c.h" #include "i2cs.h" #include "init_chip.h" #include "nvmem.h" +#include "rdd.h" #include "registers.h" #include "signed_header.h" #include "spi.h" @@ -73,11 +75,19 @@ uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = { static uint32_t board_properties; static uint8_t reboot_request_posted; +/* I2C Port definition */ +const struct i2c_port_t i2c_ports[] = { + {"master", I2C_PORT_MASTER, 100, + GPIO_I2C_SCL_INA, GPIO_I2C_SDA_INA}, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + void post_reboot_request(void) { /* Reboot the device next time TPM reset is requested. */ reboot_request_posted = 1; } + /* * There's no way to trigger on both rising and falling edges, so force a * compiler error if we try. The workaround is to use the pinmux to connect @@ -595,6 +605,9 @@ static void servo_attached(void) /* Disconnect AP and EC UART when servo is attached */ uartn_tx_disconnect(UART_AP); uartn_tx_disconnect(UART_EC); + + /* Disconnect i2cm interface to ina */ + ina_disconnect(); } void device_state_on(enum gpio_signal signal) diff --git a/board/cr50/board.h b/board/cr50/board.h index fd59137090..10f99b7a75 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -213,7 +213,10 @@ enum nvmem_users { #define CONFIG_USB_FW_UPDATE #define CONFIG_I2C +#define CONFIG_I2C_MASTER #define CONFIG_I2C_SLAVE #define CONFIG_TPM_I2CS +#define I2C_PORT_MASTER 0 + #endif /* __CROS_EC_BOARD_H */ diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc index 34b64abd06..d129763c09 100644 --- a/board/cr50/gpio.inc +++ b/board/cr50/gpio.inc @@ -41,12 +41,15 @@ GPIO(SPI_MOSI, PIN(0, 7), GPIO_INPUT) GPIO(SPI_CLK, PIN(0, 8), GPIO_INPUT) GPIO(SPI_CS_L, PIN(0, 9), GPIO_INPUT) -/* Control the load switch powering the INA 3.3V rail */ -GPIO(EN_PP3300_INA_L, PIN(1, 9), GPIO_ODR_HIGH) - /* GPIOs used for Cr50 strapping options */ GPIO(STRAP0, PIN(0, 10), GPIO_INPUT) +/* Control the load switch powering the INA 3.3V rail */ +GPIO(EN_PP3300_INA_L, PIN(0, 11), GPIO_ODR_HIGH) +/* GPIOs used for I2CM pins for INAs */ +GPIO(I2C_SCL_INA, PIN(0, 12), GPIO_INPUT) +GPIO(I2C_SDA_INA, PIN(0, 13), GPIO_INPUT) + /* Unimplemented signals which we need to emulate for now */ /* TODO(wfrichar): Half the boards don't use this signal. Take it out. */ UNIMPLEMENTED(ENTERING_RW) @@ -71,7 +74,8 @@ PINMUX(GPIO(SYS_RST_L_OUT), M0, DIO_INPUT) PINMUX(GPIO(CCD_MODE_L), M1, DIO_INPUT) PINMUX(GPIO(BATT_PRES_L), M2, 0) PINMUX(GPIO(STRAP0), A1, DIO_INPUT) - +PINMUX(GPIO(I2C_SCL_INA), B0, DIO_INPUT) +PINMUX(GPIO(I2C_SDA_INA), B1, DIO_INPUT) /* UARTs */ PINMUX(FUNC(UART0_TX), A0, DIO_OUTPUT) /* Cr50 console */ PINMUX(FUNC(UART0_RX), A13, DIO_INPUT | DIO_WAKE_FALLING) diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index 623209fa03..4c67b5f1d2 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -8,6 +8,7 @@ #include "device_state.h" #include "gpio.h" #include "hooks.h" +#include "i2c.h" #include "rbox.h" #include "rdd.h" #include "registers.h" @@ -94,6 +95,45 @@ void uartn_tx_disconnect(int uart) uart_select_tx(uart, 0); } +void ina_connect(void) +{ + /* Apply power to INA chips */ + gpio_set_level(GPIO_EN_PP3300_INA_L, 0); + /* Allow enough time for power rail to come up */ + usleep(25); + + /* + * Connect B0/B1 pads to I2C0 input SDA/SCL. Note, that the inputs + * for these pads are already enabled for the gpio signals I2C_SCL_INA + * and I2C_SDA_INA in gpio.inc. + */ + GWRITE(PINMUX, I2C0_SDA_SEL, GC_PINMUX_DIOB1_SEL); + GWRITE(PINMUX, I2C0_SCL_SEL, GC_PINMUX_DIOB0_SEL); + + /* Connect I2CS SDA/SCL output to B1/B0 pads */ + GWRITE(PINMUX, DIOB1_SEL, GC_PINMUX_I2C0_SDA_SEL); + GWRITE(PINMUX, DIOB0_SEL, GC_PINMUX_I2C0_SCL_SEL); + + /* + * Initialize the i2cm module after the INAs are powered and the signal + * lines are connected. + */ + i2cm_init(); +} + +void ina_disconnect(void) +{ + /* Disonnect I2C0 SDA/SCL output to B1/B0 pads */ + GWRITE(PINMUX, DIOB1_SEL, 0); + GWRITE(PINMUX, DIOB0_SEL, 0); + /* Disconnect B1/B0 pads to I2C0 input SDA/SCL */ + GWRITE(PINMUX, I2C0_SDA_SEL, 0); + GWRITE(PINMUX, I2C0_SCL_SEL, 0); + + /* Disable power to INA chips */ + gpio_set_level(GPIO_EN_PP3300_INA_L, 1); +} + void rdd_attached(void) { /* Indicate case-closed debug mode (active low) */ @@ -198,6 +238,17 @@ static int command_ccd(int argc, char **argv) ec_uart_enabled = 0; uartn_tx_disconnect(UART_EC); } + } else if (!strcasecmp("ina", argv[1]) && argc > 2) { + if (!parse_bool(argv[2], &val)) + return EC_ERROR_PARAM2; + + if (val) { + ina_connect(); + ccprintf("CCD: INAs enabled\n"); + } else { + ina_disconnect(); + ccprintf("CCD: INAs disabled\n"); + } } else if (argc == 2) { if (!parse_bool(argv[1], &val)) return EC_ERROR_PARAM1; @@ -217,7 +268,7 @@ static int command_ccd(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(ccd, command_ccd, - "[uart] []", + "[uart|ina] []", "Get/set the case closed debug state"); static int command_sys_rst(int argc, char **argv) diff --git a/chip/g/rdd.h b/chip/g/rdd.h index 1f19ee9b3e..45dbb049de 100644 --- a/chip/g/rdd.h +++ b/chip/g/rdd.h @@ -18,4 +18,10 @@ void rdd_attached(void); * cable is detached. */ int is_utmi_wakeup_allowed(void); + +/* Power up INAs and initialize I2C0 interface */ +void ina_connect(void); + +/* Disconnect I2C0 interface and powerdown INAs */ +void ina_disconnect(void); #endif /* __CROS_RDD_H */