diff options
author | Rong Chang <rongchang@chromium.org> | 2016-04-22 19:03:06 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-06-16 09:40:40 -0700 |
commit | 93e2d00d03d6fc6fef5d9e2126c3785ef91dae7d (patch) | |
tree | 9845a06d936d89be0187e84c2639e74d788db829 /board/elm | |
parent | 4968ef4c9d8662cc81c908db37b619e1db8cc982 (diff) | |
download | chrome-ec-93e2d00d03d6fc6fef5d9e2126c3785ef91dae7d.tar.gz |
elm: anx7688: add anx7688 hpd driver
ANX7688 is a TCPCI compatible port controller with HDMI to DP converter.
The HDMI converter needs a reset every time after enabling its function.
BRANCH=none
BUG=chrome-os-partner:52815
TEST=manual
boot elm proto
plug and unplug dingdong and check DP output
plug/unplug adapter and check pd 0 state
Change-Id: I774421d7b0b8d2cfd31e860fcd4eaed08ee48ac7
Signed-off-by: Rong Chang <rongchang@chromium.org>
Signed-off-by: Tang Zhentian1 <ztang@analogixsemi.com>
Reviewed-on: https://chromium-review.googlesource.com/340371
Commit-Ready: Koro Chen <koro.chen@mediatek.com>
Tested-by: Koro Chen <koro.chen@mediatek.com>
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Diffstat (limited to 'board/elm')
-rw-r--r-- | board/elm/board.c | 94 | ||||
-rw-r--r-- | board/elm/board.h | 6 | ||||
-rw-r--r-- | board/elm/gpio.inc | 4 | ||||
-rw-r--r-- | board/elm/usb_pd_policy.c | 14 |
4 files changed, 83 insertions, 35 deletions
diff --git a/board/elm/board.c b/board/elm/board.c index 29b77a5889..c0083c625b 100644 --- a/board/elm/board.c +++ b/board/elm/board.c @@ -17,6 +17,7 @@ #include "console.h" #include "driver/accel_kionix.h" #include "driver/accel_kx022.h" +#include "driver/tcpm/anx7688.h" #include "driver/tcpm/tcpci.h" #include "driver/temp_sensor/tmp432.h" #include "extpower.h" @@ -62,15 +63,24 @@ void pd_mcu_interrupt(enum gpio_signal signal) #endif } +void deferred_reset_pd_mcu(void); +DECLARE_DEFERRED(deferred_reset_pd_mcu); + void usb_evt(enum gpio_signal signal) { /* * check if this is from BC12 or ANX7688 CABLE_DET * note that CABLE_DET can only trigger irq when 0 -> 1 (plug in) - * since we use polling for CABLE_DET, just ignore this one for now */ if (!gpio_get_level(GPIO_BC12_WAKE_L)) task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0); + + if (!gpio_get_level(GPIO_USB_C0_CABLE_DET_L) && + gpio_get_level(GPIO_USB_C0_PWR_EN_L)) { + hook_call_deferred(&deferred_reset_pd_mcu_data, -1); + /* pull PWR_EN after 10ms */ + hook_call_deferred(&deferred_reset_pd_mcu_data, 10*MSEC); + } } #include "gpio_list.h" @@ -125,7 +135,7 @@ const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices); /* TCPC */ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = { - {I2C_PORT_TCPC, CONFIG_TCPC_I2C_BASE_ADDR, &tcpci_tcpm_drv}, + {I2C_PORT_TCPC, CONFIG_TCPC_I2C_BASE_ADDR, &anx7688_tcpm_drv}, }; struct pi3usb9281_config pi3usb9281_chips[] = { @@ -171,10 +181,9 @@ struct ec_thermal_config thermal_params[] = { BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { - /* TODO: 7688 support MUX Control 00b and 10b? */ { .port_addr = 0, /* port idx */ - .driver = &tcpci_tcpm_usb_mux_driver, + .driver = &anx7688_usb_mux_driver, }, }; @@ -182,27 +191,73 @@ struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { * Reset PD MCU * ANX7688 needs a reset pulse of 50ms after power enable. */ -void deferred_reset_pd_mcu(void); -DECLARE_DEFERRED(deferred_reset_pd_mcu); - void deferred_reset_pd_mcu(void) { - if (!gpio_get_level(GPIO_USB_C0_RST)) { + uint8_t state = gpio_get_level(GPIO_USB_C0_PWR_EN_L) | + (gpio_get_level(GPIO_USB_C0_RST) << 1); + + CPRINTS("%s %d", __func__, state); + switch (state) { + case 0: + /* + * PWR_EN_L low, RST low + * start reset sequence by turning off power enable + * and wait for 1ms. + */ + gpio_set_level(GPIO_USB_C0_PWR_EN_L, 1); + hook_call_deferred(&deferred_reset_pd_mcu_data, 1*MSEC); + break; + case 1: + /* + * PWR_EN_L high, RST low + * pull PD reset pin and wait for another 1ms + */ gpio_set_level(GPIO_USB_C0_RST, 1); - hook_call_deferred(&deferred_reset_pd_mcu_data, 50 * MSEC); - } else { + hook_call_deferred(&deferred_reset_pd_mcu_data, 1*MSEC); + /* on PD reset, trigger PD task to reset state */ + task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0); + break; + case 3: + /* + * PWR_EN_L high, RST high + * cable detected - enable power + * cable not detected - do nothing + */ + if (gpio_get_level(GPIO_USB_C0_CABLE_DET_L)) + return; + /* enable power and wait for 10ms then pull RESET_N */ + gpio_set_level(GPIO_USB_C0_PWR_EN_L, 0); + hook_call_deferred(&deferred_reset_pd_mcu_data, 10*MSEC); + break; + case 2: + /* + * PWR_EN_L low, RST high + * leave reset state + */ gpio_set_level(GPIO_USB_C0_RST, 0); + break; } } void board_reset_pd_mcu(void) { - /* Perform ANX7688 startup sequence */ - gpio_set_level(GPIO_USB_C0_PWR_EN_L, 0); - gpio_set_level(GPIO_USB_C0_RST, 0); - hook_call_deferred(&deferred_reset_pd_mcu_data, 0); + /* enable port controller's cable detection before reset */ + anx7688_enable_cable_detection(0); + + /* wait for 10ms, then start port controller's reset sequence */ + hook_call_deferred(&deferred_reset_pd_mcu_data, 10*MSEC); } +int command_pd_reset(int argc, char **argv) +{ + board_reset_pd_mcu(); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(resetpd, command_pd_reset, + "", + "Reset PD IC", + NULL); + /** * There is a level shift for AC_OK & LID_OPEN signal between AP & EC, * disable it (drive high) when AP is off, otherwise enable it (drive low). @@ -217,13 +272,6 @@ static void board_extpower_buffer_to_soc(void) /* Initialize board. */ static void board_init(void) { - /* - * Assert wake GPIO to PD MCU to wake it from hibernate. - * This cannot be done from board_pre_init() (or from any function - * called before system_pre_init()), otherwise a spurious wake will - * occur -- see stm32 check_reset_cause() WORKAROUND comment. - */ - /* Enable Level shift of AC_OK & LID_OPEN signals */ board_extpower_buffer_to_soc(); /* Enable rev1 testing GPIOs */ @@ -234,8 +282,8 @@ static void board_init(void) /* Enable BC 1.2 */ gpio_enable_interrupt(GPIO_BC12_CABLE_INT); - /* Turn on PD */ - board_reset_pd_mcu(); + /* Check if typeC is already connected, and do 7688 power on flow */ + usb_evt(0); /* Update VBUS supplier */ usb_charger_vbus_change(0, pd_snk_is_vbus_provided(0)); diff --git a/board/elm/board.h b/board/elm/board.h index ef2abd1028..46f4216af2 100644 --- a/board/elm/board.h +++ b/board/elm/board.h @@ -93,6 +93,7 @@ #define CONFIG_USB_PD_PORT_COUNT 1 #define CONFIG_USB_PD_TCPM_MUX +#define CONFIG_USB_PD_TCPM_ANX7688 #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_USB_PD_TRY_SRC #define CONFIG_USB_PD_VBUS_DETECT_GPIO @@ -209,11 +210,6 @@ void board_reset_pd_mcu(void); /* Set AP reset pin according to parameter */ void board_set_ap_reset(int asserted); -/* Control type-C DP route and hotplug detect signal */ -void board_typec_dp_on(int port); -void board_typec_dp_off(int port, int *dp_flags); -void board_typec_dp_set(int port, int level); - #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BOARD_H */ diff --git a/board/elm/gpio.inc b/board/elm/gpio.inc index 7dbce4fde0..16591f11cd 100644 --- a/board/elm/gpio.inc +++ b/board/elm/gpio.inc @@ -79,8 +79,8 @@ GPIO(LEVEL_SHIFT_EN_L, PIN(F, 10), GPIO_OUT_LOW) /* LID/AC level shift */ GPIO(USB_C0_5V_EN, PIN(D, 8), GPIO_OUT_LOW) /* USBC port 0 5V */ GPIO(USB_C0_CHARGE_L, PIN(D, 9), GPIO_OUT_LOW) /* USBC port 0 charge */ -GPIO(USB_C0_RST, PIN(D, 10), GPIO_OUT_LOW) /* ANX7688 reset */ -GPIO(USB_C0_PWR_EN_L, PIN(B, 15), GPIO_OUT_LOW) /* ANX7688 power enable */ +GPIO(USB_C0_RST, PIN(D, 10), GPIO_ODR_HIGH) /* ANX7688 reset */ +GPIO(USB_C0_PWR_EN_L, PIN(B, 15), GPIO_ODR_HIGH) /* ANX7688 power enable */ GPIO(USB_C0_EXTPWR_EN, PIN(F, 2), GPIO_OUT_HIGH) /* ANX7688 3.3V ext power enable */ GPIO(USB_DP_HPD, PIN(F, 3), GPIO_INPUT) GPIO(EN_TP_INT_L, PIN(E, 14), GPIO_OUT_LOW) /* touchpad interrupt enable */ diff --git a/board/elm/usb_pd_policy.c b/board/elm/usb_pd_policy.c index e54ad16c93..2d27f539b9 100644 --- a/board/elm/usb_pd_policy.c +++ b/board/elm/usb_pd_policy.c @@ -7,6 +7,7 @@ #include "charge_manager.h" #include "common.h" #include "console.h" +#include "driver/tcpm/anx7688.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" #include "gpio.h" @@ -24,7 +25,7 @@ #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) #define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP | PDO_FIXED_EXTERNAL) + PDO_FIXED_COMM_CAP) /* TODO: fill in correct source and sink capabilities */ const uint32_t pd_src_pdo[] = { @@ -56,11 +57,11 @@ int pd_set_power_supply_ready(int port) /* Provide VBUS */ gpio_set_level(GPIO_USB_C0_5V_EN, 1); + anx7688_set_power_supply_ready(port); + /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); - tcpc_write(port, TCPC_REG_COMMAND, 0x77); - return EC_SUCCESS; } @@ -69,10 +70,10 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ gpio_set_level(GPIO_USB_C0_5V_EN, 0); + anx7688_power_supply_reset(port); + /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); - - tcpc_write(port, TCPC_REG_COMMAND, 0x66); } void pd_set_input_current_limit(int port, uint32_t max_ma, @@ -306,6 +307,8 @@ static int svdm_dp_attention(int port, uint32_t *payload) int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); int ack = 1; + anx7688_update_hpd(port, lvl, irq); + dp_status[port] = payload[1]; cur_lvl = gpio_get_level(GPIO_USB_DP_HPD); @@ -327,6 +330,7 @@ static int svdm_dp_attention(int port, uint32_t *payload) static void svdm_exit_dp_mode(int port) { svdm_safe_dp_mode(port); + anx7688_hpd_disable(port); } static int svdm_enter_gfu_mode(int port, uint32_t mode_caps) |