[RAMEN9610-13997][COMMON] drivers: usb/usbpd: support role swap
authorKim Taejeong <tj.kim@samsung.com>
Fri, 29 Mar 2019 01:54:43 +0000 (10:54 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:23:21 +0000 (20:23 +0300)
Change-Id: I9d6ec02ed07bf81b1104324f2dfd2a0d62c3ed54
Signed-off-by: Kim Taejeong <tj.kim@samsung.com>
13 files changed:
arch/arm64/configs/erd9610_defconfig [changed mode: 0755->0644]
drivers/ccic/s2mu106-usbpd.c
drivers/ccic/usbpd.c
drivers/ccic/usbpd_cc.c
drivers/ccic/usbpd_manager.c
drivers/muic/muic_manager.c
drivers/power/supply/power_supply_sysfs.c
drivers/power/supply/s2mu106_charger.c [changed mode: 0755->0644]
drivers/power/supply/s2mu106_pmeter.c [changed mode: 0755->0644]
drivers/usb/dwc3/otg.c
include/linux/ccic/usbpd-s2mu106.h
include/linux/ccic/usbpd_ext.h
include/linux/power_supply.h

old mode 100755 (executable)
new mode 100644 (file)
index c93f1a4..c537ea6
@@ -437,7 +437,8 @@ CONFIG_USB_NOTIFY_LAYER=y
 CONFIG_USB_NOTIFIER=y
 CONFIG_USB_HW_PARAM=y
 CONFIG_USB_DWC3=y
-CONFIG_DUAL_ROLE_USB_INTF=y
+#CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_TYPEC=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_CONFIGFS=y
 CONFIG_USB_CONFIGFS_ACM=y
index 08ab1eb4562c728009d78035998e9b5adcd4e6ea..26300009943a131de7592a6530b1ed35f4209196 100644 (file)
@@ -78,8 +78,7 @@ static void s2mu106_src(struct i2c_client *i2c);
 static void s2mu106_snk(struct i2c_client *i2c);
 static void s2mu106_assert_rd(void *_data);
 static void s2mu106_assert_rp(void *_data);
-static int s2mu106_set_attach(struct s2mu106_usbpd_data *pdic_data, u8 mode);
-static int s2mu106_set_detach(struct s2mu106_usbpd_data *pdic_data, u8 mode);
+static void s2mu106_assert_drp(void *_data);
 static void s2mu106_usbpd_check_rid(struct s2mu106_usbpd_data *pdic_data);
 static int s2mu106_usbpd_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
 static int s2mu106_usbpd_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
@@ -90,6 +89,8 @@ static void s2mu106_usbpd_notify_detach(struct s2mu106_usbpd_data *pdic_data);
 #endif
 static void s2mu106_usbpd_detach_init(struct s2mu106_usbpd_data *pdic_data);
 static int s2mu106_usbpd_set_cc_control(struct s2mu106_usbpd_data  *pdic_data, int val);
+static void s2mu106_usbpd_set_rp_scr_sel(struct s2mu106_usbpd_data *pdic_data,
+                                                       CCIC_RP_SCR_SEL scr_sel);
 
 char *rid_text[] = {
        "UNDEFINED",
@@ -114,15 +115,19 @@ static void s2mu106_usbpd_test_read(struct s2mu106_usbpd_data *usbpd_data)
        s2mu106_usbpd_read_reg(i2c, 0xe2, &data[5]);
        s2mu106_usbpd_read_reg(i2c, 0xb3, &data[6]);
        s2mu106_usbpd_read_reg(i2c, 0xb4, &data[7]);
+       s2mu106_usbpd_read_reg(i2c, 0xf7, &data[8]);
 
-       pr_info("%s, 0x1(%x) 0x18(%x) 0x27(%x) 0x28(%x) 0x40(%x) 0xe2(%x) 0xb3(%x) 0xb4(%x)\n",
-                       __func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+       pr_info("%s, 0x1(%x) 0x18(%x) 0x27(%x) 0x28(%x) 0x40(%x) 0xe2(%x) 0xb3(%x) 0xb4(%x) 0xf7(%X)\n",
+                                       __func__, data[0], data[1], data[2], data[3], data[4],
+                                                                               data[5], data[6], data[7], data[8]);
 }
 
 void s2mu106_rprd_mode_change(struct s2mu106_usbpd_data *usbpd_data, u8 mode)
 {
        u8 data = 0;
        struct i2c_client *i2c = usbpd_data->i2c;
+       struct device *dev = &i2c->dev;
+       struct usbpd_data *pd_data = dev_get_drvdata(dev);
        pr_info("%s, mode=0x%x\n", __func__, mode);
 
        mutex_lock(&usbpd_data->lpm_mutex);
@@ -131,14 +136,28 @@ void s2mu106_rprd_mode_change(struct s2mu106_usbpd_data *usbpd_data, u8 mode)
 
        switch (mode) {
        case TYPE_C_ATTACH_DFP: /* SRC */
-               s2mu106_set_detach(usbpd_data, mode);
+               s2mu106_usbpd_set_cc_control(usbpd_data, USBPD_CC_OFF);
+               usbpd_data->status_reg |= PLUG_DETACH;
+               s2mu106_usbpd_set_rp_scr_sel(usbpd_data, PLUG_CTRL_RP0);
+               s2mu106_assert_rp(pd_data);
+               msleep(50);
+               s2mu106_usbpd_set_rp_scr_sel(usbpd_data, PLUG_CTRL_RP80);
                msleep(S2MU106_ROLE_SWAP_TIME_MS);
-               s2mu106_set_attach(usbpd_data, mode);
+               s2mu106_assert_drp(pd_data);
                break;
        case TYPE_C_ATTACH_UFP: /* SNK */
-               s2mu106_set_detach(usbpd_data, mode);
+               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_MUIC,
+                       IFCONN_NOTIFY_ID_ROLE_SWAP,
+                       IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP, NULL);
+               s2mu106_usbpd_set_cc_control(usbpd_data, USBPD_CC_OFF);
+               usbpd_data->status_reg |= PLUG_DETACH;
+               s2mu106_assert_rp(pd_data);
+               s2mu106_usbpd_set_rp_scr_sel(usbpd_data, PLUG_CTRL_RP0);
+               msleep(50);
+               s2mu106_assert_rd(pd_data);
+               s2mu106_usbpd_set_rp_scr_sel(usbpd_data, PLUG_CTRL_RP80);
                msleep(S2MU106_ROLE_SWAP_TIME_MS);
-               s2mu106_set_attach(usbpd_data, mode);
+               s2mu106_assert_drp(pd_data);
                break;
        case TYPE_C_ATTACH_DRP: /* DRP */
                s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
@@ -150,6 +169,24 @@ skip:
        mutex_unlock(&usbpd_data->lpm_mutex);
 }
 
+void usbpd_charger_test_read(struct s2mu106_usbpd_data *usbpd_data)
+{
+       struct power_supply *psy_charger;
+       union power_supply_propval val;
+       int ret = 0;
+
+       psy_charger = power_supply_get_by_name("s2mu106-charger");
+
+       if (psy_charger) {
+               ret = psy_charger->desc->set_property(psy_charger,
+                                                       POWER_SUPPLY_PROP_USBPD_TEST_READ, &val);
+       } else {
+               pr_err("%s: Fail to get psy battery\n", __func__);
+
+               return;
+       }
+}
+
 void vbus_turn_on_ctrl(struct s2mu106_usbpd_data *usbpd_data, bool enable)
 {
        struct power_supply *psy_otg;
@@ -227,9 +264,9 @@ static int s2mu106_usbpd_get_pmeter_volt(struct s2mu106_usbpd_data *pdic_data)
        union power_supply_propval val;
        int ret = 0;
 
-       if (psy_pm) {
+       if (psy_pm)
                ret = psy_pm->desc->get_property(psy_pm, POWER_SUPPLY_PROP_VCHGIN, &val);
-       else {
+       else {
                pr_err("%s: Fail to get pmeter\n", __func__);
                return -1;
        }
@@ -245,6 +282,31 @@ static int s2mu106_usbpd_get_pmeter_volt(struct s2mu106_usbpd_data *pdic_data)
        return 0;
 }
 
+static int s2mu106_usbpd_get_pmeter_current(struct s2mu106_usbpd_data *pdic_data)
+{
+
+       struct power_supply *psy_pm = pdic_data->psy_pm;
+       union power_supply_propval val;
+       int ret = 0;
+
+       if (psy_pm)
+               psy_pm->desc->get_property(psy_pm, POWER_SUPPLY_PROP_ICHGIN, &val);
+       else {
+               pr_err("%s: Fail to get pmeter\n", __func__);
+               return -1;
+       }
+
+       if (ret) {
+                       pr_err("%s: fail to set power_suppy pmeter property(%d)\n",
+               __func__, ret);
+               return -1;
+       }
+
+       pdic_data->pm_chgin_i = val.intval;
+
+       return 0;
+}
+
 static int s2mu106_usbpd_check_vbus(struct s2mu106_usbpd_data *pdic_data,
                                                                                                int volt, CCIC_VBUS_SEL mode)
 {
@@ -344,17 +406,23 @@ static void s2mu106_pr_swap(void *_data, int val)
        else if (val == USBPD_SOURCE_ON) {
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SRC;
+#elif defined(CONFIG_TYPEC)
+               pdic_data->typec_power_role = TYPEC_SOURCE;
+               typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
+#endif
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC,
                                                                IFCONN_NOTIFY_ID_ROLE_SWAP, 1/* source */, 0);
-#endif
        } else if (val == USBPD_SOURCE_OFF) {
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_BATTERY,
                                                                IFCONN_NOTIFY_ID_DETACH, 0, 0);
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SNK;
+#elif defined(CONFIG_TYPEC)
+               pdic_data->typec_power_role = TYPEC_SINK;
+               typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
+#endif
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC,
                                                                IFCONN_NOTIFY_ID_ROLE_SWAP, 0/* sink */, 0);
-#endif
        }
 }
 
@@ -721,7 +789,6 @@ static bool s2mu106_poll_status(void *_data)
        u64 status_reg_val = 0;
        msg_header_type header;
        int data_obj_num = 0;
-       int msg_id = 0;
 
        ret = s2mu106_usbpd_bulk_read(i2c, S2MU106_REG_INT_STATUS0,
                        S2MU106_MAX_NUM_INT_STATUS, intr);
@@ -776,29 +843,24 @@ static bool s2mu106_poll_status(void *_data)
        if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_DR_SWAP)
                status_reg_val |= MSG_DR_SWAP;
 
