From d603cb843718ea7672adcfa3aefe89e8e9b25718 Mon Sep 17 00:00:00 2001 From: chailu1 Date: Tue, 2 Nov 2021 13:48:22 +0800 Subject: [PATCH] sgm7220: add typeC mode switch interface for sgm7220 UFP/DFP/DRP add typeC mode switch interface for sgm7220 Change-Id: I6def0c4b4694c5647fe1ced8ee64eb385f3b91b2 Signed-off-by: chailu1 Reviewed-on: https://gerrit.mot.com/2100812 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/typec/mmi_tcpc/inc/sgm7220.h | 5 ++ drivers/usb/typec/mmi_tcpc/tcpc_sgm7220.c | 67 ++++++++++++++++++++--- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/drivers/usb/typec/mmi_tcpc/inc/sgm7220.h b/drivers/usb/typec/mmi_tcpc/inc/sgm7220.h index f804bd3e22ef..3a77003871e9 100644 --- a/drivers/usb/typec/mmi_tcpc/inc/sgm7220.h +++ b/drivers/usb/typec/mmi_tcpc/inc/sgm7220.h @@ -65,4 +65,9 @@ #define CTR_DISABLE_RD_RP_SHIFT 2 #define CTR_DISABLE_RD_RP (0x01 << CTR_DISABLE_RD_RP_SHIFT) /*RW*/ +/* SET_MODE_SELECT */ +#define SET_MODE_SELECT_DEFAULT 0x00 +#define SET_MODE_SELECT_SNK 0x01 +#define SET_MODE_SELECT_SRC 0x02 +#define SET_MODE_SELECT_DRP 0x03 #endif /* #ifndef __LINUX_SGM7220_H */ diff --git a/drivers/usb/typec/mmi_tcpc/tcpc_sgm7220.c b/drivers/usb/typec/mmi_tcpc/tcpc_sgm7220.c index eccfc5a01ff2..4602fa7f96dc 100644 --- a/drivers/usb/typec/mmi_tcpc/tcpc_sgm7220.c +++ b/drivers/usb/typec/mmi_tcpc/tcpc_sgm7220.c @@ -30,6 +30,7 @@ #include "inc/tcpci.h" #include "inc/sgm7220.h" #include +#include #define SGM7220_DRV_VERSION "1.0.0_SGM7220" #define SGM7220_IRQ_WAKE_TIME (500) /* ms */ @@ -82,13 +83,6 @@ enum cable_dir_type { ORIENT_CC2 }; -enum cc_modes_type { - MODE_DEFAULT = 0, - MODE_UFP, - MODE_DFP, - MODE_DRP -}; - /* Type-C Attrs */ struct type_c_parameters { enum current_det_type current_det; /*charging current on UFP*/ @@ -351,6 +345,10 @@ static void sgm7220_process_interrupt_register(struct sgm7220_chip *chip, u8 sta } tcpci_notify_typec_state(tcpc); tcpc->typec_attach_old = TYPEC_UNATTACHED; + + val = SET_MODE_SELECT_DRP << SET_MODE_SELECT_SHIFT; + if (sgm7220_reg_update(chip->client, REG_SET, val, SET_MODE_SELECT) < 0) + pr_err("%s: force drp mode fail!\n", __func__); break; case CABLE_STATE_AS_DFP: if (tcpc->typec_attach_new != TYPEC_ATTACHED_SRC) { @@ -421,6 +419,7 @@ static void sgm7220_irq_work_handler(struct kthread_work *work) pr_err("%s: update reg fail!\n", __func__); } + tcpci_unlock_typec(tcpc); } @@ -580,6 +579,59 @@ static int sgm7220_tcpc_deinit(struct tcpc_device *tcpc_dev) return 0; } +int sgm7220_set_port_type(struct tcpc_device *tcpc, int mode) +{ + struct sgm7220_chip *chip = tcpc_get_dev_data(tcpc); + u8 value; + int ret; + + ret = sgm7220_read_device(chip->client, REG_SET, 1, &value); + if (ret < 0) { + pr_err("%s: read REG_SET fail!\n", __func__); + return ret; + } + value = (value & SET_MODE_SELECT) >> SET_MODE_SELECT_SHIFT; + pr_info("%s enter: mode = %d, now mode = %d\n", + __func__, mode, value); + + if ((mode == TYPEC_PORT_SRC && value == SET_MODE_SELECT_SRC) + ||(mode == TYPEC_PORT_SNK && value == SET_MODE_SELECT_SNK) + ||(mode == TYPEC_PORT_DRP && value == SET_MODE_SELECT_DRP)) { + pr_err("%s: alreadly at mode %d so quit\n", __func__, mode); + return 0; + } + + ret = sgm7220_reg_update(chip->client, REG_SET, 0x01, SET_I2C_DISABLE_TERM); + if (ret < 0) { + pr_err("%s: Disable RD and RP fail!\n", __func__); + return ret; + } + + if (mode == TYPEC_PORT_SRC) + value = SET_MODE_SELECT_SRC; + else if (mode == TYPEC_PORT_SNK) + value = SET_MODE_SELECT_SNK; + else if (mode == TYPEC_PORT_DRP) + value = SET_MODE_SELECT_DRP; + else + return -EINVAL; + value = value << SET_MODE_SELECT_SHIFT; + ret = sgm7220_reg_update(chip->client, REG_SET, value, SET_MODE_SELECT); + if (ret < 0) { + pr_err("%s: update mode reg fail!\n", __func__); + return ret; + } + msleep(20); + + ret = sgm7220_reg_update(chip->client, REG_SET, 0x00, SET_I2C_DISABLE_TERM); + if (ret < 0) { + pr_err("%s: Enable RD and RP fail!\n", __func__); + return ret; + } + + return ret; +} + #ifdef CONFIG_TCPC_WATCHDOG_EN int sgm7220_set_watchdog(struct tcpc_device *tcpc, bool en) { @@ -656,6 +708,7 @@ static struct tcpc_ops sgm7220_tcpc_ops = { .set_low_rp_duty = sgm7220_set_low_rp_duty, .set_vconn = sgm7220_set_vconn, .deinit = sgm7220_tcpc_deinit, + .set_port_type = sgm7220_set_port_type, #ifdef CONFIG_TCPC_WATCHDOG_EN .set_watchdog = sgm7220_set_watchdog, #endif /* CONFIG_TCPC_WATCHDOG_EN */