[RAMEN9610-14333][COMMON][9610] drivers : fix typec role swap
authorJunhan Bae <junhan84.bae@samsung.com>
Fri, 22 Mar 2019 12:14:31 +0000 (21:14 +0900)
committerhskang <hs1218.kang@samsung.com>
Sun, 21 Apr 2019 09:10:16 +0000 (18:10 +0900)
Change-Id: Iee22d39b30a81864c77fee2b555eee0cef11b634
Signed-off-by: Junhan Bae <junhan84.bae@samsung.com>
drivers/ccic/s2mu106-usbpd.c
drivers/ccic/usbpd.c
drivers/ccic/usbpd_cc.c
drivers/ccic/usbpd_manager.c
drivers/ccic/usbpd_policy.c
drivers/muic/muic_manager.c
include/linux/ccic/usbpd-s2mu106.h
include/linux/ccic/usbpd.h
include/linux/ccic/usbpd_msg.h

index 1dd158f36ae7c08f9239d657d22c2a586d9a0b05..206fa562f551b7a10bebf3ac1b5911f4c5944168 100644 (file)
@@ -83,8 +83,6 @@ 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);
 #ifndef CONFIG_SEC_FACTORY
-static void s2mu106_usbpd_set_threshold(struct s2mu106_usbpd_data *pdic_data,
-                       CCIC_RP_RD_SEL port_sel, CCIC_THRESHOLD_SEL threshold_sel);
 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);
@@ -130,34 +128,43 @@ void s2mu106_rprd_mode_change(struct s2mu106_usbpd_data *usbpd_data, u8 mode)
        struct usbpd_data *pd_data = dev_get_drvdata(dev);
        pr_info("%s, mode=0x%x\n", __func__, mode);
 
-       mutex_lock(&usbpd_data->lpm_mutex);
+       mutex_lock(&usbpd_data->_mutex);
        if (usbpd_data->lpm_mode)
                goto skip;
 
+       pr_info("%s, %d\n", __func__, __LINE__);
        switch (mode) {
        case TYPE_C_ATTACH_DFP: /* SRC */
                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);
+               msleep(20);
+               s2mu106_usbpd_detach_init(usbpd_data);
+               s2mu106_usbpd_notify_detach(usbpd_data);
+               msleep(600);
                s2mu106_usbpd_set_rp_scr_sel(usbpd_data, PLUG_CTRL_RP80);
                msleep(S2MU106_ROLE_SWAP_TIME_MS);
                s2mu106_assert_drp(pd_data);
+               usbpd_data->status_reg |= PLUG_ATTACH;
+               schedule_delayed_work(&usbpd_data->plug_work, 0);
                break;
        case TYPE_C_ATTACH_UFP: /* SNK */
                ifconn_event_work(usbpd_data, IFCONN_NOTIFY_MUIC,
                        IFCONN_NOTIFY_ID_ROLE_SWAP,
-                       IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP, NULL);
+                       IFCONN_NOTIFY_EVENT_PD_SINK, 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);
+               msleep(20);
+               s2mu106_usbpd_detach_init(usbpd_data);
+               s2mu106_usbpd_notify_detach(usbpd_data);
+               msleep(600);
                s2mu106_assert_rd(pd_data);
                s2mu106_usbpd_set_rp_scr_sel(usbpd_data, PLUG_CTRL_RP80);
                msleep(S2MU106_ROLE_SWAP_TIME_MS);
                s2mu106_assert_drp(pd_data);
+               usbpd_data->status_reg |= PLUG_ATTACH;
+               schedule_delayed_work(&usbpd_data->plug_work, 0);
                break;
        case TYPE_C_ATTACH_DRP: /* DRP */
                s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
@@ -166,7 +173,7 @@ void s2mu106_rprd_mode_change(struct s2mu106_usbpd_data *usbpd_data, u8 mode)
                break;
        };
 skip:
-       mutex_unlock(&usbpd_data->lpm_mutex);
+       mutex_unlock(&usbpd_data->_mutex);
 }
 
 void usbpd_charger_test_read(struct s2mu106_usbpd_data *usbpd_data)
@@ -372,26 +379,7 @@ static int s2mu106_usbpd_check_accessory(struct s2mu106_usbpd_data *pdic_data)
 #if defined(CONFIG_IFCONN_NOTIFIER)
 static void process_dr_swap(struct s2mu106_usbpd_data *usbpd_data)
 {
-       struct i2c_client *i2c = usbpd_data->i2c;
-       dev_info(&i2c->dev, "%s : before - is_host : %d, is_client : %d\n",
-               __func__, usbpd_data->is_host, usbpd_data->is_client);
-       if (usbpd_data->is_host == HOST_ON) {
-               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB,
-                                       IFCONN_NOTIFY_ID_USB, IFCONN_NOTIFY_EVENT_DETACH, NULL);
-               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
-                                                               IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP, NULL);
-               usbpd_data->is_host = HOST_OFF;
-               usbpd_data->is_client = CLIENT_ON;
-       } else if (usbpd_data->is_client == CLIENT_ON) {
-               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
-                                                                       IFCONN_NOTIFY_EVENT_DETACH, NULL);
-               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
-                                                       IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP, NULL);
-               usbpd_data->is_host = HOST_ON;
-               usbpd_data->is_client = CLIENT_OFF;
-       }
-       dev_info(&i2c->dev, "%s : after - is_host : %d, is_client : %d\n",
-               __func__, usbpd_data->is_host, usbpd_data->is_client);
+       schedule_delayed_work(&usbpd_data->dr_work, msecs_to_jiffies(0));
 }
 #endif
 