+       if (intr[0] & S2MU106_REG_INT_STATUS0_MSG_ACCEPT)
+               status_reg_val |= MSG_ACCEPT;
+
        /* function that support dp control */
        if (intr[4] & S2MU106_REG_INT_STATUS4_MSG_PASS) {
                if (intr[3] & S2MU106_REG_INT_STATUS3_UNS_CMD_DATA)
                        status_reg_val |= MSG_RID;
                else {
                        usbpd_protocol_rx(data);
+                       if (data->msg_received == 0)
+                               goto out;
+
                        header = data->protocol_rx.msg_header;
                        data_obj_num = header.num_data_objs;
-                       msg_id = header.msg_id;
-                       pr_info("%s, prev msg_id =(%d), received msg_id =(%d)\n", __func__,
-                                                                               data->msg_id, msg_id);
-
-                       if (msg_id == data->msg_id)
-                               goto out;
-                       else
-                               data->msg_id = msg_id;
 
                        if (data_obj_num > 0)
                                s2mu106_usbpd_check_msg(data, &status_reg_val);
 
-                       if (intr[0] & S2MU106_REG_INT_STATUS0_MSG_ACCEPT)
-                               status_reg_val |= MSG_ACCEPT;
-
                        if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PSRDY)
                                status_reg_val |= MSG_PSRDY;
 
@@ -1242,6 +1304,12 @@ static void s2mu106_usbpd_set_rp_scr_sel(struct s2mu106_usbpd_data *pdic_data,
        u8 data = 0;
        pr_info("%s: scr_sel : (%d)\n", __func__, scr_sel);
        switch (scr_sel) {
+       case PLUG_CTRL_RP0:
+               s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
+               data &= ~S2MU106_REG_PLUG_CTRL_RP_SEL_MASK;
+               data |= S2MU106_REG_PLUG_CTRL_RP0;
+               s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data);
+               break;
        case PLUG_CTRL_RP80:
                s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
                data &= ~S2MU106_REG_PLUG_CTRL_RP_SEL_MASK;
@@ -1482,61 +1550,6 @@ static void s2mu106_usbpd_check_rid(struct s2mu106_usbpd_data *pdic_data)
        }
 }
 
