From 1e677d3f32155265f062a9011e553b39ad9dac50 Mon Sep 17 00:00:00 2001 From: Scott Collyer Date: Fri, 30 Mar 2018 13:02:34 -0700 Subject: anx7447: Add functions to the anx7447 driver to check/erase OCM flash This CL adds support to check if the OCM flash is erased and if not, will erase it at initialization time. These changes are encapsulated in a new config option CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE and this option is enabled for Yorp boards. BUG=b:77658388 BRANCH=NONE TEST=make -j buildall. Tested on a board that hadn't yet been erased. Verifed the message "anx7447: OCM flash checked and successfully erased" was in the EC log, but did not show up on subsequent reboots. Change-Id: I660e76a9498d3dc1ba821a04317b324f716c5089 Signed-off-by: Scott Collyer Reviewed-on: https://chromium-review.googlesource.com/988414 Commit-Ready: Jett Rink Tested-by: Jett Rink Reviewed-by: Daisuke Nojiri --- driver/tcpm/anx7447.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ driver/tcpm/anx7447.h | 41 ++++++++++++++++++++ 2 files changed, 146 insertions(+) (limited to 'driver') diff --git a/driver/tcpm/anx7447.c b/driver/tcpm/anx7447.c index f16a5cba0a..9b7fb8dafa 100644 --- a/driver/tcpm/anx7447.c +++ b/driver/tcpm/anx7447.c @@ -36,6 +36,9 @@ struct anx_state { int i2c_slave_addr; int mux_state; +#ifdef CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE + int flash_checked_once; +#endif }; static struct anx_state anx[CONFIG_USB_PD_PORT_COUNT]; @@ -111,6 +114,94 @@ void anx7447_set_hpd_level(int port, int hpd_lvl) anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg); } +#ifdef CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE +static inline void anx7447_reg_write_and(int port, int reg, int v_and) +{ + int val; + + if (!anx7447_reg_read(port, reg, &val)) + anx7447_reg_write(port, reg, (val & v_and)); +} + +static inline void anx7447_reg_write_or(int port, int reg, int v_or) +{ + int val; + + if (!anx7447_reg_read(port, reg, &val)) + anx7447_reg_write(port, reg, (val | v_or)); +} + +static void anx7447_flash_write_en(int port) +{ + int r; + + anx7447_reg_write(port, ANX7447_REG_FLASH_INST_TYPE, + ANX7447_FLASH_INST_TYPE_WRITEENABLE); + anx7447_reg_write_or(port, ANX7447_REG_R_FLASH_RW_CTRL, + ANX7447_R_FLASH_RW_CTRL_GENERAL_INST_EN); + do { + anx7447_reg_read(port, ANX7447_REG_R_RAM_CTRL, &r); + } while (!(r & ANX7447_R_RAM_CTRL_FLASH_DONE)); +} + +static void anx7447_flash_op_init(int port) +{ + int r; + + anx7447_reg_write_or(port, ANX7447_REG_OCM_CTRL_0, + ANX7447_OCM_CTRL_OCM_RESET); + anx7447_reg_write_or(port, ANX7447_REG_ADDR_GPIO_CTRL_0, + ANX7447_ADDR_GPIO_CTRL_0_SPI_WP); + + anx7447_flash_write_en(port); + + anx7447_reg_write_and(port, ANX7447_REG_R_FLASH_STATUS_0, + ANX7447_FLASH_STATUS_SPI_STATUS_0); + anx7447_reg_write_or(port, ANX7447_REG_R_FLASH_RW_CTRL, + ANX7447_R_FLASH_RW_CTRL_WRITE_STATUS_EN); + + do { + anx7447_reg_read(port, ANX7447_REG_R_RAM_CTRL, &r); + } while (!(r & ANX7447_R_RAM_CTRL_FLASH_DONE)); +} + +static int anx7447_flash_is_empty(int port) +{ + int r; + + anx7447_reg_read(port, ANX7447_REG_OCM_VERSION, &r); + anx7447_reg_write(port, ANX7447_REG_OCM_VERSION, 0); + + return ((r == 0) ? 1 : 0); +} + +static void anx7447_flash_check(int port) +{ + int r; + + tcpc_read(port, TCPC_REG_COMMAND, &r); + usleep(ANX7447_DELAY_IN_US); + + if (anx7447_flash_is_empty(port) == 1) + return; + + anx7447_flash_op_init(port); + + usleep(ANX7447_DELAY_IN_US); + + anx7447_flash_write_en(port); + anx7447_reg_write(port, ANX7447_REG_FLASH_ERASE_TYPE, + ANX7447_FLASH_ERASE_TYPE_CHIPERASE); + anx7447_reg_write_or(port, ANX7447_REG_R_FLASH_RW_CTRL, + ANX7447_R_FLASH_RW_CTRL_FLASH_ERASE_EN); + do { + anx7447_reg_read(port, ANX7447_REG_R_RAM_CTRL, &r); + } while (!(r & ANX7447_R_RAM_CTRL_FLASH_DONE)); + + ccprintf("anx7447: OCM flash checked and erased\n"); +} +#endif + static int anx7447_init(int port) { int rv, reg, i; @@ -135,6 +226,20 @@ static int anx7447_init(int port) return EC_ERROR_UNKNOWN; } +#ifdef CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE + /* + * The ANX7447 has an on chip microcontroller (OCM) that can provide USB + * PD functionality. If the OCM is active, then it can interfere with + * getting alerts from the TCPC when PD messages are received. Check to + * see if the flash is not erased, and if not, then erase the OCM + * flash. This status is saved in a static variable so this check only + * happens once per EC reboot. + */ + if (anx[port].flash_checked_once == 0) { + anx7447_flash_check(port); + anx[port].flash_checked_once = 1; + } +#endif rv = tcpci_tcpm_init(port); if (rv) return rv; diff --git a/driver/tcpm/anx7447.h b/driver/tcpm/anx7447.h index a2fe128f77..eac4057967 100644 --- a/driver/tcpm/anx7447.h +++ b/driver/tcpm/anx7447.h @@ -31,6 +31,47 @@ #define ANX7447_REG_INTP_CTRL_0 0x9E +/* + * This section of defines are only required to support the config option + * CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE. + */ +/* SPI registers used for OCM flash operations */ +#define ANX7447_DELAY_IN_US (20*1000) + +#define ANX7447_REG_R_RAM_CTRL 0x05 +#define ANX7447_REG_R_FLASH_RW_CTRL 0x30 +#define ANX7447_REG_R_FLASH_STATUS_0 0x31 +#define ANX7447_REG_FLASH_INST_TYPE 0x33 +#define ANX7447_REG_FLASH_ERASE_TYPE 0x34 +#define ANX7447_REG_OCM_CTRL_0 0x6E +#define ANX7447_REG_ADDR_GPIO_CTRL_0 0x88 +#define ANX7447_REG_OCM_VERSION 0xB4 + +/* R_RAM_CTRL bit definitions */ +#define ANX7447_R_RAM_CTRL_FLASH_DONE (1<<7) + +/* R_FLASH_RW_CTRL bit definitions */ +#define ANX7447_R_FLASH_RW_CTRL_GENERAL_INST_EN (1<<6) +#define ANX7447_R_FLASH_RW_CTRL_FLASH_ERASE_EN (1<<5) +#define ANX7447_R_FLASH_RW_CTRL_WRITE_STATUS_EN (1<<2) +#define ANX7447_R_FLASH_RW_CTRL_FLASH_READ (1<<1) +#define ANX7447_R_FLASH_RW_CTRL_FLASH_WRITE (1<<0) + +/* R_FLASH_STATUS_0 definitions */ +#define ANX7447_FLASH_STATUS_SPI_STATUS_0 0x43 + +/* FLASH_ERASE_TYPE bit definitions */ +#define ANX7447_FLASH_INST_TYPE_WRITEENABLE 0x06 +#define ANX7447_FLASH_ERASE_TYPE_CHIPERASE 0x60 + +/* OCM_CTRL_0 bit definitions */ +#define ANX7447_OCM_CTRL_OCM_RESET (1<<6) + +/* ADDR_GPIO_CTRL_0 bit definitions */ +#define ANX7447_ADDR_GPIO_CTRL_0_SPI_WP (1<<7) +#define ANX7447_ADDR_GPIO_CTRL_0_SPI_CLK_ENABLE (1<<6) +/* End of defines used for CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE */ + struct anx7447_i2c_addr { int tcpc_slave_addr; int spi_slave_addr; -- cgit v1.2.1