@@ -400,18 +388,18 @@ static void s2mu106_pr_swap(void *_data, int val)
        struct usbpd_data *data = (struct usbpd_data *) _data;
        struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data;
 
-       if (val == USBPD_SINK_OFF)
+       if (val == USBPD_SINK_OFF) {
+               ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC,
+                                                               IFCONN_NOTIFY_ID_ROLE_SWAP,
+                                                                       IFCONN_NOTIFY_EVENT_PD_SOURCE, 0);
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_BATTERY,
                                                                IFCONN_NOTIFY_ID_DETACH, 0, 0);
-       else if (val == USBPD_SOURCE_ON) {
+       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);
        } else if (val == USBPD_SOURCE_OFF) {
                ifconn_event_work(pdic_data, IFCONN_NOTIFY_BATTERY,
                                                                IFCONN_NOTIFY_ID_DETACH, 0, 0);
@@ -419,11 +407,18 @@ static void s2mu106_pr_swap(void *_data, int val)
                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);
+                                                               IFCONN_NOTIFY_ID_ROLE_SWAP,
+                                                                       IFCONN_NOTIFY_EVENT_PD_SINK, 0);
        }
+#if defined(CONFIG_TYPEC)
+       if (val == USBPD_PR_DONE) {
+               typec_set_pwr_role(pdic_data->port, pdic_data->typec_power_role);
+               if (pdic_data->typec_try_state_change == TYPE_C_PR_SWAP)
+                       complete(&pdic_data->role_reverse_completion);
+       }
+#endif
 }
 
 static int s2mu106_usbpd_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
@@ -699,14 +694,14 @@ static void s2mu106_assert_rd(void *_data)
        struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data;
        struct i2c_client *i2c = pdic_data->i2c;
        u8 val;
-       u8 cc1_val, cc2_val;
-
+#if 0
        s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_MON1, &val);
 
        cc1_val = val & S2MU106_REG_CTRL_MON_CC1_MASK;
        cc2_val = (val & S2MU106_REG_CTRL_MON_CC2_MASK) >> S2MU106_REG_CTRL_MON_CC2_SHIFT;
+#endif
 
-       if (cc1_val == 2) {
+       if (pdic_data->cc1_val == USBPD_Rd) {
                s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, &val);
                val = (val & ~S2MU106_REG_PLUG_CTRL_CC_MANUAL_MASK) |
                                S2MU106_REG_PLUG_CTRL_CC1_MANUAL_ON;
@@ -721,7 +716,7 @@ static void s2mu106_assert_rd(void *_data)
                }
        }
 
-       if (cc2_val == 2) {
+       if (pdic_data->cc2_val == USBPD_Rd) {
                s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, &val);
                val = (val & ~S2MU106_REG_PLUG_CTRL_CC_MANUAL_MASK) |
                                S2MU106_REG_PLUG_CTRL_CC2_MANUAL_ON;
@@ -1091,6 +1086,14 @@ static int s2mu106_vbus_on_check(void *_data)
        return s2mu106_usbpd_check_vbus(pdic_data, 3500, VBUS_ON);
 }
 
+static void s2mu106_set_pwr_opmode(void *_data, int mode)
+{
+       struct usbpd_data *data = (struct usbpd_data *) _data;
+       struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data;
+
+       typec_set_pwr_opmode(pdic_data->port, mode);
+}
+
 #if defined(CONFIG_CHECK_CTYPE_SIDE) || defined(CONFIG_CCIC_SYSFS)
 static int s2mu106_get_side_check(void *_data)
 {
@@ -1279,24 +1282,6 @@ static int s2mu106_set_check_msg_pass(void *_data, int val)
        return 0;
 }
 #ifndef CONFIG_SEC_FACTORY
-static void s2mu106_usbpd_set_threshold(struct s2mu106_usbpd_data *pdic_data,
-                       CCIC_RP_RD_SEL port_sel, CCIC_THRESHOLD_SEL threshold_sel)
-{
-       struct i2c_client *i2c = pdic_data->i2c;
-
-       if (threshold_sel > S2MU106_THRESHOLD_MAX) {
-               dev_err(pdic_data->dev, "%s : threshold overflow!!\n", __func__);
-               return;
-       } else {
-               if (port_sel == PLUG_CTRL_RD)
-                       s2mu106_usbpd_write_reg(i2c,
-                               S2MU106_REG_PLUG_CTRL_SET_RD, threshold_sel);
-               else if (port_sel == PLUG_CTRL_RP)
-                       s2mu106_usbpd_write_reg(i2c,
-                               S2MU106_REG_PLUG_CTRL_SET_RP, threshold_sel);
-       }
-}
-
 static void s2mu106_usbpd_set_rp_scr_sel(struct s2mu106_usbpd_data *pdic_data,
                                                        CCIC_RP_SCR_SEL scr_sel)
 {
@@ -1315,20 +1300,12 @@ static void s2mu106_usbpd_set_rp_scr_sel(struct s2mu106_usbpd_data *pdic_data,
                data &= ~S2MU106_REG_PLUG_CTRL_RP_SEL_MASK;
                data |= S2MU106_REG_PLUG_CTRL_RP80;
                s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data);
-               s2mu106_usbpd_set_threshold(pdic_data, PLUG_CTRL_RD,
-                                               S2MU106_THRESHOLD_214MV);
-               s2mu106_usbpd_set_threshold(pdic_data, PLUG_CTRL_RP,
-                                               S2MU106_THRESHOLD_1628MV);
                break;
        case PLUG_CTRL_RP180:
                s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data);
                data &= ~S2MU106_REG_PLUG_CTRL_RP_SEL_MASK;
                data |= S2MU106_REG_PLUG_CTRL_RP180;
                s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data);