-static int s2mu106_set_attach(struct s2mu106_usbpd_data *pdic_data, u8 mode)
-{
-       u8 data;
-       int ret = 0;
-       struct i2c_client *i2c = pdic_data->i2c;
-       struct device *dev = &i2c->dev;
-
-       s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
-       data &= ~(S2MU106_REG_PLUG_CTRL_MODE_MASK | S2MU106_REG_PLUG_CTRL_RP_SEL_MASK);
-       data |= mode | S2MU106_REG_PLUG_CTRL_RP180;
-       s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data);
-
-       s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PD_CTRL, &data);
-       data &= ~S2MU106_REG_LPM_EN;
-       s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PD_CTRL, data);
-
-       dev_info(dev, "%s s2mu106 force to attach\n", __func__);
-
-       return ret;
-}
-
-static int s2mu106_set_detach(struct s2mu106_usbpd_data *pdic_data, u8 mode)
-{
-       u8 data;
-       int ret = 0;
-       struct i2c_client *i2c = pdic_data->i2c;
-       struct device *dev = &i2c->dev;
-
-       if (mode == TYPE_C_ATTACH_DFP) {
-               s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, &data);
-               data |= S2MU106_REG_PLUG_CTRL_RpRd_Rp_Source_Mode;
-               s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, data);
-       } else if (mode == TYPE_C_ATTACH_UFP) {
-               s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, &data);
-               data |= S2MU106_REG_PLUG_CTRL_RpRd_Rd_Sink_Mode;
-               s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, data);
-       }
-
-       msleep(50);
-
-       s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, S2MU106_RESET_REG_00);
-       s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
-       data &= ~(S2MU106_REG_PLUG_CTRL_MODE_MASK | S2MU106_REG_PLUG_CTRL_RP_SEL_MASK);
-       data |= S2MU106_REG_PLUG_CTRL_DFP | S2MU106_REG_PLUG_CTRL_RP0;
-       s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data);
-
-       s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PD_CTRL, &data);
-       data |= S2MU106_REG_LPM_EN;
-       s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PD_CTRL, data);
-
-       dev_info(dev, "%s s2mu106 force to detach\n", __func__);
-
-       return ret;
-}
-
 int s2mu106_set_normal_mode(struct s2mu106_usbpd_data *pdic_data)
 {
        u8 data;
@@ -1914,6 +1927,9 @@ static void s2mu106_usbpd_otg_attach(struct s2mu106_usbpd_data *pdic_data)
        pdic_data->is_host = HOST_ON;
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
        pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SRC;
+#elif defined(CONFIG_TYPEC)
+       pdic_data->typec_power_role = TYPEC_SOURCE;
+       typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
 #endif
 #if defined(CONFIG_IFCONN_NOTIFIER)
        /* USB */
@@ -2071,8 +2087,19 @@ static void s2mu106_usbpd_prevent_watchdog_reset(
                        s2mu106_usbpd_read_reg(i2c, S2MU106_REG_INT_STATUS2, &val);
                        if (val & S2MU106_REG_INT_STATUS2_WAKEUP)
                                pr_info("%s auto wakeup success\n", __func__);
+                       else {
+                               msleep(22);
+                               s2mu106_usbpd_set_vbus_wakeup(pdic_data, VBUS_WAKEUP_DISABLE);
+                               usleep_range(1000, 1200);
+                               s2mu106_usbpd_set_vbus_wakeup(pdic_data, VBUS_WAKEUP_ENABLE);
+                               usleep_range(1000, 1200);
+                               s2mu106_usbpd_read_reg(i2c, S2MU106_REG_INT_STATUS2, &val);
+                               if (val & S2MU106_REG_INT_STATUS2_WAKEUP)
+                                       pr_info("%s auto wakeup success\n", __func__);
                        else
                                s2mu106_usbpd_set_mode(pdic_data, PD_NORMAL_MODE);
+                       }
+
                        s2mu106_set_irq_enable(pdic_data, ENABLED_INT_0, ENABLED_INT_1,
                                                                ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4,
                                                                                                                                ENABLED_INT_5);
@@ -2126,6 +2153,10 @@ static void s2mu106_usbpd_detach_init(struct s2mu106_usbpd_data *pdic_data)
        if (pdic_data->power_role_dual == DUAL_ROLE_PROP_PR_SRC) {
                vbus_turn_on_ctrl(pdic_data, VBUS_OFF);
        }
+#elif defined(CONFIG_TYPEC)
+       if (pdic_data->typec_power_role == TYPEC_SOURCE) {
+               vbus_turn_on_ctrl(pdic_data, VBUS_OFF);
+       }
 #endif
        pdic_data->detach_valid = true;
        mutex_unlock(&pdic_data->cc_mutex);
@@ -2183,6 +2214,11 @@ static void s2mu106_usbpd_notify_detach(struct s2mu106_usbpd_data *pdic_data)
                pdic_data->is_client = CLIENT_OFF;
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_NONE;
+#elif defined(CONFIG_TYPEC)
+               pdic_data->typec_power_role = TYPEC_SINK;
+               typec_set_pwr_role(pdic_data->port, TYPEC_SINK);
+               pdic_data->typec_data_role = TYPEC_DEVICE;
+               typec_set_data_role(pdic_data->port, TYPEC_DEVICE);
 #endif
                /* USB */
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
@@ -2238,6 +2274,9 @@ static void s2mu106_usbpd_check_host(struct s2mu106_usbpd_data *pdic_data,
                                IFCONN_NOTIFY_ID_ATTACH, IFCONN_NOTIFY_EVENT_DETACH, NULL);
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_NONE;
+#elif defined(CONFIG_TYPEC)
+               pdic_data->typec_power_role = TYPEC_SINK;
+               typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
 #endif
                /* add to turn off external 5V */
                vbus_turn_on_ctrl(pdic_data, VBUS_OFF);
@@ -2262,6 +2301,9 @@ static void s2mu106_usbpd_check_client(struct s2mu106_usbpd_data *pdic_data,
                                IFCONN_NOTIFY_ID_ATTACH, IFCONN_NOTIFY_EVENT_DETACH, NULL);
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_NONE;
+#elif defined(CONFIG_TYPEC)
+               pdic_data->typec_power_role = TYPEC_SINK;
+               typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
 #endif
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_USB,
                                IFCONN_NOTIFY_ID_USB, IFCONN_NOTIFY_EVENT_DETACH, NULL);
@@ -2339,6 +2381,9 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data)
                                pdic_data->is_client = CLIENT_ON;
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SNK;
+#elif defined(CONFIG_TYPEC)
+                               pdic_data->typec_power_role = TYPEC_SINK;
+                               typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
 #endif
                                ifconn_event_work(pdic_data,
                                                IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
@@ -2466,6 +2511,7 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data)
                attach_status = s2mu106_get_status(pd_data, PLUG_ATTACH);
                rid_status = s2mu106_get_status(pd_data, MSG_RID);
                s2mu106_usbpd_detach_init(pdic_data);
+               s2mu106_usbpd_notify_detach(pdic_data);
                if (attach_status) {
                        ret = s2mu106_check_port_detect(pdic_data);
                        if (ret >= 0) {
@@ -2476,7 +2522,7 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data)
                                goto hard_reset;
                        }
                }
-               s2mu106_usbpd_notify_detach(pdic_data);
+#if 0
                mutex_lock(&pdic_data->lpm_mutex);
                if (!pdic_data->lpm_mode) {
                        if (s2mu106_usbpd_lpm_check(pdic_data) > 0) {
@@ -2487,6 +2533,7 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data)
                                ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5);
                }
                mutex_unlock(&pdic_data->lpm_mutex);
+#endif
                goto out;
        }
 
@@ -2730,7 +2777,15 @@ static int s2mu106_usbpd_irq_init(struct s2mu106_usbpd_data *_data)
 
 static void s2mu106_usbpd_init_configure(struct s2mu106_usbpd_data *_data)
 {
+       s2mu106_usbpd_test_read(_data);
+       s2mu106_usbpd_get_pmeter_volt(_data);
+       s2mu106_usbpd_get_pmeter_current(_data);
+       pr_info("%s, chgin(%d), chgin_i(%d)\n", __func__,
+                                                       _data->pm_chgin, _data->pm_chgin_i);
+       usbpd_charger_test_read(_data);
        s2mu106_set_normal_mode(_data);
+       pr_info("%s, usbpd irq gpio value(%d)\n", __func__,
+                                                                       gpio_get_value(_data->irq_gpio));
        msleep(25);
        _data->detach_valid = true;
        s2mu106_set_lpm_mode(_data);
@@ -2763,6 +2818,10 @@ static void s2mu106_usbpd_pdic_data_init(struct s2mu106_usbpd_data *_data)
        _data->lpcharge_water = false;
 #endif
        _data->check_rid_wa = false;
+#if defined(CONFIG_TYPEC)
+       _data->typec_power_role = TYPEC_SINK;
+       _data->typec_data_role = TYPEC_DEVICE;
+#endif
 }
 
 static int of_s2mu106_dt(struct device *dev,
@@ -2782,6 +2841,8 @@ static int of_s2mu106_dt(struct device *dev,
                                                _data->irq_gpio);
                        _data->irq_gpio = 0;
                }
+               ret = gpio_get_value(_data->irq_gpio);
+               pr_info("%s, usbpd irq gpio value(%d)\n", __func__, ret);
                if (of_find_property(np_usbpd, "vconn-en", NULL))
                        _data->vconn_en = true;
                else
