summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/yorp/board.h1
-rw-r--r--driver/tcpm/anx7447.c105
-rw-r--r--driver/tcpm/anx7447.h41
-rw-r--r--include/config.h7
4 files changed, 154 insertions, 0 deletions
diff --git a/board/yorp/board.h b/board/yorp/board.h
index e827677578..f9d8a9fb93 100644
--- a/board/yorp/board.h
+++ b/board/yorp/board.h
@@ -83,6 +83,7 @@
#undef CONFIG_USB_PD_TCPC_LOW_POWER
#undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
#define CONFIG_USB_PD_TCPM_ANX7447 /* C0 TCPC: ANX7447QN */
+#define CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE
#define CONFIG_USB_PD_TCPM_PS8751 /* C1 TCPC: PS8751 */
#define CONFIG_USB_PD_TCPM_MUX
#define CONFIG_USB_PD_TCPM_TCPCI
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;
diff --git a/include/config.h b/include/config.h
index ca44183ef1..35aa5d0852 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2858,6 +2858,13 @@
#undef CONFIG_USB_PD_TCPM_PS8805
/*
+ * Check the ANX7447 OCM flash at initialization time. If not erased, will then
+ * erase the OCM flash. (note this is intended to be a temporary option and
+ * won't be needed when ANX7447 are put on boards with OCM already erased)
+ */
+#undef CONFIG_USB_PD_TCPM_ANX7447_OCM_ERASE
+
+/*
* Use this option if the TCPC port controller supports the optional register
* 18h CONFIG_STANDARD_OUTPUT to steer the high-speed muxes.
*/