-               s2mu106_usbpd_set_threshold(pdic_data, PLUG_CTRL_RD,
-                                               S2MU106_THRESHOLD_428MV);
-               s2mu106_usbpd_set_threshold(pdic_data, PLUG_CTRL_RP,
-                                               S2MU106_THRESHOLD_2057MV);
                break;
        default:
                break;
@@ -1382,32 +1359,32 @@ int s2mu106_usbpd_check_msg(void *_data, u64 *val)
                        }
 
                        switch (vdm_command) {
-                               case DisplayPort_Status_Update:
-                                       *val |= VDM_DP_STATUS_UPDATE;
-                                       break;
-                               case DisplayPort_Configure:
-                                       *val |= VDM_DP_CONFIGURE;
-                                       break;
-                               case Attention:
-                                       *val |= VDM_ATTENTION;
-                                       break;
-                               case Exit_Mode:
-                                       *val |= VDM_EXIT_MODE;
-                                       break;
-                               case Enter_Mode:
-                                       *val |= VDM_ENTER_MODE;
-                                       break;
-                               case Discover_Modes:
-                                       *val |= VDM_ENTER_MODE;
-                                       break;
-                               case Discover_SVIDs:
-                                       *val |= VDM_DISCOVER_SVID;
-                                       break;
-                               case Discover_Identity:
-                                       *val |= VDM_DISCOVER_IDENTITY;
-                                       break;
-                               default:
-                                       break;
+                       case DisplayPort_Status_Update:
+                               *val |= VDM_DP_STATUS_UPDATE;
+                               break;
+                       case DisplayPort_Configure:
+                               *val |= VDM_DP_CONFIGURE;
+                               break;
+                       case Attention:
+                               *val |= VDM_ATTENTION;
+                               break;
+                       case Exit_Mode:
+                               *val |= VDM_EXIT_MODE;
+                               break;
+                       case Enter_Mode:
+                               *val |= VDM_ENTER_MODE;
+                               break;
+                       case Discover_Modes:
+                               *val |= VDM_ENTER_MODE;
+                               break;
+                       case Discover_SVIDs:
+                               *val |= VDM_DISCOVER_SVID;
+                               break;
+                       case Discover_Identity:
+                               *val |= VDM_DISCOVER_IDENTITY;
+                               break;
+                       default:
+                               break;
                        }
                        break;
                default:
@@ -1560,7 +1537,7 @@ int s2mu106_set_normal_mode(struct s2mu106_usbpd_data *pdic_data)
 
        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_DRP | S2MU106_REG_PLUG_CTRL_RP180;
+       data |= S2MU106_REG_PLUG_CTRL_DRP | S2MU106_REG_PLUG_CTRL_RP80;
 
        s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PD_CTRL, &data_lpm);
        data_lpm &= ~S2MU106_REG_LPM_EN;
@@ -2096,8 +2073,8 @@ 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
-                               s2mu106_usbpd_set_mode(pdic_data, PD_NORMAL_MODE);
+                               else
+                                       s2mu106_usbpd_set_mode(pdic_data, PD_NORMAL_MODE);
                        }
 
                        s2mu106_set_irq_enable(pdic_data, ENABLED_INT_0, ENABLED_INT_1,
@@ -2156,6 +2133,7 @@ static void s2mu106_usbpd_detach_init(struct s2mu106_usbpd_data *pdic_data)
        if (pdic_data->typec_power_role == TYPEC_SOURCE) {
                vbus_turn_on_ctrl(pdic_data, VBUS_OFF);
        }
+       pd_data->pd_support = 0;
 #endif
        pdic_data->detach_valid = true;
        mutex_unlock(&pdic_data->cc_mutex);
@@ -2212,20 +2190,19 @@ static void s2mu106_usbpd_notify_detach(struct s2mu106_usbpd_data *pdic_data)
 #if defined(CONFIG_DUAL_ROLE_USB_INTF)
                pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_NONE;
 #elif defined(CONFIG_TYPEC)
+               if (pdic_data->partner) {
+                       pr_info("%s, %d\n", __func__, __LINE__);
+                       if (!IS_ERR(pdic_data->partner)) {
+                               typec_unregister_partner(pdic_data->partner);
+                               pdic_data->partner = NULL;
+                       }
+               }
                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,
                                                                                IFCONN_NOTIFY_EVENT_DETACH, NULL);
-#if defined(CONFIG_DUAL_ROLE_USB_INTF)
-               if (!pdic_data->try_state_change)
-                       s2mu106_rprd_mode_change(pdic_data, TYPE_C_ATTACH_DRP);
-#else
-       s2mu106_rprd_mode_change(pdic_data, TYPE_C_ATTACH_DRP);
-#endif
        }
 #else
        usbpd_manager_plug_detach(dev, 1);
@@ -2326,6 +2303,9 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data)
        cc1_val = val & S2MU106_REG_CTRL_MON_CC1_MASK;
        cc2_val = (val & S2MU106_REG_CTRL_MON_CC2_MASK) >> S2MU106_REG_CTRL_MON_CC2_SHIFT;
 
+       pdic_data->cc1_val = cc1_val;
+       pdic_data->cc2_val = cc2_val;
+
        dev_info(dev, "%s, attach cc pin check cc1_val(%x), cc2_val(%x)\n",
                                        __func__, cc1_val, cc2_val);
 
@@ -2420,7 +2400,7 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data)
 #ifdef CONFIG_CCIC_TRY_SNK
                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_DRP | S2MU106_REG_PLUG_CTRL_RP180;
+               data |= S2MU106_REG_PLUG_CTRL_DRP | S2MU106_REG_PLUG_CTRL_RP80;
                s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data);
 #endif
                return -1;