@@ -2839,6 +2900,14 @@ static int s2mu106_usbpd_probe(struct i2c_client *i2c,
        mutex_init(&pdic_data->cc_mutex);
        wake_lock_init(&pdic_data->wake_lock, WAKE_LOCK_SUSPEND, "pdic_wake");
 
+#ifdef CONFIG_PM_S2MU106
+       pdic_data->psy_pm = power_supply_get_by_name("s2mu106_pmeter");
+       if (!pdic_data->psy_pm)
+               pr_err("%s: Fail to get pmeter\n", __func__);
+       s2mu106_usbpd_set_pmeter_mode(pdic_data, PM_TYPE_VCHGIN);
+       s2mu106_usbpd_set_pmeter_mode(pdic_data, PM_TYPE_ICHGIN);
+#endif
+
        s2mu106_usbpd_init_configure(pdic_data);
        s2mu106_usbpd_pdic_data_init(pdic_data);
 
@@ -2859,11 +2928,6 @@ static int s2mu106_usbpd_probe(struct i2c_client *i2c,
 
        usbpd_set_ops(dev, &s2mu106_ops);
 
-#ifdef CONFIG_PM_S2MU106
-       pdic_data->psy_pm = power_supply_get_by_name("s2mu106_pmeter");
-       if (!pdic_data->psy_pm)
-               pr_err("%s: Fail to get pmeter\n", __func__);
-#endif
        s2mu106_usbpd_reg_init(pdic_data);
 
        pdic_data->pdic_queue =
@@ -2886,6 +2950,13 @@ static int s2mu106_usbpd_probe(struct i2c_client *i2c,
 #endif
        if (pdic_data->rid == REG_RID_UNDF)
                pdic_data->rid = REG_RID_MAX;
+#if defined(CONFIG_TYPEC)
+       ret = typec_init(pdic_data);
+       if (ret < 0) {
+               pr_err("failed to init typec\n");
+               goto err_return;
+       }
+#endif
 
        ret = s2mu106_usbpd_irq_init(pdic_data);
        if (ret) {
@@ -2975,6 +3046,8 @@ static int s2mu106_usbpd_remove(struct i2c_client *i2c)
                devm_dual_role_instance_unregister(_data->dev,
                                                _data->dual_role);
                devm_kfree(_data->dev, _data->desc);
+#elif defined(CONFIG_TYPEC)
+               typec_unregister_port(_data->port);
 #endif
                disable_irq_wake(_data->i2c->irq);
                free_irq(_data->i2c->irq, _data);
index 6d38a0867567c7ed62acc33810d753219a25e772..26a0a09581a0dc201658a9537a4a906a36c6fcd6 100644 (file)
@@ -368,6 +368,8 @@ protocol_state usbpd_protocol_rx_wait_for_phy_message(struct protocol_data *rx)
                        dev_err(pd_data->dev, "[Rx] Got SOFTRESET.\n");
                        state = PRL_Rx_Layer_Reset_for_Receive;
                } else {
+                       pr_info("%s, prev msg_id =(%d), received msg_id =(%d)\n", __func__,
+                                                                       rx->stored_message_id, rx->msg_header.msg_id);
                        if (rx->stored_message_id == rx->msg_header.msg_id) {
                                pd_data->id_matched = 0;
                                return state;
index 4c472c27a8598830ce3fb6c55beb188b751ae411..ed6f694092303bf06a139b9bd74e622d0080d34c 100644 (file)
 #include <linux/completion.h>
 #include <linux/usb_notify.h>
 
-#if (defined CONFIG_CCIC_NOTIFIER || defined CONFIG_DUAL_ROLE_USB_INTF \
-                       || defined CONFIG_IFCONN_NOTIFIER)
+#if (defined CONFIG_CCIC_NOTIFIER || defined CONFIG_DUAL_ROLE_USB_INTF)
+#include <linux/ccic/usbpd_ext.h>
+#elif defined(CONFIG_TYPEC)
 #include <linux/ccic/usbpd_ext.h>
-#endif
-#if defined CONFIG_IFCONN_NOTIFIER
-#include <linux/ifconn/ifconn_notifier.h>
 #endif
 #include <linux/ccic/usbpd.h>
+
+#if defined CONFIG_CCIC_S2MU004
+#include <linux/ccic/usbpd-s2mu004.h>
+#elif defined CONFIG_CCIC_S2MU106
 #include <linux/ccic/usbpd-s2mu106.h>
+#elif defined CONFIG_CCIC_S2MU205
+#include <linux/ccic/usbpd-s2mu205.h>
+#endif
 
 #if defined(CONFIG_CCIC_NOTIFIER)
 static void ccic_event_notifier(struct work_struct *data)
@@ -61,6 +66,7 @@ static void ccic_event_notifier(struct work_struct *data)
                        event_work);
                break;
        }
+
        ccic_noti.src = CCIC_NOTIFY_DEV_CCIC;
        ccic_noti.dest = event_work->dest;
        ccic_noti.id = event_work->id;
@@ -79,9 +85,18 @@ static void ccic_event_notifier(struct work_struct *data)
 
 extern void ccic_event_work(void *data, int dest, int id, int attach, int event)
 {
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *usbpd_data = data;
+#elif defined CONFIG_CCIC_S2MU106
        struct s2mu106_usbpd_data *usbpd_data = data;
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *usbpd_data = data;
+#endif
        struct ccic_state_work *event_work;
-
+#if defined(CONFIG_TYPEC)
+       struct typec_partner_desc desc;
+       enum typec_pwr_opmode mode;
+#endif
 
        event_work = kmalloc(sizeof(struct ccic_state_work), GFP_ATOMIC);
        pr_info("usb: %s,event_work(%p)\n", __func__, event_work);
@@ -103,12 +118,45 @@ extern void ccic_event_work(void *data, int dest, int id, int attach, int event)
                        dual_role_instance_changed(usbpd_data->dual_role);
 
                if (usbpd_data->try_state_change &&
-                       (usbpd_data->data_role_dual != IFCONN_NOTIFY_EVENT_DETACH)) {
+                       (usbpd_data->data_role_dual != USB_STATUS_NOTIFY_DETACH)) {
                        /* Role change try and new mode detected */
                        pr_info("usb: %s, reverse_completion\n", __func__);
                        complete(&usbpd_data->reverse_completion);
                }
        }
+#elif defined(CONFIG_TYPEC)
+       if (id == CCIC_NOTIFY_ID_USB) {
+               if (usbpd_data->typec_try_state_change &&
+                       (event != USB_STATUS_NOTIFY_DETACH)) {
+                       // Role change try and new mode detected
+                       pr_info("usb: %s, role_reverse_completion\n", __func__);
+                       complete(&usbpd_data->role_reverse_completion);
+               }
+
+               if (event == USB_STATUS_NOTIFY_ATTACH_UFP) {
+                       mode = typec_get_pd_support(usbpd_data);
+                       typec_set_pwr_opmode(usbpd_data->port, mode);
+                       desc.usb_pd = mode == TYPEC_PWR_MODE_PD;
+                       desc.accessory = TYPEC_ACCESSORY_NONE; /* XXX: handle accessories */
+                       desc.identity = NULL;
+                       usbpd_data->typec_data_role = TYPEC_DEVICE;
+                       typec_set_data_role(usbpd_data->port, TYPEC_DEVICE);
+                       usbpd_data->partner = typec_register_partner(usbpd_data->port, &desc);
+               } else if (event == USB_STATUS_NOTIFY_ATTACH_DFP) {
+                       mode = typec_get_pd_support(usbpd_data);
+                       typec_set_pwr_opmode(usbpd_data->port, mode);
+                       desc.usb_pd = mode == TYPEC_PWR_MODE_PD;
+                       desc.accessory = TYPEC_ACCESSORY_NONE; /* XXX: handle accessories */
+                       desc.identity = NULL;
+                       usbpd_data->typec_data_role = TYPEC_HOST;
+                       typec_set_data_role(usbpd_data->port, TYPEC_HOST);
+                       usbpd_data->partner = typec_register_partner(usbpd_data->port, &desc);
+               } else {
+                       if (!IS_ERR(usbpd_data->partner))
+                               typec_unregister_partner(usbpd_data->partner);
+                       usbpd_data->partner = NULL;
+               }
+       }
 #endif
 
        if (queue_work(usbpd_data->ccic_wq, &event_work->ccic_work) == 0) {
@@ -147,7 +195,10 @@ extern void ifconn_event_work(void *pd_data, int dest, int id, int event, void *
 {
        struct s2mu106_usbpd_data *usbpd_data = pd_data;
        struct ifconn_state_work *event_work;
-
+#if defined(CONFIG_TYPEC)
+       struct typec_partner_desc desc;
+       enum typec_pwr_opmode mode;
+#endif
        event_work = kmalloc(sizeof(struct ifconn_state_work), GFP_ATOMIC);
        INIT_WORK(&event_work->ifconn_work, ifconn_event_notifier);
 
@@ -173,6 +224,44 @@ extern void ifconn_event_work(void *pd_data, int dest, int id, int event, void *
                        complete(&usbpd_data->reverse_completion);
                }
        }
+#elif defined(CONFIG_TYPEC)
+           if (id == IFCONN_NOTIFY_ID_USB) {
+               if (usbpd_data->typec_try_state_change &&
+                   (event != IFCONN_NOTIFY_EVENT_DETACH)) {
+                   // Role change try and new mode detected
+                   pr_info("usb: %s, role_reverse_completion\n", __func__);
+                   complete(&usbpd_data->role_reverse_completion);
+               }
+
+               if (event == IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP) {
+                   pr_info("usb: %s, line : %d\n", __func__, __LINE__);
+                   mode = typec_get_pd_support(usbpd_data);
+                   typec_set_pwr_opmode(usbpd_data->port, mode);
+                   desc.usb_pd = mode == TYPEC_PWR_MODE_PD;
+                   desc.accessory = TYPEC_ACCESSORY_NONE; /* XXX: handle accessories */
+                   desc.identity = NULL;
+                   usbpd_data->typec_data_role = TYPEC_DEVICE;
+                   typec_set_data_role(usbpd_data->port, TYPEC_DEVICE);
+                   usbpd_data->partner = typec_register_partner(usbpd_data->port, &desc);
+               } else if (event == IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP) {
+                   pr_info("usb: %s, line : %d\n", __func__, __LINE__);
+                   mode = typec_get_pd_support(usbpd_data);
+                   typec_set_pwr_opmode(usbpd_data->port, mode);
+                   desc.usb_pd = mode == TYPEC_PWR_MODE_PD;
+                   desc.accessory = TYPEC_ACCESSORY_NONE; /* XXX: handle accessories */
+                   desc.identity = NULL;
+                   usbpd_data->typec_data_role = TYPEC_HOST;
+                   typec_set_data_role(usbpd_data->port, TYPEC_HOST);
+                   usbpd_data->partner = typec_register_partner(usbpd_data->port, &desc);
+               } else {
+                   pr_info("usb: %s, line : %d\n", __func__, __LINE__);
+                   if (!IS_ERR(usbpd_data->partner))
+                       typec_unregister_partner(usbpd_data->partner);
+                   usbpd_data->partner = NULL;
+               }
+               pr_info("usb: %s, line : %d\n", __func__, __LINE__);
+           }
+           pr_info("usb: %s, line : %d\n", __func__, __LINE__);
 #endif
 
        if (queue_work(usbpd_data->ifconn_wq, &event_work->ifconn_work) == 0) {
@@ -194,8 +283,16 @@ void role_swap_check(struct work_struct *wk)
 {
        struct delayed_work *delay_work =
                container_of(wk, struct delayed_work, work);
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *usbpd_data =
+               container_of(delay_work, struct s2mu004_usbpd_data, role_swap_work);
+#elif defined CONFIG_CCIC_S2MU106
        struct s2mu106_usbpd_data *usbpd_data =
                container_of(delay_work, struct s2mu106_usbpd_data, role_swap_work);
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *usbpd_data =
+               container_of(delay_work, struct s2mu205_usbpd_data, role_swap_work);
+#endif
        int mode = 0;
 
        pr_info("%s: ccic_set_dual_role check again.\n", __func__);
@@ -206,7 +303,13 @@ void role_swap_check(struct work_struct *wk)
                disable_irq(usbpd_data->irq);
                /* exit from Disabled state and set mode to DRP */
                mode =  TYPE_C_ATTACH_DRP;
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU106
                s2mu106_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, mode);
+#endif
                enable_irq(usbpd_data->irq);
        }
 }
@@ -215,10 +318,16 @@ static int ccic_set_dual_role(struct dual_role_phy_instance *dual_role,
                                   enum dual_role_property prop,
                                   const unsigned int *val)
 {
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *usbpd_data = dual_role_get_drvdata(dual_role);
+#elif defined CONFIG_CCIC_S2MU106
        struct s2mu106_usbpd_data *usbpd_data = dual_role_get_drvdata(dual_role);
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *usbpd_data = dual_role_get_drvdata(dual_role);
+#endif
        struct i2c_client *i2c;
 
-       ifconn_notifier_event_t attached_state;
+       USB_STATUS attached_state;
        int mode;
        int timeout = 0;
        int ret = 0;
@@ -234,47 +343,62 @@ static int ccic_set_dual_role(struct dual_role_phy_instance *dual_role,
        attached_state = usbpd_data->data_role_dual;
        pr_info("%s : request prop = %d , attached_state = %d\n", __func__, prop, attached_state);
 
-       if (attached_state != IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP
-           && attached_state != IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP) {
+       if (attached_state != USB_STATUS_NOTIFY_ATTACH_DFP
+           && attached_state != USB_STATUS_NOTIFY_ATTACH_UFP) {
                pr_err("%s : current mode : %d - just return \n", __func__, attached_state);
                return 0;
        }
 
-       if (attached_state == IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP
+       if (attached_state == USB_STATUS_NOTIFY_ATTACH_DFP
            && *val == DUAL_ROLE_PROP_MODE_DFP) {
                pr_err("%s : current mode : %d - request mode : %d just return \n",
                        __func__, attached_state, *val);
                return 0;
        }
 
-       if (attached_state == IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP
+       if (attached_state == USB_STATUS_NOTIFY_ATTACH_UFP
            && *val == DUAL_ROLE_PROP_MODE_UFP) {
                pr_err("%s : current mode : %d - request mode : %d just return \n",
                        __func__, attached_state, *val);
                return 0;
        }
 
-       if (attached_state == IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP) {
+       if (attached_state == USB_STATUS_NOTIFY_ATTACH_DFP) {
                /* Current mode DFP and Source  */
                pr_info("%s: try reversing, from Source to Sink\n", __func__);
                /* turns off VBUS first */
                vbus_turn_on_ctrl(usbpd_data, 0);
-#if defined(CONFIG_IFCONN_NOTIFIER)
+#if defined(CONFIG_MUIC_SUPPORT_CCIC_OTG_CTRL)
+               muic_disable_otg_detect();
+#endif
+#if defined(CONFIG_CCIC_NOTIFIER)
                /* muic */
-               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_MUIC,
-                                       IFCONN_NOTIFY_ID_ATTACH, IFCONN_NOTIFY_EVENT_DETACH, NULL);
+               ccic_event_work(usbpd_data,
+                       CCIC_NOTIFY_DEV_MUIC, CCIC_NOTIFY_ID_ATTACH, 0/*attach*/, 0/*rprd*/);
 #endif
                /* exit from Disabled state and set mode to UFP */
                mode =  TYPE_C_ATTACH_UFP;
                usbpd_data->try_state_change = TYPE_C_ATTACH_UFP;
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU106
                s2mu106_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, mode);
+#endif
        } else {
                /* Current mode UFP and Sink  */
                pr_info("%s: try reversing, from Sink to Source\n", __func__);
                /* exit from Disabled state and set mode to UFP */
                mode =  TYPE_C_ATTACH_DFP;
                usbpd_data->try_state_change = TYPE_C_ATTACH_DFP;
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU106
                s2mu106_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, mode);
+#endif
        }
 
        reinit_completion(&usbpd_data->reverse_completion);
@@ -289,7 +413,13 @@ static int ccic_set_dual_role(struct dual_role_phy_instance *dual_role,
                disable_irq(usbpd_data->irq);
                /* exit from Disabled state and set mode to DRP */
                mode =  TYPE_C_ATTACH_DRP;
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU106
                s2mu106_rprd_mode_change(usbpd_data, mode);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, mode);
+#endif
                enable_irq(usbpd_data->irq);
                ret = -EIO;
        } else {
@@ -316,9 +446,15 @@ int dual_role_get_local_prop(struct dual_role_phy_instance *dual_role,
                                    enum dual_role_property prop,
                                    unsigned int *val)
 {
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *usbpd_data = dual_role_get_drvdata(dual_role);
+#elif defined CONFIG_CCIC_S2MU106
        struct s2mu106_usbpd_data *usbpd_data = dual_role_get_drvdata(dual_role);
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *usbpd_data = dual_role_get_drvdata(dual_role);
+#endif
 
-       ifconn_notifier_event_t attached_state;
+       USB_STATUS attached_state;
        int power_role_dual;
 
        if (!usbpd_data) {
@@ -339,7 +475,7 @@ int dual_role_get_local_prop(struct dual_role_phy_instance *dual_role,
                return 0;
        }
 
-       if (attached_state == IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP) {
+       if (attached_state == USB_STATUS_NOTIFY_ATTACH_DFP) {
                if (prop == DUAL_ROLE_PROP_MODE)
                        *val = DUAL_ROLE_PROP_MODE_DFP;
                else if (prop == DUAL_ROLE_PROP_PR)
@@ -348,7 +484,7 @@ int dual_role_get_local_prop(struct dual_role_phy_instance *dual_role,
                        *val = DUAL_ROLE_PROP_DR_HOST;
                else
                        return -EINVAL;
-       } else if (attached_state == IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP) {
+       } else if (attached_state == USB_STATUS_NOTIFY_ATTACH_UFP) {
                if (prop == DUAL_ROLE_PROP_MODE)
                        *val = DUAL_ROLE_PROP_MODE_UFP;
                else if (prop == DUAL_ROLE_PROP_PR)
@@ -393,7 +529,13 @@ int dual_role_set_prop(struct dual_role_phy_instance *dual_role,
 
 int dual_role_init(void *_data)
 {
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *pdic_data = _data;
+#elif defined CONFIG_CCIC_S2MU106
        struct s2mu106_usbpd_data *pdic_data = _data;
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *pdic_data = _data;
+#endif
        struct dual_role_phy_desc *desc;
        struct dual_role_phy_instance *dual_role;
 
@@ -421,4 +563,161 @@ int dual_role_init(void *_data)
 
        return 0;
 }
+#elif defined(CONFIG_TYPEC)
+void typec_role_swap_check(struct work_struct *wk)
+{
+       struct delayed_work *delay_work =
+               container_of(wk, struct delayed_work, work);
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *usbpd_data =
+               container_of(delay_work, struct s2mu004_usbpd_data, typec_role_swap_work);
+#elif defined CONFIG_CCIC_S2MU106
+       struct s2mu106_usbpd_data *usbpd_data =
+               container_of(delay_work, struct s2mu106_usbpd_data, typec_role_swap_work);
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *usbpd_data =
+               container_of(delay_work, struct s2mu205_usbpd_data, typec_role_swap_work);
+#endif
+
+       pr_info("%s: ccic_set_dual_role check again.\n", __func__);
+       usbpd_data->typec_try_state_change = 0;
+
+       if (usbpd_data->detach_valid) { /* modify here using pd_state */
+               pr_err("%s: ccic_set_dual_role reverse failed, set mode to DRP\n", __func__);
+               disable_irq(usbpd_data->irq);
+               /* exit from Disabled state and set mode to DRP */
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DRP);
+#elif defined CONFIG_CCIC_S2MU106
+               s2mu106_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DRP);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DRP);
+#endif
+               enable_irq(usbpd_data->irq);
+       }
+}
+
+int typec_port_type_set(const struct typec_capability *cap, enum typec_port_type port_type)
+{
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *usbpd_data = container_of(cap, struct s2mu004_usbpd_data, typec_cap);
+#elif defined CONFIG_CCIC_S2MU106
+       struct s2mu106_usbpd_data *usbpd_data = container_of(cap, struct s2mu106_usbpd_data, typec_cap);
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *usbpd_data = container_of(cap, struct s2mu205_usbpd_data, typec_cap);
+#endif
+
+       int timeout = 0;
+
+       if (!usbpd_data) {
+               pr_err("%s : usbpd_data is null\n", __func__);
+               return -EINVAL;
+       }
+
+       pr_info("%s : typec_power_role=%d, typec_data_role=%d, port_type=%d\n",
+               __func__, usbpd_data->typec_power_role, usbpd_data->typec_data_role, port_type);
+
+       switch (port_type) {
+       case TYPEC_PORT_DFP:
+               pr_info("%s : try reversing, from UFP(Sink) to DFP(Source)\n", __func__);
+               usbpd_data->typec_try_state_change = TYPE_C_ATTACH_DFP;
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DFP);
+#elif defined CONFIG_CCIC_S2MU106
+               s2mu106_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DFP);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DFP);
+#endif
+
+               break;
+       case TYPEC_PORT_UFP:
+               pr_info("%s : try reversing, from DFP(Source) to UFP(Sink)\n", __func__);
+               /* turns off VBUS first */
+               vbus_turn_on_ctrl(usbpd_data, 0);
+#if defined(CONFIG_CCIC_NOTIFIER)
+               ccic_event_work(usbpd_data,
+                       CCIC_NOTIFY_DEV_MUIC, CCIC_NOTIFY_ID_ATTACH,
+                       0/*attach*/, 0/*rprd*/);
+#endif
+               usbpd_data->typec_try_state_change = TYPE_C_ATTACH_UFP;
+#if defined CONFIG_CCIC_S2MU004
+               s2mu004_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_UFP);
+#elif defined CONFIG_CCIC_S2MU106
+               s2mu106_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_UFP);
+#elif defined CONFIG_CCIC_S2MU205
+               s2mu205_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_UFP);
+#endif
+
+               break;
+       case TYPEC_PORT_DRP:
+               pr_info("%s : set to DRP (No action)\n", __func__);
+               return 0;
+       default :
+               pr_info("%s : invalid typec_role\n", __func__);
+               return -EINVAL;
+       }
+
+       if (usbpd_data->typec_try_state_change) {
+               reinit_completion(&usbpd_data->role_reverse_completion);
+               timeout =
+                   wait_for_completion_timeout(&usbpd_data->role_reverse_completion,
+                                               msecs_to_jiffies
+                                               (DUAL_ROLE_SET_MODE_WAIT_MS));
+
+               if (!timeout) {
+                       pr_err("%s: reverse failed, set mode to DRP\n", __func__);
+                       disable_irq(usbpd_data->irq);
+                       /* exit from Disabled state and set mode to DRP */
+                       usbpd_data->typec_try_state_change = 0;
+#if defined CONFIG_CCIC_S2MU004
+                       s2mu004_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DRP);
+#elif defined CONFIG_CCIC_S2MU106
+                       s2mu106_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DRP);
+#elif defined CONFIG_CCIC_S2MU205
+                       s2mu205_rprd_mode_change(usbpd_data, TYPE_C_ATTACH_DRP);
+#endif
+
+                       enable_irq(usbpd_data->irq);
+                       return -EIO;
+               } else {
+                       pr_err("%s: reverse success, one more check\n", __func__);
+                       schedule_delayed_work(&usbpd_data->typec_role_swap_work, msecs_to_jiffies(DUAL_ROLE_SET_MODE_WAIT_MS));
+               }
+       }
+
+       return 0;
+}
+
+int typec_get_pd_support(void *_data)
+{
+       return TYPEC_PWR_MODE_USB;
+}
+
+int typec_init(void *_data)
+{
+#if defined CONFIG_CCIC_S2MU004
+       struct s2mu004_usbpd_data *pdic_data = _data;
+#elif defined CONFIG_CCIC_S2MU106
+       struct s2mu106_usbpd_data *pdic_data = _data;
+#elif defined CONFIG_CCIC_S2MU205
+       struct s2mu205_usbpd_data *pdic_data = _data;
+#endif
+
+       pdic_data->typec_cap.revision = USB_TYPEC_REV_1_2;
+       pdic_data->typec_cap.pd_revision = 0x300;
+       pdic_data->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
+       pdic_data->typec_cap.port_type_set = typec_port_type_set;
+       pdic_data->typec_cap.type = TYPEC_PORT_DRP;
+       pdic_data->port = typec_register_port(pdic_data->dev, &pdic_data->typec_cap);
+       if (IS_ERR(pdic_data->port)) {
+               pr_err("%s : unable to register typec_register_port\n", __func__);
+               return -1;
+       } else
+               pr_err("%s : success typec_register_port port=%pK\n", __func__, pdic_data->port);
+
+       init_completion(&pdic_data->role_reverse_completion);
+       INIT_DELAYED_WORK(&pdic_data->typec_role_swap_work, typec_role_swap_check);
+
+       return 0;
+}
 #endif
index 22a64049475b4b8778a7ed7762213e7f4a34bdc3..a8383c9cdeafac99cd2e673fbf784e8b9e6e1ed2 100644 (file)
@@ -989,7 +989,7 @@ int usbpd_manager_match_request(struct usbpd_data *pd_data)
        //pr_info("Rx Request Current : %dmA\n", max_min*10);
 
     /* Compare Pdo and Rdo */
-    if ((src_max_current >= max_min) && (pos == 1))
+    if ((src_max_current >= op) && (pos == 1))
                return 0;
     else
                return -1;
index bace721691612eea416b46f254e515d19c803358..27c0b8c4cead976c6ada51bad58223a6242ee8e2 100644 (file)
@@ -230,7 +230,7 @@ void muic_manager_handle_ccic_detach(struct muic_interface_t *muic_if)
        ccic->attached_dev = 0;
        ccic->ccic_evt_rid = 0;
        ccic->ccic_evt_rprd = 0;
-       ccic->ccic_evt_roleswap = 0;
+       //ccic->ccic_evt_roleswap = 0;
        ccic->ccic_evt_dcdcnt = 0;
        ccic->ccic_evt_attached = MUIC_CCIC_NOTI_UNDEFINED;
 
@@ -715,39 +715,19 @@ static int muic_manager_handle_ccic_role_swap(struct muic_interface_t *muic_if,
 {
 #ifdef CONFIG_IFCONN_NOTIFIER
        struct ifconn_notifier_template *pnoti = (struct ifconn_notifier_template *)data;
-#else
-       CC_NOTI_TYPEDEF *pnoti = (CC_NOTI_TYPEDEF *)data;
-#endif
+
        struct ccic_desc_t *ccic = muic_if->ccic;
-       
-       pr_info("%s: src:%d dest:%d sub1:%d\n", __func__,
-               pnoti->src, pnoti->dest, pnoti->sub1);
-       
-       if (pnoti->sub1 == true) {
-               /* sink -> src */
-               ccic->ccic_evt_rprd = 1;
-               ccic->ccic_evt_roleswap = 1;
-               ccic->attached_dev = ATTACHED_DEV_OTG_MUIC;
-               if (muic_if->set_cable_state)
-                       muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
-       } else {
-               /* src -> sink */
-               muic_manager_handle_ccic_detach(muic_if);
 
-               ccic->ccic_evt_attached = MUIC_CCIC_NOTI_ATTACH;
-               ccic->ccic_evt_rprd = 1;
-               ccic->ccic_evt_roleswap = 1;
-               ccic->attached_dev = ATTACHED_DEV_TYPE3_CHARGER_MUIC;
-               if (muic_if->set_cable_state)
-                       muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
-       }
+       pr_info("%s: event:%d\n", __func__, pnoti->event);
 
-       return 0;       
+       if (pnoti->event == IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP)
+               ccic->ccic_evt_roleswap = 1;
+#endif
+       return 0;
 }
 
 static int muic_manager_handle_otg(struct muic_interface_t *muic_if, void *data)
 {
-       int ret = MUIC_NORMAL_OTG;
        struct ccic_desc_t *ccic = muic_if->ccic;
 #ifdef CONFIG_IFCONN_NOTIFIER
        struct ifconn_notifier_template *pnoti = (struct ifconn_notifier_template *)data;
@@ -761,20 +741,12 @@ static int muic_manager_handle_otg(struct muic_interface_t *muic_if, void *data)
 #ifndef CONFIG_IFCONN_NOTIFIER
        if (pnoti->sub1 == true) {
 #endif
-               /* OTG Attach */
-               if (muic_if->check_usb_killer) {
-                       ret = muic_if->check_usb_killer(muic_if->muic_data);
-               }
-
-               if (ret == MUIC_NORMAL_OTG) {
-                       MUIC_SEND_NOTI_TO_CCIC_ATTACH(ATTACHED_DEV_OTG_MUIC);
-                       ccic->ccic_evt_rprd = 1;
-                       ccic->attached_dev = ATTACHED_DEV_OTG_MUIC;
-                       if (muic_if->set_cable_state)
-                               muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
-                       muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
-               } else
-                       pr_info("[MUIC] %s USB Killer Detected!!!\n", __func__);
+               MUIC_SEND_NOTI_TO_CCIC_ATTACH(ATTACHED_DEV_OTG_MUIC);
+               ccic->ccic_evt_rprd = 1;
+               ccic->attached_dev = ATTACHED_DEV_OTG_MUIC;
+               if (muic_if->set_cable_state)
+                       muic_if->set_cable_state(muic_if->muic_data, ccic->attached_dev);
+               muic_manager_switch_path(muic_if, MUIC_PATH_USB_AP);
 #ifndef CONFIG_IFCONN_NOTIFIER
        }
 #endif
index 23525cd8bf2e2bc8331c2ebf9ba64350cf0bdedd..4ffa65fe52ee62b89af2353008e580b5b64f12bd 100644 (file)
@@ -284,6 +284,7 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(co_enable),
        POWER_SUPPLY_ATTR(rr_enable),
        POWER_SUPPLY_ATTR(usbpd_reset),
+       POWER_SUPPLY_ATTR(usbpd_test_read),
 };
 
 static struct attribute *
old mode 100755 (executable)
new mode 100644 (file)
index 39d809f..c0565dd
@@ -551,6 +551,7 @@ static int s2mu106_chg_set_property(struct power_supply *psy,
        int buck_state = ENABLE;
        union power_supply_propval value;
        int ret;
+       u8 data = 0;
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -662,12 +663,20 @@ static int s2mu106_chg_set_property(struct power_supply *psy,
                }
                break;
        case POWER_SUPPLY_PROP_FUELGAUGE_RESET:
-               s2mu106_update_reg(charger->i2c, 0xE3, 0x03 << 6, 0x03 << 6);
+               s2mu106_read_reg(charger->i2c, 0xE3, &data);
+               data |= 0x03 << 6;
+               s2mu106_write_reg(charger->i2c, 0xE3, data);
                msleep(1000);
-               s2mu106_update_reg(charger->i2c, 0xE3, 0x00 << 6, 0x03 << 6);
+               data &= ~(0x03 << 6);
+               s2mu106_write_reg(charger->i2c, 0xE3, data);
                msleep(50);
                pr_info("%s: reset fuelgauge when surge occur!\n", __func__);
                break;
+       case POWER_SUPPLY_PROP_USBPD_TEST_READ:
+               s2mu106_test_read(charger->i2c);
+               s2mu106_read_reg(charger->i2c, 0xEC, &data);
+               pr_info("%s, charger 0xEC=(%x)\n", __func__, data);
+               break;
        default:
                return -EINVAL;
        }
old mode 100755 (executable)
new mode 100644 (file)
index 7701e34..0b1a32d
@@ -226,14 +226,16 @@ static int s2mu106_pm_get_ichgin(struct s2mu106_pmeter_data *pmeter)
 
        s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_ICHGIN, &data1);
        s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_ICHGIN, &data2);
