From 32e49e5e3b7724fa302f13893e7154ef319c9daf Mon Sep 17 00:00:00 2001 From: Xin Ji Date: Thu, 19 Mar 2020 15:33:41 +0800 Subject: tcpm/anx7447.c: use chip internal timer to generate HPD IRQ Anx7447 has 2 ways to generate HPD IRQ: 1): internal timer delay ~750ms. 2): outside timer delay(configured by EC anx7447.c). Some board didn't have accurate timer cause method #2 cannot be used, this patch change the default policy to method #1. BRANCH=none BUG=b:151696902 TEST=tested on STM32 board Change-Id: Ifcccacc484f82e4ed047d4caa7d86318f60d0192 Signed-off-by: Xin Ji Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2112312 Tested-by: Devin Lu Reviewed-by: Jett Rink Commit-Queue: Jett Rink --- driver/tcpm/anx7447.c | 38 ++++++++++++++++++++++++++++---------- driver/tcpm/anx7447.h | 3 +++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/driver/tcpm/anx7447.c b/driver/tcpm/anx7447.c index e83ca32d9b..fa614f5454 100644 --- a/driver/tcpm/anx7447.c +++ b/driver/tcpm/anx7447.c @@ -93,7 +93,7 @@ static inline int anx7447_reg_read(int port, int reg, int *val) return rv; } -void anx7447_hpd_mode_en(int port) +void anx7447_hpd_mode_init(int port) { int reg, rv; @@ -101,7 +101,13 @@ void anx7447_hpd_mode_en(int port) if (rv) return; - reg |= ANX7447_REG_HPD_MODE; + /* + * Set ANX7447_REG_HPD_MODE bit as 0, then the TCPC will generate the + * HPD pulse from internal timer (by using ANX7447_REG_HPD_IRQ0) + * instead of using the ANX7447_REG_HPD_OUT to set the HPD IRQ signal. + */ + reg &= ~(ANX7447_REG_HPD_MODE | ANX7447_REG_HPD_PLUG | + ANX7447_REG_HPD_UNPLUG); anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg); } @@ -125,10 +131,18 @@ void anx7447_set_hpd_level(int port, int hpd_lvl) if (rv) return; - if (hpd_lvl) - reg |= ANX7447_REG_HPD_OUT; - else - reg &= ~ANX7447_REG_HPD_OUT; + /* + * When ANX7447_REG_HPD_MODE is 1, use ANX7447_REG_HPD_OUT + * to generate HPD event, otherwise use ANX7447_REG_HPD_UNPLUG + * and ANX7447_REG_HPD_PLUG. + */ + if (hpd_lvl) { + reg &= ~ANX7447_REG_HPD_UNPLUG; + reg |= ANX7447_REG_HPD_PLUG; + } else { + reg &= ~ANX7447_REG_HPD_PLUG; + reg |= ANX7447_REG_HPD_UNPLUG; + } anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg); } @@ -483,11 +497,15 @@ void anx7447_tcpc_update_hpd_status(const struct usb_mux *me, if (now < hpd_deadline[port]) usleep(hpd_deadline[port] - now); + /* + * For generate hardware HPD IRQ, need clear bit + * ANX7447_REG_HPD_IRQ0 first, then set it. This bit is not + * write clear. + */ anx7447_reg_read(port, ANX7447_REG_HPD_CTRL_0, ®); - reg &= ~ANX7447_REG_HPD_OUT; + reg &= ~ANX7447_REG_HPD_IRQ0; anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - reg |= ANX7447_REG_HPD_OUT; + reg |= ANX7447_REG_HPD_IRQ0; anx7447_reg_write(port, ANX7447_REG_HPD_CTRL_0, reg); } /* enforce 2-ms delay between HPD pulses */ @@ -510,7 +528,7 @@ static int anx7447_mux_init(const struct usb_mux *me) memset(&mux[port], 0, sizeof(struct anx_usb_mux)); /* init hpd status */ - anx7447_hpd_mode_en(port); + anx7447_hpd_mode_init(port); anx7447_set_hpd_level(port, 0); anx7447_hpd_output_en(port); diff --git a/driver/tcpm/anx7447.h b/driver/tcpm/anx7447.h index 049b82d4bb..b1d571c7c8 100644 --- a/driver/tcpm/anx7447.h +++ b/driver/tcpm/anx7447.h @@ -27,6 +27,9 @@ #define ANX7447_REG_HPD_CTRL_0 0x7E #define ANX7447_REG_HPD_MODE 0x01 #define ANX7447_REG_HPD_OUT 0x02 +#define ANX7447_REG_HPD_IRQ0 0x04 +#define ANX7447_REG_HPD_PLUG 0x08 +#define ANX7447_REG_HPD_UNPLUG 0x10 #define ANX7447_REG_HPD_DEGLITCH_H 0x80 #define ANX7447_REG_HPD_OEN 0x40 -- cgit v1.2.1