@@ -2452,21 +2432,6 @@ static int s2mu106_usbpd_check_619k(struct s2mu106_usbpd_data *pdic_data)
 }
 #endif
 
-#ifndef CONFIG_SEC_FACTORY
-static void s2mu106_usbpd_check_reboost(struct s2mu106_usbpd_data *pdic_data)
-{
-       if (!pdic_data->is_otg_reboost)
-               return;
-
-       dev_info(pdic_data->dev, "%s %d: Detached, go back to 180uA\n",
-                                       __func__, __LINE__);
-       s2mu106_usbpd_set_rp_scr_sel(pdic_data, PLUG_CTRL_RP180);
-       pdic_data->is_otg_reboost = false;
-
-       return;
-}
-#endif
-
 static irqreturn_t s2mu106_irq_thread(int irq, void *data)
 {
        struct s2mu106_usbpd_data *pdic_data = data;
@@ -2502,9 +2467,7 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data)
                if (ret)
                        goto skip_detach;
 #endif /* CONFIG_SEC_FACTORY */
-#ifndef CONFIG_SEC_FACTORY
-               s2mu106_usbpd_check_reboost(pdic_data);
-#endif
+               s2mu106_usbpd_set_rp_scr_sel(pdic_data, PLUG_CTRL_RP80);
                attach_status = s2mu106_get_status(pd_data, PLUG_ATTACH);
                rid_status = s2mu106_get_status(pd_data, MSG_RID);
                s2mu106_usbpd_detach_init(pdic_data);
@@ -2573,6 +2536,43 @@ out:
        return IRQ_HANDLED;
 }
 
+static void s2mu106_usbpd_plug_work(struct work_struct *work)
+{
+       struct s2mu106_usbpd_data *pdic_data =
+               container_of(work, struct s2mu106_usbpd_data, plug_work.work);
+
+       s2mu106_irq_thread(-1, pdic_data);
+}
+
+static void s2mu106_usbpd_dr_work(struct work_struct *work)
+{
+       struct s2mu106_usbpd_data *usbpd_data =
+               container_of(work, struct s2mu106_usbpd_data, dr_work.work);
+       struct i2c_client *i2c = usbpd_data->i2c;
+
+       dev_info(&i2c->dev, "%s : before - is_host : %d, is_client : %d\n",
+               __func__, usbpd_data->is_host, usbpd_data->is_client);
+       if (usbpd_data->is_host == HOST_ON) {
+               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB,
+                                       IFCONN_NOTIFY_ID_USB, IFCONN_NOTIFY_EVENT_DETACH, NULL);
+
+               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
+                                                               IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP, NULL);
+               usbpd_data->is_host = HOST_OFF;
+               usbpd_data->is_client = CLIENT_ON;
+       } else if (usbpd_data->is_client == CLIENT_ON) {
+               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
+                                                                       IFCONN_NOTIFY_EVENT_DETACH, NULL);
+
+               ifconn_event_work(usbpd_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB,
+                                                       IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP, NULL);
+               usbpd_data->is_host = HOST_ON;
+               usbpd_data->is_client = CLIENT_OFF;
+       }
+       dev_info(&i2c->dev, "%s : after - is_host : %d, is_client : %d\n",
+               __func__, usbpd_data->is_host, usbpd_data->is_client);
+}
+
 static int s2mu106_usbpd_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
@@ -2715,7 +2715,6 @@ static int s2mu106_usbpd_reg_init(struct s2mu106_usbpd_data *_data)
 #ifdef CONFIG_PM_S2MU106
        s2mu106_usbpd_set_pmeter_mode(_data, PM_TYPE_VCHGIN);
 #endif
-       s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, S2MU106_RESET_REG_00);
 
        s2mu106_usbpd_set_vconn_manual(_data, true);
 
@@ -2962,6 +2961,9 @@ static int s2mu106_usbpd_probe(struct i2c_client *i2c,
        }
        INIT_DELAYED_WORK(&pdic_data->water_detect_handler, S2MU106_PDIC_water_detect_handler);
        INIT_DELAYED_WORK(&pdic_data->water_dry_handler, S2MU106_PDIC_water_dry_handler);
+       INIT_DELAYED_WORK(&pdic_data->water_dry_handler, S2MU106_PDIC_water_dry_handler);
+       INIT_DELAYED_WORK(&pdic_data->plug_work, s2mu106_usbpd_plug_work);
+       INIT_DELAYED_WORK(&pdic_data->dr_work, s2mu106_usbpd_dr_work);
 
        if (pdic_data->detach_valid) {
                mutex_lock(&pdic_data->_mutex);
@@ -3094,6 +3096,7 @@ static usbpd_phy_ops_type s2mu106_ops = {
        .get_side_check         = s2mu106_get_side_check,
        .pr_swap                        = s2mu106_pr_swap,
        .vbus_on_check          = s2mu106_vbus_on_check,
+       .set_pwr_opmode         = s2mu106_set_pwr_opmode,
 };
 
 #if defined CONFIG_PM
index 26a0a09581a0dc201658a9537a4a906a36c6fcd6..c441086e9a77cff400ff2d2cd6a1e61c0268ab64 100644 (file)
@@ -332,6 +332,7 @@ void usbpd_set_ops(struct device *dev, usbpd_phy_ops_type *ops)
        pd_data->phy_ops.get_side_check = ops->get_side_check;
        pd_data->phy_ops.pr_swap = ops->pr_swap;
        pd_data->phy_ops.vbus_on_check = ops->vbus_on_check;
+       pd_data->phy_ops.set_pwr_opmode = ops->set_pwr_opmode;
 }
 
 protocol_state usbpd_protocol_rx_layer_reset_for_receive(struct protocol_data *rx)