-       
+
        if (data1 < 0 || data2 < 0)
                return -EINVAL;
 
        charge_current = (int)((data1 << 4) | (data2 >> 4));
 
+#if 0
        pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, current = %d\n",
                        __func__, data1, data2, charge_current);
+#endif
        return charge_current;
 }
 
index cfe9da1ed57b8d5b48d1b7591b91219838beb992..e6077060d0d07c90633f422f6fd69bd3ea90c3d0 100644 (file)
 #include <soc/samsung/exynos-pm.h>
 #endif
 
-#if defined(CONFIG_TYPEC)
-#include <linux/usb/typec.h>
-#endif
-
 #include "core.h"
 #include "otg.h"
 #include "io.h"
 
 /* -------------------------------------------------------------------------- */
 
-#if defined(CONFIG_TYPEC)
-struct intf_typec {
-       /* struct mutex lock; */ /* device lock */
-       struct device *dev;
-       struct typec_port *port;
-       struct typec_capability cap;
-       struct typec_partner *partner;
-};
-#endif
-
 int otg_connection;
 static int dwc3_otg_statemachine(struct otg_fsm *fsm)
 {
@@ -703,11 +689,6 @@ int dwc3_otg_init(struct dwc3 *dwc)
        struct dwc3_otg *dotg;
        struct dwc3_ext_otg_ops *ops = NULL;
        int ret = 0;
-#if defined(CONFIG_TYPEC)
-       struct intf_typec       *typec;
-       struct typec_partner_desc partner;
-#endif
-
 
        dev_info(dwc->dev, "%s\n", __func__);
 
@@ -766,34 +747,6 @@ int dwc3_otg_init(struct dwc3 *dwc)
                }
        }
 
