From 0f3e28cdb19ea3ed9748f185d5dcb6cc74f874eb Mon Sep 17 00:00:00 2001 From: chailu1 Date: Wed, 8 Dec 2021 17:50:12 +0800 Subject: [PATCH] pd: bring up sc2150a pd/sc2150a add sc2150a driver Change-Id: I81ae4c312571ca19fa92ae7dcc842e3a67551a6a Reviewed-on: https://gerrit.mot.com/2138697 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/typec/mmi_tcpc/inc/tcpci.h | 3 + drivers/usb/typec/mmi_tcpc/inc/tcpci_core.h | 1 + drivers/usb/typec/mmi_tcpc/tcpc_rt1711h.c | 63 ++++++++++++++++----- drivers/usb/typec/mmi_tcpc/tcpci.c | 10 ++++ drivers/usb/typec/mmi_tcpc/tcpci_alert.c | 5 +- drivers/usb/typec/mmi_tcpc/tcpci_typec.c | 24 +++++++- 6 files changed, 87 insertions(+), 19 deletions(-) diff --git a/drivers/usb/typec/mmi_tcpc/inc/tcpci.h b/drivers/usb/typec/mmi_tcpc/inc/tcpci.h index f7efcb6c0dcf..c2cf3c03238f 100644 --- a/drivers/usb/typec/mmi_tcpc/inc/tcpci.h +++ b/drivers/usb/typec/mmi_tcpc/inc/tcpci.h @@ -37,6 +37,8 @@ #include "pd_core.h" #endif /* CONFIG_USB_POWER_DELIVERY */ +#define SC2150A_DID 0x0000 + #define PE_STATE_FULL_NAME 0 #define TCPC_LOW_RP_DUTY (100) /* 10 % */ @@ -72,6 +74,7 @@ static inline int tcpci_check_vbus_valid(struct tcpc_device *tcpc) int tcpci_check_vbus_valid_from_ic(struct tcpc_device *tcpc); int tcpci_check_vsafe0v(struct tcpc_device *tcpc, bool detect_en); +int tcpci_get_chip_id(struct tcpc_device *tcpc, uint32_t *chip_id); int tcpci_alert_status_clear(struct tcpc_device *tcpc, uint32_t mask); int tcpci_fault_status_clear(struct tcpc_device *tcpc, uint8_t status); int tcpci_set_alert_mask(struct tcpc_device *tcpc, uint32_t mask); diff --git a/drivers/usb/typec/mmi_tcpc/inc/tcpci_core.h b/drivers/usb/typec/mmi_tcpc/inc/tcpci_core.h index 7d40758919f6..2b5e17b25fd7 100644 --- a/drivers/usb/typec/mmi_tcpc/inc/tcpci_core.h +++ b/drivers/usb/typec/mmi_tcpc/inc/tcpci_core.h @@ -212,6 +212,7 @@ struct tcpc_ops { int (*alert_status_clear)(struct tcpc_device *tcpc, uint32_t mask); int (*fault_status_clear)(struct tcpc_device *tcpc, uint8_t status); int (*set_alert_mask)(struct tcpc_device *tcpc, uint32_t mask); + int (*get_chip_id)(struct tcpc_device *tcpc, uint32_t *chip_id); int (*get_alert_mask)(struct tcpc_device *tcpc, uint32_t *mask); int (*get_alert_status)(struct tcpc_device *tcpc, uint32_t *alert); int (*get_power_status)(struct tcpc_device *tcpc, uint16_t *pwr_status); diff --git a/drivers/usb/typec/mmi_tcpc/tcpc_rt1711h.c b/drivers/usb/typec/mmi_tcpc/tcpc_rt1711h.c index 15b4834346a0..42d40fc513ff 100644 --- a/drivers/usb/typec/mmi_tcpc/tcpc_rt1711h.c +++ b/drivers/usb/typec/mmi_tcpc/tcpc_rt1711h.c @@ -724,7 +724,9 @@ static int rt1711_tcpc_init(struct tcpc_device *tcpc, bool sw_reset) if (chip->chip_id == RT1711H_DID_A) { rt1711_i2c_write8(tcpc, TCPC_V10_REG_FAULT_CTRL, TCPC_V10_REG_FAULT_CTRL_DIS_VCONN_OV); - } + } else if (chip->chip_id == SC2150A_DID) + rt1711_i2c_write8(tcpc, TCPC_V10_REG_COMMAND, + TCPM_CMD_ENABLE_VBUS_DETECT); /* * CC Detect Debounce : 26.7*val us @@ -793,6 +795,15 @@ int rt1711_fault_status_clear(struct tcpc_device *tcpc, uint8_t status) return 0; } +int rt1711_get_chip_id(struct tcpc_device *tcpc, uint32_t *chip_id) +{ + struct rt1711_chip *chip = tcpc_get_dev_data(tcpc); + + *chip_id = chip->chip_id; + + return 0; +} + int rt1711_get_alert_mask(struct tcpc_device *tcpc, uint32_t *mask) { int ret; @@ -883,6 +894,7 @@ static int rt1711_get_cc(struct tcpc_device *tcpc, int *cc1, int *cc2) { int status, role_ctrl, cc_role; bool act_as_sink, act_as_drp; + struct rt1711_chip *chip = tcpc_get_dev_data(tcpc); status = rt1711_i2c_read8(tcpc, TCPC_V10_REG_CC_STATUS); if (status < 0) @@ -920,6 +932,15 @@ static int rt1711_get_cc(struct tcpc_device *tcpc, int *cc1, int *cc2) * If status is not open, then OR in termination to convert to * enum tcpc_cc_voltage_status. */ + if (chip->chip_id == SC2150A_DID && act_as_drp && + act_as_sink) { + if ((*cc1 + *cc2) > (2 * TYPEC_CC_VOLT_RA)) { + if (*cc1 == TYPEC_CC_VOLT_RA) + *cc1 = TYPEC_CC_VOLT_OPEN; + if (*cc2 == TYPEC_CC_VOLT_RA) + *cc2 = TYPEC_CC_VOLT_OPEN; + } + } if (*cc1 != TYPEC_CC_VOLT_OPEN) *cc1 |= (act_as_sink << 2); @@ -953,18 +974,22 @@ static int rt1711_enable_vsafe0v_detect( static int rt1711_set_cc(struct tcpc_device *tcpc, int pull) { - int ret; - uint8_t data; + int ret = 0; + uint8_t data = 0; + uint8_t old_data = 0; int rp_lvl = TYPEC_CC_PULL_GET_RP_LVL(pull), pull1, pull2; + struct rt1711_chip *chip = tcpc_get_dev_data(tcpc); RT1711_INFO("pull = 0x%02X\n", pull); pull = TYPEC_CC_PULL_GET_RES(pull); + if (chip->chip_id == SC2150A_DID) + old_data = rt1711_i2c_read8(tcpc, TCPC_V10_REG_ROLE_CTRL); if (pull == TYPEC_CC_DRP) { data = TCPC_V10_REG_ROLE_CTRL_RES_SET( 1, rp_lvl, TYPEC_CC_RD, TYPEC_CC_RD); - - ret = rt1711_i2c_write8( - tcpc, TCPC_V10_REG_ROLE_CTRL, data); + if (chip->chip_id != SC2150A_DID || old_data != data) + ret = rt1711_i2c_write8( + tcpc, TCPC_V10_REG_ROLE_CTRL, data); if (ret == 0) { #ifdef CONFIG_TCPC_VSAFE0V_DETECT_IC @@ -980,14 +1005,17 @@ static int rt1711_set_cc(struct tcpc_device *tcpc, int pull) pull1 = pull2 = pull; - if (pull == TYPEC_CC_RP && tcpc->typec_is_attached_src) { - if (tcpc->typec_polarity) - pull1 = TYPEC_CC_OPEN; - else - pull2 = TYPEC_CC_OPEN; + if (chip->chip_id != SC2150A_DID) { + if (pull == TYPEC_CC_RP && tcpc->typec_is_attached_src) { + if (tcpc->typec_polarity) + pull1 = TYPEC_CC_OPEN; + else + pull2 = TYPEC_CC_OPEN; + } } data = TCPC_V10_REG_ROLE_CTRL_RES_SET(0, rp_lvl, pull1, pull2); - ret = rt1711_i2c_write8(tcpc, TCPC_V10_REG_ROLE_CTRL, data); + if (chip->chip_id != SC2150A_DID || old_data != data) + ret = rt1711_i2c_write8(tcpc, TCPC_V10_REG_ROLE_CTRL, data); } return 0; @@ -1229,6 +1257,8 @@ static int rt1711_transmit(struct tcpc_device *tcpc, if (data_cnt > 0) memcpy(packet.data, (uint8_t *) data, data_cnt); + if (chip->chip_id == SC2150A_DID) + packet.cnt += 4; rv = rt1711_block_write(chip->client, TCPC_V10_REG_TX_BYTE_CNT, @@ -1262,6 +1292,7 @@ static struct tcpc_ops rt1711_tcpc_ops = { .init = rt1711_tcpc_init, .alert_status_clear = rt1711_alert_status_clear, .fault_status_clear = rt1711_fault_status_clear, + .get_chip_id= rt1711_get_chip_id, .get_alert_mask = rt1711_get_alert_mask, .get_alert_status = rt1711_get_alert_status, .get_power_status = rt1711_get_power_status, @@ -1462,7 +1493,7 @@ static int rt1711_tcpcdev_init(struct rt1711_chip *chip, struct device *dev) #endif /* CONFIG_USB_PD_RETRY_CRC_DISCARD */ #ifdef CONFIG_USB_PD_REV30 - if (chip->chip_id >= RT1715_DID_D) + if ((chip->chip_id >= RT1715_DID_D) || (chip->chip_id == SC2150A_DID)) chip->tcpc->tcpc_flags |= TCPC_FLAGS_PD_REV30; if (chip->tcpc->tcpc_flags & TCPC_FLAGS_PD_REV30) @@ -1477,6 +1508,8 @@ static int rt1711_tcpcdev_init(struct rt1711_chip *chip, struct device *dev) #define RICHTEK_1711_VID 0x29cf #define RICHTEK_1711_PID 0x1711 +#define SC2150A_VID 0x311C +#define SC2150A_PID 0x2150 static inline int rt1711h_check_revision(struct i2c_client *client) { @@ -1490,7 +1523,7 @@ static inline int rt1711h_check_revision(struct i2c_client *client) return -EIO; } - if (vid != RICHTEK_1711_VID) { + if ((vid != RICHTEK_1711_VID) && (vid != SC2150A_VID)) { pr_info("%s failed, VID=0x%04x\n", __func__, vid); return -ENODEV; } @@ -1501,7 +1534,7 @@ static inline int rt1711h_check_revision(struct i2c_client *client) return -EIO; } - if (pid != RICHTEK_1711_PID) { + if ((pid != RICHTEK_1711_PID) && (pid != SC2150A_PID)) { pr_info("%s failed, PID=0x%04x\n", __func__, pid); return -ENODEV; } diff --git a/drivers/usb/typec/mmi_tcpc/tcpci.c b/drivers/usb/typec/mmi_tcpc/tcpci.c index 266e4a6d5b71..6adbefc7d229 100644 --- a/drivers/usb/typec/mmi_tcpc/tcpci.c +++ b/drivers/usb/typec/mmi_tcpc/tcpci.c @@ -117,6 +117,16 @@ int tcpci_check_vsafe0v( return ret; } +int tcpci_get_chip_id(struct tcpc_device *tcpc, uint32_t *chip_id) +{ + if (tcpc->ops->get_chip_id == NULL) + return -ENOTSUPP; + else + tcpc->ops->get_chip_id(tcpc, chip_id); + + return 0; +} + int tcpci_alert_status_clear( struct tcpc_device *tcpc, uint32_t mask) { diff --git a/drivers/usb/typec/mmi_tcpc/tcpci_alert.c b/drivers/usb/typec/mmi_tcpc/tcpci_alert.c index 21d1501cf1e2..ccc3307c271c 100644 --- a/drivers/usb/typec/mmi_tcpc/tcpci_alert.c +++ b/drivers/usb/typec/mmi_tcpc/tcpci_alert.c @@ -347,6 +347,7 @@ int tcpci_alert(struct tcpc_device *tcpc) int rv = 0, i = 0; uint32_t alert_status = 0, alert_mask = 0; const uint8_t typec_role = tcpc->typec_role; + uint32_t chip_id; rv = tcpci_get_alert_status(tcpc, &alert_status); if (rv < 0) @@ -360,7 +361,9 @@ int tcpci_alert(struct tcpc_device *tcpc) TCPC_INFO("Alert:0x%04x, Mask:0x%04x\n", alert_status, alert_mask); #endif /* CONFIG_USB_PD_DBG_ALERT_STATUS */ - alert_status &= alert_mask; + rv = tcpci_get_chip_id(tcpc,&chip_id); + if (rv || SC2150A_DID != chip_id) + alert_status &= alert_mask; if (typec_role == TYPEC_ROLE_UNKNOWN || typec_role >= TYPEC_ROLE_NR) { diff --git a/drivers/usb/typec/mmi_tcpc/tcpci_typec.c b/drivers/usb/typec/mmi_tcpc/tcpci_typec.c index 78c5c5e4b10c..b7b82f999395 100644 --- a/drivers/usb/typec/mmi_tcpc/tcpci_typec.c +++ b/drivers/usb/typec/mmi_tcpc/tcpci_typec.c @@ -845,11 +845,18 @@ static inline bool typec_role_is_try_src( static inline void typec_try_src_entry(struct tcpc_device *tcpc) { + uint32_t chip_id; + int rv = 0; TYPEC_NEW_STATE(typec_try_src); tcpc->typec_drp_try_timeout = false; tcpci_set_cc(tcpc, TYPEC_CC_RP); tcpc_enable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY); + + rv = tcpci_get_chip_id(tcpc, &chip_id); + if (!rv && SC2150A_DID == chip_id) { + tcpc_typec_handle_cc_change(tcpc); + } } static inline void typec_trywait_snk_entry(struct tcpc_device *tcpc) @@ -904,11 +911,18 @@ static inline bool typec_role_is_try_sink( static inline void typec_try_snk_entry(struct tcpc_device *tcpc) { + int rv = 0; + uint32_t chip_id; TYPEC_NEW_STATE(typec_try_snk); tcpc->typec_drp_try_timeout = false; tcpci_set_cc(tcpc, TYPEC_CC_RD); tcpc_enable_timer(tcpc, TYPEC_TRY_TIMER_DRP_TRY); + + rv = tcpci_get_chip_id(tcpc, &chip_id); + if (!rv && SC2150A_DID == chip_id) { + tcpc_typec_handle_cc_change(tcpc); + } } static inline void typec_trywait_src_entry(struct tcpc_device *tcpc) @@ -1561,6 +1575,8 @@ static inline bool typec_handle_cc_changed_entry(struct tcpc_device *tcpc) static inline void typec_attach_wait_entry(struct tcpc_device *tcpc) { bool as_sink; + int rv = 0; + uint32_t chip_id; #ifdef CONFIG_USB_POWER_DELIVERY struct pd_port *pd_port = &tcpc->pd_port; #endif /* CONFIG_USB_POWER_DELIVERY */ @@ -1630,10 +1646,12 @@ static inline void typec_attach_wait_entry(struct tcpc_device *tcpc) #ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT tcpci_notify_attachwait_state(tcpc, as_sink); #endif /* CONFIG_TYPEC_NOTIFY_ATTACHWAIT */ - - if (as_sink) + rv = tcpci_get_chip_id(tcpc, &chip_id); + if (as_sink) { TYPEC_NEW_STATE(typec_attachwait_snk); - else { + if (!rv && SC2150A_DID == chip_id) + tcpci_set_cc(tcpc, TYPEC_CC_RD); + } else { /* Advertise Rp level before Attached.SRC Ellisys 3.1.6359 */ tcpci_set_cc(tcpc, TYPEC_CC_PULL(tcpc->typec_local_rp_level, TYPEC_CC_RP));