@@ -650,6 +651,8 @@ int usbpd_init(struct device *dev, void *phy_driver_data)
        usbpd_init_policy(pd_data);
        usbpd_init_manager(pd_data);
 
+       pd_data->pd_support = 0;
+
        mutex_init(&pd_data->accept_mutex);
 
        pd_data->policy_wqueue =
index ed6f694092303bf06a139b9bd74e622d0080d34c..917ece236ea8fc13860da43c1f410e955133b007 100644 (file)
@@ -41,6 +41,8 @@
 #include <linux/ccic/usbpd-s2mu205.h>
 #endif
 
+#include <linux/usb_notify.h>
+
 #if defined(CONFIG_CCIC_NOTIFIER)
 static void ccic_event_notifier(struct work_struct *data)
 {
@@ -225,43 +227,51 @@ extern void ifconn_event_work(void *pd_data, int dest, int id, int event, void *
                }
        }
 #elif defined(CONFIG_TYPEC)
-           if (id == IFCONN_NOTIFY_ID_USB) {
+       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);
+                       (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);
+               if (usbpd_data->partner == NULL) {
+                       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_pwr_role(usbpd_data->port, usbpd_data->typec_power_role);
+                               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_pwr_role(usbpd_data->port, usbpd_data->typec_power_role);
+                               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__);
                } 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;
+                       if (event == IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP) {
+                               pr_info("usb: %s, line : %d\n", __func__, __LINE__);
+                               usbpd_data->typec_data_role = TYPEC_DEVICE;
+                               typec_set_data_role(usbpd_data->port, TYPEC_DEVICE);
+                       } else if (event == IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP) {
+                               usbpd_data->typec_data_role = TYPEC_HOST;
+                               typec_set_data_role(usbpd_data->port, TYPEC_HOST);
+                       } else
+                               pr_info("usb: %s, line : %d\n", __func__, __LINE__);
                }
-               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) {
@@ -652,7 +662,7 @@ int typec_port_type_set(const struct typec_capability *cap, enum typec_port_type
        case TYPEC_PORT_DRP:
                pr_info("%s : set to DRP (No action)\n", __func__);
                return 0;
-       default :
+       default:
                pr_info("%s : invalid typec_role\n", __func__);
                return -EINVAL;
        }
@@ -679,10 +689,114 @@ int typec_port_type_set(const struct typec_capability *cap, enum typec_port_type
 
                        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));
-               }
+               } else
+                       pr_err("%s: reverse success\n", __func__);
+       }
+
+       return 0;
+}
+
+static int typec_pr_set(const struct typec_capability *cap, enum typec_role role)
+{
+#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, role=%d\n",
+               __func__, usbpd_data->typec_power_role, usbpd_data->typec_data_role, role);
+
+       if (role == TYPEC_SINK) {
+               pr_info("%s, try reversing, from Source to Sink\n", __func__);
+               usbpd_data->typec_try_state_change = TYPE_C_PR_SWAP;
+               usbpd_manager_send_pr_swap(usbpd_data->dev);
+       } else if (role == TYPEC_SOURCE) {
+               pr_info("%s, try reversing, from Sink to Source\n", __func__);
+               usbpd_data->typec_try_state_change = TYPE_C_PR_SWAP;
+               usbpd_manager_send_pr_swap(usbpd_data->dev);
+       } else {
+               pr_info("invalid power role\n");
+               return -EIO;
+       }
+
+       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\n", __func__);
+                       disable_irq(usbpd_data->irq);
+                       /* exit from Disabled state and set mode to DRP */
+                       usbpd_data->typec_try_state_change = 0;
+                       return -EIO;
+               } else
+                       pr_err("%s: reverse success\n", __func__);
+       }
+
+       return 0;
+}
+
+static int typec_dr_set(const struct typec_capability *cap, enum typec_data_role role)
+{
+#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, role=%d\n",
+               __func__, usbpd_data->typec_power_role, usbpd_data->typec_data_role, role);
+
+       if (role == TYPEC_DEVICE) {
+               pr_info("%s, try reversing, from DFP to UFP\n", __func__);
+               usbpd_data->typec_try_state_change = TYPE_C_DR_SWAP;
+               usbpd_manager_send_dr_swap(usbpd_data->dev);
+       } else if (role == TYPEC_HOST) {
+               pr_info("%s, try reversing, from UFP to DFP\n", __func__);
+               usbpd_data->typec_try_state_change = TYPE_C_DR_SWAP;
+               usbpd_manager_send_dr_swap(usbpd_data->dev);
+       } else {
+               pr_info("invalid power role\n");
+               return -EIO;
+       }
+
+       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\n", __func__);
+                       disable_irq(usbpd_data->irq);
+                       /* exit from Disabled state and set mode to DRP */
+                       usbpd_data->typec_try_state_change = 0;
+                       return -EIO;
+               } else
+                       pr_err("%s: reverse success\n", __func__);
        }
 
        return 0;
@@ -690,7 +804,13 @@ int typec_port_type_set(const struct typec_capability *cap, enum typec_port_type
 
 int typec_get_pd_support(void *_data)
 {
-       return TYPEC_PWR_MODE_USB;
+       struct s2mu106_usbpd_data *pdic_data = _data;
+       struct usbpd_data *pd_data = dev_get_drvdata(pdic_data->dev);
+
+       if (pd_data->pd_support)
+               return TYPEC_PWR_MODE_PD;
+       else
+               return TYPEC_PWR_MODE_USB;
 }
 
 int typec_init(void *_data)
@@ -706,9 +826,12 @@ int typec_init(void *_data)
        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.pr_set = typec_pr_set;
+       pdic_data->typec_cap.dr_set = typec_dr_set;
        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);