-#if defined(CONFIG_TYPEC)
-       typec = devm_kzalloc(dwc->dev, sizeof(*typec), GFP_KERNEL);
-       if (!typec)
-               return -ENOMEM;
-
-       /* mutex_init(&md05->lock); */
-       typec->dev = dwc->dev;
-
-       typec->cap.type = TYPEC_PORT_DRP;
-       typec->cap.revision = USB_TYPEC_REV_1_1;
-       typec->cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
-
-       typec->port = typec_register_port(dwc->dev, &typec->cap);
-       if (!typec->port)
-               return -ENODEV;
-
-       typec_set_data_role(typec->port, TYPEC_DEVICE);
-       typec_set_pwr_role(typec->port, TYPEC_SINK);
-       typec_set_pwr_opmode(typec->port, TYPEC_PWR_MODE_USB);
-
-       dotg->typec = typec;
-
-       typec->partner = typec_register_partner(typec->port, &partner);
-       if (!dotg->typec->partner)
-               dev_err(dwc->dev, "failed register partner\n");
-#endif
-
-
        wake_lock_init(&dotg->wakelock, WAKE_LOCK_SUSPEND, "dwc3-otg");
 
        ret = sysfs_create_group(&dwc->dev->kobj, &dwc3_otg_attr_group);
