summaryrefslogtreecommitdiff
path: root/board/elm
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2016-04-22 19:03:06 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-06-16 09:40:40 -0700
commit93e2d00d03d6fc6fef5d9e2126c3785ef91dae7d (patch)
tree9845a06d936d89be0187e84c2639e74d788db829 /board/elm
parent4968ef4c9d8662cc81c908db37b619e1db8cc982 (diff)
downloadchrome-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.c94
-rw-r--r--board/elm/board.h6
-rw-r--r--board/elm/gpio.inc4
-rw-r--r--board/elm/usb_pd_policy.c14
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)