+       pdic_data->partner = NULL;
        if (IS_ERR(pdic_data->port)) {
                pr_err("%s : unable to register typec_register_port\n", __func__);
                return -1;
index a8383c9cdeafac99cd2e673fbf784e8b9e6e1ed2..1f51584deca904d345477c10202e5f0fe747c36c 100644 (file)
@@ -140,6 +140,13 @@ void usbpd_manager_send_pr_swap(struct device *dev)
        usbpd_manager_inform_event(pd_noti.pd_data, MANAGER_SEND_PR_SWAP);
 }
 
+void usbpd_manager_send_dr_swap(struct device *dev)
+{
+       pr_info("%s: call send pr swap msg\n", __func__);
+
+       usbpd_manager_inform_event(pd_noti.pd_data, MANAGER_SEND_DR_SWAP);
+}
+
 static void init_source_cap_data(struct usbpd_manager_data *_data)
 {
 /*     struct usbpd_data *pd_data = manager_to_usbpd(_data);
@@ -160,7 +167,7 @@ static void init_source_cap_data(struct usbpd_manager_data *_data)
        data_obj->power_data_obj.data_role_swap = 1;
        data_obj->power_data_obj.dual_role_power = 1;
        data_obj->power_data_obj.usb_suspend_support = 1;
-       data_obj->power_data_obj.usb_comm_capable = 0;
+       data_obj->power_data_obj.usb_comm_capable = 1;
 
 }
 
@@ -182,7 +189,7 @@ static void init_sink_cap_data(struct usbpd_manager_data *_data)
        data_obj->power_data_obj_sink.dual_role_power = 1;
        data_obj->power_data_obj_sink.higher_capability = 1;
        data_obj->power_data_obj_sink.externally_powered = 0;
-       data_obj->power_data_obj_sink.usb_comm_capable = 0;
+       data_obj->power_data_obj_sink.usb_comm_capable = 1;
        data_obj->power_data_obj_sink.data_role_swap = 1;
        data_obj->power_data_obj_sink.voltage = 5000/50;
        data_obj->power_data_obj_sink.op_current = 3000/10;
@@ -331,6 +338,10 @@ void usbpd_manager_inform_event(struct usbpd_data *pd_data,
                usbpd_manager_command_to_policy(pd_data->dev,
                                        MANAGER_REQ_PR_SWAP);
                break;
+       case MANAGER_SEND_DR_SWAP:
+               usbpd_manager_command_to_policy(pd_data->dev,
+                                       MANAGER_REQ_DR_SWAP);
+               break;
        default:
                pr_info("%s: not matched event(%d)\n", __func__, event);
        }
@@ -881,7 +892,7 @@ data_obj_type usbpd_manager_select_capability(struct usbpd_data *pd_data)
        int pdo_num = pd_noti.sink_status.selected_pdo_num;
 #endif
        obj.request_data_object.no_usb_suspend = 1;
-       obj.request_data_object.usb_comm_capable = 0;
+       obj.request_data_object.usb_comm_capable = 1;
        obj.request_data_object.capability_mismatch = 0;
        obj.request_data_object.give_back = 0;
 #ifdef CONFIG_IFCONN_NOTIFIER
index c89a5d7b9a41e1ba0969c776b5739352124b88b1..d08449200175938c1cb4b81db85f5d751eabd561 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/ifconn/ifconn_notifier.h>
 #endif
 
+#include <linux/ccic/usbpd-s2mu106.h>
+
 #define CHECK_MSG(pd, msg, ret) do {\
        if (pd->phy_ops.get_status(pd, msg))\
                return ret;\
@@ -333,7 +335,10 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy)
        /* 1) PD State Inform for AP */
        dev_info(pd_data->dev, "%s\n", __func__);
 
-       policy->pd_support = 1;
+       if (pd_data->pd_support == 0) {
+               pd_data->pd_support = 1;
+               pd_data->phy_ops.set_pwr_opmode(pd_data, TYPEC_PWR_MODE_PD);
+       }
 
        /* 2) Wait Message or State */
        CHECK_MSG(pd_data, MSG_GET_SRC_CAP, PE_SRC_Give_Source_Cap);
@@ -345,6 +350,7 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy)
        CHECK_MSG(pd_data, MSG_SOFTRESET, PE_SRC_Soft_Reset);
        CHECK_MSG(pd_data, MSG_ERROR, PE_SRC_Send_Soft_Reset);
        CHECK_MSG(pd_data, MSG_BIST, PE_BIST_Receive_Mode);
+
 #if 0
        CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity);
        CHECK_MSG(pd_data, VDM_DISCOVER_SVID, PE_UFP_VDM_Get_SVIDs);
@@ -1107,6 +1113,9 @@ policy_state usbpd_policy_snk_transition_sink(struct policy_data *policy)
 #if defined(CONFIG_IFCONN_NOTIFIER)
                        pd_noti.sink_status.current_pdo_num = pd_noti.sink_status.selected_pdo_num;
 #endif
+                       /* 2) Notify Plug Attach */
+                       usbpd_manager_plug_attach(pd_data->dev);
+
                        ret = PE_SNK_Ready;
                        break;
                }
@@ -1136,11 +1145,10 @@ policy_state usbpd_policy_snk_ready(struct policy_data *policy)
        /* 1) PD State Inform to AP */
        dev_info(pd_data->dev, "%s\n", __func__);
 