@@ -814,11 +767,6 @@ void dwc3_otg_exit(struct dwc3 *dwc)
        if (!dotg->ext_otg_ops)
                return;
 
-#if defined(CONFIG_TYPEC)
-       typec_unregister_partner(dotg->typec->partner);
-       typec_unregister_port(dotg->typec->port);
-#endif
-
        dwc3_ext_otg_exit(dotg);
 
        sysfs_remove_group(&dwc->dev->kobj, &dwc3_otg_attr_group);
index 02adc3e4953fec1b4e075d0b9395480df6119e5a..cd28f1c98aa9be642ff34eb71667ed1372296c7c 100644 (file)
@@ -17,6 +17,9 @@
 #if defined CONFIG_IFCONN_NOTIFIER
 #include <linux/ifconn/ifconn_notifier.h>
 #endif
+#if defined(CONFIG_TYPEC)
+#include <linux/usb/typec.h>
+#endif
 
 #include <linux/power_supply.h>
 
@@ -39,9 +42,7 @@
 #define S2MU106_HARD_RESET_DELAY_MS            (300)
 #define S2MU106_WAIT_RD_DETACH_DELAY_MS                (200)
 #define S2MU106_WAIT_ATTACH_DELAY_MS           (30)
-#if defined(CONFIG_DUAL_ROLE_USB_INTF)
 #define DUAL_ROLE_SET_MODE_WAIT_MS             (2000)