-       /* enable pd support for typec role swap */
-       policy->pd_support = 1;
-
-       /* 2) Notify Plug Attach */
-       usbpd_manager_plug_attach(pd_data->dev);
+       if (pd_data->pd_support == 0) {
+               pd_data->pd_support = 1;
+               pd_data->phy_ops.set_pwr_opmode(pd_data, TYPEC_PWR_MODE_PD);
+       }
 
        /* 3) Message Check */
        CHECK_MSG(pd_data, MSG_GET_SNK_CAP, PE_SNK_Give_Sink_Cap);
@@ -1566,7 +1574,6 @@ policy_state usbpd_policy_drs_dfp_ufp_accept_dr_swap(struct policy_data *policy)
        mutex_lock(&pd_data->accept_mutex);
        usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header,
                                                USBPD_Accept, USBPD_DFP, power_role);
-
        pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP);
        mutex_unlock(&pd_data->accept_mutex);
 
@@ -1621,6 +1628,7 @@ policy_state usbpd_policy_drs_dfp_ufp_send_dr_swap(struct policy_data *policy)
                        if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) {
                                dev_info(pd_data->dev, "%s, got Accept\n", __func__);
                                ret = PE_DRS_DFP_UFP_Change_to_UFP;
+                               pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP);
                                break;
                        }
                        if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) {
@@ -1705,7 +1713,6 @@ policy_state usbpd_policy_drs_ufp_dfp_accept_dr_swap(struct policy_data *policy)
        mutex_lock(&pd_data->accept_mutex);
        usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header,
                                        USBPD_Accept, USBPD_UFP, power_role);
-       pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP);
        mutex_unlock(&pd_data->accept_mutex);
        return PE_DRS_UFP_DFP_Change_to_DFP;
 }
@@ -1722,6 +1729,7 @@ policy_state usbpd_policy_drs_ufp_dfp_change_to_dfp(struct policy_data *policy)
 
        dev_info(pd_data->dev, "%s\n", __func__);
 
+       pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP);
        pd_data->phy_ops.get_power_role(pd_data, &power_role);
 
        if (power_role == USBPD_SOURCE)
@@ -1907,7 +1915,7 @@ policy_state usbpd_policy_prs_src_snk_send_swap(struct policy_data *policy)
 
        }
 
-       return PE_SRC_Ready;
+       return ret;
 }
 
 policy_state usbpd_policy_prs_src_snk_accept_swap(struct policy_data *policy)
@@ -2038,9 +2046,11 @@ policy_state usbpd_policy_prs_src_snk_wait_source_on(struct policy_data *policy)
                if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) {
                        dev_info(pd_data->dev, "got PSRDY.\n");
                        pd_data->counter.swap_hard_reset_counter = 0;
+                       pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_OFF);
                        /* Self SoftReset for Message ID Clear */
                        pd_data->phy_ops.soft_reset(pd_data);
-                       mdelay(15);
+                       msleep(20);
+                       pd_data->phy_ops.pr_swap(pd_data, USBPD_PR_DONE);
                        ret = PE_SNK_Startup;
                        break;
                }
@@ -2131,6 +2141,7 @@ policy_state usbpd_policy_prs_snk_src_send_swap(struct policy_data *policy)
                ms = usbpd_check_time1(pd_data);
                if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) {
                        ret = PE_PRS_SNK_SRC_Transition_off;
+                       pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK);
                        break;
                }
 
@@ -2170,8 +2181,10 @@ policy_state usbpd_policy_prs_snk_src_accept_swap(struct policy_data *policy)
 
        /* Send Accept Message */
        pd_data->phy_ops.get_data_role(pd_data, &data_role);
+
        usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept,
                                                                                                        data_role, USBPD_SINK);
+
        pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK);
 
        return PE_PRS_SNK_SRC_Transition_off;
@@ -2199,6 +2212,7 @@ policy_state usbpd_policy_prs_snk_src_transition_to_off(struct policy_data *poli
        while (1) {
                if (policy->plug_valid == 0) {
                        ret = PE_PRS_SNK_SRC_Transition_off;
+                       pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP);
                        break;
                }
                ms = usbpd_check_time1(pd_data);
@@ -2296,6 +2310,8 @@ policy_state usbpd_policy_prs_snk_src_source_on(struct policy_data *policy)
                /* Self SoftReset for Message ID Clear */
                pd_data->phy_ops.soft_reset(pd_data);
 
+               pd_data->phy_ops.pr_swap(pd_data, USBPD_PR_DONE);
+
                return PE_SRC_Startup;
        }
 
@@ -2549,7 +2565,7 @@ policy_state usbpd_policy_ufp_vdm_get_identity(struct policy_data *policy)
        Request Identity information from DPM
        **********************************************/
 
-       return PE_UFP_VDM_Get_Identity_NAK;
+       return PE_UFP_VDM_Send_Identity;
 }
 
 policy_state usbpd_policy_ufp_vdm_send_identity(struct policy_data *policy)
@@ -2569,7 +2585,7 @@ policy_state usbpd_policy_ufp_vdm_send_identity(struct policy_data *policy)
        policy->tx_msg_header.msg_type = USBPD_Vendor_Defined;
        policy->tx_msg_header.port_data_role = USBPD_UFP;
        policy->tx_msg_header.port_power_role = power_role;
-       policy->tx_msg_header.num_data_objs = 1;
+       policy->tx_msg_header.num_data_objs = 4;
 
        policy->tx_data_obj[0].structured_vdm.svid = PD_SID;
        policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM;
@@ -2578,6 +2594,10 @@ policy_state usbpd_policy_ufp_vdm_send_identity(struct policy_data *policy)
        policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK;
        policy->tx_data_obj[0].structured_vdm.command = Discover_Identity;
 
+       policy->tx_data_obj[1].object = 0xD10004E8;
+       policy->tx_data_obj[2].object = 0x0;
+       policy->tx_data_obj[3].object = 0x68600000;
+
        /* TODO: data object should be prepared from device manager */
 
        if (usbpd_send_msg(pd_data, &policy->tx_msg_header,
index 27c0b8c4cead976c6ada51bad58223a6242ee8e2..65e762c1d2c17974a751f229567ade2a5c2c3454 100644 (file)
@@ -720,8 +720,16 @@ static int muic_manager_handle_ccic_role_swap(struct muic_interface_t *muic_if,
 
        pr_info("%s: event:%d\n", __func__, pnoti->event);
 
-       if (pnoti->event == IFCONN_NOTIFY_EVENT_USB_ATTACH_UFP)
+       if (pnoti->event == IFCONN_NOTIFY_EVENT_PD_SINK) {
                ccic->ccic_evt_roleswap = 1;
+       } else if (pnoti->event == IFCONN_NOTIFY_EVENT_PD_SOURCE) {
+               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);
+       }
 #endif
        return 0;
 }
index cd28f1c98aa9be642ff34eb71667ed1372296c7c..f7568633ef80ba9637d84cea12b738be66f8eeb0 100644 (file)
@@ -38,7 +38,7 @@
 #define TA_WATER_CHK_DURATION_MS       5000
 
 /* define timer */
-#define S2MU106_ROLE_SWAP_TIME_MS              (1350)
+#define S2MU106_ROLE_SWAP_TIME_MS              (500)
 #define S2MU106_HARD_RESET_DELAY_MS            (300)
 #define S2MU106_WAIT_RD_DETACH_DELAY_MS                (200)
 #define S2MU106_WAIT_ATTACH_DELAY_MS           (30)
@@ -588,6 +588,8 @@ typedef enum {
        TYPE_C_ATTACH_DFP = 1, /* Host */
        TYPE_C_ATTACH_UFP = 2, /* Device */
        TYPE_C_ATTACH_DRP = 3, /* Dual role */
+       TYPE_C_PR_SWAP = 4,
+       TYPE_C_DR_SWAP = 5,
 } CCIC_OTP_MODE;
 
 typedef enum {
@@ -661,6 +663,8 @@ struct s2mu106_usbpd_data {
        bool vbus_short_check;
        bool vbus_short;
        bool vbus_access;
+       int cc1_val;
+       int cc2_val;
 #ifndef CONFIG_SEC_FACTORY
        bool lpcharge_water;
 #endif
@@ -699,6 +703,7 @@ struct s2mu106_usbpd_data {
        struct notifier_block type3_nb;
        struct workqueue_struct *pdic_queue;
        struct delayed_work plug_work;
+       struct delayed_work dr_work;
        struct delayed_work water_detect_handler;
        struct delayed_work ta_water_detect_handler;
        struct delayed_work water_dry_handler;
index 01658554a527163892294f4d0656d64129ddcaf1..3e293d08c0969e95e49dae5ad189a8908192c099 100644 (file)
@@ -41,7 +41,7 @@
 #define tVDMWaitModeEntry      (50)    /* 40~50  ms */
 #define tVDMWaitModeExit       (50)    /* 40~50  ms */
 #define tDiscoverIdentity      (50)    /* 40~50  ms */
-#define tSwapSourceStart        (20)   /* 20  ms */
+#define tSwapSourceStart        (30)   /* 30  ms */
 #define tTypeCSinkWaitCap       (310)  /* 310~620 ms */
 #define tTypeCSendSourceCap (100) /* 100~200ms */
 #define tSrcRecover (880) /* 660~1000ms */
@@ -254,6 +254,7 @@ typedef enum usbpd_manager_event {
        MANAGER_UVDM_RECEIVE_MESSAGE            = 17,
        MANAGER_START_DISCOVER_IDENTITY = 18,
        MANAGER_SEND_PR_SWAP    = 19,
+       MANAGER_SEND_DR_SWAP    = 20,
 } usbpd_manager_event_type;
 
 enum usbpd_msg_status {
@@ -351,6 +352,7 @@ typedef struct usbpd_phy_ops {
        void    (*pr_swap)(void *, int);
        int    (*vbus_on_check)(void *);
        int             (*get_side_check)(void *_data);
+       void    (*set_pwr_opmode)(void *_data, int mode);
 } usbpd_phy_ops_type;
 
 struct policy_data {
@@ -493,6 +495,8 @@ struct usbpd_data {
 
        struct timeval          time1;
        struct timeval          time2;
+
+       int                                     pd_support;
 };
 
 static inline struct usbpd_data *protocol_rx_to_usbpd(struct protocol_data *rx)
@@ -548,6 +552,7 @@ extern bool usbpd_manager_vdm_request_enabled(struct usbpd_data *);
 extern void usbpd_manager_acc_handler_cancel(struct device *);
 extern void usbpd_manager_acc_detach_handler(struct work_struct *);
 extern void usbpd_manager_send_pr_swap(struct device *);
+extern void usbpd_manager_send_dr_swap(struct device *);
 extern void usbpd_policy_work(struct work_struct *);
 extern void usbpd_protocol_tx(struct usbpd_data *);
 extern void usbpd_protocol_rx(struct usbpd_data *);
index b7b6258c3123b259e7706342615e90fe6cffa0ad..a0c2ca01fb1e3c7b17345ffc17b40280b50ac962 100644 (file)
@@ -310,6 +310,7 @@ enum usbpd_power_role_swap {
        USBPD_SINK_ON,
        USBPD_SOURCE_OFF,
        USBPD_SOURCE_ON,
+       USBPD_PR_DONE,
 };
 
 enum usbpd_port_role {