-#endif
 #define S2MU106_WATER_CHK_INTERVAL_TIME                (300)
 #define S2MU106_ATTACH_STATE_CHECK_TIME                (1000)
 
@@ -684,6 +685,16 @@ struct s2mu106_usbpd_data {
        struct completion reverse_completion;
        int try_state_change;
        struct delayed_work role_swap_work;
+#elif defined(CONFIG_TYPEC)
+       struct typec_port *port;
+       struct typec_partner *partner;
+       struct usb_pd_identity partner_identity;
+       struct typec_capability typec_cap;
+       struct completion role_reverse_completion;
+       int typec_power_role;
+       int typec_data_role;
+       int typec_try_state_change;
+       struct delayed_work typec_role_swap_work;
 #endif
        struct notifier_block type3_nb;
        struct workqueue_struct *pdic_queue;
@@ -694,6 +705,7 @@ struct s2mu106_usbpd_data {
     int pm_cc1;
     int pm_cc2;
     int pm_chgin;
+    int pm_chgin_i;
        struct power_supply_desc ccic_desc;
        struct power_supply *psy_pm;
        struct power_supply *psy_ccic;
@@ -709,9 +721,7 @@ extern void s2mu106_usbpd_set_muic_type(int type);
 #if defined(CONFIG_CCIC_NOTIFIER)
 extern void s2mu106_control_option_command(struct s2mu106_usbpd_data *usbpd_data, int cmd);
 #endif
-#if defined(CONFIG_DUAL_ROLE_USB_INTF)
 extern void s2mu106_rprd_mode_change(struct s2mu106_usbpd_data *usbpd_data, u8 mode);
-#endif
 extern void vbus_turn_on_ctrl(struct s2mu106_usbpd_data *usbpd_data, bool enable);
 extern int s2mu106_set_lpm_mode(struct s2mu106_usbpd_data *pdic_data);
 extern int s2mu106_set_normal_mode(struct s2mu106_usbpd_data *pdic_data);
index b7c0cacf4d6608aa25a9cfc9bff617236b3eed93..ac2a78510c2b1e06ee315920bade2cf72d5cc329 100644 (file)
@@ -3,6 +3,8 @@
 #endif
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
 #include <linux/usb/class-dual-role.h>
+#elif defined(CONFIG_TYPEC)
+#include <linux/usb/typec.h>
 #endif
 
 #ifndef __USBPD_EXT_H__
@@ -115,5 +117,11 @@ extern int dual_role_set_prop(struct dual_role_phy_instance *dual_role,
                              enum dual_role_property prop,
                              const unsigned int *val);
 extern int dual_role_init(void *_data);
+#elif defined(CONFIG_TYPEC)
+extern void typec_role_swap_check(struct work_struct *wk);
+extern int typec_port_type_set(const struct typec_capability *cap,
+                    enum typec_port_type port_type);
+extern int typec_get_pd_support(void *_data);
+extern int typec_init(void *_data);
 #endif
 #endif
index e6d70fcff400d1252e572eaef760eefcb6398456..eed131d3daaf393c9c5b5be5719f4de218bac535 100644 (file)
@@ -185,6 +185,7 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_CO_ENABLE,
        POWER_SUPPLY_PROP_RR_ENABLE,
        POWER_SUPPLY_PROP_USBPD_RESET,
+       POWER_SUPPLY_PROP_USBPD_TEST_READ,
 };
 
 enum power_supply_type {