From: Junhan Bae Date: Thu, 21 Feb 2019 09:10:01 +0000 (+0900) Subject: [RAMEN9610-12413][COMMON][9610] usbpd : update s2mu106 drivers for usbpd compliance X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=82b801ee83144610821a40e292e77ff6259be693;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [RAMEN9610-12413][COMMON][9610] usbpd : update s2mu106 drivers for usbpd compliance Change-Id: I88bfa9de57153f0d802d689c81f97ce452e5848e Signed-off-by: Junhan Bae --- diff --git a/arch/arm64/boot/dts/exynos/exynos9610_battery_data.dtsi b/arch/arm64/boot/dts/exynos/exynos9610_battery_data.dtsi index 27cb51483cc8..5d17568a16c5 100644 --- a/arch/arm64/boot/dts/exynos/exynos9610_battery_data.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos9610_battery_data.dtsi @@ -54,10 +54,10 @@ * POWER_SUPPLY_TYPE_ of power_supply.h */ battery,input_current_limit = - <500 450 500 3000 500 1200 1200 1000 1000 2000 + <500 450 500 3000 500 1200 1200 1000 1000 3000 1000 500 500 3000 2000 500 450>; battery,fast_charging_current = - <500 450 500 3000 500 1200 1200 1000 1000 2000 + <500 450 500 3000 500 1200 1200 1000 1000 3000 1000 500 500 3000 2000 500 450>; battery,full_check_current = <300 0 300 300 300 300 300 300 300 300 diff --git a/drivers/ccic/s2mu106-usbpd.c b/drivers/ccic/s2mu106-usbpd.c index 133ce1c6fde7..4784cd7c6bcb 100644 --- a/drivers/ccic/s2mu106-usbpd.c +++ b/drivers/ccic/s2mu106-usbpd.c @@ -28,6 +28,10 @@ #include #include +#if defined(CONFIG_PM_S2MU106) +#include +#endif + #include #if defined(CONFIG_MUIC_NOTIFIER) #include @@ -156,6 +160,12 @@ void vbus_turn_on_ctrl(struct s2mu106_usbpd_data *usbpd_data, bool enable) int ret = 0, retry_cnt = 0; pr_info("%s %d, enable=%d\n", __func__, __LINE__, enable); + + if (usbpd_data->detach_valid) { + dev_info(usbpd_data->dev, "%s, ignore vbus control\n", __func__); + return; + } + psy_otg = power_supply_get_by_name("otg"); if (psy_otg) { @@ -187,6 +197,114 @@ void vbus_turn_on_ctrl(struct s2mu106_usbpd_data *usbpd_data, bool enable) } +#ifdef CONFIG_PM_S2MU106 +static void s2mu106_usbpd_set_pmeter_mode(struct s2mu106_usbpd_data *pdic_data, + int mode) +{ + struct power_supply *psy_pm = pdic_data->psy_pm; + union power_supply_propval val; + int ret = 0; + + pr_info("%s, mode=%d\n", __func__, mode); + + if (psy_pm) { + val.intval = mode; + ret = psy_pm->desc->set_property(psy_pm, + POWER_SUPPLY_PROP_CO_ENABLE, &val); + } else { + pr_err("%s: Fail to get pmeter\n", __func__); + return; + } + + if (ret) { + pr_err("%s: Fail to set pmeter\n", __func__); + return; + } +} + +static int s2mu106_usbpd_get_pmeter_volt(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) { + ret = psy_pm->desc->get_property(psy_pm, POWER_SUPPLY_PROP_VCHGIN, &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 = val.intval; + + return 0; +} + +static int s2mu106_usbpd_check_vbus(struct s2mu106_usbpd_data *pdic_data, + int volt, CCIC_VBUS_SEL mode) +{ + int delay = 20; + int retry = 100; + int i = 0; + int ret = 0; + + if (mode == VBUS_OFF) { + for (i = 0; i < retry; i++) { + ret = s2mu106_usbpd_get_pmeter_volt(pdic_data); + if (ret < 0) + return ret; + + if (pdic_data->pm_chgin < volt) { + pr_info("%s chgin volt(%d) finish!\n", __func__, + pdic_data->pm_chgin); + return true; + } else { + pr_info("%s chgin volt(%d) waiting 400ms!\n", + __func__, pdic_data->pm_chgin); + msleep(400); + return true; + } + msleep(delay); + } + } else if (mode == VBUS_ON) { + ret = s2mu106_usbpd_get_pmeter_volt(pdic_data); + if (ret < 0) + return ret; + if (pdic_data->pm_chgin > volt) + return true; + } + + pr_info("%s failed check vbus volt(%d->%d) mode(%d)!\n", + __func__, volt, pdic_data->pm_chgin, mode); + + return false; +} +#endif + +static int s2mu106_usbpd_check_accessory(struct s2mu106_usbpd_data *pdic_data) +{ + struct i2c_client *i2c = pdic_data->i2c; + u8 val, cc1_val, cc2_val; + + 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; + + if ((cc1_val == USBPD_Rd && cc2_val == USBPD_Rd) || + (cc1_val == USBPD_Ra && cc2_val == USBPD_Ra)) + return -1; + + return 0; +} + #if defined(CONFIG_IFCONN_NOTIFIER) static void process_dr_swap(struct s2mu106_usbpd_data *usbpd_data) { @@ -196,8 +314,6 @@ static void process_dr_swap(struct s2mu106_usbpd_data *usbpd_data) 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_MUIC, - IFCONN_NOTIFY_ID_ATTACH, 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; @@ -205,8 +321,6 @@ static void process_dr_swap(struct s2mu106_usbpd_data *usbpd_data) } 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_MUIC, IFCONN_NOTIFY_ID_ATTACH, - IFCONN_NOTIFY_EVENT_ATTACH, 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; @@ -217,6 +331,31 @@ static void process_dr_swap(struct s2mu106_usbpd_data *usbpd_data) } #endif +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) + ifconn_event_work(pdic_data, IFCONN_NOTIFY_BATTERY, + IFCONN_NOTIFY_ID_DETACH, 0, 0); + else if (val == USBPD_SOURCE_ON) { +#if defined(CONFIG_DUAL_ROLE_USB_INTF) + pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SRC; + 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; + ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC, + IFCONN_NOTIFY_ID_ROLE_SWAP, 0/* sink */, 0); +#endif + } +} + static int s2mu106_usbpd_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) { int ret; @@ -585,10 +724,8 @@ static bool s2mu106_poll_status(void *_data) s2mu106_set_irq_enable(pdic_data, ENABLED_INT_0, ENABLED_INT_1, ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5); - if (intr[5] & S2MU106_REG_INT_STATUS5_HARD_RESET) { + if (intr[5] & S2MU106_REG_INT_STATUS5_HARD_RESET) status_reg_val |= MSG_HARDRESET; - goto out; - } /* when occur detach & attach atomic */ if (intr[4] & S2MU106_REG_INT_STATUS4_USB_DETACH) { @@ -614,6 +751,7 @@ static bool s2mu106_poll_status(void *_data) mutex_unlock(&pdic_data->lpm_mutex); } + pdic_data->check_msg_pass = 1; #ifdef CONFIG_CCIC_VDM /* function that support dp control */ if (pdic_data->check_msg_pass) { @@ -701,7 +839,7 @@ static bool s2mu106_poll_status(void *_data) #ifdef CONFIG_CCIC_VDM /* read message if data object message */ if (status_reg_val & - (MSG_REQUEST | MSG_SNK_CAP + (MSG_PSRDY | MSG_REQUEST | MSG_SNK_CAP | VDM_DISCOVER_IDENTITY | VDM_DISCOVER_SVID | VDM_DISCOVER_MODE | VDM_ENTER_MODE | VDM_EXIT_MODE | VDM_ATTENTION | MSG_PASS)) { @@ -712,7 +850,7 @@ static bool s2mu106_poll_status(void *_data) #else /* read message if data object message */ if (status_reg_val & - (MSG_REQUEST | MSG_SNK_CAP + (MSG_PSRDY | MSG_REQUEST | MSG_SNK_CAP | VDM_DISCOVER_IDENTITY | VDM_DISCOVER_SVID | VDM_DISCOVER_MODE | VDM_ENTER_MODE | VDM_EXIT_MODE | VDM_ATTENTION)) { @@ -731,6 +869,15 @@ out: return 0; } +static void s2mu106_soft_reset(void *_data) +{ + struct usbpd_data *data = (struct usbpd_data *) _data; + struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; + struct i2c_client *i2c = pdic_data->i2c; + + s2mu106_self_soft_reset(i2c); +} + static int s2mu106_hard_reset(void *_data) { struct usbpd_data *data = (struct usbpd_data *) _data; @@ -738,6 +885,7 @@ static int s2mu106_hard_reset(void *_data) struct i2c_client *i2c = pdic_data->i2c; int ret; u8 reg; + u8 Read_Value = 0; if (pdic_data->rid != REG_RID_UNDF && pdic_data->rid != REG_RID_MAX) return 0; @@ -748,16 +896,22 @@ static int s2mu106_hard_reset(void *_data) | S2MU106_REG_MSG_SEND_CON_OP_MODE); if (ret < 0) goto fail; - udelay(5); + ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_REG_MSG_SEND_CON_SOP_HardRST | S2MU106_REG_MSG_SEND_CON_OP_MODE | S2MU106_REG_MSG_SEND_CON_SEND_MSG_EN); if (ret < 0) goto fail; + + /* USB PD CC Off*/ + Read_Value &= ~S2MU106_REG_PLUG_CTRL_CC_MANUAL_MASK; + Read_Value |= S2MU106_REG_PLUG_CTRL_CC_MANUAL_EN; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, Read_Value); + + ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_REG_MSG_SEND_CON_OP_MODE + | S2MU106_REG_MSG_SEND_CON_HARD_EN); udelay(1); - ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_REG_MSG_SEND_CON_OP_MODE); - udelay(1); - ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_RESET_REG_00); + ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_REG_MSG_SEND_CON_HARD_EN); if (ret < 0) goto fail; @@ -804,8 +958,7 @@ static int s2mu106_tx_msg(void *_data, u8 reg_data = 0; u8 msg_id = 0; - mutex_lock(&pdic_data->_mutex); - + mutex_lock(&pdic_data->cc_mutex); /* if there is no attach, skip tx msg */ if (pdic_data->detach_valid) goto done; @@ -829,11 +982,8 @@ static int s2mu106_tx_msg(void *_data, s2mu106_send_msg(i2c); - pdic_data->status_reg = 0; - data->wait_for_msg_arrived = 0; - done: - mutex_unlock(&pdic_data->_mutex); + mutex_unlock(&pdic_data->cc_mutex); return ret; } @@ -864,20 +1014,67 @@ static int s2mu106_set_otg_control(void *_data, int val) struct usbpd_data *data = (struct usbpd_data *) _data; struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; + mutex_lock(&pdic_data->cc_mutex); if (val) vbus_turn_on_ctrl(pdic_data, VBUS_ON); else vbus_turn_on_ctrl(pdic_data, VBUS_OFF); + mutex_unlock(&pdic_data->cc_mutex); return 0; } static int s2mu106_set_cc_control(void *_data, int val) +{ + struct usbpd_data *data = (struct usbpd_data *) _data; + struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; + int ret = 0; + + mutex_lock(&pdic_data->cc_mutex); + ret = s2mu106_usbpd_set_cc_control(pdic_data, val); + mutex_unlock(&pdic_data->cc_mutex); + + return ret; +} + +static int s2mu106_vbus_on_check(void *_data) { struct usbpd_data *data = (struct usbpd_data *) _data; struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; - return s2mu106_usbpd_set_cc_control(pdic_data, val); + return s2mu106_usbpd_check_vbus(pdic_data, 4600, VBUS_ON); +} + +static int s2mu106_check_bist_message(void *_data) +{ + struct usbpd_data *data = (struct usbpd_data *) _data; + struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; + struct i2c_client *i2c = pdic_data->i2c; + u8 reg_data = 0; + msg_header_type rx_msg_header; + + /* 1) PD State Inform to AP */ + dev_info(data->dev, "%s\n", __func__); + + /* 2) Get Rx Message ID */ + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_MSG_RX_HEADER_H, ®_data); + rx_msg_header.byte[1] = reg_data; + dev_info(data->dev, "rx_msg_header.byte[1] = 0x%02X.\n", rx_msg_header.byte[1]); + + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_MSG_RX_HEADER_L, ®_data); + rx_msg_header.byte[0] = reg_data; + dev_info(data->dev, "rx_msg_header.byte[0] = 0x%02X.\n", rx_msg_header.byte[0]); + + dev_info(data->dev, "rx_msg_header.word = 0x%04X.\n", rx_msg_header.word); + + /* 3) Check Bist Message */ + if ((rx_msg_header.msg_type == 3) && (rx_msg_header.num_data_objs != 0)) { + dev_info(data->dev, "got check_bist_message is BIST.\n"); + return 0; + } else { + dev_info(data->dev, "got check_bist_message is NOT BIST.\n"); + return -1; + } } #if defined(CONFIG_CHECK_CTYPE_SIDE) || defined(CONFIG_CCIC_SYSFS) @@ -1056,13 +1253,6 @@ static int s2mu106_get_data_role(void *_data, int *val) return 0; } -static void s2mu106_get_vbus_short_check(void *_data, bool *val) -{ - struct usbpd_data *data = (struct usbpd_data *) _data; - struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; - *val = pdic_data->vbus_short; -} - static int s2mu106_set_check_msg_pass(void *_data, int val) { struct usbpd_data *data = (struct usbpd_data *) _data; @@ -1139,6 +1329,11 @@ int s2mu106_usbpd_check_vdm_msg(void *_data, u64 *val) return 0; } + if (data->protocol_rx.msg_header.msg_type == USBPD_Source_Capabilities) { + *val |= MSG_SRC_CAP; + return 0; + } + if (data->protocol_rx.msg_header.msg_type != USBPD_Vendor_Defined) { dev_info(data->dev, "%s msg type is wrong\n", __func__); return 0; @@ -1177,25 +1372,30 @@ static int s2mu106_usbpd_set_cc_control(struct s2mu106_usbpd_data *pdic_data, i u8 data = 0; dev_info(pdic_data->dev, "%s, (%d)\n", __func__, val); - mutex_lock(&pdic_data->cc_mutex); - if (pdic_data->detach_valid) - goto out; - - val = 1; + if (pdic_data->detach_valid) { + dev_info(pdic_data->dev, "%s, ignore cc control\n", __func__); + return 0; + } if (val) { s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, &data); data &= ~S2MU106_REG_PLUG_CTRL_CC_MANUAL_MASK; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, data); + + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL, &data); + data |= S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL, data); } else { s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, &data); data &= ~S2MU106_REG_PLUG_CTRL_CC_MANUAL_MASK; data |= S2MU106_REG_PLUG_CTRL_CC_MANUAL_EN; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_CC12, data); + + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL, &data); + data &= ~S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL, data); } -out: - mutex_unlock(&pdic_data->cc_mutex); return 0; } @@ -1724,7 +1924,7 @@ static void s2mu106_usbpd_otg_attach(struct s2mu106_usbpd_data *pdic_data) { struct i2c_client *i2c = pdic_data->i2c; struct device *dev = &i2c->dev; - + /* otg */ pdic_data->is_host = HOST_ON; #if defined(CONFIG_DUAL_ROLE_USB_INTF) @@ -1734,6 +1934,9 @@ static void s2mu106_usbpd_otg_attach(struct s2mu106_usbpd_data *pdic_data) /* USB */ ifconn_event_work(pdic_data, IFCONN_NOTIFY_USB, IFCONN_NOTIFY_ID_USB, IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP, NULL); +#endif +#ifdef CONFIG_PM_S2MU106 + s2mu106_usbpd_check_vbus(pdic_data, 80, VBUS_OFF); #endif /* add to turn on external 5V */ vbus_turn_on_ctrl(pdic_data, VBUS_ON); @@ -1860,33 +2063,8 @@ EOH: } #endif -#if defined(CONFIG_DUAL_ROLE_USB_INTF) -static void s2mu106_usbpd_control_cc12_rd(struct s2mu106_usbpd_data *pdic_data, - bool enable) -{ - struct i2c_client *i2c = pdic_data->i2c; - u8 data = 0; - - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data); - dev_info(pdic_data->dev, "%s, enable : %s current reg value(%x)\n", __func__, - enable ? "ON" : "OFF", data); - - if (enable) { - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data); - data &= ~S2MU106_REG_PLUG_CTRL_MODE_MASK; - data |= S2MU106_REG_PLUG_CTRL_UFP; - s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data); - } else { - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data); - data &= ~S2MU106_REG_PLUG_CTRL_MODE_MASK; - data |= S2MU106_REG_PLUG_CTRL_DRP; - s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data); - } -} -#endif - static void s2mu106_usbpd_prevent_watchdog_reset( - struct s2mu106_usbpd_data *pdic_data) + struct s2mu106_usbpd_data *pdic_data) { struct i2c_client *i2c = pdic_data->i2c; u8 val = 0; @@ -1904,13 +2082,14 @@ static void s2mu106_usbpd_prevent_watchdog_reset( ENABLED_INT_2_WAKEUP, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5); 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, + s2mu106_set_irq_enable(pdic_data, ENABLED_INT_0, ENABLED_INT_1, + ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5); } } @@ -1918,58 +2097,6 @@ static void s2mu106_usbpd_prevent_watchdog_reset( mutex_unlock(&pdic_data->lpm_mutex); } -static void s2mu106_vbus_short_check(struct s2mu106_usbpd_data *pdic_data) -{ - struct i2c_client *i2c = pdic_data->i2c; - struct device *dev = pdic_data->dev; - u8 val = 0; - u8 cc1_val = 0, cc2_val = 0; - u8 rp_currentlvl = 0; - - if (pdic_data->vbus_short_check) - return; - - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_FSM_MON, &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; - - dev_info(dev, "%s, 10k check : cc1_val(%x), cc2_val(%x)\n", - __func__, cc1_val, cc2_val); - - if (cc1_val == USBPD_10k || cc2_val == USBPD_10k) - rp_currentlvl = RP_CURRENT_LEVEL3; - else if (cc1_val == USBPD_22k || cc2_val == USBPD_22k) - rp_currentlvl = RP_CURRENT_LEVEL2; - else if (cc1_val == USBPD_56k || cc2_val == USBPD_56k) - rp_currentlvl = RP_CURRENT_LEVEL_DEFAULT; - -#ifdef CONFIG_IFCONN_NOTIFIER - pd_noti.sink_status.rp_currentlvl = rp_currentlvl; - pd_noti.event = IFCONN_NOTIFY_EVENT_ATTACH; - ifconn_event_work(pdic_data, IFCONN_NOTIFY_BATTERY, - IFCONN_NOTIFY_ID_POWER_STATUS, - IFCONN_NOTIFY_EVENT_ATTACH, &pd_noti); -#endif - 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; - - dev_info(dev, "%s, vbus short check : cc1_val(%x), cc2_val(%x)\n", - __func__, cc1_val, cc2_val); - - if (cc1_val == USBPD_Rp || cc2_val == USBPD_Rp) { - pdic_data->vbus_short = true; - } else { - pdic_data->vbus_short = false; - ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC, - IFCONN_NOTIFY_ID_TA, IFCONN_NOTIFY_EVENT_ATTACH, NULL); - } - - pdic_data->vbus_short_check = true; -} - static void s2mu106_usbpd_detach_init(struct s2mu106_usbpd_data *pdic_data) { struct device *dev = pdic_data->dev; @@ -1979,20 +2106,28 @@ static void s2mu106_usbpd_detach_init(struct s2mu106_usbpd_data *pdic_data) dev_info(dev, "%s\n", __func__); + mutex_lock(&pdic_data->cc_mutex); s2mu106_usbpd_set_cc_control(pdic_data, USBPD_CC_OFF); - +#if defined(CONFIG_DUAL_ROLE_USB_INTF) + if (pdic_data->power_role_dual == DUAL_ROLE_PROP_PR_SRC) { + vbus_turn_on_ctrl(pdic_data, VBUS_OFF); + } +#endif + pdic_data->detach_valid = true; + mutex_unlock(&pdic_data->cc_mutex); usbpd_manager_plug_detach(dev, 0); + + /* wait flushing policy engine work */ + usbpd_cancel_policy_work(dev); + pdic_data->status_reg = 0; usbpd_reinit(dev); /* for ccic hw detect */ s2mu106_usbpd_write_reg(i2c, S2MU106_REG_MSG_SEND_CON, S2MU106_RESET_REG_00); pdic_data->rid = REG_RID_MAX; pdic_data->check_rid_wa = false; - pdic_data->detach_valid = true; pdic_data->is_factory_mode = false; pdic_data->is_pr_swap = false; - pdic_data->vbus_short_check = false; - pdic_data->vbus_short = false; if (pdic_data->regulator_en) ret = regulator_disable(pdic_data->regulator); #ifdef CONFIG_BATTERY_SAMSUNG @@ -2009,12 +2144,6 @@ static void s2mu106_usbpd_detach_init(struct s2mu106_usbpd_data *pdic_data) static void s2mu106_usbpd_notify_detach(struct s2mu106_usbpd_data *pdic_data) { struct device *dev = pdic_data->dev; - struct usbpd_data *pd_data = dev_get_drvdata(pdic_data->dev); - struct usbpd_manager_data *manager = &pd_data->manager; - - if (manager->dp_is_connect == 1) - usbpd_dp_detach(pd_data); - #if defined(CONFIG_IFCONN_NOTIFIER) /* MUIC */ ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC, IFCONN_NOTIFY_ID_ATTACH, @@ -2033,15 +2162,6 @@ static void s2mu106_usbpd_notify_detach(struct s2mu106_usbpd_data *pdic_data) vbus_turn_on_ctrl(pdic_data, VBUS_OFF); } usbpd_manager_acc_detach(dev); -#if defined(CONFIG_DUAL_ROLE_USB_INTF) - pr_info("%s, data_role (%d)\n", __func__, pdic_data->data_role_dual); - if (pdic_data->data_role_dual == IFCONN_NOTIFY_EVENT_USB_ATTACH_DFP && - !pdic_data->try_state_change) { - s2mu106_usbpd_control_cc12_rd(pdic_data, true); - msleep(S2MU106_WAIT_RD_DETACH_DELAY_MS); - s2mu106_usbpd_control_cc12_rd(pdic_data, false); - } -#endif /* usb or otg */ dev_info(dev, "%s %d: is_host = %d, is_client = %d\n", __func__, __LINE__, pdic_data->is_host, pdic_data->is_client); @@ -2075,7 +2195,7 @@ static void s2mu106_usbpd_try_snk(struct s2mu106_usbpd_data *pdic_data) dev_info(dev, "%s\n", __func__); s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data); - data &= ~ S2MU106_REG_PLUG_CTRL_MODE_MASK; + data &= ~S2MU106_REG_PLUG_CTRL_MODE_MASK; data |= S2MU106_REG_PLUG_CTRL_UFP; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data); @@ -2084,7 +2204,7 @@ static void s2mu106_usbpd_try_snk(struct s2mu106_usbpd_data *pdic_data) s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_MON2, &data); if ((data & S2MU106_PR_MASK) != S2MU106_PDIC_SINK) { s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, &data); - data &= ~ S2MU106_REG_PLUG_CTRL_MODE_MASK; + data &= ~S2MU106_REG_PLUG_CTRL_MODE_MASK; data |= S2MU106_REG_PLUG_CTRL_DFP; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_PORT, data); @@ -2098,13 +2218,7 @@ static void s2mu106_usbpd_try_snk(struct s2mu106_usbpd_data *pdic_data) static void s2mu106_usbpd_check_host(struct s2mu106_usbpd_data *pdic_data, CCIC_HOST_REASON host) { - struct usbpd_data *pd_data = dev_get_drvdata(pdic_data->dev); - struct usbpd_manager_data *manager = &pd_data->manager; - if (host == HOST_ON && pdic_data->is_host == HOST_ON) { - if (manager->dp_is_connect == 1) - usbpd_dp_detach(pd_data); - dev_info(pdic_data->dev, "%s %d: turn off host\n", __func__, __LINE__); ifconn_event_work(pdic_data, IFCONN_NOTIFY_MUIC, IFCONN_NOTIFY_ID_ATTACH, IFCONN_NOTIFY_EVENT_DETACH, NULL); @@ -2183,6 +2297,7 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data) #endif if ((data & S2MU106_PR_MASK) == S2MU106_PDIC_SINK) { dev_info(dev, "SINK\n"); + pdic_data->detach_valid = false; pdic_data->power_role = PDIC_SINK; pdic_data->data_role = USBPD_UFP; s2mu106_snk(i2c); @@ -2215,9 +2330,14 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data) } } #endif - s2mu106_vbus_short_check(pdic_data); } else if ((data & S2MU106_PR_MASK) == S2MU106_PDIC_SOURCE) { dev_info(dev, "SOURCE\n"); + ret = s2mu106_usbpd_check_accessory(pdic_data); + if (ret < 0) { + dev_info(&i2c->dev, "%s attach accessory\n", __func__); + return -1; + } + pdic_data->detach_valid = false; pdic_data->power_role = PDIC_SOURCE; pdic_data->data_role = USBPD_DFP; s2mu106_dfp(i2c); @@ -2235,9 +2355,7 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data) dev_err(&i2c->dev, "Failed to enable vconn LDO: %d\n", ret); } - s2mu106_set_vconn_source(pd_data, USBPD_VCONN_ON); - - msleep(tTypeCSinkWaitCap); /* dont over 310~620ms(tTypeCSinkWaitCap) */ + msleep(100); } else { dev_err(dev, "%s, PLUG Error\n", __func__); #ifdef CONFIG_CCIC_TRY_SNK @@ -2249,8 +2367,6 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data) return -1; } - pdic_data->detach_valid = false; - s2mu106_set_irq_enable(pdic_data, ENABLED_INT_0, ENABLED_INT_1, ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5); @@ -2315,15 +2431,6 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data) if (s2mu106_get_status(pd_data, MSG_NONE)) goto out; - if (s2mu106_get_status(pd_data, MSG_HARDRESET)) { - s2mu106_usbpd_set_cc_control(pdic_data, USBPD_CC_OFF); - s2mu106_self_soft_reset(i2c); - pdic_data->status_reg = 0; - usbpd_rx_hard_reset(dev); - usbpd_kick_policy_work(dev); - goto out; - } - if (s2mu106_get_status(pd_data, MSG_SOFTRESET)) usbpd_rx_soft_reset(pd_data); @@ -2362,6 +2469,18 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data) mutex_unlock(&pdic_data->lpm_mutex); goto out; } + + if (s2mu106_get_status(pd_data, MSG_HARDRESET)) { + mutex_lock(&pdic_data->cc_mutex); + s2mu106_usbpd_set_cc_control(pdic_data, USBPD_CC_OFF); + mutex_unlock(&pdic_data->cc_mutex); + s2mu106_self_soft_reset(i2c); + pdic_data->status_reg = 0; + usbpd_rx_hard_reset(dev); + usbpd_kick_policy_work(dev); + goto out; + } + #if defined(CONFIG_SEC_FACTORY) skip_detach: #endif /* CONFIG_SEC_FACTORY */ @@ -2410,17 +2529,17 @@ static int s2mu106_usbpd_set_property(struct power_supply *psy, u8 data = 0; switch (psp) { - case POWER_SUPPLY_PROP_AUTHENTIC: - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_VBUS_MUX, &data); - data &= ~(S2MU106_REG_RD_OR_VBUS_MUX_SEL); - s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_VBUS_MUX, data); - break; - case POWER_SUPPLY_PROP_USBPD_RESET: - s2mu106_usbpd_set_vbus_wakeup(pdic_data, VBUS_WAKEUP_DISABLE); - s2mu106_usbpd_set_vbus_wakeup(pdic_data, VBUS_WAKEUP_ENABLE); - break; - default: - return -EINVAL; + case POWER_SUPPLY_PROP_AUTHENTIC: + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_VBUS_MUX, &data); + data &= ~(S2MU106_REG_RD_OR_VBUS_MUX_SEL); + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_VBUS_MUX, data); + break; + case POWER_SUPPLY_PROP_USBPD_RESET: + s2mu106_usbpd_set_vbus_wakeup(pdic_data, VBUS_WAKEUP_DISABLE); + s2mu106_usbpd_set_vbus_wakeup(pdic_data, VBUS_WAKEUP_ENABLE); + break; + default: + return -EINVAL; } return 0; } @@ -2459,36 +2578,63 @@ static int s2mu106_usbpd_reg_init(struct s2mu106_usbpd_data *_data) struct i2c_client *i2c = _data->i2c; u8 data = 0; - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL, &data); - data |= S2MU106_REG_PLUG_CTRL_VDM_DISABLE | - S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY; - s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL, data); - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PHY_CTRL_IFG, &data); data |= S2MU106_PHY_IFG_35US << S2MU106_REG_IFG_SHIFT; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PHY_CTRL_IFG, data); + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_MSG_SEND_CON, &data); + data |= S2MU106_REG_MSG_SEND_CON_HARD_EN; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_MSG_SEND_CON, data); + + /* for SMPL issue */ + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_ANALOG_OTP_0A, &data); + data |= S2MU106_REG_OVP_ON; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_ANALOG_OTP_0A, data); + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PD_CTRL_2, &data); data &= ~S2MU106_REG_CC_OCP_MASK; data |= S2MU106_CC_OCP_575MV << S2MU106_REG_CC_OCP_SHIFT; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PD_CTRL_2, data); + /* enable Rd monitor status when cc is attached at sink */ + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_MON, &data); + data |= S2MU106_REG_PLUG_CTRL_SET_MON_RD; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_MON, data); + + /* diable rd or vbus mux */ s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_VBUS_MUX, &data); - data &= ~S2MU106_REG_DET_RD_OR_VBUS; + data &= ~S2MU106_REG_RD_OR_VBUS_MUX_SEL; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_VBUS_MUX, data); - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RD, &data); - data |= S2MU106_REG_USB31_EN; - s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RD, data); - - s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL, &data); - data &= ~S2MU106_REG_PLUG_CTRL_UFP_ATTACH_OPT; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PHY_CTRL_00, 0x80); + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_BMC_CTRL, &data); + data |= 0x01 << 2; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_BMC_CTRL, data); + + /* set debounce time + devide by 300 and unit is ms */ + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_CC_TIMER1, 0xe4); + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_CC_TIMER2, 0x0c); + + /* enable support acc */ + s2mu106_usbpd_read_reg(i2c, S2MU106_REG_PLUG_CTRL_CC_HOLD, &data); + data |= S2MU106_REG_PLUG_CTRL_SUPPORT_ACC; + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_CC_HOLD, data); + + /* fix trim code */ + s2mu106_usbpd_read_reg(i2c, 0x00, &data); + data |= 0x1 | 0x3 << 2; + s2mu106_usbpd_write_reg(i2c, 0x00, data); + + data = 0; + data |= (S2MU106_REG_PLUG_CTRL_SSM_DISABLE | + S2MU106_REG_PLUG_CTRL_VDM_DISABLE); s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL, data); /* set Rd threshold to 400mV */ s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RD_2, S2MU106_THRESHOLD_600MV); s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RP_2, S2MU106_THRESHOLD_1200MV); - s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RD, S2MU106_THRESHOLD_214MV); + s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RD, S2MU106_THRESHOLD_300MV | 0x40); s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_SET_RP, S2MU106_THRESHOLD_2057MV); if (_data->vconn_en) { @@ -2498,11 +2644,11 @@ static int s2mu106_usbpd_reg_init(struct s2mu106_usbpd_data *_data) data |= S2MU106_REG_PLUG_CTRL_VCONN_MANUAL_EN; s2mu106_usbpd_write_reg(i2c, S2MU106_REG_PLUG_CTRL_RpRd, 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_write_reg(i2c, S2MU106_REG_MSG_SEND_CON, S2MU106_RESET_REG_00); - s2mu106_usbpd_set_vconn_manual(_data, true); return 0; @@ -2587,8 +2733,7 @@ static void s2mu106_usbpd_pdic_data_init(struct s2mu106_usbpd_data *_data) _data->is_otg_vboost = false; _data->is_otg_reboost = false; _data->is_pr_swap = false; - _data->vbus_short = false; - _data->vbus_short_check = false; + _data->vbus_access = false; #ifndef CONFIG_SEC_FACTORY _data->lpcharge_water = false; #endif @@ -2689,6 +2834,11 @@ 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 = @@ -2833,6 +2983,7 @@ static usbpd_phy_ops_type s2mu106_ops = { .tx_msg = s2mu106_tx_msg, .rx_msg = s2mu106_rx_msg, .hard_reset = s2mu106_hard_reset, + .soft_reset = s2mu106_soft_reset, .set_power_role = s2mu106_set_power_role, .get_power_role = s2mu106_get_power_role, .set_data_role = s2mu106_set_data_role, @@ -2844,9 +2995,11 @@ static usbpd_phy_ops_type s2mu106_ops = { .poll_status = s2mu106_poll_status, .driver_reset = s2mu106_driver_reset, .set_otg_control = s2mu106_set_otg_control, - .get_vbus_short_check = s2mu106_get_vbus_short_check, .set_cc_control = s2mu106_set_cc_control, .get_side_check = s2mu106_get_side_check, + .pr_swap = s2mu106_pr_swap, + .vbus_on_check = s2mu106_vbus_on_check, + .check_bist_message = s2mu106_check_bist_message, }; #if defined CONFIG_PM diff --git a/drivers/ccic/usbpd.c b/drivers/ccic/usbpd.c index 37cd7691db03..e1e8d5654c68 100644 --- a/drivers/ccic/usbpd.c +++ b/drivers/ccic/usbpd.c @@ -19,6 +19,46 @@ extern struct pdic_notifier_data pd_noti; #endif +#define MS_TO_NS(msec) ((msec) * 1000 * 1000) + +void usbpd_timer1_start(struct usbpd_data *pd_data) +{ + do_gettimeofday(&pd_data->time1); +} + +int usbpd_check_time1(struct usbpd_data *pd_data) +{ + int ms = 0; + int sec = 0; + struct timeval time; + + do_gettimeofday(&time); + + sec = time.tv_sec - pd_data->time1.tv_sec; + ms = (time.tv_usec - pd_data->time1.tv_usec) / 1000; + + return (sec * 1000) + ms; +} + +void usbpd_timer2_start(struct usbpd_data *pd_data) +{ + do_gettimeofday(&pd_data->time2); +} + +int usbpd_check_time2(struct usbpd_data *pd_data) +{ + int ms = 0; + int sec = 0; + struct timeval time; + + do_gettimeofday(&time); + + sec = time.tv_sec - pd_data->time2.tv_sec; + ms = (time.tv_usec - pd_data->time2.tv_usec) / 1000; + + return (sec * 1000) + ms; +} + static void increase_message_id_counter(struct usbpd_data *pd_data) { pd_data->counter.message_id_counter++; @@ -66,6 +106,7 @@ void usbpd_init_protocol(struct usbpd_data *pd_data) { rx_layer_init(&pd_data->protocol_rx); tx_layer_init(&pd_data->protocol_tx); + pd_data->id_matched = 0; } void usbpd_init_counters(struct usbpd_data *pd_data) @@ -274,6 +315,7 @@ void usbpd_set_ops(struct device *dev, usbpd_phy_ops_type *ops) pd_data->phy_ops.tx_msg = ops->tx_msg; pd_data->phy_ops.rx_msg = ops->rx_msg; pd_data->phy_ops.hard_reset = ops->hard_reset; + pd_data->phy_ops.soft_reset = ops->soft_reset; pd_data->phy_ops.set_power_role = ops->set_power_role; pd_data->phy_ops.get_power_role = ops->get_power_role; pd_data->phy_ops.set_data_role = ops->set_data_role; @@ -285,9 +327,11 @@ void usbpd_set_ops(struct device *dev, usbpd_phy_ops_type *ops) pd_data->phy_ops.poll_status = ops->poll_status; pd_data->phy_ops.driver_reset = ops->driver_reset; pd_data->phy_ops.set_otg_control = ops->set_otg_control; - pd_data->phy_ops.get_vbus_short_check = ops->get_vbus_short_check; pd_data->phy_ops.set_cc_control = ops->set_cc_control; 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.check_bist_message = ops->check_bist_message; } protocol_state usbpd_protocol_rx_layer_reset_for_receive(struct protocol_data *rx) @@ -322,8 +366,12 @@ 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 { - if (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; + } + + pd_data->id_matched = 1; dev_err(pd_data->dev, "[Rx] [0x%x] [0x%x]\n", rx->msg_header.word, rx->data_obj[0].object); @@ -581,7 +629,7 @@ int usbpd_init(struct device *dev, void *phy_driver_data) ret = sysfs_create_group(&pd_data->ccic_dev->kobj, &ccic_sysfs_group); if (ret) pr_err("%s: ccic sysfs fail, ret %d", __func__, ret); - else + else dev_set_drvdata(pd_data->ccic_dev, pd_data); } #endif @@ -596,7 +644,13 @@ int usbpd_init(struct device *dev, void *phy_driver_data) usbpd_init_policy(pd_data); usbpd_init_manager(pd_data); + pd_data->policy_wqueue = + create_singlethread_workqueue(dev_name(dev)); + if (!pd_data->policy_wqueue) + pr_err("%s: Fail to Create Workqueue\n", __func__); + INIT_WORK(&pd_data->worker, usbpd_policy_work); + init_completion(&pd_data->msg_arrived); return 0; diff --git a/drivers/ccic/usbpd_manager.c b/drivers/ccic/usbpd_manager.c index bbdce419ef11..1aa4ab2f68f8 100644 --- a/drivers/ccic/usbpd_manager.c +++ b/drivers/ccic/usbpd_manager.c @@ -60,15 +60,6 @@ void s2mu106_select_pdo(int num) { struct usbpd_data *pd_data = pd_noti.pd_data; struct usbpd_manager_data *manager = &pd_data->manager; - bool vbus_short; - - pd_data->phy_ops.get_vbus_short_check(pd_data, &vbus_short); - - if (vbus_short) { - pr_info(" %s : PDO(%d) is ignored becasue of vbus short\n", - __func__, pd_noti.sink_status.selected_pdo_num); - return; - } if (pd_noti.sink_status.selected_pdo_num == num) return; @@ -142,6 +133,13 @@ void usbpd_manager_start_discover_msg_cancel(struct device *dev) cancel_delayed_work_sync(&manager->start_discover_msg_handler); } +void usbpd_manager_send_pr_swap(struct device *dev) +{ + pr_info("%s: call send pr swap msg\n", __func__); + + usbpd_manager_inform_event(pd_noti.pd_data, MANAGER_SEND_PR_SWAP); +} + static void init_source_cap_data(struct usbpd_manager_data *_data) { /* struct usbpd_data *pd_data = manager_to_usbpd(_data); @@ -187,12 +185,12 @@ static void init_sink_cap_data(struct usbpd_manager_data *_data) 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 = 500/10; + data_obj->power_data_obj_sink.op_current = 3000/10; (data_obj + 1)->power_data_obj_variable.supply_type = POWER_TYPE_VARIABLE; (data_obj + 1)->power_data_obj_variable.max_voltage = _data->sink_cap_max_volt / 50; (data_obj + 1)->power_data_obj_variable.min_voltage = 5000 / 50; - (data_obj + 1)->power_data_obj_variable.max_current = 500 / 10; + (data_obj + 1)->power_data_obj_variable.max_current = 3000 / 10; } void usbpd_manager_receive_samsung_uvdm_message(struct usbpd_data *pd_data) @@ -215,12 +213,24 @@ void usbpd_manager_plug_attach(struct device *dev) manager->template.data = &pd_noti.sink_status; ifconn_event_work(pdic_data, IFCONN_NOTIFY_MANAGER, IFCONN_NOTIFY_ID_POWER_STATUS, IFCONN_NOTIFY_EVENT_ATTACH, &pd_noti); + manager->pd_attached = 1; #endif + pr_info("%s: usbpd plug atached\n", __func__); } void usbpd_manager_plug_detach(struct device *dev, bool notify) { +#if defined(CONFIG_IFCONN_NOTIFIER) struct usbpd_data *pd_data = dev_get_drvdata(dev); + struct s2mu106_usbpd_data *pdic_data = pd_data->phy_driver_data; + struct usbpd_manager_data *manager = &pd_data->manager; + + if (manager->pd_attached && pdic_data->power_role == PDIC_SINK) { + ifconn_event_work(pdic_data, IFCONN_NOTIFY_BATTERY, + IFCONN_NOTIFY_ID_DETACH, 0, 0); + manager->pd_attached = 0; + } +#endif pr_info("%s: usbpd plug detached\n", __func__); @@ -228,18 +238,18 @@ void usbpd_manager_plug_detach(struct device *dev, bool notify) } void usbpd_manager_acc_detach(struct device *dev) -{ +{ struct usbpd_data *pd_data = dev_get_drvdata(dev); struct usbpd_manager_data *manager = &pd_data->manager; pr_info("%s\n", __func__); - if ( manager->acc_type != CCIC_DOCK_DETACHED ) { + if (manager->acc_type != CCIC_DOCK_DETACHED) { pr_info("%s: schedule_delayed_work \n", __func__); - if ( manager->acc_type == CCIC_DOCK_HMT ) + if (manager->acc_type == CCIC_DOCK_HMT) schedule_delayed_work(&manager->acc_detach_handler, msecs_to_jiffies(1000)); else schedule_delayed_work(&manager->acc_detach_handler, msecs_to_jiffies(0)); - } + } } int usbpd_manager_command_to_policy(struct device *dev, @@ -316,6 +326,10 @@ void usbpd_manager_inform_event(struct usbpd_data *pd_data, usbpd_manager_command_to_policy(pd_data->dev, MANAGER_REQ_VDM_DISCOVER_IDENTITY); break; + case MANAGER_SEND_PR_SWAP: + usbpd_manager_command_to_policy(pd_data->dev, + MANAGER_REQ_PR_SWAP); + break; default: pr_info("%s: not matched event(%d)\n", __func__, event); } @@ -513,7 +527,7 @@ static int usbpd_manager_check_accessory(struct usbpd_manager_data *manager) break; } } else if (vid == SAMSUNG_MPA_VENDOR_ID) { - switch(pid) { + switch (pid) { case MPA_PRODUCT_ID: acc_type = CCIC_DOCK_MPA; pr_info("%s : Samsung MPA connected.\n", __func__); @@ -525,10 +539,10 @@ static int usbpd_manager_check_accessory(struct usbpd_manager_data *manager) } } manager->acc_type = acc_type; - } else + } else acc_type = manager->acc_type; - if (acc_type != CCIC_DOCK_NEW) + if (acc_type != CCIC_DOCK_NEW) usbpd_manager_send_dock_intent(acc_type); usbpd_manager_send_dock_uevent(vid, pid, acc_type); @@ -704,27 +718,27 @@ int usbpd_manager_get_status(struct usbpd_data *pd_data) multi_func_preference = pd_obj->displayport_status.multi_function_preferred; if (multi_func_preference) { - if(manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { + if (manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { pin_assignment = IFCONN_NOTIFY_DP_PIN_D; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { pin_assignment = IFCONN_NOTIFY_DP_PIN_B; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { pin_assignment = IFCONN_NOTIFY_DP_PIN_F; } else { pr_info("wrong pin assignment value\n"); } } else { - if(manager->pin_assignment & DP_PIN_ASSIGNMENT_C) { + if (manager->pin_assignment & DP_PIN_ASSIGNMENT_C) { pin_assignment = IFCONN_NOTIFY_DP_PIN_C; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_E) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_E) { pin_assignment = IFCONN_NOTIFY_DP_PIN_E; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_A) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_A) { pin_assignment = IFCONN_NOTIFY_DP_PIN_A; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { pin_assignment = IFCONN_NOTIFY_DP_PIN_D; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { pin_assignment = IFCONN_NOTIFY_DP_PIN_B; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { pin_assignment = IFCONN_NOTIFY_DP_PIN_F; } else { pr_info("wrong pin assignment value\n"); @@ -761,7 +775,7 @@ int usbpd_manager_get_configure(struct usbpd_data *pd_data) ifconn_event_work(pdic_data, IFCONN_NOTIFY_MANAGER, IFCONN_NOTIFY_ID_DP_LINK_CONF, IFCONN_NOTIFY_EVENT_ATTACH, manager); - + return 0; } @@ -790,27 +804,27 @@ int usbpd_manager_get_attention(struct usbpd_data *pd_data) multi_func_preference = pd_obj->displayport_status.multi_function_preferred; if (multi_func_preference) { - if(manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { + if (manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { pin_assignment = IFCONN_NOTIFY_DP_PIN_D; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { pin_assignment = IFCONN_NOTIFY_DP_PIN_B; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { pin_assignment = IFCONN_NOTIFY_DP_PIN_F; } else { pr_info("wrong pin assignment value\n"); } } else { - if(manager->pin_assignment & DP_PIN_ASSIGNMENT_C) { + if (manager->pin_assignment & DP_PIN_ASSIGNMENT_C) { pin_assignment = IFCONN_NOTIFY_DP_PIN_C; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_E) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_E) { pin_assignment = IFCONN_NOTIFY_DP_PIN_E; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_A) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_A) { pin_assignment = IFCONN_NOTIFY_DP_PIN_A; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_D) { pin_assignment = IFCONN_NOTIFY_DP_PIN_D; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_B) { pin_assignment = IFCONN_NOTIFY_DP_PIN_B; - } else if(manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { + } else if (manager->pin_assignment & DP_PIN_ASSIGNMENT_F) { pin_assignment = IFCONN_NOTIFY_DP_PIN_F; } else { pr_info("wrong pin assignment value\n"); @@ -943,7 +957,7 @@ int usbpd_manager_match_request(struct usbpd_data *pd_data) unsigned supply_type = pd_data->source_request_obj.power_data_obj_supply_type.supply_type; - unsigned mismatch, max_min, op, pos; + unsigned src_max_current, mismatch, max_min, op, pos; if (supply_type == POWER_TYPE_FIXED) { pr_info("REQUEST: FIXED\n"); @@ -960,19 +974,26 @@ int usbpd_manager_match_request(struct usbpd_data *pd_data) } log_fixed_variable: + /* Tx Source PDO */ + src_max_current = pd_data->source_data_obj.power_data_obj.max_current; + + /* Rx Request RDO */ mismatch = pd_data->source_request_obj.request_data_object.capability_mismatch; max_min = pd_data->source_request_obj.request_data_object.min_current; op = pd_data->source_request_obj.request_data_object.op_current; pos = pd_data->source_request_obj.request_data_object.object_position; - pr_info("Obj position: %d\n", pos); - pr_info("Mismatch: %d\n", mismatch); - pr_info("Operating Current: %d mA\n", op*10); - if (pd_data->source_request_obj.request_data_object.give_back) - pr_info("Min current: %d mA\n", max_min*10); - else - pr_info("Max current: %d mA\n", max_min*10); - return 0; + pr_info("%s %x\n", __func__, pd_data->source_request_obj.object); + + /*src_max_current is already *10 value ex) src_max_current 500mA */ + //pr_info("Tx SourceCap Current : %dmA\n", src_max_current*10); + //pr_info("Rx Request Current : %dmA\n", max_min*10); + + /* Compare Pdo and Rdo */ + if ((src_max_current >= max_min) && (pos == 1)) + return 0; + else + return -1; log_battery: mismatch = pd_data->source_request_obj.request_data_object_battery.capability_mismatch; @@ -1088,9 +1109,10 @@ int usbpd_init_manager(struct usbpd_data *pd_data) #endif mutex_init(&manager->vdm_mutex); manager->pd_data = pd_data; + manager->pd_attached = 0; manager->power_role_swap = true; manager->data_role_swap = true; - manager->vconn_source_swap = true; + manager->vconn_source_swap = false; manager->alt_sended = 0; manager->vdm_en = 0; manager->acc_type = 0; diff --git a/drivers/ccic/usbpd_policy.c b/drivers/ccic/usbpd_policy.c index 88dccc42d706..39010cc07c4f 100644 --- a/drivers/ccic/usbpd_policy.c +++ b/drivers/ccic/usbpd_policy.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #if defined(CONFIG_MUIC_NOTIFIER) @@ -41,22 +40,76 @@ policy_state usbpd_policy_src_startup(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Send_Capabilities; + int ms = 0; + /********************************************** + Actions on entry: + Reset CapsCounter + Reset Protocol Layer + Start SwapSourceStartTimer (only after Swap) + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) CapsCounter Reset */ pd_data->counter.caps_counter = 0; + + /* 3) PD Protocol Initialization */ usbpd_init_protocol(pd_data); + /* 4) Fro tSrcrecover after PE_SRC_Transition_to_default */ + if (policy->txhardresetflag == 1) { + policy->txhardresetflag = 0; + + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Startup; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= 200) + break; + } + } + + /* 5) Configuration Channel On */ pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); - return PE_SRC_Send_Capabilities; + return ret; } policy_state usbpd_policy_src_discovery(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = 0; + int ms = 0; + + /********************************************** + Actions on entry: + Initialize and run SourceCapabilityTimer + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - msleep(tSendSourceCap); + + /* 2) Delay*/ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Discovery; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= tTypeCSendSourceCap) + break; + } + + if (ret == PE_SRC_Discovery) + return ret; + /* 3) Caps Counter Check */ if (pd_data->counter.caps_counter <= USBPD_nCapsCount) return PE_SRC_Send_Capabilities; else @@ -66,126 +119,198 @@ policy_state usbpd_policy_src_discovery(struct policy_data *policy) policy_state usbpd_policy_src_send_capabilities(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + bool received_goodcrc = 0; + int ret = 0; + int ms = 0; + + /********************************************** + Actions on entry: + Request present source capabilities from Device Policy Manager + Send PD Capabilities message + Increment CapsCounter (optional) + If GoodCRC received: + - stop NoResponseTimer + - reset HardResetCounter and CapsCounter + - initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + /* 2) Source Capabilities PDO Read & Write */ policy->tx_msg_header.word = pd_data->source_msg_header.word; policy->tx_data_obj[0].object = pd_data->source_data_obj.object; - dev_info(pd_data->dev, "%s\n", __func__); - + /* 3) Interrupt Status Bit Clear */ + pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC | MSG_REQUEST | + MSG_GET_SNK_CAP); + /* 4) Add Caps Counter */ pd_data->counter.caps_counter++; - if (usbpd_send_msg(pd_data, &policy->tx_msg_header, - policy->tx_data_obj)) { - pd_data->policy.state = PE_SRC_Send_Capabilities; - if (usbpd_wait_msg(pd_data, MSG_REQUEST, tSenderResponseSRC)) { - if (policy->rx_msg_header.msg_type == USBPD_Request && - policy->rx_msg_header.num_data_objs > 0) { - pd_data->counter.hard_reset_counter = 0; - pd_data->counter.caps_counter = 0; - pd_data->source_request_obj.object - = policy->rx_data_obj[0].object; - dev_info(pd_data->dev, "got Request.\n"); - return PE_SRC_Negotiate_Capability; - } else { - dev_err(pd_data->dev, - "Not get request object\n"); - goto hard_reset; - } - } else if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { - if (policy->abnormal_state) - return PE_SRC_Send_Capabilities; + /* 5) Send Message */ + usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); + + /* 6) Start Timer */ + usbpd_timer1_start(pd_data); // Setting 25ms is actual 25 ~ 29ms + /* 7) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Send_Capabilities; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_REQUEST)) { + pd_data->counter.hard_reset_counter = 0; pd_data->counter.caps_counter = 0; - dev_err(pd_data->dev, - "%s NoResponseTimer\n", __func__); - goto hard_reset; - } else { /* not receive good crc */ - if (policy->abnormal_state) - return PE_SRC_Send_Capabilities; - return PE_SRC_Discovery; - } - } else - return PE_SRC_Discovery; - -hard_reset: - if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) - return Error_Recovery; + usbpd_protocol_rx(pd_data); + pd_data->source_request_obj.object + = policy->rx_data_obj[0].object; + dev_info(pd_data->dev, "got Request.\n"); + ret = PE_SRC_Negotiate_Capability; + break; + } - return PE_SRC_Hard_Reset; -} -#if 0 -policy_state usbpd_policy_src_send_capabilities(struct policy_data *policy) -{ - struct usbpd_data *pd_data = policy_to_usbpd(policy); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) + received_goodcrc = 1; - policy->tx_msg_header.word = pd_data->source_msg_header.word; - policy->tx_data_obj[0].object = pd_data->source_data_obj.object; + if (policy->rx_hardreset) { + ret = 0; + break; + } - dev_info(pd_data->dev, "%s 0x%x 0x%x\n", __func__ - , policy->tx_msg_header.word - , policy->tx_data_obj[0].object); + /* TD.PD.SRC.E14 Atomic Message Sequence */ + if (pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP)) { + ret = PE_SRC_Send_Soft_Reset; + break; + } - pd_data->counter.caps_counter++; - if (usbpd_send_msg(pd_data, &policy->tx_msg_header, - policy->tx_data_obj)) { - pd_data->counter.hard_reset_counter = 0; - pd_data->counter.caps_counter = 0; - if (usbpd_wait_msg(pd_data, MSG_REQUEST, tSenderResponse)) { - if (policy->rx_msg_header.msg_type == USBPD_Request && - policy->rx_msg_header.num_data_objs > 0) { - pd_data->source_request_obj.object - = policy->rx_data_obj[0].object; - dev_info(pd_data->dev, "got Request.\n"); - return PE_SRC_Negotiate_Capability; - } else { - dev_err(pd_data->dev, - "Not get request object\n"); - return Error_Recovery; + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Discovery; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_PING)) { + ret = PE_SRC_Send_Soft_Reset; + break; + } + + if (ms >= tSenderResponse) { + if (received_goodcrc) { + ret = PE_SRC_Hard_Reset; + + if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) + ret = Error_Recovery; + + break; } - } else { - dev_err(pd_data->dev, - "%s NoResponseTimer\n", __func__); - return PE_SRC_Hard_Reset; } - } else - return PE_SRC_Discovery; - if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) - return Error_Recovery; + if (ms >= 100) { + ret = PE_SRC_Discovery; + break; + } + } - return PE_SRC_Send_Capabilities; + return ret; } -#endif + policy_state usbpd_policy_src_negotiate_capability(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); - + int ret = PE_SRC_Negotiate_Capability; + + /********************************************** + Actions on entry: + Get Device Policy Manager evaluation of sink request: + - Can be met + - Can??t be met + - Could be met later from Power Reserve + If the sink request for Operating Current or Operating Power can be met, + but the sink still requires more power Capability Mismatch this + information will be passed to Device Policy Manager + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - if (usbpd_manager_match_request(pd_data) == 0) - return PE_SRC_Transition_Supply; /* Accept */ - else - return PE_SRC_Capability_Response; /* Reject */ + + /* 2) Analysis Received Request Message */ + if (usbpd_manager_match_request(pd_data) == 0) { + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, USBPD_DFP, USBPD_SOURCE); + ret = PE_SRC_Transition_Supply; /* Accept */ + } else { + ret = PE_SRC_Capability_Response; /* Reject */ + } + + return ret; } policy_state usbpd_policy_src_transition_supply(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Ready; + int ms1 = 0, ms2 = 0; + + /********************************************** + Actions on entry: + Initialize and run SourceActivityTimer (see Section 8.3.3.5) + If GotoMin send GotoMin message + Else send Accept message (within tReceiverResponse) + Wait tSrcTransition and request Device Policy Manager to transition Power Supply + + Actions on exit: + Send PS_RDY message + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - /* TODO: If GotoMin send GotoMin message */ - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, - USBPD_DFP, USBPD_SOURCE)) { - msleep(tSrcTransition); + /* 2) Send Message */ + // Move to PE_SRC_Nego + //usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, USBPD_DFP, USBPD_SOURCE); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_PS_RDY, USBPD_DFP, USBPD_SOURCE)) - return PE_SRC_Ready; - else - return PE_SRC_Send_Soft_Reset; - } else { - return PE_SRC_Send_Soft_Reset; + /* 3) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 4) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Transition_Supply; + break; + } + ms1 = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + + usbpd_timer2_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Transition_Supply; + break; + } + ms2 = usbpd_check_time2(pd_data); + if (ms2 > tSrcTransition) + break; + } + + if (ret == PE_SRC_Transition_Supply) + return ret; + + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_PS_RDY, USBPD_DFP, USBPD_SOURCE); + ret = PE_SRC_Ready; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Send_Soft_Reset; + break; + } + + if (ms1 >= 5) { + ret = PE_SRC_Hard_Reset; + break; + } } - return PE_SRC_Transition_Supply; + + return ret; } policy_state usbpd_policy_src_ready(struct policy_data *policy) @@ -193,12 +318,27 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int data_role = 0; + /********************************************** + Actions on entry: + Initialize and run SourceActivityTimer (see Section 8.3.3.5) + Initialize and run DiscoverIdentityTimer + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + + policy->pd_support = 1; + + /* 2) Wait Message or State */ CHECK_MSG(pd_data, MSG_GET_SRC_CAP, PE_SRC_Give_Source_Cap); CHECK_MSG(pd_data, MSG_REQUEST, PE_SRC_Negotiate_Capability); CHECK_MSG(pd_data, MSG_PR_SWAP, PE_PRS_SRC_SNK_Evaluate_Swap); CHECK_MSG(pd_data, MSG_DR_SWAP, PE_DRS_Evaluate_Port); CHECK_MSG(pd_data, MSG_VCONN_SWAP, PE_VCS_Evaluate_Swap); + CHECK_MSG(pd_data, MSG_GET_SNK_CAP, PE_DR_SRC_Give_Sink_Cap); + CHECK_MSG(pd_data, MSG_SOFTRESET, PE_SRC_Soft_Reset); + CHECK_MSG(pd_data, MSG_ERROR, PE_SRC_Send_Soft_Reset); +#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); CHECK_MSG(pd_data, VDM_DISCOVER_MODE, PE_UFP_VDM_Get_Modes); @@ -207,7 +347,8 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy) CHECK_MSG(pd_data, VDM_DP_STATUS_UPDATE, PE_UFP_VDM_Evaluate_Status); CHECK_MSG(pd_data, VDM_DP_CONFIGURE, PE_UFP_VDM_Evaluate_Configure); CHECK_MSG(pd_data, UVDM_MSG, PE_DFP_UVDM_Receive_Message); - +#endif + /* 3) Command Check from AP */ CHECK_CMD(pd_data, MANAGER_REQ_GET_SNKCAP, PE_SRC_Get_Sink_Cap); CHECK_CMD(pd_data, MANAGER_REQ_GOTOMIN, PE_SRC_Transition_Supply); CHECK_CMD(pd_data, MANAGER_REQ_SRCCAP_CHANGE, PE_SRC_Send_Capabilities); @@ -220,10 +361,20 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy) CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_SVID, PE_DFP_VDM_SVIDs_Request); CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_MODE, PE_DFP_VDM_Modes_Request); CHECK_CMD(pd_data, MANAGER_REQ_VDM_ENTER_MODE, PE_DFP_VDM_Mode_Entry_Request); + CHECK_CMD(pd_data, MANAGER_REQ_VDM_EXIT_MODE, PE_DFP_VDM_Mode_Exit_Request); CHECK_CMD(pd_data, MANAGER_REQ_VDM_STATUS_UPDATE, PE_DFP_VDM_Status_Update); CHECK_CMD(pd_data, MANAGER_REQ_VDM_DisplayPort_Configure, PE_DFP_VDM_DisplayPort_Configure); CHECK_CMD(pd_data, MANAGER_REQ_VDM_ATTENTION, PE_UFP_VDM_Attention_Request); + /* 7) Check bist message */ + if (pd_data->phy_ops.check_bist_message(pd_data) == 0) { + dev_info(pd_data->dev, "check_bist_message : Rx_Msg is BIST\n"); + return PE_BIST_Receive_Mode; + } else { + dev_info(pd_data->dev, "check_bist_message : Rx_Msg is NOT BIST\n"); + } + + /* for data role swap test if (usbpd_manager_vdm_request_enabled(pd_data)) { msleep(tDiscoverIdentity); @@ -232,9 +383,10 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy) */ pd_data->phy_ops.get_data_role(pd_data, &data_role); +#if 0 if (data_role == USBPD_DFP) usbpd_manager_vdm_request_enabled(pd_data); - +#endif return PE_SRC_Ready; } @@ -242,40 +394,109 @@ policy_state usbpd_policy_src_disabled(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Disable Power Delivery + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + return PE_SRC_Disabled; } policy_state usbpd_policy_src_capability_response(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = 0; + int data_role = 0; + int ms = 0; + /********************************************** + Actions on entry: + Send Reject message if request can't be met + Send Wait message if request could be met later from the Power + Reserve and present Contract is still valid + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Reject, - USBPD_DFP, USBPD_SOURCE)) { - return PE_SRC_Ready; - /* TODO: if (Contract Invalid) - return(PE_SRC_Hard_Reset) */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 2) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Reject, + data_role, USBPD_SOURCE); + + /* 3) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 4) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Capability_Response; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + ret = PE_SRC_Ready; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Send_Soft_Reset; + break; + } + if (ms >= 5) { + ret = PE_SRC_Hard_Reset; + break; + } } - /* - else if (no Explicit Contract && Reject message sent - || Wait message sent) - return(PE_SRC_Wait_New_Capabilities); - */ - return PE_SRC_Capability_Response; + + return ret; } policy_state usbpd_policy_src_hard_reset(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Transition_to_default; + int ms = 0; - dev_info(pd_data->dev, "%s\n", __func__); + /********************************************** + Actions on entry: + Generate Hard Reset signalling + Start PSHardResetTimer + Increment HardResetCounter + **********************************************/ - msleep(tPSHardReset); + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + /* 2) Send Hardreset */ pd_data->phy_ops.hard_reset(pd_data); + + /* 3) Configuration Channel On */ pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_OFF); + + /* 4) Set Tx HardReset Flag After SRC_HADRESET */ + policy->txhardresetflag = 1; + + /* 5) Delay : Setting 25 is actual 57.3ms */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Hard_Reset; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= tPSHardReset) + break; + } + + if (ret == PE_SRC_Hard_Reset) + return ret; + + /* 6) Add Hardreset Counter */ pd_data->counter.hard_reset_counter++; return PE_SRC_Transition_to_default; @@ -284,10 +505,34 @@ policy_state usbpd_policy_src_hard_reset(struct policy_data *policy) policy_state usbpd_policy_src_hard_reset_received(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Transition_to_default; + int ms = 0; + + /********************************************** + Actions on entry: + Start PSHardResetTimer + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - msleep(tPSHardReset); + /* 2) Delay */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Hard_Reset_Received; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= tPSHardReset) + break; + } + + if (ret == PE_SRC_Hard_Reset_Received) + return ret; + + /* 3) Set Tx HardReset Flag After SRC_HADRESET */ + policy->txhardresetflag = 1; return PE_SRC_Transition_to_default; } @@ -295,10 +540,43 @@ policy_state usbpd_policy_src_hard_reset_received(struct policy_data *policy) policy_state usbpd_policy_src_transition_to_default(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Startup; + int ms = 0; + + /********************************************** + Actions on entry: + Request Device Policy Manager to request power + supply Hard Resets to vSafe5V via vSafe0V + Reset local HW + If Type-C request Device Policy Manager to set + Port Data Role to DFP and turn off VCONN + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 2) VBUS Turn off */ + pd_data->phy_ops.set_otg_control(pd_data, 0); + + /* 3) Delay */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Transition_to_default; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= tSrcRecover) + break; + } + + if (ret == PE_SRC_Transition_to_default) + return ret; + + /* 4) initial reset */ pd_data->phy_ops.driver_reset(pd_data); + + pd_data->phy_ops.set_otg_control(pd_data, 1); /* Request Device Policy Manager to request power supply Hard Resets to vSafe5V via vSafe0V @@ -312,27 +590,38 @@ policy_state usbpd_policy_src_transition_to_default(struct policy_data *policy) Initialize and start NoResponseTimer Inform Protocol Layer Hard Reset complete */ + + /* confirm VBUS ON : done by set_otg_control */ return PE_SRC_Startup; } policy_state usbpd_policy_src_give_source_cap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Give_Source_Cap; + int data_role = 0; + int ms = 0; + + /********************************************** + Action on entry : + Request source capabilities from Device Policy Manager + Send Capabilities message + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - /* - TODO: Request source capabilities from Device Policy Manager - Send Capabilities message - */ + /* 2) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + /* 3) Message Setting */ policy->tx_msg_header.msg_type = USBPD_Source_Capabilities; - policy->tx_msg_header.port_data_role = USBPD_DFP; + policy->tx_msg_header.port_data_role = data_role; policy->tx_msg_header.port_power_role = USBPD_SOURCE; policy->tx_msg_header.num_data_objs = 1; - policy->tx_data_obj[0].power_data_obj.max_current = 100; - policy->tx_data_obj[0].power_data_obj.voltage = 100; + policy->tx_data_obj[0].power_data_obj.max_current = 1500 / 10; + policy->tx_data_obj[0].power_data_obj.voltage = 5000 / 50; policy->tx_data_obj[0].power_data_obj.peak_current = 0; policy->tx_data_obj[0].power_data_obj.data_role_swap = 1; policy->tx_data_obj[0].power_data_obj.usb_comm_capable = 1; @@ -341,35 +630,87 @@ policy_state usbpd_policy_src_give_source_cap(struct policy_data *policy) policy->tx_data_obj[0].power_data_obj.dual_role_power = 1; policy->tx_data_obj[0].power_data_obj.supply = 0; - if (usbpd_send_msg(pd_data, &policy->tx_msg_header, - policy->tx_data_obj)) - return PE_SRC_Ready; - else - return PE_SRC_Give_Source_Cap; + /* 4) Send Message */ + usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); + + /* 5) Start Timer */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Give_Source_Cap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_REQUEST)) { + ret = PE_SRC_Negotiate_Capability; + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Send_Soft_Reset; + break; + } + if (ms >= tSenderResponse) { + ret = PE_SRC_Hard_Reset; + break; + } + } + + return ret; } policy_state usbpd_policy_src_get_sink_cap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + int ret = PE_SRC_Get_Sink_Cap; + int ms = 0; + + /********************************************** + Actions on entry: + Send Get_Sink_Cap message + Initialize and run + SenderResponseTimer + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + pd_data->phy_ops.get_data_role(pd_data, &data_role); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Get_Sink_Cap, USBPD_DFP, USBPD_SOURCE)) { - pd_data->policy.state = PE_SRC_Get_Sink_Cap; - if (usbpd_wait_msg(pd_data, MSG_SNK_CAP, tSenderResponse)) { - /* TODO: pass sink cap to device policy manager */ + /* 2) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_Get_Sink_Cap, data_role, USBPD_SOURCE); + + /* 3) Wait Message */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) + break; + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_SNK_CAP)) { dev_info(pd_data->dev, "got SinkCap.\n"); + ret = PE_SRC_Ready; + break; + } + if (ms >= tSenderResponse) { + ret = PE_SRC_Ready; + break; } } - return PE_SRC_Ready; + + return ret; } policy_state usbpd_policy_src_wait_new_capabilities(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Wait for new Source Capabilities + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); return PE_SRC_Send_Capabilities; @@ -378,88 +719,260 @@ policy_state usbpd_policy_src_wait_new_capabilities(struct policy_data *policy) policy_state usbpd_policy_src_send_soft_reset(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Send_Soft_Reset; + int data_role = 0; + int ms = 0; + + /********************************************** + Actions on entry: + Reset Protocol Layer + Send Soft Reset message + Initialize and run SenderResponseTimer + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 2) USB PD Protocol Initialization */ usbpd_init_protocol(pd_data); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Soft_Reset, USBPD_DFP, USBPD_SOURCE)) { - pd_data->policy.state = PE_SRC_Send_Soft_Reset; - if (usbpd_wait_msg(pd_data, MSG_ACCEPT, tSenderResponse)) - return PE_SRC_Send_Capabilities; - if (policy->abnormal_state) - return PE_SRC_Send_Soft_Reset; + /* 3) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 4) Self SoftReset */ + pd_data->phy_ops.soft_reset(pd_data); + + /* 5) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Soft_Reset, + data_role, USBPD_SOURCE); + + /* 6) Start Timer */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Send_Soft_Reset; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { + ret = PE_SRC_Send_Capabilities; + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Hard_Reset; + break; + } + if (ms >= tSenderResponse) { + ret = PE_SRC_Hard_Reset; + break; + } } - return PE_SRC_Hard_Reset; + + return ret; } policy_state usbpd_policy_src_soft_reset(struct policy_data *policy) { -#if 0 struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SRC_Soft_Reset; + int data_role = 0; + int ms = 0; + /********************************************** + Actions on entry: + Reset Protocol Layer + Send Accept message + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Accept, USBPD_DFP, USBPD_SOURCE)) - return PE_SRC_Send_Capabilities; - else - return PE_SRC_Hard_Reset; -#endif - return PE_SRC_Send_Capabilities; + /* 2) USB PD Protocol Initialization */ + usbpd_init_protocol(pd_data); + + /* 3) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 4) Self SoftReset */ + pd_data->phy_ops.soft_reset(pd_data); + + /* 5) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, data_role, USBPD_SOURCE); + + /* 6) Start Timer */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SRC_Soft_Reset; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + ret = PE_SRC_Send_Capabilities; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Hard_Reset; + break; + } + if (ms >= 5) { + ret = PE_SRC_Ready; + break; + } + } + + return ret; } policy_state usbpd_policy_snk_startup(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Reset Protocol Layer + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) PD Protocol Initialization */ usbpd_init_protocol(pd_data); - pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); + /* 3) Configuration Channel On */ + //pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); + //Move to PE_SNK_Wait_for_Capabilities return PE_SNK_Discovery; } policy_state usbpd_policy_snk_discovery(struct policy_data *policy) { + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = 0; + int vbus_check = 0; + int ms = 0; + + /********************************************** + Actions on entry: + Wait for VBUS + **********************************************/ + /* TODO: wait vbus */ /* if coming from HardReset && NoResponseTimer timeout && HardResetCounter <= nHardResetCount, return(PE_SNK_Hard_Reset) */ - return PE_SNK_Wait_for_Capabilities; + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 3) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Discovery; + break; + } + ms = usbpd_check_time1(pd_data); + + vbus_check = pd_data->phy_ops.vbus_on_check(pd_data); + if (vbus_check < 0 || vbus_check > 0) { + ret = PE_SNK_Wait_for_Capabilities; + break; + } + + /* TimeOver Check */ + if (ms >= tNoResponse) { + /* HardReset Count Check */ + if (pd_data->counter.hard_reset_counter <= USBPD_nHardResetCount) { + ret = PE_SNK_Hard_Reset; + break; + } else { + ret = Error_Recovery; + break; + } + } + } + + return ret; } policy_state usbpd_policy_snk_wait_for_capabilities(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SNK_Wait_for_Capabilities; + int ms = 0; + /********************************************** + Actions on entry: + Initialize and run SinkWaitCapTimer + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - pd_data->policy.state = PE_SNK_Wait_for_Capabilities; - if (usbpd_wait_msg(pd_data, MSG_SRC_CAP, tSinkWaitCap)) - return PE_SNK_Evaluate_Capability; + /* Configuration Channel On */ + pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); + + /* Start Timer */ + usbpd_timer1_start(pd_data); + + /* 4) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Wait_for_Capabilities; + break; + } + ms = usbpd_check_time1(pd_data); + /* Rx Source Capabilities */ + if (pd_data->phy_ops.get_status(pd_data, MSG_SRC_CAP)) { + ret = PE_SNK_Evaluate_Capability; + break; + } - if (policy->abnormal_state) - return PE_SNK_Wait_for_Capabilities; #if !defined(CONFIG_SEC_FACTORY) - if (pd_data->counter.hard_reset_counter <= USBPD_nHardResetCount) - return PE_SNK_Hard_Reset; - else - return Error_Recovery; + /* TimeOver Check */ + if (ms >= tTypeCSinkWaitCap) { + /* HardReset Count Check */ + if (pd_data->counter.hard_reset_counter <= USBPD_nHardResetCount) { + ret = PE_SNK_Hard_Reset; + break; + } else { + ret = Error_Recovery; + break; + } + } #endif - return PE_SNK_Wait_for_Capabilities; + } + + return ret; } policy_state usbpd_policy_snk_evaluate_capability(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); int sink_request_obj_num = 0; + int ret = PE_SNK_Evaluate_Capability; + + /********************************************** + Actions on entry: + Reset HardResetCounter to zero. + Ask Device Policy Manager to evaluate the options based on supplied + capabilities, any Power Reserve that it needs, and respond indicating + the selected capability and, optionally, a Capability Mismatch + **********************************************/ + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 3) Get Rx Buffer */ usbpd_protocol_rx(pd_data); -#ifdef CONFIG_IFCONN_NOTIFIER + + /* 4) Select PDO */ +#if defined(CONFIG_IFCONN_NOTIFIER) if (pd_noti.sink_status.selected_pdo_num == 0) { pd_noti.sink_status.selected_pdo_num = 1; if (policy->sink_cap_received) { @@ -468,68 +981,148 @@ policy_state usbpd_policy_snk_evaluate_capability(struct policy_data *policy) } } #endif + /* 5) Select Object Position */ sink_request_obj_num = usbpd_manager_evaluate_capability(pd_data); + /* 6) Branch */ if (sink_request_obj_num > 0) - return PE_SNK_Select_Capability; + ret = PE_SNK_Select_Capability; else - return PE_SNK_Hard_Reset; + ret = PE_SNK_Hard_Reset; + + return ret; } policy_state usbpd_policy_snk_select_capability(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SNK_Select_Capability; + int data_role = 0; + int ms = 0; - dev_info(pd_data->dev, "%s\n", __func__); + /********************************************** + Actions on entry: + Send Request based on Device Policy Manager response: + - Request from present capabilities + - Optionally Indicate that other capabilities would be preferred (Capability Mismatch) + Initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform to AP */ + //dev_info(pd_data->dev, "%s\n", __func__); + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 2) Message Header Setting */ policy->tx_msg_header.msg_type = USBPD_Request; - policy->tx_msg_header.port_data_role = USBPD_UFP; + policy->tx_msg_header.port_data_role = data_role; policy->tx_msg_header.port_power_role = USBPD_SINK; - policy->tx_msg_header.num_data_objs = 1; + policy->tx_msg_header.num_data_objs = 1; /* Initial Select PDO = 1 */ + /* 3) Select PDO */ policy->tx_data_obj[0] = usbpd_manager_select_capability(pd_data); - if (usbpd_send_msg(pd_data, &policy->tx_msg_header, - policy->tx_data_obj)) { - unsigned msg; - pd_data->policy.state = PE_SNK_Select_Capability; - msg = usbpd_wait_msg(pd_data, MSG_ACCEPT | MSG_REJECT - | MSG_WAIT, tSenderResponse); - if (policy->abnormal_state) - return PE_SNK_Select_Capability; - if (msg & MSG_ACCEPT) - return PE_SNK_Transition_Sink; - else if (msg & (MSG_REJECT | MSG_WAIT)) - return PE_SNK_Ready; - else - return PE_SNK_Hard_Reset; + /* 4) Send Message*/ + usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); + + /* 5) Start Timer*/ + usbpd_timer1_start(pd_data); + + /* 6) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Select_Capability; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP)) { + ret = PE_SNK_Send_Soft_Reset; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { + ret = PE_SNK_Transition_Sink; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { + ret = PE_SNK_Ready; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT | MSG_WAIT)) { + /* 1st Power Negotiation Check */ + if (pd_noti.sink_status.selected_pdo_num == 0) + ret = PE_SNK_Wait_for_Capabilities; + else + ret = PE_SNK_Ready; + + break; + } - /* If no explicit contract - policy->state = PE_SNK_Wait_for_Capabilities; - */ + /* TimeOver Check */ + if (ms >= tSenderResponse) { + ret = PE_SNK_Hard_Reset; + break; + } } - return Error_Recovery; + + return ret; } +uint32_t RX_PS_READY_Message_ID; + policy_state usbpd_policy_snk_transition_sink(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SNK_Transition_Sink; + int ms = 0; + + /********************************************** + Actions on entry: + Initialize and run PSTransitionTimer + **********************************************/ + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 2) Policy Engine State Setting */ policy->state = PE_SNK_Transition_Sink; - if (usbpd_wait_msg(pd_data, MSG_PSRDY, tPSTransition)) { - dev_info(pd_data->dev, "got PS_READY.\n"); -#ifdef CONFIG_IFCONN_NOTIFIER - pd_noti.sink_status.current_pdo_num = pd_noti.sink_status.selected_pdo_num; + + /* 3) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 4) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Transition_Sink; + break; + } + ms = usbpd_check_time1(pd_data); + /* PD Certification(Ellisys) : TD.PD.SNK.E10 GetSinkCap in place of PS_RDY */ + if (pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP)) { + ret = PE_SNK_Hard_Reset; + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { + /* Device Information */ + dev_info(pd_data->dev, "got PS_READY.\n"); + +#if defined(CONFIG_IFCONN_NOTIFIER) + pd_noti.sink_status.current_pdo_num = pd_noti.sink_status.selected_pdo_num; #endif - return PE_SNK_Ready; - } + ret = PE_SNK_Ready; + break; + } - if (policy->abnormal_state) - return PE_SNK_Transition_Sink; + /* TimeOver Check */ + if (ms >= tPSTransition) { + ret = PE_SNK_Hard_Reset; + break; + } + } - return PE_SNK_Hard_Reset; + return ret; } policy_state usbpd_policy_snk_ready(struct policy_data *policy) @@ -537,15 +1130,30 @@ policy_state usbpd_policy_snk_ready(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int data_role = 0; + /********************************************** + Actions on entry: + Initialize and run SinkActivityTimer2 + Initialize and run SinkRequestTimer3 (on receiving Wait) + Initialize and run DiscoverIdentityTimer5 + **********************************************/ + + /* 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); + /* 3) Message Check */ CHECK_MSG(pd_data, MSG_GET_SNK_CAP, PE_SNK_Give_Sink_Cap); - CHECK_MSG(pd_data, MSG_SRC_CAP, PE_SNK_Evaluate_Capability); CHECK_MSG(pd_data, MSG_PR_SWAP, PE_PRS_SNK_SRC_Evaluate_Swap); CHECK_MSG(pd_data, MSG_DR_SWAP, PE_DRS_Evaluate_Port); CHECK_MSG(pd_data, MSG_VCONN_SWAP, PE_VCS_Evaluate_Swap); + CHECK_MSG(pd_data, MSG_GET_SRC_CAP, PE_DR_SNK_Give_Source_Cap); + +#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); CHECK_MSG(pd_data, VDM_DISCOVER_MODE, PE_UFP_VDM_Get_Modes); @@ -554,7 +1162,9 @@ policy_state usbpd_policy_snk_ready(struct policy_data *policy) CHECK_MSG(pd_data, VDM_DP_STATUS_UPDATE, PE_UFP_VDM_Evaluate_Status); CHECK_MSG(pd_data, VDM_DP_CONFIGURE, PE_UFP_VDM_Evaluate_Configure); CHECK_MSG(pd_data, UVDM_MSG, PE_DFP_UVDM_Receive_Message); +#endif + /* 5) Command Check from AP */ CHECK_CMD(pd_data, MANAGER_REQ_NEW_POWER_SRC, PE_SNK_Select_Capability); CHECK_CMD(pd_data, MANAGER_REQ_PR_SWAP, PE_PRS_SNK_SRC_Send_Swap); CHECK_CMD(pd_data, MANAGER_REQ_DR_SWAP, PE_DRS_Evaluate_Send_Port); @@ -566,92 +1176,304 @@ policy_state usbpd_policy_snk_ready(struct policy_data *policy) CHECK_CMD(pd_data, MANAGER_REQ_VDM_ENTER_MODE, PE_DFP_VDM_Mode_Entry_Request); CHECK_CMD(pd_data, MANAGER_REQ_VDM_STATUS_UPDATE, PE_DFP_VDM_Status_Update); CHECK_CMD(pd_data, MANAGER_REQ_VDM_DisplayPort_Configure, PE_DFP_VDM_DisplayPort_Configure); - CHECK_CMD(pd_data, MANAGER_REQ_UVDM_SEND_MESSAGE,PE_DFP_UVDM_Send_Message); + CHECK_CMD(pd_data, MANAGER_REQ_UVDM_SEND_MESSAGE, PE_DFP_UVDM_Send_Message); + /* 6) Data Role Check */ pd_data->phy_ops.get_data_role(pd_data, &data_role); + /* 7) Check bist message */ + if (pd_data->phy_ops.check_bist_message(pd_data) == 0) { + dev_info(pd_data->dev, "check_bist_message : Rx_Msg is BIST\n"); + return PE_BIST_Receive_Mode; + } else { + dev_info(pd_data->dev, "check_bist_message : Rx_Msg is NOT BIST\n"); + } + +#if 0 if (data_role == USBPD_DFP) usbpd_manager_vdm_request_enabled(pd_data); +#endif return PE_SNK_Ready; } -policy_state usbpd_policy_snk_hard_reset(struct policy_data *policy) +policy_state usbpd_policy_snk_hard_reset(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + + /********************************************** + Actions on entry: + Generate Hard Reset signalling. + Increment HardResetCounter. + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + pd_data->phy_ops.hard_reset(pd_data); + pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_OFF); + /* increase hard reset counter */ + pd_data->counter.hard_reset_counter++; + + return PE_SNK_Transition_to_default; +} + +policy_state usbpd_policy_snk_transition_to_default(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SNK_Startup; + int ms = 0; + + /********************************************** + Hard reset signalling received + + Actions on entry: + Request Device Policy Manager to request power sink transition to default + Reset local HW + If Type-C set Port Data Role to UFP and turn off VCONN + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Driver Reset */ + pd_data->phy_ops.driver_reset(pd_data); + + /* 3) Vconn Off */ + usbpd_manager_turn_off_vconn(pd_data); + + /* 4) Wait 200ms */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Transition_to_default; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= 200) + break; + } + + return ret; +} + +policy_state usbpd_policy_snk_give_sink_cap(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SNK_Give_Sink_Cap; + int data_role = 0; + int ms = 0; + /********************************************** + Get Sink Cap Message received + + Actions on entry: + Get present sink capabilities from Device Policy Manager + Send Capabilities message (based on Device Policy Manager response) + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 2) TODO JETSEO ????*/ +#if defined(CONFIG_IFCONN_NOTIFIER) + pd_noti.sink_status.selected_pdo_num = 0; +#endif + + /* 3) Sink Cap Message Setting */ + policy->tx_msg_header.word = pd_data->sink_msg_header.word; + policy->tx_msg_header.port_data_role = data_role; + policy->tx_data_obj[0].object = pd_data->sink_data_obj[0].object; + policy->tx_data_obj[1].object = pd_data->sink_data_obj[1].object; + + policy->sink_cap_received = 1; + + /* 4) Send Message */ + usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); + + /* 5) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 6) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Give_Sink_Cap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + dev_info(pd_data->dev, "got snk_give_sink_cap MSG_GOODCRC.\n"); + ret = PE_SNK_Ready; + break; + } + + /* TimeOver Check */ + if (ms >= 5) { + dev_info(pd_data->dev, "got snk_give_sink_cap Timer1_overflag.\n"); + ret = PE_SNK_Send_Soft_Reset; + break; + } + } + + return ret; +} + +policy_state usbpd_policy_snk_get_source_cap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_SNK_Get_Source_Cap; + int data_role = 0; + int ms = 0; + + /********************************************** + Actions on entry: + Send Get_Source_Cap message + **********************************************/ + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); - pd_data->phy_ops.hard_reset(pd_data); - pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_OFF); - /* increase hard reset counter */ - pd_data->counter.hard_reset_counter++; + pd_data->phy_ops.get_data_role(pd_data, &data_role); - return PE_SNK_Transition_to_default; + /* 2) Send Message*/ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_Get_Source_Cap, data_role, USBPD_SINK); + + /* 3) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 4) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Get_Source_Cap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + ret = PE_SNK_Ready; + break; + } + + /* TimeOver Check */ + if (ms >= 5) { + ret = PE_SNK_Get_Source_Cap; + break; + } + } + + return ret; } -policy_state usbpd_policy_snk_transition_to_default(struct policy_data *policy) +policy_state usbpd_policy_snk_send_soft_reset(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); - + int ret = PE_SNK_Send_Soft_Reset; + int data_role = 0; + int ms = 0; + /********************************************** + Actions on entry: + Reset Protocol Layer + Send Soft Reset message + Initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - pd_data->phy_ops.driver_reset(pd_data); + /* 2) USB PD Protocol Initialization */ + usbpd_init_protocol(pd_data); - usbpd_manager_turn_off_vconn(pd_data); + /* 3) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 4) Self SoftReset */ + pd_data->phy_ops.soft_reset(pd_data); + + /* 5) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Soft_Reset, + data_role, USBPD_SINK); + + /* 6) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 7) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Send_Soft_Reset; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { + ret = PE_SNK_Wait_for_Capabilities; + break; + } -/* pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP); */ + /* TimeOver Check */ + if (ms >= tSenderResponse) { + ret = PE_SNK_Hard_Reset; + break; + } + } - return PE_SNK_Startup; + return ret; } -policy_state usbpd_policy_snk_give_sink_cap(struct policy_data *policy) +policy_state usbpd_policy_snk_soft_reset(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + int ret = PE_SNK_Soft_Reset; + int ms = 0; + + /********************************************** + Soft Reset message received + + Actions on entry: + Reset Protocol Layer + Send Accept message + **********************************************/ + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); -#ifdef CONFIG_IFCONN_NOTIFIER - pd_noti.sink_status.selected_pdo_num = 0; -#endif - policy->tx_msg_header.word = pd_data->sink_msg_header.word; - policy->tx_data_obj[0].object = pd_data->sink_data_obj[0].object; - policy->tx_data_obj[1].object = pd_data->sink_data_obj[1].object; + /* 2) USB PD Protocol Initialization */ + usbpd_init_protocol(pd_data); - policy->sink_cap_received = 1; + /* 3) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); - if (usbpd_send_msg(pd_data, &policy->tx_msg_header, - policy->tx_data_obj)) - return PE_SNK_Ready; - else - return PE_SNK_Give_Sink_Cap; -} + /* 4) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, + data_role, USBPD_SINK); -policy_state usbpd_policy_snk_get_source_cap(struct policy_data *policy) -{ - struct usbpd_data *pd_data = policy_to_usbpd(policy); + /* 5) Start Timer */ + usbpd_timer1_start(pd_data); - dev_info(pd_data->dev, "%s\n", __func__); + /* 6) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_SNK_Soft_Reset; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + ret = PE_SNK_Wait_for_Capabilities; + break; + } - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Get_Source_Cap, USBPD_UFP, USBPD_SINK)) - return PE_SNK_Ready; - else - return PE_SNK_Get_Source_Cap; -} + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SNK_Hard_Reset; + break; + } -policy_state usbpd_policy_snk_soft_reset(struct policy_data *policy) -{ -#if 0 - struct usbpd_data *pd_data = policy_to_usbpd(policy); + if (ms >= 5) { + ret = PE_SNK_Ready; + break; + } + } - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Accept, USBPD_UFP, USBPD_SINK)) - return PE_SNK_Wait_for_Capabilities; - else - return PE_SNK_Hard_Reset; -#endif - return PE_SNK_Wait_for_Capabilities; + return ret; } policy_state usbpd_policy_drs_evaluate_port(struct policy_data *policy) @@ -660,6 +1482,10 @@ policy_state usbpd_policy_drs_evaluate_port(struct policy_data *policy) int data_role = 0; int power_role = 0; + /********************************************** + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); if (policy->modal_operation) { @@ -685,6 +1511,10 @@ policy_state usbpd_policy_drs_evaluate_send_port(struct policy_data *policy) int data_role = 0; int power_role = 0; + /********************************************** + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); if (policy->modal_operation) { @@ -709,6 +1539,15 @@ policy_state usbpd_policy_drs_dfp_ufp_evaluate_dr_swap(struct policy_data *polic struct usbpd_data *pd_data = policy_to_usbpd(policy); bool drs_ok; + /********************************************** + DR_Swap message received & not in Modal Operation + + Actions on entry: + Get evaluation of Data Role Swap + request from Device Policy Manager + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); drs_ok = usbpd_manager_data_role_swap(pd_data); @@ -724,6 +1563,11 @@ policy_state usbpd_policy_drs_dfp_ufp_accept_dr_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Accept message + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -741,6 +1585,12 @@ policy_state usbpd_policy_drs_dfp_ufp_change_to_ufp(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Request Device Policy Manager to + change port to UFP + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP); @@ -756,21 +1606,44 @@ policy_state usbpd_policy_drs_dfp_ufp_send_dr_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + int ret = 0; + int ms = 0; + /********************************************** + Actions on entry: + Send Swap DR message + Initialize and run SenderResponseTimer + **********************************************/ dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_DR_Swap, USBPD_DFP, power_role)) { - unsigned msg; - pd_data->policy.state = PE_DRS_DFP_UFP_Send_DR_Swap; - msg = usbpd_wait_msg(pd_data, MSG_ACCEPT | MSG_REJECT - | MSG_WAIT, tSenderResponse); - if (policy->abnormal_state) - return PE_DRS_DFP_UFP_Send_DR_Swap; - - if (msg & MSG_ACCEPT) - return PE_DRS_DFP_UFP_Change_to_UFP; + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_DRS_DFP_UFP_Send_DR_Swap; + break; + } + ms = usbpd_check_time1(pd_data); + 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; + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { + dev_info(pd_data->dev, "%s, got Reject\n", __func__); + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { + dev_info(pd_data->dev, "%s, got Wait\n", __func__); + break; + } + if (ms >= tSenderResponse) + break; + } + if (ret > 0) + return ret; } if (power_role == USBPD_SOURCE) @@ -784,6 +1657,11 @@ policy_state usbpd_policy_drs_dfp_ufp_reject_dr_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Reject or Wait message as appropriate + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -803,6 +1681,12 @@ policy_state usbpd_policy_drs_ufp_dfp_evaluate_dr_swap(struct policy_data *polic struct usbpd_data *pd_data = policy_to_usbpd(policy); bool drs_ok; + /********************************************** + Actions on entry: + Get evaluation of Data Role Swap + request from Device Policy Manager + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); drs_ok = usbpd_manager_data_role_swap(pd_data); @@ -818,6 +1702,11 @@ policy_state usbpd_policy_drs_ufp_dfp_accept_dr_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Accept message + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -833,6 +1722,11 @@ policy_state usbpd_policy_drs_ufp_dfp_change_to_dfp(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Request Device Policy Manager to change port to DFP + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP); @@ -848,21 +1742,45 @@ policy_state usbpd_policy_drs_ufp_dfp_send_dr_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + int ret = 0; + int ms = 0; + + /********************************************** + Actions on entry: + Send Swap DR message + Initialize and run SenderResponseTimer + **********************************************/ dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_DR_Swap, USBPD_UFP, power_role)) { - unsigned msg; - pd_data->policy.state = PE_DRS_UFP_DFP_Send_DR_Swap; - msg = usbpd_wait_msg(pd_data, MSG_ACCEPT | MSG_REJECT - | MSG_WAIT, tSenderResponse); - if (policy->abnormal_state) - return PE_DRS_UFP_DFP_Send_DR_Swap; - - if (msg & MSG_ACCEPT) - return PE_DRS_UFP_DFP_Change_to_DFP; + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_DRS_UFP_DFP_Send_DR_Swap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { + dev_info(pd_data->dev, "%s, got Accept\n", __func__); + ret = PE_DRS_UFP_DFP_Change_to_DFP; + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { + dev_info(pd_data->dev, "%s, got Reject\n", __func__); + break; + } + if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { + dev_info(pd_data->dev, "%s, got Wait\n", __func__); + break; + } + if (ms > tSenderResponse) + break; + } + if (ret > 0) + return ret; } if (power_role == USBPD_SOURCE) @@ -875,12 +1793,20 @@ policy_state usbpd_policy_drs_ufp_dfp_reject_dr_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + int data_role = 0; + + /********************************************** + Actions on entry: + Send Reject or Wait message as appropriate + **********************************************/ dev_info(pd_data->dev, "%s\n", __func__); + + pd_data->phy_ops.get_data_role(pd_data, &data_role); pd_data->phy_ops.get_power_role(pd_data, &power_role); if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Reject, USBPD_UFP, USBPD_SINK)) { + USBPD_Reject, data_role, USBPD_SINK)) { if (power_role == USBPD_SOURCE) return PE_SRC_Ready; else @@ -893,11 +1819,20 @@ policy_state usbpd_policy_drs_ufp_dfp_reject_dr_swap(struct policy_data *policy) policy_state usbpd_policy_prs_src_snk_reject_pr_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + /********************************************** + Actions on entry: + Send Reject or Wait message as appropriate + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + pd_data->phy_ops.get_data_role(pd_data, &data_role); + if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Reject, USBPD_DFP, USBPD_SOURCE)) + USBPD_Reject, data_role, USBPD_SOURCE)) return PE_SRC_Ready; return PE_PRS_SRC_SNK_Reject_PR_Swap; @@ -908,10 +1843,18 @@ policy_state usbpd_policy_prs_src_snk_evaluate_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); bool prs_ok; + /********************************************** + Actions on entry: + Get evaluation of swap request from Device Policy Manager + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 2) DPM Check to support roleswap */ prs_ok = usbpd_manager_power_role_swap(pd_data); + /* 3) Branch */ if (prs_ok) return PE_PRS_SRC_SNK_Accept_Swap; else @@ -921,54 +1864,152 @@ policy_state usbpd_policy_prs_src_snk_evaluate_swap(struct policy_data *policy) policy_state usbpd_policy_prs_src_snk_send_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + int ret = PE_SRC_Ready; + int ms = 0; - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_PR_Swap, USBPD_DFP, USBPD_SOURCE)) { - unsigned msg; + /********************************************** + Actions on entry: + Send PR_Swap message + Initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_PR_Swap, data_role, USBPD_SOURCE); + + /* 3) Start Timer */ + usbpd_timer1_start(pd_data); + + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SRC_SNK_Send_Swap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { + ret = PE_PRS_SRC_SNK_Transition_off; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { + ret = PE_SRC_Ready; + break; + } - pd_data->policy.state = PE_PRS_SRC_SNK_Send_Swap; - msg = usbpd_wait_msg(pd_data, MSG_ACCEPT | MSG_REJECT - | MSG_WAIT, tSenderResponse); - if (policy->abnormal_state) - return PE_PRS_SRC_SNK_Send_Swap; + if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { + ret = PE_SRC_Ready; + break; + } + + /* TimeOver Check */ + if (ms >= tSenderResponse + 5) { + ret = PE_SRC_Ready; + break; + } - if (msg & MSG_ACCEPT) - return PE_PRS_SRC_SNK_Transition_off; } + return PE_SRC_Ready; } policy_state usbpd_policy_prs_src_snk_accept_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Accept, USBPD_DFP, USBPD_SOURCE)) - return PE_PRS_SRC_SNK_Transition_off; + /********************************************** + Actions on entry: + Send Accept message + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + 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_SOURCE); + + return PE_PRS_SRC_SNK_Transition_off; - return PE_PRS_SRC_SNK_Accept_Swap; } policy_state usbpd_policy_prs_src_snk_transition_to_off(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); struct usbpd_manager_data *manager = &pd_data->manager; + int ret = PE_PRS_SRC_SNK_Assert_Rd; + int ms = 0; + + /********************************************** + Actions on entry: + Tell Device Policy Manager to turn off power supply + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + /* 2) Delay */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SRC_SNK_Transition_off; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= tSrcTransition) + break; + } + + if (ret == PE_PRS_SRC_SNK_Transition_off) + return ret; + + pd_data->phy_ops.pr_swap(pd_data, USBPD_SOURCE_OFF); + + /* 3) VBUS off */ pd_data->phy_ops.set_otg_control(pd_data, 0); pr_info("%s, %d\n", __func__, manager->acc_type); + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SRC_SNK_Transition_off; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= 500) + break; + } +#if 0 + /* TODO: svid_0 == 0 confition check? + * based on 004 code 600ms no condition vs here 150ms w/ condition */ /* skip delay when GEARVR is attached */ if (manager->acc_type != CCIC_DOCK_HMT || manager->SVID_0 == 0) - msleep(150); + msleep(600); +#endif - return PE_PRS_SRC_SNK_Assert_Rd; + return ret; } policy_state usbpd_policy_prs_src_snk_assert_rd(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request DPM to assert Rd + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Asserted Rd */ pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK); return PE_PRS_SRC_SNK_Wait_Source_on; @@ -977,43 +2018,64 @@ policy_state usbpd_policy_prs_src_snk_assert_rd(struct policy_data *policy) policy_state usbpd_policy_prs_src_snk_wait_source_on(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); - struct usbpd_manager_data *manager = &pd_data->manager; - int wait_time = 0; - + int ret = 0; + int data_role = 0; + int ms = 0; + /********************************************** + Actions on entry: + Send PS_RDY message + Initialize and run PSSourceOnTimer + **********************************************/ + + /* 1) PD State Inform for AP */ dev_info(pd_data->dev, "%s\n", __func__); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_PS_RDY, USBPD_DFP, USBPD_SINK)) { - pd_data->policy.state = PE_PRS_SRC_SNK_Wait_Source_on; - if (manager->acc_type == CCIC_DOCK_HMT) - wait_time = 2000; - else - wait_time = tPSSourceOn; - if (usbpd_wait_msg(pd_data, MSG_PSRDY, tPSSourceOn)) { - pd_data->counter.swap_hard_reset_counter = 0; + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 2) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_PS_RDY, data_role, USBPD_SINK); + usbpd_timer1_start(pd_data); + + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SRC_SNK_Wait_Source_on; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { dev_info(pd_data->dev, "got PSRDY.\n"); - mdelay(10); - pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); - return PE_SNK_Startup; - } else { - if (policy->abnormal_state) - return PE_PRS_SRC_SNK_Wait_Source_on; - goto hard_reset; + pd_data->counter.swap_hard_reset_counter = 0; + mdelay(15); + + /* Self SoftReset for Message ID Clear */ + pd_data->phy_ops.soft_reset(pd_data); + + ret = PE_SNK_Startup; + break; + } + if (ms >= tPSSourceOn) { + ret = PE_SNK_Hard_Reset; + if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) + ret = Error_Recovery; + break; } } - return PE_PRS_SRC_SNK_Wait_Source_on; -hard_reset: - if (pd_data->counter.swap_hard_reset_counter > USBPD_nHardResetCount) - return Error_Recovery; + pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); - return PE_SNK_Hard_Reset; + return ret; } policy_state usbpd_policy_prs_snk_src_reject_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Send Reject or Wait message as appropriate + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, @@ -1027,77 +2089,156 @@ policy_state usbpd_policy_prs_snk_src_evaluate_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); bool prs_ok; + int ret = PE_PRS_SNK_SRC_Evaluate_Swap; + + /********************************************** + Actions on entry: + Get evaluation of swap request from Device Policy Manager + **********************************************/ + + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 2) Power Role Swap Check */ prs_ok = usbpd_manager_power_role_swap(pd_data); if (prs_ok) - return PE_PRS_SNK_SRC_Accept_Swap; + ret = PE_PRS_SNK_SRC_Accept_Swap; else - return PE_PRS_SNK_SRC_Reject_Swap; + ret = PE_PRS_SNK_SRC_Reject_Swap; + + return ret; } policy_state usbpd_policy_prs_snk_src_send_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + int ret = PE_SNK_Ready; + int ms = 0; + /********************************************** + Actions on entry: + Send PR_Swap message + Initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_PR_Swap, USBPD_UFP, USBPD_SINK)) { - unsigned msg; + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_PR_Swap, data_role, USBPD_SINK); + + usbpd_timer1_start(pd_data); + + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SNK_SRC_Send_Swap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { + ret = PE_PRS_SNK_SRC_Transition_off; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { + ret = PE_SNK_Ready; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { + ret = PE_SNK_Ready; + break; + } + + /* TimeOver Check */ + if (ms >= tSenderResponse) { + ret = PE_SNK_Ready; + break; + } - pd_data->policy.state = PE_PRS_SNK_SRC_Send_Swap; - msg = usbpd_wait_msg(pd_data, MSG_ACCEPT | MSG_REJECT - | MSG_WAIT, tSenderResponse); - if (policy->abnormal_state) - return PE_PRS_SNK_SRC_Send_Swap; - if (msg & MSG_ACCEPT) - return PE_PRS_SNK_SRC_Transition_off; } - return PE_SNK_Ready; + + return ret; } policy_state usbpd_policy_prs_snk_src_accept_swap(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + /********************************************** + Actions on entry: + Send Accept message + **********************************************/ + + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Accept, USBPD_DFP, USBPD_SINK)) - return PE_PRS_SNK_SRC_Transition_off; + /* 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_Accept_Swap; + return PE_PRS_SNK_SRC_Transition_off; } policy_state usbpd_policy_prs_snk_src_transition_to_off(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); - + int ret = 0; + int ms = 0; + /********************************************** + Actions on entry: + Initialize and run PSSourceOffTimer + Tell Device Policy Manager to turn off Power Sink. + **********************************************/ + + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); + pd_data->phy_ops.pr_swap(pd_data, USBPD_SINK_OFF); usbpd_manager_turn_off_power_sink(pd_data); - pd_data->policy.state = PE_PRS_SNK_SRC_Transition_off; - if (usbpd_wait_msg(pd_data, MSG_PSRDY, tPSSourceOff)) { - pd_data->counter.swap_hard_reset_counter = 0; - dev_info(pd_data->dev, "got PSRDY.\n"); - return PE_PRS_SNK_SRC_Assert_Rp; - } - if (policy->abnormal_state) - return PE_PRS_SNK_SRC_Transition_off; + /* Start Timer 750ms */ + usbpd_timer1_start(pd_data); - if (pd_data->counter.swap_hard_reset_counter > USBPD_nHardResetCount) - return Error_Recovery; + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SNK_SRC_Transition_off; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { + dev_info(pd_data->dev, "got PSRDY.\n"); + ret = PE_PRS_SNK_SRC_Assert_Rp; + break; + } + if (ms >= tPSSourceOff) { + ret = PE_SRC_Hard_Reset; + pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); + if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) + ret = Error_Recovery; + break; + } + } - return PE_SRC_Hard_Reset; + return ret; } policy_state usbpd_policy_prs_snk_src_assert_rp(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request DPM to assert Rp + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.set_power_role(pd_data, USBPD_SOURCE); @@ -1108,19 +2249,67 @@ policy_state usbpd_policy_prs_snk_src_assert_rp(struct policy_data *policy) policy_state usbpd_policy_prs_snk_src_source_on(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + int ret = 0; + int ms = 0; + /********************************************** + Actions on entry: + Tell Device Policy Manager to turn on Source + Initialize and run SourceActivityTimer (see Section 8.3.3.6.1.2)1 + **********************************************/ + + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); + /* 2) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + pd_data->phy_ops.pr_swap(pd_data, USBPD_SOURCE_ON); + + /* 3) VBUS on */ pd_data->phy_ops.set_otg_control(pd_data, 1); - msleep(150); + /* 4) Dealy */ + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SNK_SRC_Source_on; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= 200) + break; + } + if (ret == PE_PRS_SNK_SRC_Source_on) + return ret; + + /* 5) send PS_RDY */ if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_PS_RDY, USBPD_DFP, USBPD_SOURCE)) { - msleep(tSwapSourceStart); /* 20ms */ + USBPD_PS_RDY, data_role, USBPD_SOURCE)) { pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); + usbpd_timer1_start(pd_data); + while (1) { + if (policy->plug_valid == 0) { + ret = PE_PRS_SNK_SRC_Source_on; + break; + } + ms = usbpd_check_time1(pd_data); + if (ms >= tSwapSourceStart) + break; + } + + if (ret == PE_PRS_SNK_SRC_Source_on) + return ret; + /* TODO: 4) check GoodCRC : may need to be added for certification */ + + /* Self SoftReset for Message ID Clear */ + pd_data->phy_ops.soft_reset(pd_data); + return PE_SRC_Startup; } + return PE_PRS_SNK_SRC_Source_on; } @@ -1129,7 +2318,16 @@ policy_state usbpd_policy_vcs_evaluate_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); bool vcs_ok; + /********************************************** + Actions on entry: + Get evaluation of VCONN swap + request from Device Policy Manager + **********************************************/ + + /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Request from DPM */ vcs_ok = usbpd_manager_vconn_source_swap(pd_data); if (vcs_ok) @@ -1145,6 +2343,11 @@ policy_state usbpd_policy_vcs_accept_swap(struct policy_data *policy) int power_role = 0; int data_role = 0; + /********************************************** + Actions on entry: + Send Accept message + **********************************************/ + pd_data->phy_ops.get_vconn_source(pd_data, &vconn_source); pd_data->phy_ops.get_power_role(pd_data, &power_role); pd_data->phy_ops.get_data_role(pd_data, &data_role); @@ -1165,40 +2368,96 @@ policy_state usbpd_policy_vcs_send_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int vconn_source = 0; int power_role = 0; + int ret = PE_VCS_Send_Swap; + int ms = 0; + + /********************************************** + Actions on entry: + Send VCONN_Swap message + Initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform for AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Get Vconn Source */ pd_data->phy_ops.get_vconn_source(pd_data, &vconn_source); + + /* 3) Get Power Role */ pd_data->phy_ops.get_power_role(pd_data, &power_role); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_VCONN_Swap, USBPD_DFP, power_role)) { - if (vconn_source) - return PE_VCS_Wait_for_VCONN; - else - return PE_VCS_Turn_On_VCONN; + /* 4) Send Vconn Swap */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_VCONN_Swap, USBPD_DFP, power_role); + + /* 5) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 6) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_VCS_Send_Swap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + if (vconn_source) + ret = PE_VCS_Wait_for_VCONN; + else + ret = PE_VCS_Turn_On_VCONN; + break; + } + /* TimeOver Check */ + if (ms >= 5) { + if (power_role == USBPD_SINK) + ret = PE_SNK_Hard_Reset; + else + ret = PE_SRC_Hard_Reset; + break; + } } - return PE_VCS_Send_Swap; + return ret; } policy_state usbpd_policy_vcs_wait_for_vconn(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_VCS_Wait_for_VCONN; + int ms = 0; + /********************************************** + Actions on entry: + Start VCONNOnTimer + **********************************************/ dev_info(pd_data->dev, "%s\n", __func__); - pd_data->policy.state = PE_VCS_Wait_for_VCONN; - if (usbpd_wait_msg(pd_data, MSG_PSRDY, tVCONNSourceOn)) { - pd_data->counter.swap_hard_reset_counter = 0; - dev_info(pd_data->dev, "got PSRDY.\n"); - return PE_VCS_Turn_Off_VCONN; - } - if (policy->abnormal_state) - return PE_VCS_Wait_for_VCONN; + /* 5) Start Timer */ + usbpd_timer1_start(pd_data); - if (pd_data->counter.swap_hard_reset_counter > USBPD_nHardResetCount) - return Error_Recovery; + /* 6) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_VCS_Wait_for_VCONN; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { + pd_data->counter.swap_hard_reset_counter = 0; + ret = PE_VCS_Turn_Off_VCONN; + break; + } + /* TimeOver Check */ + if (ms >= tVCONNSourceOn) { + if (pd_data->counter.swap_hard_reset_counter > USBPD_nHardResetCount) + ret = Error_Recovery; + else + ret = PE_SNK_Hard_Reset; + break; + } + } - return PE_SNK_Hard_Reset; + return ret; } policy_state usbpd_policy_vcs_turn_off_vconn(struct policy_data *policy) @@ -1206,6 +2465,11 @@ policy_state usbpd_policy_vcs_turn_off_vconn(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Tell Device Policy Manager to turn off VCONN + **********************************************/ + pd_data->phy_ops.get_power_role(pd_data, &power_role); dev_info(pd_data->dev, "%s\n", __func__); @@ -1222,6 +2486,11 @@ policy_state usbpd_policy_vcs_turn_on_vconn(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Tell Device Policy Manager to turn on VCONN + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.set_vconn_source(pd_data, USBPD_VCONN_ON); @@ -1235,6 +2504,11 @@ policy_state usbpd_policy_vcs_send_ps_rdy(struct policy_data *policy) int power_role = 0; int data_role = 0; + /********************************************** + Actions on entry: + Send PS_RDY message + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1258,6 +2532,11 @@ policy_state usbpd_policy_vcs_reject_vconn_swap(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Reject or Wait message as appropriate + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1275,6 +2554,12 @@ policy_state usbpd_policy_vcs_reject_vconn_swap(struct policy_data *policy) policy_state usbpd_policy_ufp_vdm_get_identity(struct policy_data *policy) { + + /********************************************** + Actions on entry: + Request Identity information from DPM + **********************************************/ + return PE_UFP_VDM_Get_Identity_NAK; } @@ -1283,6 +2568,11 @@ policy_state usbpd_policy_ufp_vdm_send_identity(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover Identity ACK + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1316,6 +2606,12 @@ policy_state usbpd_policy_ufp_vdm_get_identity_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: NAK + Send Discover Identity NAK/BUSY Command + response as requested + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1346,6 +2642,11 @@ policy_state usbpd_policy_ufp_vdm_get_svids(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request SVIDs information from DPM + **********************************************/ + if (usbpd_manager_get_svids(pd_data) == 0) return PE_UFP_VDM_Send_SVIDs; else @@ -1358,6 +2659,11 @@ policy_state usbpd_policy_ufp_vdm_send_svids(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover SVIDs ACK + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1395,6 +2701,12 @@ policy_state usbpd_policy_ufp_vdm_get_svids_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover SVIDs NAK/BUSY Command + response as requested + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1425,6 +2737,11 @@ policy_state usbpd_policy_ufp_vdm_get_modes(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request Modes information from DPM + **********************************************/ + if (usbpd_manager_get_modes(pd_data) == 0) return PE_UFP_VDM_Send_Modes; else @@ -1436,6 +2753,11 @@ policy_state usbpd_policy_ufp_vdm_send_modes(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover Modes ACK + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1469,6 +2791,12 @@ policy_state usbpd_policy_ufp_vdm_get_modes_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover Modes NAK/BUSY Command + response as requested + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1501,8 +2829,19 @@ policy_state usbpd_policy_ufp_vdm_evaluate_mode_entry(struct policy_data *policy { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request DPM to evaluate request to enter a Mode + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); + /* Certification: Ellisys: TD.PD.VDMU.E15.Applicability */ + if (usbpd_manager_get_svids(pd_data) == 0) + return PE_UFP_VDM_Mode_Entry_ACK; + else + return PE_UFP_VDM_Mode_Entry_NAK; + /* Todo check DPM evaluate request to enter a mode */ @@ -1521,6 +2860,11 @@ policy_state usbpd_policy_ufp_vdm_mode_entry_ack(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Enter Mode ACK Command + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1539,6 +2883,7 @@ policy_state usbpd_policy_ufp_vdm_mode_entry_ack(struct policy_data *policy) if (usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj)) { + /* TODO: may need to wait a while(5ms) and send status_update */ if (power_role == USBPD_SINK) return PE_SNK_Ready; else @@ -1552,6 +2897,11 @@ policy_state usbpd_policy_ufp_vdm_mode_entry_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Enter Mode NAK Command response as requested + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1582,6 +2932,11 @@ policy_state usbpd_policy_ufp_vdm_mode_exit(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request DPM to evaluate request to exit the requested Mode + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); if (pd_data->phy_ops.get_status(pd_data, VDM_EXIT_MODE)) { @@ -1606,6 +2961,11 @@ policy_state usbpd_policy_ufp_vdm_mode_exit_ack(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Exit Mode ACK Command + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1637,6 +2997,11 @@ policy_state usbpd_policy_ufp_vdm_mode_exit_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Exit Mode NAK Command + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1668,6 +3033,11 @@ policy_state usbpd_policy_ufp_vdm_attention_request(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Attention Command request + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1700,6 +3070,9 @@ policy_state usbpd_policy_ufp_vdm_evaluate_status(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1726,6 +3099,9 @@ policy_state usbpd_policy_ufp_vdm_status_ack(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1757,6 +3133,9 @@ policy_state usbpd_policy_ufp_vdm_status_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1788,6 +3167,9 @@ policy_state usbpd_policy_ufp_vdm_evaluate_configure(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1814,6 +3196,9 @@ policy_state usbpd_policy_ufp_vdm_configure_ack(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1845,6 +3230,9 @@ policy_state usbpd_policy_ufp_vdm_configure_nak(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1878,6 +3266,12 @@ policy_state usbpd_policy_dfp_vdm_identity_request(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover Identity request + Start VDMResponseTimer + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1905,9 +3299,16 @@ policy_state usbpd_policy_dfp_vdm_identity_request(struct policy_data *policy) if (policy->rx_data_obj[0].structured_vdm.command_type == Responder_ACK) return PE_DFP_VDM_Identity_ACKed; + else if (policy->rx_data_obj[0].structured_vdm.command_type == Responder_NAK + || policy->rx_data_obj[0].structured_vdm.command_type == Responder_BUSY) + return PE_DFP_VDM_Identity_NAKed; } } - return PE_DFP_VDM_Identity_NAKed; + + if (pd_data->counter.swap_hard_reset_counter > USBPD_nHardResetCount) + return Error_Recovery; + + return PE_SRC_Hard_Reset; } static policy_state usbpd_policy_dfp_vdm_response(struct policy_data *policy, @@ -1916,6 +3317,9 @@ static policy_state usbpd_policy_dfp_vdm_response(struct policy_data *policy, struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + usbpd_manager_inform_event(pd_data, event); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1930,6 +3334,11 @@ policy_state usbpd_policy_dfp_vdm_identity_acked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of identity + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, @@ -1940,6 +3349,11 @@ policy_state usbpd_policy_dfp_vdm_identity_naked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of result + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, @@ -1951,6 +3365,12 @@ policy_state usbpd_policy_dfp_vdm_svids_request(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Discover SVIDs request + Start VDMResponseTimer + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -1984,6 +3404,11 @@ policy_state usbpd_policy_dfp_vdm_svids_acked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of SVIDs + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, @@ -1994,6 +3419,11 @@ policy_state usbpd_policy_dfp_vdm_svids_naked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of result + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, @@ -2006,6 +3436,12 @@ policy_state usbpd_policy_dfp_vdm_modes_request(struct policy_data *policy) struct usbpd_manager_data *manager = &pd_data->manager; int power_role = 0; + /********************************************** + Actions on entry: + Send Discover Modes request + Start VDMResponseTimer + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -2039,6 +3475,11 @@ policy_state usbpd_policy_dfp_vdm_modes_acked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of Modes + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, @@ -2049,6 +3490,11 @@ policy_state usbpd_policy_dfp_vdm_modes_naked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of result + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, @@ -2061,6 +3507,12 @@ policy_state usbpd_policy_dfp_vdm_entry_request(struct policy_data *policy) struct usbpd_manager_data *manager = &pd_data->manager; int power_role = 0; + /********************************************** + Actions on entry: + Send Mode Entry request + Start VDMModeEntryTimer + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -2097,6 +3549,11 @@ policy_state usbpd_policy_dfp_vdm_entry_acked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Request DPM to enter the mode + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_ENTER_MODE_ACKED); @@ -2106,6 +3563,11 @@ policy_state usbpd_policy_dfp_vdm_entry_naked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of reason for failure + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_ENTER_MODE_NAKED); @@ -2116,6 +3578,12 @@ policy_state usbpd_policy_dfp_vdm_exit_request(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + Actions on entry: + Send Exit Mode request + Start VDMModeExitTimer + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -2149,6 +3617,11 @@ policy_state usbpd_policy_dfp_vdm_exit_acked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of ACK + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_EXIT_MODE_ACKED); @@ -2158,6 +3631,11 @@ policy_state usbpd_policy_dfp_vdm_exit_naked(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform DPM of NAK + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_EXIT_MODE_NAKED); @@ -2167,6 +3645,11 @@ policy_state usbpd_policy_dfp_vdm_attention_request(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + Actions on entry: + Inform Device Policy Manager of Attention Command request + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_ATTENTION_REQUEST); @@ -2177,6 +3660,9 @@ policy_state usbpd_policy_dfp_vdm_status_update(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -2229,6 +3715,9 @@ policy_state usbpd_policy_dfp_vdm_status_update_acked(struct policy_data *policy { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_STATUS_UPDATE_ACKED); @@ -2238,6 +3727,9 @@ policy_state usbpd_policy_dfp_vdm_status_update_naked(struct policy_data *policy { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_STATUS_UPDATE_NAKED); @@ -2246,9 +3738,11 @@ policy_state usbpd_policy_dfp_vdm_status_update_naked(struct policy_data *policy policy_state usbpd_policy_dfp_vdm_displayport_configure(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); - struct usbpd_manager_data *manager = &pd_data->manager; int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.get_power_role(pd_data, &power_role); @@ -2259,7 +3753,7 @@ policy_state usbpd_policy_dfp_vdm_displayport_configure(struct policy_data *poli policy->tx_msg_header.port_power_role = power_role; policy->tx_msg_header.num_data_objs = 2; - policy->tx_data_obj[0].structured_vdm.svid = manager->SVID_0; + policy->tx_data_obj[0].structured_vdm.svid = PD_SID_1; policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; policy->tx_data_obj[0].structured_vdm.version = 0; policy->tx_data_obj[0].structured_vdm.obj_pos = 1;/* Todo select which_mode */ @@ -2268,14 +3762,9 @@ policy_state usbpd_policy_dfp_vdm_displayport_configure(struct policy_data *poli /* second object for vdo */ policy->tx_data_obj[1].object = 0; - policy->tx_data_obj[1].displayport_configurations.select_configuration = - USB_U_AS_UFP_D; - policy->tx_data_obj[1].displayport_configurations.displayport_protocol = - DP_V_1_3; -// policy->tx_data_obj[1].displayport_configurations.ufp_u_pin_assignment = -// manager->pin_assignment; - policy->tx_data_obj[1].displayport_configurations.ufp_u_pin_assignment = - 4; + policy->tx_data_obj[1].displayport_configurations.select_configuration = USB_U_AS_UFP_D; + policy->tx_data_obj[1].displayport_configurations.displayport_protocol = DP_V_1_3; + policy->tx_data_obj[1].displayport_configurations.ufp_u_pin_assignment = PIN_ASSIGNMENT_D; /* TODO: obj_pos , vdo should be set by device manager */ if (usbpd_send_msg(pd_data, &policy->tx_msg_header, @@ -2298,6 +3787,9 @@ policy_state usbpd_policy_dfp_vdm_displayport_configure_acked(struct policy_data { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_DisplayPort_Configure_ACKED); @@ -2307,6 +3799,9 @@ policy_state usbpd_policy_dfp_vdm_displayport_configure_naked(struct policy_data { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); return usbpd_policy_dfp_vdm_response(policy, MANAGER_DisplayPort_Configure_NACKED); @@ -2318,6 +3813,9 @@ policy_state usbpd_policy_dfp_uvdm_send_message(struct policy_data *policy) struct usbpd_manager_data *manager = &pd_data->manager; int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); pd_data->phy_ops.set_check_msg_pass(pd_data, CHECK_MSG_PASS); @@ -2337,6 +3835,9 @@ policy_state usbpd_policy_dfp_uvdm_receive_message(struct policy_data *policy) struct usbpd_data *pd_data = policy_to_usbpd(policy); int power_role = 0; + /********************************************** + **********************************************/ + dev_info(pd_data->dev, "%s\n", __func__); usbpd_manager_inform_event(pd_data, MANAGER_UVDM_RECEIVE_MESSAGE); @@ -2349,10 +3850,333 @@ policy_state usbpd_policy_dfp_uvdm_receive_message(struct policy_data *policy) return PE_SNK_Ready; } +policy_state usbpd_policy_dr_src_get_source_cap(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_DR_SRC_Get_Source_Cap; + int data_role = 0; + int ms = 0; + + /********************************************** + get source capabilities request from Device Policy Manager + + Actions on entry: + Send Get_Source_Cap message + Initialize and run SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 3) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Get_Source_Cap, data_role, USBPD_SOURCE); + + /* 4) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 5) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_DR_SRC_Get_Source_Cap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SRC_Send_Soft_Reset; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_SRC_CAP)) { + ret = PE_SRC_Ready; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { + ret = PE_SRC_Ready; + break; + } + + /* TimeOver Check */ + if (ms >= tSenderResponse) { + ret = PE_SRC_Ready; + break; + } + } + + /********************************************** + Actions on exit: + Pass source capabilities/outcome to Device Policy Manager + + Source capabilities message received + | SenderResponseTimer Timeout | Reject message received + **********************************************/ + + return ret; +} + +policy_state usbpd_policy_dr_src_give_sink_cap(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int data_role = 0; + int ret = PE_DR_SRC_Give_Sink_Cap; + int ms = 0; + + /********************************************** + Actions on entry: + Get present sink capabilities from Device Policy Manager + Send Capabilities message (based on Device Policy Manager response) + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 3) Sink Cap Message Setting */ + policy->tx_msg_header.word = pd_data->sink_msg_header.word; + policy->tx_msg_header.port_data_role = data_role; + policy->tx_data_obj[0].object = pd_data->sink_data_obj[0].object; + policy->tx_data_obj[1].object = pd_data->sink_data_obj[1].object; + + /* 4) Send Message */ + usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); + + /* 5) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 6) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_DR_SRC_Give_Sink_Cap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + dev_info(pd_data->dev, "got dr_src_give_sink_cap MSG_GOODCRC.\n"); + ret = PE_SRC_Ready; + break; + } + + if (ms >= 5) { + ret = PE_SRC_Send_Soft_Reset; + dev_info(pd_data->dev, "got dr_src_give_sink_cap Timer1_overflag.\n"); + break; + } + } + + /* 8) Sink Capabilities message sent */ + return ret; +} + +policy_state usbpd_policy_dr_snk_get_sink_cap(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_DR_SNK_Get_Sink_Cap; + int data_role = 0; + int ms = 0; + + /********************************************** + get sink capabilities request from Device Policy Manager + + Actions on entry: + Send Get_Sink_Cap message + Initialize and run + SenderResponseTimer + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 3) Send Message */ + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_Get_Sink_Cap, data_role, USBPD_SINK); + + /* 4) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 5) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) { + ret = PE_DR_SNK_Get_Sink_Cap; + break; + } + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { + ret = PE_SNK_Send_Soft_Reset; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_SNK_CAP)) { + ret = PE_SNK_Ready; + break; + } + + if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { + ret = PE_SNK_Ready; + break; + } + + /* TimeOver Check */ + if (ms >= tSenderResponse) { + ret = PE_SNK_Ready; + break; + } + } + + /********************************************** + Actions on exit: + Pass sink capabilities/outcome to + Device Policy Manager + + Sink capabilities message received + | SenderResponseTimer Timeout | Reject message received + **********************************************/ + + return ret; +} + +policy_state usbpd_policy_dr_snk_give_source_cap(struct policy_data *policy) +{ + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_DR_SNK_Give_Source_Cap; + int data_role = 0; + int ms = 0; + /********************************************** + Actions on entry: + Request source capabilities from + Device Policy Manager + Send Capabilities message + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + usbpd_protocol_rx(pd_data); + + if (!pd_data->id_matched) + return PE_SNK_Ready; + +#if 0 + /* 2) Message ID Check and Ignored */ + if (pd_data->phy_ops.compare_message_id(pd_data) != 0) { + dev_info(pd_data->dev, "After compare_message_id not Match move to PE_SNK_Ready.\n"); + return PE_SNK_Ready; + } else { + dev_info(pd_data->dev, "After compare_message_id Match move to PE_SNK_Ready.\n"); + } +#endif + + /* 3) Read Data Role */ + pd_data->phy_ops.get_data_role(pd_data, &data_role); + + /* 4) Message Setting */ + policy->tx_msg_header.msg_type = USBPD_Source_Capabilities; + policy->tx_msg_header.port_data_role = data_role; + policy->tx_msg_header.port_power_role = USBPD_SINK; + policy->tx_msg_header.num_data_objs = 1; + + policy->tx_data_obj[0].power_data_obj.max_current = 1500 / 10; + policy->tx_data_obj[0].power_data_obj.voltage = 5000 / 50; + policy->tx_data_obj[0].power_data_obj.peak_current = 0; + policy->tx_data_obj[0].power_data_obj.rsvd = 0; + policy->tx_data_obj[0].power_data_obj.data_role_swap = 1; + policy->tx_data_obj[0].power_data_obj.usb_comm_capable = 1; + policy->tx_data_obj[0].power_data_obj.externally_powered = 0; + policy->tx_data_obj[0].power_data_obj.usb_suspend_support = 1; + policy->tx_data_obj[0].power_data_obj.dual_role_power = 1; + policy->tx_data_obj[0].power_data_obj.supply = 0; + + /* 5) Send Message */ + usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); + + /* 6) Start Timer */ + usbpd_timer1_start(pd_data); + + /* 7) Wait Message or State */ + while (1) { + if (policy->plug_valid == 0) + break; + ms = usbpd_check_time1(pd_data); + if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { + ret = PE_SNK_Ready; + break; + } + + if (ms >= 5) { + ret = PE_SNK_Send_Soft_Reset; + break; + } + } + + return ret; +} +#if 1 //JETSEO +policy_state usbpd_policy_bist_receive_mode(struct policy_data *policy) +{ + + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_BIST_Receive_Mode; + + /********************************************** + Actions on entry: + Tell Protocol Layer to go to BIST + Receive Mode + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /* 2) Interrupt Status All Mask */ + + /********************************************** + Actions on exit: + Goto bist frame received state + or Hard Reset signaling received + **********************************************/ + ret = PE_BIST_Frame_Received; + + return ret; + +} + +policy_state usbpd_policy_bist_frame_received(struct policy_data *policy) +{ + + struct usbpd_data *pd_data = policy_to_usbpd(policy); + int ret = PE_BIST_Frame_Received; + + /********************************************** + Actions on entry: + Consume Frame + **********************************************/ + + /* 1) PD State Inform to AP */ + dev_info(pd_data->dev, "%s\n", __func__); + + /********************************************** + Actions on exit: + Detach + or Hard Reset signaling received + **********************************************/ + + return ret; + +} +#endif policy_state usbpd_error_recovery(struct policy_data *policy) { struct usbpd_data *pd_data = policy_to_usbpd(policy); + /********************************************** + **********************************************/ + dev_err(pd_data->dev, "%s\n", __func__); return Error_Recovery; @@ -2382,6 +4206,7 @@ void usbpd_policy_work(struct work_struct *work) switch (next_state) { case PE_SRC_Startup: next_state = usbpd_policy_src_startup(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SRC_Discovery: next_state = usbpd_policy_src_discovery(policy); @@ -2397,18 +4222,22 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_SRC_Ready: next_state = usbpd_policy_src_ready(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SRC_Disabled: next_state = usbpd_policy_src_disabled(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SRC_Capability_Response: next_state = usbpd_policy_src_capability_response(policy); break; case PE_SRC_Hard_Reset: next_state = usbpd_policy_src_hard_reset(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SRC_Hard_Reset_Received: next_state = usbpd_policy_src_hard_reset_received(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SRC_Transition_to_default: next_state = usbpd_policy_src_transition_to_default(policy); @@ -2427,10 +4256,12 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_SRC_Soft_Reset: next_state = usbpd_policy_src_soft_reset(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SNK_Startup: next_state = usbpd_policy_snk_startup(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SNK_Discovery: next_state = usbpd_policy_snk_discovery(policy); @@ -2449,12 +4280,15 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_SNK_Ready: next_state = usbpd_policy_snk_ready(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SNK_Hard_Reset: next_state = usbpd_policy_snk_hard_reset(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SNK_Transition_to_default: next_state = usbpd_policy_snk_transition_to_default(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_SNK_Give_Sink_Cap: next_state = usbpd_policy_snk_give_sink_cap(policy); @@ -2462,10 +4296,14 @@ void usbpd_policy_work(struct work_struct *work) case PE_SNK_Get_Source_Cap: next_state = usbpd_policy_snk_get_source_cap(policy); break; + case PE_SNK_Send_Soft_Reset: + next_state = usbpd_policy_snk_send_soft_reset(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); + break; case PE_SNK_Soft_Reset: next_state = usbpd_policy_snk_soft_reset(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; - case PE_DRS_Evaluate_Port: next_state = usbpd_policy_drs_evaluate_port(policy); break; @@ -2477,12 +4315,14 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_DRS_DFP_UFP_Accept_DR_Swap: next_state = usbpd_policy_drs_dfp_ufp_accept_dr_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_DRS_DFP_UFP_Change_to_UFP: next_state = usbpd_policy_drs_dfp_ufp_change_to_ufp(policy); break; case PE_DRS_DFP_UFP_Send_DR_Swap: next_state = usbpd_policy_drs_dfp_ufp_send_dr_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_DRS_DFP_UFP_Reject_DR_Swap: next_state = usbpd_policy_drs_dfp_ufp_reject_dr_swap(policy); @@ -2492,12 +4332,14 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_DRS_UFP_DFP_Accept_DR_Swap: next_state = usbpd_policy_drs_ufp_dfp_accept_dr_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_DRS_UFP_DFP_Change_to_DFP: next_state = usbpd_policy_drs_ufp_dfp_change_to_dfp(policy); break; case PE_DRS_UFP_DFP_Send_DR_Swap: next_state = usbpd_policy_drs_ufp_dfp_send_dr_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_DRS_UFP_DFP_Reject_DR_Swap: next_state = usbpd_policy_drs_ufp_dfp_reject_dr_swap(policy); @@ -2511,9 +4353,11 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_PRS_SRC_SNK_Send_Swap: next_state = usbpd_policy_prs_src_snk_send_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_PRS_SRC_SNK_Accept_Swap: next_state = usbpd_policy_prs_src_snk_accept_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_PRS_SRC_SNK_Transition_off: next_state = usbpd_policy_prs_src_snk_transition_to_off(policy); @@ -2532,9 +4376,11 @@ void usbpd_policy_work(struct work_struct *work) break; case PE_PRS_SNK_SRC_Send_Swap: next_state = usbpd_policy_prs_snk_src_send_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_PRS_SNK_SRC_Accept_Swap: next_state = usbpd_policy_prs_snk_src_accept_swap(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; case PE_PRS_SNK_SRC_Transition_off: next_state = usbpd_policy_prs_snk_src_transition_to_off(policy); @@ -2708,8 +4554,29 @@ void usbpd_policy_work(struct work_struct *work) case PE_DFP_UVDM_Receive_Message: next_state = usbpd_policy_dfp_uvdm_receive_message(policy); break; + case PE_DR_SRC_Get_Source_Cap: + next_state = usbpd_policy_dr_src_get_source_cap(policy); + break; + case PE_DR_SRC_Give_Sink_Cap: + next_state = usbpd_policy_dr_src_give_sink_cap(policy); + break; + case PE_DR_SNK_Get_Sink_Cap: + next_state = usbpd_policy_dr_snk_get_sink_cap(policy); + break; + case PE_DR_SNK_Give_Source_Cap: + next_state = usbpd_policy_dr_snk_give_source_cap(policy); + break; +#if 1 //JETSEO + case PE_BIST_Receive_Mode: + next_state = usbpd_policy_bist_receive_mode(policy); + break; + case PE_BIST_Frame_Received: + next_state = usbpd_policy_bist_frame_received(policy); + break; +#endif case Error_Recovery: next_state = usbpd_error_recovery(policy); + store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); break; default: @@ -2745,6 +4612,7 @@ void usbpd_policy_work(struct work_struct *work) next_state = PE_SRC_Startup; } } + break; } dev_info(pd_data->dev, "%s saved state %x next_state %x \n", __func__, saved_state, next_state); @@ -2768,6 +4636,8 @@ void usbpd_init_policy(struct usbpd_data *pd_data) policy->modal_operation = 0; policy->sink_cap_received = 0; policy->send_sink_cap = 0; + policy->txhardresetflag = 0; + policy->pd_support = 0; for (i = 0; i < USBPD_MAX_COUNT_MSG_OBJECT; i++) { policy->rx_data_obj[i].object = 0; policy->tx_data_obj[i].object = 0; @@ -2778,6 +4648,16 @@ void usbpd_kick_policy_work(struct device *dev) { struct usbpd_data *pd_data = dev_get_drvdata(dev); - schedule_work(&pd_data->worker); + if (pd_data->policy_wqueue) + queue_work(pd_data->policy_wqueue, &pd_data->worker); + else + schedule_work(&pd_data->worker); } +void usbpd_cancel_policy_work(struct device *dev) +{ + struct usbpd_data *pd_data = dev_get_drvdata(dev); + + if (pd_data->policy_wqueue) + flush_workqueue(pd_data->policy_wqueue); +} diff --git a/drivers/ifconn/ifconn_notifier.c b/drivers/ifconn/ifconn_notifier.c index 3fdebd562555..6203c50be444 100644 --- a/drivers/ifconn/ifconn_notifier.c +++ b/drivers/ifconn/ifconn_notifier.c @@ -149,24 +149,24 @@ int ifconn_notifier_notify(ifconn_notifier_t src, memcpy(&(pnoti[src].ifconn_template[listener]), template, sizeof(struct ifconn_notifier_template)); } - return -1; + ret = NOTIFY_BAD; + } else { + nb = pnoti[src].nb[listener]; + ret = nb->notifier_call(nb, (unsigned long)noti_id, template); } - - nb = pnoti[src].nb[listener]; - ret = nb->notifier_call(nb, (unsigned long)noti_id, template); } switch (ret) { case NOTIFY_STOP_MASK: case NOTIFY_BAD: - pr_err("%s: notify error occur(0x%x)\n", __func__, ret); + pr_err("%s: src(%d) notify error occur(0x%x)\n", __func__, src, ret); break; case NOTIFY_DONE: case NOTIFY_OK: - pr_info("%s: notify done(0x%x)\n", __func__, ret); + pr_info("%s: src(%d) notify done(0x%x)\n", __func__, src, ret); break; default: - pr_info("%s: notify status unknown(0x%x)\n", __func__, ret); + pr_info("%s: src(%d) notify status unknown(0x%x)\n", __func__, src, ret); break; } diff --git a/drivers/mfd/s2mu106_core.c b/drivers/mfd/s2mu106_core.c index ace20bdf421d..dcbc7e2c4617 100644 --- a/drivers/mfd/s2mu106_core.c +++ b/drivers/mfd/s2mu106_core.c @@ -28,10 +28,6 @@ #include #include -#if defined(CONFIG_CHARGER_S2MU106) -#define CONFIG_PM_S2MU106 -#endif - static struct mfd_cell s2mu106_devs[] = { #if defined(CONFIG_CHARGER_S2MU106) { .name = "s2mu106-charger", }, diff --git a/drivers/mfd/s2mu106_irq.c b/drivers/mfd/s2mu106_irq.c index f861f2899fdb..2738159c8a7c 100644 --- a/drivers/mfd/s2mu106_irq.c +++ b/drivers/mfd/s2mu106_irq.c @@ -32,6 +32,9 @@ #if defined(CONFIG_MUIC_S2MU106) #include #endif +#if defined(CONFIG_PM_S2MU106) +#include +#endif /* TODO : add IP Header file include*/ static const u8 s2mu106_mask_reg[] = { @@ -78,7 +81,7 @@ static struct i2c_client *get_i2c(struct s2mu106_dev *s2mu106, return s2mu106->muic; #endif #if defined(CONFIG_PM_S2MU106) - case PM_VAL_UP1 ... PM_INT2: + case PM_VALUP1 ... PM_INT2: return s2mu106->muic; #endif #if defined(CONFIG_MST_S2MU106) @@ -334,6 +337,12 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data) #endif #if defined(CONFIG_PM_S2MU106) if (irq_src & S2MU106_IRQSRC_PM) { + s2mu106_read_reg(s2mu106->muic, S2MU106_PM_VALUP1, &irq_reg[PM_VALUP1]); + s2mu106_read_reg(s2mu106->muic, S2MU106_PM_VALUP2, &irq_reg[PM_VALUP2]); + s2mu106_read_reg(s2mu106->muic, S2MU106_PM_INT1, &irq_reg[PM_INT1]); + s2mu106_read_reg(s2mu106->muic, S2MU106_PM_INT2, &irq_reg[PM_INT2]); + pr_info("%s: powermeter interrupt(0x%02x, 0x%02x, 0x%02x, 0x%02x)\n", __func__, + irq_reg[PM_VALUP1], irq_reg[PM_VALUP2], irq_reg[PM_INT1], irq_reg[PM_INT2]); } #endif #if defined(CONFIG_MST_S2MU106) diff --git a/drivers/muic/muic_manager.c b/drivers/muic/muic_manager.c index 1c4d60537137..bace72169161 100644 --- a/drivers/muic/muic_manager.c +++ b/drivers/muic/muic_manager.c @@ -711,6 +711,40 @@ static int muic_manager_handle_ccic_TA(struct muic_interface_t *muic_if, void *d #endif #endif +static int muic_manager_handle_ccic_role_swap(struct muic_interface_t *muic_if, void *data) +{ +#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); + } + + return 0; +} + static int muic_manager_handle_otg(struct muic_interface_t *muic_if, void *data) { int ret = MUIC_NORMAL_OTG; @@ -767,6 +801,7 @@ static int muic_manager_handle_notification(struct notifier_block *nb, int water = IFCONN_NOTIFY_ID_WATER; int otg = IFCONN_NOTIFY_ID_OTG; int ta = IFCONN_NOTIFY_ID_TA; + int role_swap = IFCONN_NOTIFY_ID_ROLE_SWAP; #else CC_NOTI_TYPEDEF *pnoti = (CC_NOTI_TYPEDEF *) data; int attach = CCIC_NOTIFY_ID_ATTACH; @@ -814,6 +849,9 @@ static int muic_manager_handle_notification(struct notifier_block *nb, muic_manager_handle_ccic_TA(muic_if, data); #endif #endif + } else if (pnoti->id == role_swap) { + pr_info("%s: NOTIFY_ID_ROLE_SWAP\n", __func__); + muic_manager_handle_ccic_role_swap(muic_if, data); } else { pr_info("%s: Undefined Noti. ID\n", __func__); } diff --git a/drivers/muic/s2mu106-muic-afc.c b/drivers/muic/s2mu106-muic-afc.c index 637f0d530c16..e694fabc0cb6 100644 --- a/drivers/muic/s2mu106-muic-afc.c +++ b/drivers/muic/s2mu106-muic-afc.c @@ -49,7 +49,7 @@ /* powermeter */ #if defined(CONFIG_PM_S2MU106) -#include "../battery_v2/include/s2mu106_pmeter.h" +#include #endif static struct s2mu106_muic_data *static_data; diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index c6fdbc12845c..5dbfed13b48c 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -657,6 +657,14 @@ config CHARGER_S2MU106 S2MU106 incluse pmic, led driver. You have to define MFD_S2MU106 +config PM_S2MU106 + tristate "S2MU106 power meter support" + depends on (MFD_S2MU106) && I2C + help + Say Y here to enable support for the S2MU106 power meter. + S2MU106 power meter is dependent on MFD_S2MU106 + so it needs to be defined. + config SMALL_CHARGER tristate "Small charger support" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index de4e49b81101..c12a30b7d737 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -85,7 +85,8 @@ obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o obj-$(CONFIG_FUELGAUGE_S2MU004) += s2mu004_fuelgauge.o obj-$(CONFIG_CHARGER_S2MU004) += s2mu004_charger.o obj-$(CONFIG_FUELGAUGE_S2MU106) += s2mu106_fuelgauge.o -obj-$(CONFIG_CHARGER_S2MU106) += s2mu106_charger.o s2mu106_pmeter.o +obj-$(CONFIG_CHARGER_S2MU106) += s2mu106_charger.o obj-$(CONFIG_BATTERY_S2MU00X) += s2mu00x_battery.o obj-$(CONFIG_BATTERY_S2MU00X_ERD) += s2mu00x_erd_battery.o obj-$(CONFIG_CHARGER_S2MCS02) += s2mcs02_charger.o +obj-$(CONFIG_PM_S2MU106) += s2mu106_pmeter.o diff --git a/drivers/power/supply/s2mu00x_battery.c b/drivers/power/supply/s2mu00x_battery.c index 8ecc694106a0..7ea664107294 100644 --- a/drivers/power/supply/s2mu00x_battery.c +++ b/drivers/power/supply/s2mu00x_battery.c @@ -143,6 +143,7 @@ struct s2mu00x_battery_info { struct power_supply_desc psy_ac_desc; struct mutex iolock; + struct mutex ifconn_lock; struct wake_lock monitor_wake_lock; struct workqueue_struct *monitor_wqueue; @@ -159,12 +160,16 @@ struct s2mu00x_battery_info { int max_charging_current; #if defined(CONFIG_USE_CCIC) + struct delayed_work select_pdo_work; int pdo_max_input_vol; int pdo_max_chg_power; int pdo_sel_num; int pdo_sel_vol; int pdo_sel_cur; + + int pd_input_current; + bool pd_attach; #endif int topoff_current; @@ -205,6 +210,7 @@ struct s2mu00x_battery_info { #if defined(CONFIG_SMALL_CHARGER) int small_input; /* input current limit (mA) */ int small_chg; /* charge current limit (mA) */ + int small_input_flag; #endif #if defined(CONFIG_MUIC_NOTIFIER) @@ -255,22 +261,37 @@ static int set_charging_current(struct s2mu00x_battery_info *battery) topoff_current = battery->pdata->charging_current[battery->cable_type].full_check_current; struct power_supply *psy; - int ret; + int ret = 0; pr_info("%s: cable_type(%d), current(%d, %d, %d)\n", __func__, battery->cable_type, input_current, charging_current, topoff_current); mutex_lock(&battery->iolock); /*Limit input & charging current according to the max current*/ - get_charging_current(battery, &input_current, &charging_current);\ + if (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA || + battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) { + pr_info("%s, %d, %d\n", __func__, input_current, battery->pd_input_current); + input_current = battery->pd_input_current; + + if (input_current >= 1500) + input_current = input_current - 50; + + if (input_current > 2000) { + battery->small_input_flag = input_current - 2000; + input_current = 2000; + } + } else + get_charging_current(battery, &input_current, &charging_current); /* set input current limit */ if (battery->input_current != input_current) { value.intval = input_current; psy = power_supply_get_by_name(battery->pdata->charger_name); - if (!psy) - return -EINVAL; + if (!psy) { + ret = -EINVAL; + goto out; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); @@ -282,8 +303,10 @@ static int set_charging_current(struct s2mu00x_battery_info *battery) value.intval = charging_current; psy = power_supply_get_by_name(battery->pdata->charger_name); - if (!psy) - return -EINVAL; + if (!psy) { + ret = -EINVAL; + goto out; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); @@ -295,8 +318,10 @@ static int set_charging_current(struct s2mu00x_battery_info *battery) value.intval = topoff_current; psy = power_supply_get_by_name(battery->pdata->charger_name); - if (!psy) - return -EINVAL; + if (!psy) { + ret = -EINVAL; + goto out; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_FULL, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); @@ -306,25 +331,36 @@ static int set_charging_current(struct s2mu00x_battery_info *battery) #if defined(CONFIG_SMALL_CHARGER) if (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA || battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) { - value.intval = battery->pdata->small_input_current; + + if (battery->small_input_flag == 0) { + ret = 0; + goto out; + } + + value.intval = battery->small_input_flag; psy = power_supply_get_by_name(battery->pdata->smallcharger_name); - if (!psy) - return -EINVAL; + if (!psy) { + ret = -EINVAL; + goto out; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); value.intval = battery->pdata->small_charging_current; psy = power_supply_get_by_name(battery->pdata->smallcharger_name); - if (!psy) - return -EINVAL; + if (!psy) { + ret = -EINVAL; + goto out; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); } #endif +out: mutex_unlock(&battery->iolock); - return 0; + return ret; } @@ -365,6 +401,10 @@ static int set_charger_mode( if (charger_mode == S2MU00X_BAT_CHG_MODE_CHARGING && (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA || battery->cable_type == POWER_SUPPLY_TYPE_USB_PD)) { + + if (battery->small_input_flag == 0) + return 0; + psy = power_supply_get_by_name(battery->pdata->smallcharger_name); if (!psy) return -EINVAL; @@ -372,6 +412,7 @@ static int set_charger_mode( if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); } else if (charger_mode != S2MU00X_BAT_CHG_MODE_CHARGING) { + battery->small_input_flag = 0; psy = power_supply_get_by_name(battery->pdata->smallcharger_name); if (!psy) return -EINVAL; @@ -464,6 +505,7 @@ static int set_battery_status(struct s2mu00x_battery_info *battery, battery->input_current = 0; battery->charging_current = 0; battery->topoff_current = 0; + battery->small_input_flag = 0; break; case POWER_SUPPLY_STATUS_FULL: @@ -910,19 +952,16 @@ static int s2mu00x_battery_handle_notification(struct notifier_block *nb, return 0; } #endif + #if defined(CONFIG_IFCONN_NOTIFIER) #if defined(CONFIG_USE_CCIC) -static int s2mu00x_bat_set_pdo(struct s2mu00x_battery_info *battery, - ifconn_pd_sink_status_t *pdo_data) +static void usbpd_select_pdo_work(struct work_struct *work) { - int ret = -1; - int pdo_num = battery->pdo_sel_num; + struct s2mu00x_battery_info *battery = + container_of(work, struct s2mu00x_battery_info, select_pdo_work.work); - if (pdo_num > pdo_data->available_pdo_num + 1 || pdo_num < 1) { - dev_info(battery->dev, "%s: wrong pdo number. Stop pdo select.\n", - __func__); - return ret; - } + int pdo_num = battery->pdo_sel_num; + int ret = -1; ret = ifconn_notifier_notify(IFCONN_NOTIFY_BATTERY, IFCONN_NOTIFY_MANAGER, @@ -930,13 +969,26 @@ static int s2mu00x_bat_set_pdo(struct s2mu00x_battery_info *battery, pdo_num, IFCONN_NOTIFY_PARAM_DATA, NULL); - if (ret < 0) { + if (ret < 0) pr_err("%s: Fail to send noti\n", __func__); + +} + +static int s2mu00x_bat_set_pdo(struct s2mu00x_battery_info *battery, + ifconn_pd_sink_status_t *pdo_data) +{ + int ret = -1; + int pdo_num = battery->pdo_sel_num; + + if (pdo_num > pdo_data->available_pdo_num + 1 || pdo_num < 1) { + dev_info(battery->dev, "%s: wrong pdo number. Stop pdo select.\n", + __func__); return ret; } ret = POWER_SUPPLY_TYPE_PREPARE_TA; + schedule_delayed_work(&battery->select_pdo_work, msecs_to_jiffies(50)); return ret; } @@ -969,7 +1021,7 @@ static int s2mu00x_bat_pdo_check(struct s2mu00x_battery_info *battery, goto end_pdo_check; } - for (i = 1; i <= pdo_data->available_pdo_num + 1; i++) { + for (i = 1; i <= pdo_data->available_pdo_num; i++) { dev_info(battery->dev, "%s: pdo_num:%d, max_voltage:%d, max_current:%d\n", __func__, i, pdo_data->power_list[i].max_voltage, pdo_data->power_list[i].max_current); @@ -990,6 +1042,8 @@ static int s2mu00x_bat_pdo_check(struct s2mu00x_battery_info *battery, } } + battery->pd_input_current = pd_input_current_limit; + if (battery->pdo_sel_num == 0) { dev_info(battery->dev, "%s: There is no proper pdo. Do normal TA setting\n", __func__); current_cable = POWER_SUPPLY_TYPE_MAINS; @@ -1013,24 +1067,39 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb, struct power_supply *psy; int ret; - dev_info(battery->dev, "%s: action (%ld) dump(0x%01x, 0x%01x, 0x%02x, 0x%04x, 0x%04x, 0x%04x, 0x%04x)\n", + dev_info(battery->dev, "%s: action(%ld) dump(0x%01x, 0x%01x, 0x%02x, 0x%04x, 0x%04x, 0x%04x, 0x%04x)\n", __func__, action, ifconn_info->src, ifconn_info->dest, ifconn_info->id, ifconn_info->attach, ifconn_info->rprd, ifconn_info->cable_type, ifconn_info->event); - ifconn_info->cable_type = (muic_attached_dev_t)ifconn_info->event; + ifconn_info->cable_type = (muic_attached_dev_t)ifconn_info->event; +#if defined(CONFIG_USE_CCIC) + dev_info(battery->dev, "%s: pd_attach(%d)\n", __func__, battery->pd_attach); +#endif action = ifconn_info->id; + mutex_lock(&battery->ifconn_lock); - if (attached_dev == ATTACHED_DEV_MHL_MUIC) + if (attached_dev == ATTACHED_DEV_MHL_MUIC) { + mutex_unlock(&battery->ifconn_lock); return 0; + } switch (action) { case IFCONN_NOTIFY_ID_DETACH: +#if defined(CONFIG_USE_CCIC) + if ((ifconn_info->src == IFCONN_NOTIFY_MANAGER) && battery->pd_attach) { + pr_info("%s, Skip cable check when PD TA attaching\n", __func__); + mutex_unlock(&battery->ifconn_lock); + return 0; + } + + battery->pd_attach = false; +#endif cmd = "DETACH"; cable_type = POWER_SUPPLY_TYPE_BATTERY; break; case IFCONN_NOTIFY_ID_ATTACH: #if defined(CONFIG_USE_CCIC) - if (battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) { + if ((ifconn_info->src == IFCONN_NOTIFY_MANAGER) && battery->pd_attach) { pr_info("%s: PD TA is attached. Skip cable check\n", __func__); cable_type = POWER_SUPPLY_TYPE_USB_PD; cmd = "PD ATTACH"; @@ -1043,6 +1112,7 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb, #if defined(CONFIG_USE_CCIC) case IFCONN_NOTIFY_ID_POWER_STATUS: cable_type = s2mu00x_bat_pdo_check(battery, ifconn_info); + battery->pd_attach = true; switch (cable_type) { case POWER_SUPPLY_TYPE_USB_PD: cmd = "PD ATTACH"; @@ -1083,8 +1153,10 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb, value.intval = true; psy = power_supply_get_by_name(battery->pdata->charger_name); - if (!psy) + if (!psy) { + mutex_unlock(&battery->ifconn_lock); return -EINVAL; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); @@ -1094,8 +1166,10 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb, value.intval = false; psy = power_supply_get_by_name(battery->pdata->charger_name); - if (!psy) + if (!psy) { + mutex_unlock(&battery->ifconn_lock); return -EINVAL; + } ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, &value); if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); @@ -1116,6 +1190,7 @@ end_ifconn_handle: alarm_cancel(&battery->monitor_alarm); wake_lock(&battery->monitor_wake_lock); queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 0); + mutex_unlock(&battery->ifconn_lock); return 0; } #endif @@ -1238,10 +1313,14 @@ static int get_battery_info(struct s2mu00x_battery_info *battery) pr_err("%s: battery status = %d, charger status = %d\n", __func__, battery->status, value.intval); #endif + psy = power_supply_get_by_name("s2mu106_pmeter"); + ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VCHGIN, &value); /* Get input voltage & current from powermeter */ - battery->vchg_voltage = s2mu106_powermeter_get_vchg_voltage(); - battery->vchg_current = s2mu106_powermeter_get_vchg_current(); + battery->vchg_voltage = value.intval; + + ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ICHGIN, &value); + battery->vchg_current = value.intval; dev_info(battery->dev, "%s:Vnow(%dmV),Inow(%dmA),Imax(%dmA),Ichg(%dmA),SOC(%d%%),Tbat(%d),SOH(%d%%)" @@ -1778,6 +1857,7 @@ static int s2mu00x_battery_probe(struct platform_device *pdev) battery->dev = &pdev->dev; mutex_init(&battery->iolock); + mutex_init(&battery->ifconn_lock); wake_lock_init(&battery->monitor_wake_lock, WAKE_LOCK_SUSPEND, "sec-battery-monitor"); @@ -1791,12 +1871,15 @@ static int s2mu00x_battery_probe(struct platform_device *pdev) battery->input_current = 0; battery->charging_current = 0; battery->topoff_current = 0; + battery->small_input_flag = 0; battery->max_input_current = battery->pdata->max_input_current; battery->max_charging_current = battery->pdata->max_charging_current; #if defined(CONFIG_USE_CCIC) battery->pdo_max_input_vol = battery->pdata->pdo_max_input_vol; battery->pdo_max_chg_power = battery->pdata->pdo_max_chg_power; + battery->pd_input_current = 2000; + battery->pd_attach = false; #endif battery->temp_high = battery->pdata->temp_high; battery->temp_high_recovery = battery->pdata->temp_high_recovery; @@ -1809,6 +1892,8 @@ static int s2mu00x_battery_probe(struct platform_device *pdev) battery->is_recharging = false; battery->cable_type = POWER_SUPPLY_TYPE_BATTERY; + battery->pd_attach = false; + #if defined(CONFIG_CHARGER_S2MU106) psy = power_supply_get_by_name(battery->pdata->charger_name); if (!psy) @@ -1859,6 +1944,9 @@ static int s2mu00x_battery_probe(struct platform_device *pdev) alarm_init(&battery->monitor_alarm, ALARM_BOOTTIME, bat_monitor_alarm); battery->monitor_alarm_interval = DEFAULT_ALARM_INTERVAL; +#if defined(CONFIG_USE_CCIC) + INIT_DELAYED_WORK(&battery->select_pdo_work, usbpd_select_pdo_work); +#endif /* Register power supply to framework */ psy_cfg.drv_data = battery; psy_cfg.supplied_to = s2mu00x_supplied_to; @@ -1915,6 +2003,10 @@ static int s2mu00x_battery_probe(struct platform_device *pdev) s2mu00x_ifconn_handle_notification, IFCONN_NOTIFY_BATTERY, IFCONN_NOTIFY_MANAGER); + ifconn_notifier_register(&battery->ifconn_nb, + s2mu00x_ifconn_handle_notification, + IFCONN_NOTIFY_BATTERY, + IFCONN_NOTIFY_CCIC); #elif defined(CONFIG_MUIC_NOTIFIER) pr_info("%s: Register MUIC notifier\n", __func__); muic_notifier_register(&battery->batt_nb, s2mu00x_battery_handle_notification, @@ -1950,6 +2042,7 @@ err_irr: wake_lock_destroy(&battery->monitor_wake_lock); wake_lock_destroy(&battery->vbus_wake_lock); mutex_destroy(&battery->iolock); + mutex_destroy(&battery->ifconn_lock); err_parse_dt_nomem: kfree(battery->pdata); err_bat_free: diff --git a/drivers/power/supply/s2mu106_charger.c b/drivers/power/supply/s2mu106_charger.c index 175eedcee6e2..79799e4063e6 100755 --- a/drivers/power/supply/s2mu106_charger.c +++ b/drivers/power/supply/s2mu106_charger.c @@ -68,7 +68,7 @@ static void s2mu106_test_read(struct i2c_client *i2c) static int s2mu106_charger_otg_control( struct s2mu106_charger_data *charger, bool enable) { - u8 chg_sts2, chg_ctrl0, temp; + u8 chg_sts2, chg_ctrl0; pr_info("%s: called charger otg control : %s\n", __func__, enable ? "ON" : "OFF"); @@ -87,14 +87,12 @@ static int s2mu106_charger_otg_control( if (!enable) { s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL0, CHG_MODE, REG_MODE_MASK); - s2mu106_update_reg(charger->i2c, 0xAE, 0x80, 0xF0); } else { s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL3, S2MU106_SET_OTG_OCP_1500mA << SET_OTG_OCP_SHIFT, SET_OTG_OCP_MASK); - msleep(30); - s2mu106_update_reg(charger->i2c, 0xAE, 0x00, 0xF0); +// msleep(30); s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL0, OTG_BST_MODE, REG_MODE_MASK); charger->cable_type = POWER_SUPPLY_TYPE_OTG; @@ -104,10 +102,8 @@ static int s2mu106_charger_otg_control( s2mu106_read_reg(charger->i2c, S2MU106_CHG_STATUS2, &chg_sts2); s2mu106_read_reg(charger->i2c, S2MU106_CHG_CTRL0, &chg_ctrl0); - s2mu106_read_reg(charger->i2c, 0xAE, &temp); pr_info("%s S2MU106_CHG_STATUS2: 0x%x\n", __func__, chg_sts2); pr_info("%s S2MU106_CHG_CTRL0: 0x%x\n", __func__, chg_ctrl0); - pr_info("%s 0xAE: 0x%x\n", __func__, temp); power_supply_changed(charger->psy_otg); return enable; @@ -119,6 +115,7 @@ static void s2mu106_enable_charger_switch( if (charger->otg_on) { pr_info("[DEBUG] %s: skipped set(%d) : OTG is on\n", __func__, onoff); + charger->is_charging = false; return; } @@ -624,6 +621,12 @@ static int s2mu106_chg_set_property(struct power_supply *psy, charger->is_charging = true; break; } + + if (buck_state) + s2mu106_enable_charger_switch(charger, charger->is_charging); + else + s2mu106_set_buck(charger, buck_state); + value.intval = charger->is_charging; psy = power_supply_get_by_name(charger->pdata->fuelgauge_name); @@ -633,10 +636,6 @@ static int s2mu106_chg_set_property(struct power_supply *psy, if (ret < 0) pr_err("%s: Fail to execute property\n", __func__); - if (buck_state) - s2mu106_enable_charger_switch(charger, charger->is_charging); - else - s2mu106_set_buck(charger, buck_state); } else { pr_info("[DEBUG]%s: SKIP CHARGING CONTROL while OTG(%d)\n", __func__, value.intval); diff --git a/drivers/power/supply/s2mu106_pmeter.c b/drivers/power/supply/s2mu106_pmeter.c index 8fd6ccb163e7..7701e3416249 100755 --- a/drivers/power/supply/s2mu106_pmeter.c +++ b/drivers/power/supply/s2mu106_pmeter.c @@ -20,70 +20,377 @@ #include #include #include +#include +#include +#define EN_IRQ 0 +#define VOLTAGE_9V 8000 +#define VOLTAGE_5V 6000 -struct s2mu106_pmeter_data *g_pmeter; -int s2mu106_powermeter_get_vchg_voltage(void) +static enum power_supply_property s2mu106_pmeter_props[] = { +}; + +static const unsigned char enable_bit_data[PM_TYPE_MAX] = +{0x80, 0x40, 0x20, 0x01, 0x08, 0x04, 0x02, 0x80, +0x40, 0x01, 0x10, 0x80}; + +static int s2mu106_pm_enable(struct s2mu106_pmeter_data *pmeter, + int mode, enum pm_type type) { - struct s2mu106_pmeter_data *pmeter; - u8 ret; - u8 v_12 = 0, v_13 = 0; - int chg_voltage = 0; + u8 addr1 = S2MU106_PM_REQ_BOX_CO1; + u8 addr2 = S2MU106_PM_REQ_BOX_CO2; + u8 data1, data2; + + /* Default PM mode = continuous */ + if (mode == REQUEST_RESPONSE_MODE) { + pr_info ("%s PM mode : Request Response mode (RR)\n", __func__); + addr1 = S2MU106_PM_REQ_BOX_RR1; + addr2 = S2MU106_PM_REQ_BOX_RR2; + } + + s2mu106_read_reg(pmeter->i2c, addr1, &data1); + s2mu106_read_reg(pmeter->i2c, addr2, &data2); + + switch (type) { + case PM_TYPE_VCHGIN ... PM_TYPE_VGPADC: + case PM_TYPE_VCC2: + data1 |= enable_bit_data[type]; + break; + case PM_TYPE_ICHGIN: + case PM_TYPE_IWCIN: + case PM_TYPE_IOTG: + case PM_TYPE_ITX: + data2 |= enable_bit_data[type]; + break; + default: + return -EINVAL; + } + + s2mu106_write_reg(pmeter->i2c, addr1, data1); + s2mu106_write_reg(pmeter->i2c, addr2, data2); + + pr_info ("%s data1 : 0x%2x, data2 0x%2x\n", __func__, data1, data2); + return 0; +} - pmeter = g_pmeter; +static int s2mu106_pm_get_vchgin(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VCHGIN, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VCHGIN, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 5; + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} - s2mu106_read_reg(pmeter->i2c, 0x12, &v_12); - s2mu106_read_reg(pmeter->i2c, 0x13, &v_13); +static int s2mu106_pm_get_vwcin(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VWCIN, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VWCIN, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 5; + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} - pr_info("%s: S2MU106_POWERMETER 0x57: 0x%x 0x12:0x%x 0x13:0x%x\n", __func__, ret, v_12, v_13); - chg_voltage = ((v_12 << 4) + (v_13 >> 4)) * 5; //mV +static int s2mu106_pm_get_vbyp(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VBYP, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VBYP, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 5; + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} + +static int s2mu106_pm_get_vsysa(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VSYS, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VSYS, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; - pr_info("%s: S2MU106_POWERMETER chg_voltage: %d mV\n", __func__, chg_voltage); - return chg_voltage; + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 25; + charge_voltage = charge_voltage / 10; + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; } -int s2mu106_powermeter_get_vchg_current(void) +static int s2mu106_pm_get_vbata(struct s2mu106_pmeter_data *pmeter) { - struct s2mu106_pmeter_data *pmeter; - u8 v_20 = 0, v_21 = 0; - int chg_current = 0; + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VBAT, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VBAT, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 25; + charge_voltage = charge_voltage / 10; + + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} + +static int s2mu106_pm_get_vgpadc(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VGPADC, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VGPADC, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 25; + charge_voltage = charge_voltage / 10; + + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} + +static int s2mu106_pm_get_vcc1(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VCC1, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VCC1, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; - pmeter = g_pmeter; + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 625; + charge_voltage = charge_voltage / 1000; - s2mu106_read_reg(pmeter->i2c, 0x20, &v_20); - s2mu106_read_reg(pmeter->i2c, 0x21, &v_21); + pr_info ("%s2, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} + +static int s2mu106_pm_get_vcc2(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_voltage = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_VCC2, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_VCC2, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_voltage = ((data1 << 4) | (data2 >> 4)) * 625; + charge_voltage = charge_voltage / 1000; + + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, voltage = %d\n", + __func__, data1, data2, charge_voltage); + return charge_voltage; +} + +static int s2mu106_pm_get_ichgin(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_current = 0; - chg_current = ((v_20 << 4) + (v_21 >> 4)); //mA + 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; - pr_info("%s: S2MU106_POWERMETER chg_current: %d mA\n", __func__, chg_current); - return chg_current; + charge_current = (int)((data1 << 4) | (data2 >> 4)); + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, current = %d\n", + __func__, data1, data2, charge_current); + return charge_current; } +static int s2mu106_pm_get_iwcin(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_current = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_IWCIN, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_IWCIN, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_current = (int)((data1 << 4) | (data2 >> 4)); + + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, current = %d\n", + __func__, data1, data2, charge_current); + return charge_current; +} + +static int s2mu106_pm_get_iotg(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_current = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_IOTG, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_IOTG, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_current = (int)((data1 << 4) | (data2 >> 4)); + + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, current = %d\n", + __func__, data1, data2, charge_current); + return charge_current; +} + +static int s2mu106_pm_get_itx(struct s2mu106_pmeter_data *pmeter) +{ + u8 data1, data2; + int charge_current = 0; + + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL1_ITX, &data1); + s2mu106_read_reg(pmeter->i2c, S2MU106_PM_VAL2_ITX, &data2); + + if (data1 < 0 || data2 < 0) + return -EINVAL; + + charge_current = (int)((data1 << 4) | (data2 >> 4)); + + pr_info ("%s, data1 : 0x%2x, data2 : 0x%2x, current = %d\n", + __func__, data1, data2, charge_current); + return charge_current; +} + +static int s2mu106_pm_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct s2mu106_pmeter_data *pmeter = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_VCHGIN: + val->intval = s2mu106_pm_get_vchgin(pmeter); + break; + case POWER_SUPPLY_PROP_VWCIN: + val->intval = s2mu106_pm_get_vwcin(pmeter); + break; + case POWER_SUPPLY_PROP_VBYP: + val->intval = s2mu106_pm_get_vbyp(pmeter); + break; + case POWER_SUPPLY_PROP_VSYS: + val->intval = s2mu106_pm_get_vsysa(pmeter); + break; + case POWER_SUPPLY_PROP_VBAT: + val->intval = s2mu106_pm_get_vbata(pmeter); + break; + case POWER_SUPPLY_PROP_VGPADC: + val->intval = s2mu106_pm_get_vgpadc(pmeter); + break; + case POWER_SUPPLY_PROP_VCC1: + val->intval = s2mu106_pm_get_vcc1(pmeter); + break; + case POWER_SUPPLY_PROP_VCC2: + val->intval = s2mu106_pm_get_vcc2(pmeter); + break; + case POWER_SUPPLY_PROP_ICHGIN: + val->intval = s2mu106_pm_get_ichgin(pmeter); + break; + case POWER_SUPPLY_PROP_IWCIN: + val->intval = s2mu106_pm_get_iwcin(pmeter); + break; + case POWER_SUPPLY_PROP_IOTG: + val->intval = s2mu106_pm_get_iotg(pmeter); + break; + case POWER_SUPPLY_PROP_ITX: + val->intval = s2mu106_pm_get_itx(pmeter); + break; + default: + return -EINVAL; + } + return 0; +} + +static int s2mu106_pm_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct s2mu106_pmeter_data *pmeter = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_CO_ENABLE: + s2mu106_pm_enable(pmeter, CONTINUOUS_MODE, val->intval); + break; + case POWER_SUPPLY_PROP_RR_ENABLE: + s2mu106_pm_enable(pmeter, REQUEST_RESPONSE_MODE, val->intval); + break; + default: + return -EINVAL; + } + return 0; +} +#if EN_IRQ +static irqreturn_t s2mu106_vchgin_isr(int irq, void *data) +{ + struct s2mu106_pmeter_data *pmeter = data; + int voltage; + + voltage = s2mu106_pm_get_vchgin(pmeter); + pr_info("%s voltage : %d", __func__, voltage); + + return IRQ_HANDLED; +} +#endif static const struct of_device_id s2mu106_pmeter_match_table[] = { { .compatible = "samsung,s2mu106-pmeter",}, {}, }; -static int s2mu106_pm_enable(struct s2mu106_pmeter_data *pmeter) +static void s2mu106_powermeter_initial(struct s2mu106_pmeter_data *pmeter) { - u8 data1; - - s2mu106_read_reg(pmeter->i2c, 0x5F, &data1); - data1 |= 0x80; - s2mu106_write_reg(pmeter->i2c, 0x5F, data1); - return 0; + s2mu106_pm_enable(pmeter, CONTINUOUS_MODE, PM_TYPE_VCHGIN); + s2mu106_pm_enable(pmeter, CONTINUOUS_MODE, PM_TYPE_VCC1); + s2mu106_pm_enable(pmeter, CONTINUOUS_MODE, PM_TYPE_VCC2); } static int s2mu106_pmeter_probe(struct platform_device *pdev) { struct s2mu106_dev *s2mu106 = dev_get_drvdata(pdev->dev.parent); struct s2mu106_pmeter_data *pmeter; + struct power_supply_config psy_cfg = {}; int ret = 0; pr_info("%s:[BATT] S2MU106 Power meter driver probe\n", __func__); - pmeter = kzalloc(sizeof(*pmeter), GFP_KERNEL); + pmeter = kzalloc(sizeof(struct s2mu106_pmeter_data), GFP_KERNEL); if (!pmeter) return -ENOMEM; @@ -92,10 +399,40 @@ static int s2mu106_pmeter_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmeter); - g_pmeter = pmeter; + pmeter->psy_pm_desc.name = "s2mu106_pmeter"; //pmeter->pdata->powermeter_name; + pmeter->psy_pm_desc.type = POWER_SUPPLY_TYPE_UNKNOWN; + pmeter->psy_pm_desc.get_property = s2mu106_pm_get_property; + pmeter->psy_pm_desc.set_property = s2mu106_pm_set_property; + pmeter->psy_pm_desc.properties = s2mu106_pmeter_props; + pmeter->psy_pm_desc.num_properties = ARRAY_SIZE(s2mu106_pmeter_props); + + psy_cfg.drv_data = pmeter; + + pmeter->psy_pm = power_supply_register(&pdev->dev, &pmeter->psy_pm_desc, &psy_cfg); + if (IS_ERR(pmeter->psy_pm)) { + pr_err("%s: Failed to Register psy_chg\n", __func__); + ret = PTR_ERR(pmeter->psy_pm); + goto err_power_supply_register; + } + +#if EN_IRQ + pmeter->irq_vchgin = s2mu106->pdata->irq_base + S2MU106_PM_IRQ1_VCHGINUP; + ret = request_threaded_irq(pmeter->irq_vchgin, NULL, + s2mu106_vchgin_isr, 0, "vchgin-irq", pmeter); + if (ret < 0) { + pr_err("%s: Fail to request SYS in IRQ: %d: %d\n", + __func__, pmeter->irq_vchgin, ret); + } +#endif + s2mu106_powermeter_initial(pmeter); + pr_info("%s:[BATT] S2MU106 pmeter driver loaded OK\n", __func__); - s2mu106_pm_enable(pmeter); + return ret; + +err_power_supply_register: + mutex_destroy(&pmeter->pmeter_mutex); + kfree(pmeter); return ret; } @@ -147,7 +484,7 @@ static struct platform_driver s2mu106_pmeter_driver = { static int __init s2mu106_pmeter_init(void) { int ret = 0; - + pr_info("%s\n", __func__); ret = platform_driver_register(&s2mu106_pmeter_driver); return ret; diff --git a/drivers/usb/notify/usb_notifier.c b/drivers/usb/notify/usb_notifier.c index 8131dbc6290e..f67051328dcb 100644 --- a/drivers/usb/notify/usb_notifier.c +++ b/drivers/usb/notify/usb_notifier.c @@ -548,7 +548,7 @@ static int vbus_handle_notification(struct notifier_block *nb, static int otg_accessory_power(bool enable) { -#if !defined(CONFIG_CCIC_S2MM005) +#if 0 u8 on = (u8)!!enable; union power_supply_propval val; diff --git a/include/linux/ccic/usbpd-s2mu106.h b/include/linux/ccic/usbpd-s2mu106.h index 13d1b37d4df2..e44c5cb92b92 100644 --- a/include/linux/ccic/usbpd-s2mu106.h +++ b/include/linux/ccic/usbpd-s2mu106.h @@ -54,12 +54,12 @@ /*****************************************/ /***********DEFINITION REGISTER***********/ /*****************************************/ -#define S2MU106_RESET_REG_00 (0x00) +#define S2MU106_RESET_REG_00 (0x00) /* reg 0x00 VBUS WAKEUP CONTROL */ #define S2MU106_REG_VBUS_WAKEUP_DIS_SHIFT (1) #define S2MU106_REG_VBUS_WAKEUP_DIS \ - (0x1 << S2MU106_REG_VBUS_WAKEUP_DIS_SHIFT) /* 0x02 */ + (0x1 << S2MU106_REG_VBUS_WAKEUP_DIS_SHIFT) /* 0x02 */ /* reg 0x01 LPM MODE ENABLE */ #define S2MU106_REG_LP_LDO_D_SHIFT (0) @@ -76,11 +76,36 @@ #define S2MU106_REG_IFG_SHIFT (4) #define S2MU106_REG_IFG_MASK (0xf << S2MU106_REG_IFG_SHIFT) /* 0xf0 */ +/* reg 0x04 */ +#define S2MU106_REG_OTP_CC_PUB_SHIFT (7) +#define S2MU106_REG_CC_PU_LPM_CTRL_DIS_SHIFT (2) +#define S2MU106_REG_CC2_RS_SW_ON_SHIFT (1) +#define S2MU106_REG_CC1_RS_SW_ON_SHIFT (0) + +#define S2MU106_REG_OTP_CC_PUB_MASK \ + (0x1 << S2MU106_REG_OTP_CC_PUB_SHIFT) +#define S2MU106_REG_CC_PU_LPM_CTRL_DIS_MASK \ + (0x1 << S2MU106_REG_CC_PU_LPM_CTRL_DIS_SHIFT) +#define S2MU106_REG_CC2_RS_SW_ON_MASK (0x1 << S2MU106_REG_CC2_RS_SW_ON_SHIFT) +#define S2MU106_REG_CC1_RS_SW_ON_MASK (0x1 << S2MU106_REG_CC1_RS_SW_ON_SHIFT) + +/* reg 0x08 */ +#define S2MU106_REG_LPMPUI_SEL_SHIFT (2) +#define S2MU106_REG_LPMPUI_SEL_MASK (0x3 << S2MU106_REG_LPMPUI_SEL_SHIFT) +#define S2MU106_REG_LPMPUI_SEL_250NA_MASK (0x0 << S2MU106_REG_LPMPUI_SEL_SHIFT) +#define S2MU106_REG_LPMPUI_SEL_500NA_MASK (0x1 << S2MU106_REG_LPMPUI_SEL_SHIFT) +#define S2MU106_REG_LPMPUI_SEL_1UA_MASK (0x2 << S2MU106_REG_LPMPUI_SEL_SHIFT) +#define S2MU106_REG_LPMPUI_SEL_2UA_MASK (0x3 << S2MU106_REG_LPMPUI_SEL_SHIFT) + +/* reg 0x0A */ +#define S2MU106_REG_OVP_ON_SHIFT (7) +#define S2MU106_REG_OVP_ON (0x1 << S2MU106_REG_OVP_ON_SHIFT) + /* reg 0x18 */ -#define S2MU106_REG_PLUG_CTRL_MODE_SHIFT (0) -#define S2MU106_REG_PLUG_CTRL_RP_SEL_SHIFT (4) -#define S2MU106_REG_PLUG_CTRL_DETECT_BAT_DISABLE_SHIFT (6) -#define S2MU106_REG_PLUG_CTRL_DETECT_OCP_DISABLE_SHIFT (7) +#define S2MU106_REG_PLUG_CTRL_MODE_SHIFT (0) +#define S2MU106_REG_PLUG_CTRL_RP_SEL_SHIFT (4) +#define S2MU106_REG_PLUG_CTRL_DETECT_BAT_DISABLE_SHIFT (6) +#define S2MU106_REG_PLUG_CTRL_DETECT_OCP_DISABLE_SHIFT (7) #define S2MU106_REG_PLUG_CTRL_DFP \ (0x1 << S2MU106_REG_PLUG_CTRL_MODE_SHIFT) /* 0x01 */ #define S2MU106_REG_PLUG_CTRL_UFP \ @@ -93,7 +118,7 @@ (0x1 << S2MU106_REG_PLUG_CTRL_RP_SEL_SHIFT) /* 0x10 */ #define S2MU106_REG_PLUG_CTRL_RP180 \ (0x2 << S2MU106_REG_PLUG_CTRL_RP_SEL_SHIFT) /* 0x20 */ -#define S2MU106_REG_PLUG_CTRL_MODE_MASK \ +#define S2MU106_REG_PLUG_CTRL_MODE_MASK \ (0x3 << S2MU106_REG_PLUG_CTRL_MODE_SHIFT) /* 0x03 */ #define S2MU106_REG_PLUG_CTRL_RP_SEL_MASK \ (0x3 << S2MU106_REG_PLUG_CTRL_RP_SEL_SHIFT)/* 0x30 */ @@ -103,8 +128,8 @@ (0x1 << S2MU106_REG_PLUG_CTRL_DETECT_OCP_DISABLE_SHIFT)/* 0x80 */ /* reg 0x19 */ -#define S2MU106_REG_MSG_DATA_ROLE_SHIFT (5) -#define S2MU106_REG_MSG_POWER_ROLE_SHIFT (6) +#define S2MU106_REG_MSG_DATA_ROLE_SHIFT (5) +#define S2MU106_REG_MSG_POWER_ROLE_SHIFT (6) #define S2MU106_REG_MSG_DATA_ROLE_UFP \ (0x0 << S2MU106_REG_MSG_DATA_ROLE_SHIFT) /* 0x00 */ #define S2MU106_REG_MSG_DATA_ROLE_DFP \ @@ -119,29 +144,23 @@ (0x1 << S2MU106_REG_MSG_POWER_ROLE_SHIFT) /* 0x40 */ #define S2MU106_REG_RD_OR_VBUS_MUX_SEL_SHIFT (4) -#define S2MU106_REG_RD_OR_VBUS_MUX_SEL \ +#define S2MU106_REG_RD_OR_VBUS_MUX_SEL \ (0x1 << S2MU106_REG_RD_OR_VBUS_MUX_SEL_SHIFT) -/* reg 0x1B */ -#define S2MU106_REG_DET_RD_OR_VBUS_SHIFT (4) -#define S2MU106_REG_DET_RD_OR_VBUS \ - (0x1 << S2MU106_REG_DET_RD_OR_VBUS_SHIFT) /* 0x10 */ - -/* reg 0x1E */ -#define S2MU106_REG_USB31_EN_SHIFT (6) -#define S2MU106_REG_USB31_EN \ - (0x1 << S2MU106_REG_USB31_EN_SHIFT) /* 0x40 */ +/* reg 0x22 */ +#define S2MU106_REG_PLUG_CTRL_SET_MON_RD (0x1 << 3) /* reg 0x26 */ #define S2MU106_REG_PLUG_CTRL_CC_HOLD_BIT (0x1) +#define S2MU106_REG_PLUG_CTRL_SUPPORT_ACC (0x1 << 7) /* reg 0x27 */ -#define S2MU106_REG_PLUG_CTRL_FSM_MANUAL_EN_SHIFT (2) -#define S2MU106_REG_PLUG_CTRL_RpRd_PLUG_SEL_SHIFT (3) -#define S2MU106_REG_PLUG_CTRL_VCONN_MANUAL_EN_SHIFT (4) -#define S2MU106_REG_PLUG_CTRL_RpRd_CC1_VCONN_SHIFT (5) -#define S2MU106_REG_PLUG_CTRL_RpRd_CC2_VCONN_SHIFT (6) -#define S2MU106_REG_PLUG_CTRL_RpRd_MANUAL_EN_SHIFT (7) +#define S2MU106_REG_PLUG_CTRL_FSM_MANUAL_EN_SHIFT (2) +#define S2MU106_REG_PLUG_CTRL_RpRd_PLUG_SEL_SHIFT (3) +#define S2MU106_REG_PLUG_CTRL_VCONN_MANUAL_EN_SHIFT (4) +#define S2MU106_REG_PLUG_CTRL_RpRd_CC1_VCONN_SHIFT (5) +#define S2MU106_REG_PLUG_CTRL_RpRd_CC2_VCONN_SHIFT (6) +#define S2MU106_REG_PLUG_CTRL_RpRd_MANUAL_EN_SHIFT (7) #define S2MU106_REG_PLUG_CTRL_FSM_MANUAL_EN \ (0x1 << S2MU106_REG_PLUG_CTRL_FSM_MANUAL_EN_SHIFT) /* 0x04 */ @@ -167,14 +186,13 @@ 0x1 << S2MU106_REG_PLUG_CTRL_RpRd_CC2_VCONN_SHIFT) /* 0x70 */ /* reg 0x28 */ -#define S2MU106_REG_PLUG_CTRL_CC_MANUAL_EN_SHIFT (4) -#define S2MU106_REG_PLUG_CTRL_CC1_MANUAL_EN_SHIFT (5) -#define S2MU106_REG_PLUG_CTRL_CC2_MANUAL_EN_SHIFT (6) - -#define S2MU106_REG_PLUG_CTRL_FSM_MANUAL_INPUT_MASK (0xf) -#define S2MU106_REG_PLUG_CTRL_FSM_ATTACHED_SNK (2) -#define S2MU106_REG_PLUG_CTRL_FSM_ATTACHED_SRC (6) -#define S2MU106_REG_PLUG_CTRL_FSM_ATTACH_WAIT_SRC (5) +#define S2MU106_REG_PLUG_CTRL_CC_MANUAL_EN_SHIFT (4) +#define S2MU106_REG_PLUG_CTRL_CC1_MANUAL_EN_SHIFT (5) +#define S2MU106_REG_PLUG_CTRL_CC2_MANUAL_EN_SHIFT (6) + +#define S2MU106_REG_PLUG_CTRL_FSM_MANUAL_INPUT_MASK (0xf) +#define S2MU106_REG_PLUG_CTRL_FSM_ATTACHED_SNK (2) +#define S2MU106_REG_PLUG_CTRL_FSM_ATTACHED_SRC (6) #define S2MU106_REG_PLUG_CTRL_CC_MANUAL_EN \ (0x1 << S2MU106_REG_PLUG_CTRL_CC_MANUAL_EN_SHIFT) /* 0x10 */ #define S2MU106_REG_PLUG_CTRL_CC1_MANUAL_ON \ @@ -189,21 +207,24 @@ 0x1 << S2MU106_REG_PLUG_CTRL_CC2_MANUAL_EN_SHIFT) /* 0x70 */ /* reg 0x2E */ -#define S2MU106_REG_PLUG_CTRL_VDM_DISABLE_SHIFT (1) -#define S2MU106_REG_PLUG_CTRL_UFP_ATTACH_OPT_SHIFT (5) -#define S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY_SHIFT (6) -#define S2MU106_REG_PLUG_CTRL_UFP_ATTACH_OPT \ - (0x1 << S2MU106_REG_PLUG_CTRL_UFP_ATTACH_OPT_SHIFT) /* 0x20 */ - +#define S2MU106_REG_PLUG_CTRL_SSM_DISABLE_SHIFT (0) +#define S2MU106_REG_PLUG_CTRL_VDM_DISABLE_SHIFT (1) +#define S2MU106_REG_PLUG_CTRL_ATTACH_OPT_EN_SHIFT (5) +#define S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY_SHIFT (6) +#define S2MU106_REG_PLUG_CTRL_SSM_DISABLE \ + (0x1 << S2MU106_REG_PLUG_CTRL_SSM_DISABLE_SHIFT) /* 0x01 */ #define S2MU106_REG_PLUG_CTRL_VDM_DISABLE \ (0x1 << S2MU106_REG_PLUG_CTRL_VDM_DISABLE_SHIFT) /* 0x02 */ #define S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY \ - (0x1 << S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY_SHIFT) /* 0x80 */ + (0x1 << S2MU106_REG_PLUG_CTRL_ECO_SRC_CAP_RDY_SHIFT) /* 0x40 */ +#define S2MU106_REG_PLUG_CTRL_ATTACH_OPT_EN \ + (0x1 << S2MU106_REG_PLUG_CTRL_ATTACH_OPT_EN_SHIFT) /* 0x20 */ /* reg 0x90 (For S2MU106_REG_MSG_SEND_CON) */ -#define S2MU106_REG_MSG_SEND_CON_SEND_MSG_EN_SHIFT (0) -#define S2MU106_REG_MSG_SEND_CON_OP_MODE_SHIFT (1) -#define S2MU106_REG_MSG_SEND_CON_SOP_SHIFT (2) +#define S2MU106_REG_MSG_SEND_CON_SEND_MSG_EN_SHIFT (0) +#define S2MU106_REG_MSG_SEND_CON_OP_MODE_SHIFT (1) +#define S2MU106_REG_MSG_SEND_CON_SOP_SHIFT (2) +#define S2MU106_REG_MSG_SEND_CON_HARD_EN_SHIFT (6) #define S2MU106_REG_MSG_SEND_CON_SEND_MSG_EN \ (0x1 << S2MU106_REG_MSG_SEND_CON_SEND_MSG_EN_SHIFT) /* 0x01 */ @@ -223,23 +244,25 @@ (0x5 << S2MU106_REG_MSG_SEND_CON_SOP_SHIFT) /* 0x14 */ #define S2MU106_REG_MSG_SEND_CON_SOP_CableRST \ (0x6 << S2MU106_REG_MSG_SEND_CON_SOP_SHIFT) /* 0x18 */ +#define S2MU106_REG_MSG_SEND_CON_HARD_EN \ + (0x1 << S2MU106_REG_MSG_SEND_CON_HARD_EN_SHIFT) /* 0x40 */ /* reg 0xB2 */ -#define S2MU106_PDIC_RID_SHIFT (5) -#define S2MU106_PDIC_RID_MASK (0x7 << S2MU106_PDIC_RID_SHIFT) /* 0xE0 */ +#define S2MU106_PDIC_RID_SHIFT (5) +#define S2MU106_PDIC_RID_MASK (0x7 << S2MU106_PDIC_RID_SHIFT) /* 0xE0 */ /* reg 0xB3 */ -#define S2MU106_REG_CTRL_MON_CC1_SHIFT (0) -#define S2MU106_REG_CTRL_MON_CC2_SHIFT (3) +#define S2MU106_REG_CTRL_MON_CC1_SHIFT (0) +#define S2MU106_REG_CTRL_MON_CC2_SHIFT (3) #define S2MU106_REG_CTRL_MON_CC1_MASK \ (0x7 << S2MU106_REG_CTRL_MON_CC1_SHIFT) /* 0x07 */ #define S2MU106_REG_CTRL_MON_CC2_MASK \ (0x7 << S2MU106_REG_CTRL_MON_CC2_SHIFT) /* 0x38 */ /* reg 0xB4 */ -#define S2MU106_PDIC_PLUG_ATTACH_DONE_SHIFT (1) -#define S2MU106_PDIC_SINK_SEL_MONITOR_SHIFT (2) -#define S2MU106_PDIC_SOURCE_SEL_MONITOR_SHIFT (3) +#define S2MU106_PDIC_PLUG_ATTACH_DONE_SHIFT (1) +#define S2MU106_PDIC_SINK_SEL_MONITOR_SHIFT (2) +#define S2MU106_PDIC_SOURCE_SEL_MONITOR_SHIFT (3) #define S2MU106_PDIC_SINK (1 << S2MU106_PDIC_SINK_SEL_MONITOR_SHIFT \ | 1 << S2MU106_PDIC_PLUG_ATTACH_DONE_SHIFT) /* 0x06 */ @@ -249,14 +272,14 @@ #define S2MU106_PR_MASK (S2MU106_PDIC_SINK | S2MU106_PDIC_SOURCE) /* 0x0E */ /* reg 0xF7 */ -#define S2MU106_REG_ETC_SOFT_RESET_EN_SHIFT (1) +#define S2MU106_REG_ETC_SOFT_RESET_EN_SHIFT (1) #define S2MU106_REG_ETC_SOFT_RESET_EN \ (0x1 << S2MU106_REG_ETC_SOFT_RESET_EN_SHIFT) /* 0x02 */ #define S2MU106_REG_ETC_SOFT_RESET_DIS \ (0x0 << S2MU106_REG_ETC_SOFT_RESET_EN_SHIFT) /* 0x00 */ /* reg 0xF8 */ -#define S2MU106_REG_ID_MONITOR_MSG_ID_MASK (0x07) +#define S2MU106_REG_ID_MONITOR_MSG_ID_MASK (0x07) /*****************************************/ @@ -305,219 +328,231 @@ #define S2MU106_REG_INT_STATUS5_HARD_RESET (1<<2) /* interrupt for checking message */ -#define ENABLED_INT_0 (S2MU106_REG_INT_STATUS0_MSG_ACCEPT |\ - S2MU106_REG_INT_STATUS0_VDM_DISCOVER_ID |\ - S2MU106_REG_INT_STATUS0_VDM_DISCOVER_SVID |\ - S2MU106_REG_INT_STATUS0_VDM_DISCOVER_MODE) -#define ENABLED_INT_1 (S2MU106_REG_INT_STATUS1_MSG_DR_SWAP |\ +#define ENABLED_INT_0 (S2MU106_REG_INT_STATUS0_MSG_ACCEPT |\ + S2MU106_REG_INT_STATUS0_VDM_DISCOVER_ID |\ + S2MU106_REG_INT_STATUS0_VDM_DISCOVER_SVID |\ + S2MU106_REG_INT_STATUS0_VDM_DISCOVER_MODE |\ + S2MU106_REG_INT_STATUS0_VDM_ENTER |\ + S2MU106_REG_INT_STATUS0_MSG_GOODCRC) +#define ENABLED_INT_1 (S2MU106_REG_INT_STATUS1_MSG_DR_SWAP |\ S2MU106_REG_INT_STATUS1_MSG_PR_SWAP |\ S2MU106_REG_INT_STATUS1_MSG_GETSRCCAP |\ S2MU106_REG_INT_STATUS1_MSG_GETSNKCAP |\ S2MU106_REG_INT_STATUS1_MSG_REJECT |\ - S2MU106_REG_INT_STATUS1_MSG_PSRDY) -#define ENABLED_INT_2 (S2MU106_REG_INT_STATUS2_MSG_SRC_CAP |\ + S2MU106_REG_INT_STATUS1_MSG_PSRDY |\ + S2MU106_REG_INT_STATUS1_MSG_GOTOMIN) +#define ENABLED_INT_2 (S2MU106_REG_INT_STATUS2_MSG_SRC_CAP |\ S2MU106_REG_INT_STATUS2_MSG_SNK_CAP |\ S2MU106_REG_INT_STATUS2_MSG_REQUEST |\ S2MU106_REG_INT_STATUS2_MSG_SOFTRESET |\ - S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP) + S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP |\ + S2MU106_REG_INT_STATUS2_MSG_WAIT) #define ENABLED_INT_2_WAKEUP (S2MU106_REG_INT_STATUS2_MSG_SRC_CAP |\ S2MU106_REG_INT_STATUS2_MSG_SNK_CAP |\ S2MU106_REG_INT_STATUS2_MSG_REQUEST |\ S2MU106_REG_INT_STATUS2_MSG_SOFTRESET |\ S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP |\ - S2MU106_REG_INT_STATUS2_WAKEUP) -#define ENABLED_INT_3 S2MU106_REG_INT_STATUS3_UNS_CMD_DATA -#define ENABLED_INT_4 (S2MU106_REG_INT_STATUS4_USB_DETACH |\ + S2MU106_REG_INT_STATUS2_WAKEUP |\ + S2MU106_REG_INT_STATUS2_MSG_WAIT) +#define ENABLED_INT_3 S2MU106_REG_INT_STATUS3_UNS_CMD_DATA +#define ENABLED_INT_4 (S2MU106_REG_INT_STATUS4_USB_DETACH |\ S2MU106_REG_INT_STATUS4_PLUG_IRQ |\ - S2MU106_REG_INT_STATUS4_MSG_PASS) -#define ENABLED_INT_5 (S2MU106_REG_INT_STATUS5_HARD_RESET) + S2MU106_REG_INT_STATUS4_MSG_PASS |\ + S2MU106_REG_INT_STATUS4_MSG_ERROR) +#define ENABLED_INT_5 (S2MU106_REG_INT_STATUS5_HARD_RESET) /* S2MU106 I2C registers */ enum s2mu106_usbpd_reg { - S2MU106_REG_PD_TRIM = 0x00, - S2MU106_REG_PD_CTRL = 0x01, - S2MU106_REG_PD_CTRL_2 = 0x02, - S2MU106_REG_ANALOG_OTP_04 = 0x04, - S2MU106_REG_ANALOG_OTP_08 = 0x08, - S2MU106_REG_ANALOG_OTP_0A = 0x0A, - S2MU106_REG_PHY_CTRL_IFG = 0x13, - S2MU106_REG_PLUG_CTRL_PORT = 0x18, - S2MU106_REG_PLUG_CTRL_MSG = 0x19, - S2MU106_REG_PLUG_CTRL_VBUS_MUX = 0x1B, - S2MU106_REG_PLUG_CTRL_SET_RD_2 = 0x1C, - S2MU106_REG_PLUG_CTRL_SET_RP_2 = 0x1D, - S2MU106_REG_PLUG_CTRL_SET_RD = 0x1E, - S2MU106_REG_PLUG_CTRL_SET_RP = 0x1F, - S2MU106_REG_PLUG_CTRL_CC_HOLD = 0x26, - S2MU106_REG_PLUG_CTRL_RpRd = 0x27, - S2MU106_REG_PLUG_CTRL_CC12 = 0x28, - S2MU106_REG_PLUG_CTRL = 0x2E, - S2MU106_REG_CTRL = 0x2F, - - S2MU106_REG_INT_MASK0 = 0x3E, - S2MU106_REG_INT_MASK1 = 0x3F, - S2MU106_REG_INT_MASK2 = 0x40, - S2MU106_REG_INT_MASK3 = 0x41, - S2MU106_REG_INT_MASK4 = 0x42, - S2MU106_REG_INT_STATUS0 = 0xE0, - S2MU106_REG_INT_STATUS1 = 0xE1, - S2MU106_REG_INT_STATUS2 = 0xE2, - S2MU106_REG_INT_STATUS3 = 0xE3, - S2MU106_REG_INT_STATUS4 = 0xE4, - S2MU106_REG_ADC_STATUS = 0xB2, - S2MU106_REG_PLUG_MON1 = 0xB3, - S2MU106_REG_PLUG_MON2 = 0xB4, - S2MU106_REG_PLUG_FSM_MON = 0xB7, - - S2MU106_REG_MSG_SEND_CON = 0x90, - S2MU106_REG_MSG_TX_HEADER_L = 0x91, - S2MU106_REG_MSG_TX_HEADER_H = 0x92, - S2MU106_REG_MSG_TX_OBJECT0_0_L = 0x93, - S2MU106_REG_MSG_TX_OBJECT0_0_H = 0x94, - S2MU106_REG_MSG_TX_OBJECT0_1_L = 0x95, - S2MU106_REG_MSG_TX_OBJECT0_1_H = 0x96, - S2MU106_REG_MSG_TX_OBJECT1_0_L = 0x97, - S2MU106_REG_MSG_TX_OBJECT1_0_H = 0x98, - S2MU106_REG_MSG_TX_OBJECT1_1_L = 0x99, - S2MU106_REG_MSG_TX_OBJECT1_1_H = 0x9A, - S2MU106_REG_MSG_TX_OBJECT2_0_L = 0x9B, - S2MU106_REG_MSG_TX_OBJECT2_0_H = 0x9C, - S2MU106_REG_MSG_TX_OBJECT2_1_L = 0x9D, - S2MU106_REG_MSG_TX_OBJECT2_1_H = 0x9E, - S2MU106_REG_MSG_TX_OBJECT3_0_L = 0x9F, - S2MU106_REG_MSG_TX_OBJECT3_0_H = 0xA0, - S2MU106_REG_MSG_TX_OBJECT3_1_L = 0xA1, - S2MU106_REG_MSG_TX_OBJECT3_1_H = 0xA2, - S2MU106_REG_MSG_TX_OBJECT4_0_L = 0xA3, - S2MU106_REG_MSG_TX_OBJECT4_0_H = 0xA4, - S2MU106_REG_MSG_TX_OBJECT4_1_L = 0xA5, - S2MU106_REG_MSG_TX_OBJECT4_1_H = 0xA6, - S2MU106_REG_MSG_TX_OBJECT5_0_L = 0xA7, - S2MU106_REG_MSG_TX_OBJECT5_0_H = 0xA8, - S2MU106_REG_MSG_TX_OBJECT5_1_L = 0xA9, - S2MU106_REG_MSG_TX_OBJECT5_1_H = 0xAA, - S2MU106_REG_MSG_TX_OBJECT6_0_L = 0xAB, - S2MU106_REG_MSG_TX_OBJECT6_0_H = 0xAC, - S2MU106_REG_MSG_TX_OBJECT6_1_L = 0xAD, - S2MU106_REG_MSG_TX_OBJECT6_1_H = 0xAE, - - S2MU106_REG_MSG_RX_HEADER_L = 0xC1, - S2MU106_REG_MSG_RX_HEADER_H = 0xC2, - S2MU106_REG_MSG_RX_OBJECT0_0_L = 0xC3, - S2MU106_REG_MSG_RX_OBJECT0_0_H = 0xC4, - S2MU106_REG_MSG_RX_OBJECT0_1_L = 0xC5, - S2MU106_REG_MSG_RX_OBJECT0_1_H = 0xC6, - S2MU106_REG_MSG_RX_OBJECT1_0_L = 0xC7, - S2MU106_REG_MSG_RX_OBJECT1_0_H = 0xC8, - S2MU106_REG_MSG_RX_OBJECT1_1_L = 0xC9, - S2MU106_REG_MSG_RX_OBJECT1_1_H = 0xCA, - S2MU106_REG_MSG_RX_OBJECT2_0_L = 0xCB, - S2MU106_REG_MSG_RX_OBJECT2_0_H = 0xCC, - S2MU106_REG_MSG_RX_OBJECT2_1_L = 0xCD, - S2MU106_REG_MSG_RX_OBJECT2_1_H = 0xCE, - S2MU106_REG_MSG_RX_OBJECT3_0_L = 0xCF, - S2MU106_REG_MSG_RX_OBJECT3_0_H = 0xD0, - S2MU106_REG_MSG_RX_OBJECT3_1_L = 0xD1, - S2MU106_REG_MSG_RX_OBJECT3_1_H = 0xD2, - S2MU106_REG_MSG_RX_OBJECT4_0_L = 0xD3, - S2MU106_REG_MSG_RX_OBJECT4_0_H = 0xD4, - S2MU106_REG_MSG_RX_OBJECT4_1_L = 0xD5, - S2MU106_REG_MSG_RX_OBJECT4_1_H = 0xD6, - S2MU106_REG_MSG_RX_OBJECT5_0_L = 0xD7, - S2MU106_REG_MSG_RX_OBJECT5_0_H = 0xD8, - S2MU106_REG_MSG_RX_OBJECT5_1_L = 0xD9, - S2MU106_REG_MSG_RX_OBJECT5_1_H = 0xDA, - S2MU106_REG_MSG_RX_OBJECT6_0_L = 0xDB, - S2MU106_REG_MSG_RX_OBJECT6_0_H = 0xDC, - S2MU106_REG_MSG_RX_OBJECT6_1_L = 0xDD, - S2MU106_REG_MSG_RX_OBJECT6_1_H = 0xDE, - - S2MU106_REG_ETC = 0xF7, - S2MU106_REG_ID_MONITOR = 0xF8 + S2MU106_REG_PD_TRIM = 0x00, + S2MU106_REG_PD_CTRL = 0x01, + S2MU106_REG_PD_CTRL_2 = 0x02, + S2MU106_REG_ANALOG_OTP_04 = 0x04, + S2MU106_REG_ANALOG_OTP_08 = 0x08, + S2MU106_REG_ANALOG_OTP_0A = 0x0A, + S2MU106_REG_PHY_CTRL_00 = 0x10, + S2MU106_REG_PHY_CTRL_IFG = 0x13, + S2MU106_REG_BMC_CTRL = 0x14, + S2MU106_REG_PLUG_CTRL_PORT = 0x18, + S2MU106_REG_PLUG_CTRL_MSG = 0x19, + S2MU106_REG_PLUG_CTRL_VBUS_MUX = 0x1B, + S2MU106_REG_PLUG_CTRL_SET_RD_2 = 0x1C, + S2MU106_REG_PLUG_CTRL_SET_RP_2 = 0x1D, + S2MU106_REG_PLUG_CTRL_SET_RD = 0x1E, + S2MU106_REG_PLUG_CTRL_SET_RP = 0x1F, + S2MU106_REG_PLUG_CTRL_CC_TIMER1 = 0x20, + S2MU106_REG_PLUG_CTRL_CC_TIMER2 = 0x21, + S2MU106_REG_PLUG_CTRL_SET_MON = 0x22, + S2MU106_REG_PLUG_CTRL_CC_HOLD = 0x26, + S2MU106_REG_PLUG_CTRL_RpRd = 0x27, + S2MU106_REG_PLUG_CTRL_CC12 = 0x28, + S2MU106_REG_PLUG_CTRL = 0x2E, + S2MU106_REG_CTRL = 0x2F, + + S2MU106_REG_INT_MASK0 = 0x3E, + S2MU106_REG_INT_MASK1 = 0x3F, + S2MU106_REG_INT_MASK2 = 0x40, + S2MU106_REG_INT_MASK3 = 0x41, + S2MU106_REG_INT_MASK4 = 0x42, + S2MU106_REG_INT_STATUS0 = 0xE0, + S2MU106_REG_INT_STATUS1 = 0xE1, + S2MU106_REG_INT_STATUS2 = 0xE2, + S2MU106_REG_INT_STATUS3 = 0xE3, + S2MU106_REG_INT_STATUS4 = 0xE4, + S2MU106_REG_ADC_STATUS = 0xB2, + S2MU106_REG_PLUG_MON1 = 0xB3, + S2MU106_REG_PLUG_MON2 = 0xB4, + S2MU106_REG_PLUG_FSM_MON = 0xB5, + + S2MU106_REG_MSG_SEND_CON = 0x90, + S2MU106_REG_MSG_TX_HEADER_L = 0x91, + S2MU106_REG_MSG_TX_HEADER_H = 0x92, + S2MU106_REG_MSG_TX_OBJECT0_0_L = 0x93, + S2MU106_REG_MSG_TX_OBJECT0_0_H = 0x94, + S2MU106_REG_MSG_TX_OBJECT0_1_L = 0x95, + S2MU106_REG_MSG_TX_OBJECT0_1_H = 0x96, + S2MU106_REG_MSG_TX_OBJECT1_0_L = 0x97, + S2MU106_REG_MSG_TX_OBJECT1_0_H = 0x98, + S2MU106_REG_MSG_TX_OBJECT1_1_L = 0x99, + S2MU106_REG_MSG_TX_OBJECT1_1_H = 0x9A, + S2MU106_REG_MSG_TX_OBJECT2_0_L = 0x9B, + S2MU106_REG_MSG_TX_OBJECT2_0_H = 0x9C, + S2MU106_REG_MSG_TX_OBJECT2_1_L = 0x9D, + S2MU106_REG_MSG_TX_OBJECT2_1_H = 0x9E, + S2MU106_REG_MSG_TX_OBJECT3_0_L = 0x9F, + S2MU106_REG_MSG_TX_OBJECT3_0_H = 0xA0, + S2MU106_REG_MSG_TX_OBJECT3_1_L = 0xA1, + S2MU106_REG_MSG_TX_OBJECT3_1_H = 0xA2, + S2MU106_REG_MSG_TX_OBJECT4_0_L = 0xA3, + S2MU106_REG_MSG_TX_OBJECT4_0_H = 0xA4, + S2MU106_REG_MSG_TX_OBJECT4_1_L = 0xA5, + S2MU106_REG_MSG_TX_OBJECT4_1_H = 0xA6, + S2MU106_REG_MSG_TX_OBJECT5_0_L = 0xA7, + S2MU106_REG_MSG_TX_OBJECT5_0_H = 0xA8, + S2MU106_REG_MSG_TX_OBJECT5_1_L = 0xA9, + S2MU106_REG_MSG_TX_OBJECT5_1_H = 0xAA, + S2MU106_REG_MSG_TX_OBJECT6_0_L = 0xAB, + S2MU106_REG_MSG_TX_OBJECT6_0_H = 0xAC, + S2MU106_REG_MSG_TX_OBJECT6_1_L = 0xAD, + S2MU106_REG_MSG_TX_OBJECT6_1_H = 0xAE, + + S2MU106_REG_MSG_RX_HEADER_L = 0xC1, + S2MU106_REG_MSG_RX_HEADER_H = 0xC2, + S2MU106_REG_MSG_RX_OBJECT0_0_L = 0xC3, + S2MU106_REG_MSG_RX_OBJECT0_0_H = 0xC4, + S2MU106_REG_MSG_RX_OBJECT0_1_L = 0xC5, + S2MU106_REG_MSG_RX_OBJECT0_1_H = 0xC6, + S2MU106_REG_MSG_RX_OBJECT1_0_L = 0xC7, + S2MU106_REG_MSG_RX_OBJECT1_0_H = 0xC8, + S2MU106_REG_MSG_RX_OBJECT1_1_L = 0xC9, + S2MU106_REG_MSG_RX_OBJECT1_1_H = 0xCA, + S2MU106_REG_MSG_RX_OBJECT2_0_L = 0xCB, + S2MU106_REG_MSG_RX_OBJECT2_0_H = 0xCC, + S2MU106_REG_MSG_RX_OBJECT2_1_L = 0xCD, + S2MU106_REG_MSG_RX_OBJECT2_1_H = 0xCE, + S2MU106_REG_MSG_RX_OBJECT3_0_L = 0xCF, + S2MU106_REG_MSG_RX_OBJECT3_0_H = 0xD0, + S2MU106_REG_MSG_RX_OBJECT3_1_L = 0xD1, + S2MU106_REG_MSG_RX_OBJECT3_1_H = 0xD2, + S2MU106_REG_MSG_RX_OBJECT4_0_L = 0xD3, + S2MU106_REG_MSG_RX_OBJECT4_0_H = 0xD4, + S2MU106_REG_MSG_RX_OBJECT4_1_L = 0xD5, + S2MU106_REG_MSG_RX_OBJECT4_1_H = 0xD6, + S2MU106_REG_MSG_RX_OBJECT5_0_L = 0xD7, + S2MU106_REG_MSG_RX_OBJECT5_0_H = 0xD8, + S2MU106_REG_MSG_RX_OBJECT5_1_L = 0xD9, + S2MU106_REG_MSG_RX_OBJECT5_1_H = 0xDA, + S2MU106_REG_MSG_RX_OBJECT6_0_L = 0xDB, + S2MU106_REG_MSG_RX_OBJECT6_0_H = 0xDC, + S2MU106_REG_MSG_RX_OBJECT6_1_L = 0xDD, + S2MU106_REG_MSG_RX_OBJECT6_1_H = 0xDE, + + S2MU106_REG_ETC = 0xF7, + S2MU106_REG_ID_MONITOR = 0xF8, + S2MU106_REG_ID_MONITOR2 = 0xF9 }; typedef enum { - S2MU106_THRESHOLD_128MV = 2, - S2MU106_THRESHOLD_171MV = 3, - S2MU106_THRESHOLD_214MV = 4, - S2MU106_THRESHOLD_257MV = 5, - S2MU106_THRESHOLD_300MV = 6, - S2MU106_THRESHOLD_342MV = 7, - S2MU106_THRESHOLD_385MV = 8, - S2MU106_THRESHOLD_428MV = 9, - S2MU106_THRESHOLD_450MV = 10, - S2MU106_THRESHOLD_471MV = 11, - S2MU106_THRESHOLD_492MV = 12, - S2MU106_THRESHOLD_514MV = 13, - S2MU106_THRESHOLD_535MV = 14, - S2MU106_THRESHOLD_557MV = 15, - S2MU106_THRESHOLD_578MV = 16, - S2MU106_THRESHOLD_600MV = 17, - S2MU106_THRESHOLD_621MV = 18, - S2MU106_THRESHOLD_642MV = 19, - S2MU106_THRESHOLD_685MV = 20, - S2MU106_THRESHOLD_1000MV = 27, - - S2MU106_THRESHOLD_1200MV = 32, - S2MU106_THRESHOLD_1242MV = 33, - S2MU106_THRESHOLD_1285MV = 34, - S2MU106_THRESHOLD_1328MV = 35, - S2MU106_THRESHOLD_1371MV = 36, - S2MU106_THRESHOLD_1414MV = 37, - S2MU106_THRESHOLD_1457MV = 38, - S2MU106_THRESHOLD_1500MV = 39, - S2MU106_THRESHOLD_1542MV = 40, - S2MU106_THRESHOLD_1587MV = 41, - S2MU106_THRESHOLD_1628MV = 42, - S2MU106_THRESHOLD_1671MV = 43, - S2MU106_THRESHOLD_1714MV = 44, - S2MU106_THRESHOLD_1757MV = 45, - S2MU106_THRESHOLD_1799MV = 46, - S2MU106_THRESHOLD_1842MV = 47, - S2MU106_THRESHOLD_1885MV = 48, - S2MU106_THRESHOLD_1928MV = 49, - S2MU106_THRESHOLD_1971MV = 50, - S2MU106_THRESHOLD_2014MV = 51, - S2MU106_THRESHOLD_2057MV = 52, - S2MU106_THRESHOLD_2099MV = 53, - S2MU106_THRESHOLD_2142MV = 54, - S2MU106_THRESHOLD_2185MV = 55, - S2MU106_THRESHOLD_2228MV = 56, - S2MU106_THRESHOLD_2271MV = 57, - - S2MU106_THRESHOLD_MAX = 63 + S2MU106_THRESHOLD_128MV = 2, + S2MU106_THRESHOLD_171MV = 3, + S2MU106_THRESHOLD_214MV = 4, + S2MU106_THRESHOLD_257MV = 5, + S2MU106_THRESHOLD_300MV = 6, + S2MU106_THRESHOLD_342MV = 7, + S2MU106_THRESHOLD_385MV = 8, + S2MU106_THRESHOLD_428MV = 9, + S2MU106_THRESHOLD_450MV = 10, + S2MU106_THRESHOLD_471MV = 11, + S2MU106_THRESHOLD_492MV = 12, + S2MU106_THRESHOLD_514MV = 13, + S2MU106_THRESHOLD_535MV = 14, + S2MU106_THRESHOLD_557MV = 15, + S2MU106_THRESHOLD_578MV = 16, + S2MU106_THRESHOLD_600MV = 17, + S2MU106_THRESHOLD_621MV = 18, + S2MU106_THRESHOLD_642MV = 19, + S2MU106_THRESHOLD_685MV = 20, + S2MU106_THRESHOLD_1000MV = 27, + + S2MU106_THRESHOLD_1200MV = 32, + S2MU106_THRESHOLD_1242MV = 33, + S2MU106_THRESHOLD_1285MV = 34, + S2MU106_THRESHOLD_1328MV = 35, + S2MU106_THRESHOLD_1371MV = 36, + S2MU106_THRESHOLD_1414MV = 37, + S2MU106_THRESHOLD_1457MV = 38, + S2MU106_THRESHOLD_1500MV = 39, + S2MU106_THRESHOLD_1542MV = 40, + S2MU106_THRESHOLD_1587MV = 41, + S2MU106_THRESHOLD_1628MV = 42, + S2MU106_THRESHOLD_1671MV = 43, + S2MU106_THRESHOLD_1714MV = 44, + S2MU106_THRESHOLD_1757MV = 45, + S2MU106_THRESHOLD_1799MV = 46, + S2MU106_THRESHOLD_1842MV = 47, + S2MU106_THRESHOLD_1885MV = 48, + S2MU106_THRESHOLD_1928MV = 49, + S2MU106_THRESHOLD_1971MV = 50, + S2MU106_THRESHOLD_2014MV = 51, + S2MU106_THRESHOLD_2057MV = 52, + S2MU106_THRESHOLD_2099MV = 53, + S2MU106_THRESHOLD_2142MV = 54, + S2MU106_THRESHOLD_2185MV = 55, + S2MU106_THRESHOLD_2228MV = 56, + S2MU106_THRESHOLD_2271MV = 57, + + S2MU106_THRESHOLD_MAX = 63 } CCIC_THRESHOLD_SEL; typedef enum { - S2MU106_CC_OCP_255MV = 0, - S2MU106_CC_OCP_262MV = 1, - S2MU106_CC_OCP_273MV = 2, - S2MU106_CC_OCP_282MV = 3, - S2MU106_CC_OCP_301MV = 4, - S2MU106_CC_OCP_311MV = 5, - S2MU106_CC_OCP_327MV = 6, - S2MU106_CC_OCP_339MV = 7, - S2MU106_CC_OCP_375MV = 8, - S2MU106_CC_OCP_390MV = 9, - S2MU106_CC_OCP_415MV = 10, - S2MU106_CC_OCP_433MV = 11, - S2MU106_CC_OCP_478MV = 12, - S2MU106_CC_OCP_502MV = 13, - S2MU106_CC_OCP_542MV = 14, - S2MU106_CC_OCP_575MV = 15, - - S2MU106_CC_OCP_MAX = 16 + S2MU106_CC_OCP_255MV = 0, + S2MU106_CC_OCP_262MV = 1, + S2MU106_CC_OCP_273MV = 2, + S2MU106_CC_OCP_282MV = 3, + S2MU106_CC_OCP_301MV = 4, + S2MU106_CC_OCP_311MV = 5, + S2MU106_CC_OCP_327MV = 6, + S2MU106_CC_OCP_339MV = 7, + S2MU106_CC_OCP_375MV = 8, + S2MU106_CC_OCP_390MV = 9, + S2MU106_CC_OCP_415MV = 10, + S2MU106_CC_OCP_433MV = 11, + S2MU106_CC_OCP_478MV = 12, + S2MU106_CC_OCP_502MV = 13, + S2MU106_CC_OCP_542MV = 14, + S2MU106_CC_OCP_575MV = 15, + + S2MU106_CC_OCP_MAX = 16 } CCIC_CC_OCP_SEL; typedef enum { - S2MU106_PHY_IFG_25US = 0, - S2MU106_PHY_IFG_30US = 1, - S2MU106_PHY_IFG_35US = 2, + S2MU106_PHY_IFG_25US = 0, + S2MU106_PHY_IFG_30US = 1, + S2MU106_PHY_IFG_35US = 2, } CCIC_PHY_IFG_SEL; enum s2mu106_power_role { - PDIC_SINK, - PDIC_SOURCE + PDIC_SINK, + PDIC_SOURCE }; enum s2mu106_pdic_rid { @@ -612,6 +647,7 @@ struct s2mu106_usbpd_data { struct mutex poll_mutex; struct mutex lpm_mutex; struct mutex cc_mutex; + struct mutex vbus_mutex; int vconn_en; int regulator_en; int irq_gpio; @@ -633,6 +669,7 @@ struct s2mu106_usbpd_data { bool is_muic_attached; bool vbus_short_check; bool vbus_short; + bool vbus_access; #ifndef CONFIG_SEC_FACTORY bool lpcharge_water; #endif @@ -664,8 +701,11 @@ struct s2mu106_usbpd_data { struct delayed_work water_detect_handler; struct delayed_work ta_water_detect_handler; struct delayed_work water_dry_handler; - + int pm_cc1; + int pm_cc2; + int pm_chgin; struct power_supply_desc ccic_desc; + struct power_supply *psy_pm; struct power_supply *psy_ccic; struct regulator *regulator; diff --git a/include/linux/ccic/usbpd.h b/include/linux/ccic/usbpd.h index 50cb6467530c..ff9ab9c16d51 100644 --- a/include/linux/ccic/usbpd.h +++ b/include/linux/ccic/usbpd.h @@ -3,10 +3,16 @@ #include #include + #ifdef CONFIG_IFCONN_NOTIFIER #include #endif +#include +#include +#include +#include + #define MAX_CHARGING_VOLT 12000 /* 12V */ #define USBPD_VOLT_UNIT 50 /* 50mV */ #define USBPD_CURRENT_UNIT 10 /* 10mA */ @@ -21,15 +27,15 @@ #define USBPD_nDiscoverIdentityCount (20) /* Timer */ -#define tSrcTransition (35) /* 25~35 ms */ -#define tPSSourceOn (480) /* 390~480 ms */ +#define tSrcTransition (25) /* 25~35 ms */ +#define tPSSourceOn (420) /* 390~480 ms */ #define tPSSourceOff (750) /* 750~960 ms */ -#define tSenderResponse (1000) /* 1000 ms */ +#define tSenderResponse (25) /* 24~30ms */ #define tSenderResponseSRC (300) /* 1000 ms */ #define tSendSourceCap (10) /* 1~2 s */ #define tPSHardReset (25) /* 25~35 ms */ #define tSinkWaitCap (2500) /* 2.1~2.5 s */ -#define tPSTransition (5500) /* 450~550 ms */ +#define tPSTransition (450) /* 450~550 ms */ #define tVCONNSourceOn (100) /* 24~30 ms */ #define tVDMSenderResponse (50) /* 24~30 ms */ #define tVDMWaitModeEntry (50) /* 40~50 ms */ @@ -37,6 +43,9 @@ #define tDiscoverIdentity (50) /* 40~50 ms */ #define tSwapSourceStart (20) /* 20 ms */ #define tTypeCSinkWaitCap (310) /* 310~620 ms */ +#define tTypeCSendSourceCap (100) /* 100~200ms */ +#define tSrcRecover (880) /* 660~1000ms */ +#define tNoResponse (5500) /* 660~1000ms */ /* Protocol States */ typedef enum { @@ -191,6 +200,16 @@ typedef enum { PE_DFP_UVDM_Send_Message = 0xD0, PE_DFP_UVDM_Receive_Message = 0xD1, + /* Dual Role */ + PE_DR_SRC_Get_Source_Cap = 0xE0, + PE_DR_SRC_Give_Sink_Cap = 0xE1, + PE_DR_SNK_Get_Sink_Cap = 0xE2, + PE_DR_SNK_Give_Source_Cap = 0xE3, + + /* Bist Mode */ + PE_BIST_Receive_Mode = 0xE4, + PE_BIST_Frame_Received = 0xE5, + Error_Recovery = 0xFF } policy_state; @@ -234,6 +253,7 @@ typedef enum usbpd_manager_event { MANAGER_UVDM_SEND_MESSAGE = 16, MANAGER_UVDM_RECEIVE_MESSAGE = 17, MANAGER_START_DISCOVER_IDENTITY = 18, + MANAGER_SEND_PR_SWAP = 19, } usbpd_manager_event_type; enum usbpd_msg_status { @@ -315,6 +335,7 @@ typedef struct usbpd_phy_ops { int (*tx_msg)(void *, msg_header_type *, data_obj_type *); int (*rx_msg)(void *, msg_header_type *, data_obj_type *); int (*hard_reset)(void *); + void (*soft_reset)(void *); int (*set_power_role)(void *, int); int (*get_power_role)(void *, int *); int (*set_data_role)(void *, int); @@ -326,9 +347,11 @@ typedef struct usbpd_phy_ops { bool (*poll_status)(void *); void (*driver_reset)(void *); int (*set_otg_control)(void *, int); - void (*get_vbus_short_check)(void *, bool *); int (*set_cc_control)(void *, int); - int (*get_side_check)(void *); + void (*pr_swap)(void *, int); + int (*vbus_on_check)(void *); + int (*check_bist_message)(void *); + int (*get_side_check)(void *_data); } usbpd_phy_ops_type; struct policy_data { @@ -345,6 +368,8 @@ struct policy_data { bool abnormal_state; bool sink_cap_received; bool send_sink_cap; + bool txhardresetflag; + bool pd_support; }; struct protocol_data { @@ -367,12 +392,13 @@ struct usbpd_counter { struct usbpd_manager_data { usbpd_manager_command_type cmd; /* request to policy engine */ usbpd_manager_event_type event; /* policy engine infromed */ - - msg_header_type uvdm_msg_header; - data_obj_type uvdm_data_obj[USBPD_MAX_COUNT_MSG_OBJECT]; #if defined(CONFIG_IFCONN_NOTIFIER) struct ifconn_notifier_template template; #endif + + msg_header_type uvdm_msg_header; + data_obj_type uvdm_data_obj[USBPD_MAX_COUNT_MSG_OBJECT]; + int alt_sended; int vdm_en; /* request */ @@ -435,6 +461,8 @@ struct usbpd_manager_data { struct delayed_work select_pdo_handler; struct delayed_work start_discover_msg_handler; muic_attached_dev_t attached_dev; + + int pd_attached; }; struct usbpd_data { @@ -454,9 +482,15 @@ struct usbpd_data { data_obj_type sink_data_obj[2]; data_obj_type source_request_obj; struct usbpd_manager_data manager; + struct workqueue_struct *policy_wqueue; struct work_struct worker; struct completion msg_arrived; unsigned wait_for_msg_arrived; + int lc_test; + int id_matched; + + struct timeval time1; + struct timeval time2; }; static inline struct usbpd_data *protocol_rx_to_usbpd(struct protocol_data *rx) @@ -504,7 +538,6 @@ extern int usbpd_manager_get_status(struct usbpd_data *pd_data); extern int usbpd_manager_get_configure(struct usbpd_data *pd_data); extern int usbpd_manager_get_attention(struct usbpd_data *pd_data); extern void usbpd_dp_detach(struct usbpd_data *pd_data); - extern void usbpd_manager_inform_event(struct usbpd_data *, usbpd_manager_event_type); extern int usbpd_manager_evaluate_capability(struct usbpd_data *); @@ -512,10 +545,12 @@ extern data_obj_type usbpd_manager_select_capability(struct usbpd_data *); 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_policy_work(struct work_struct *); extern void usbpd_protocol_tx(struct usbpd_data *); extern void usbpd_protocol_rx(struct usbpd_data *); extern void usbpd_kick_policy_work(struct device *); +extern void usbpd_cancel_policy_work(struct device *); extern void usbpd_rx_hard_reset(struct device *); extern void usbpd_rx_soft_reset(struct usbpd_data *); extern void usbpd_policy_reset(struct usbpd_data *, unsigned flag); @@ -530,4 +565,11 @@ extern unsigned usbpd_wait_msg(struct usbpd_data *pd_data, unsigned msg_status, unsigned ms); extern void usbpd_reinit(struct device *); extern void usbpd_init_protocol(struct usbpd_data *); + +/* for usbpd certification polling */ +void usbpd_timer1_start(struct usbpd_data *pd_data); +int usbpd_check_time1(struct usbpd_data *pd_data); +void usbpd_timer2_start(struct usbpd_data *pd_data); +int usbpd_check_time2(struct usbpd_data *pd_data); + #endif diff --git a/include/linux/ccic/usbpd_ext.h b/include/linux/ccic/usbpd_ext.h index ef0e5a2ab442..b7c0cacf4d66 100644 --- a/include/linux/ccic/usbpd_ext.h +++ b/include/linux/ccic/usbpd_ext.h @@ -5,7 +5,6 @@ #include #endif - #ifndef __USBPD_EXT_H__ #define __USBPD_EXT_H__ @@ -34,6 +33,7 @@ enum { /* Samsung Acc VID */ #define SAMSUNG_VENDOR_ID 0x04E8 #define SAMSUNG_MPA_VENDOR_ID 0x04B4 +#define TypeC_DP_SUPPORT (0xFF01) /* Samsung Acc PID */ #define GEARVR_PRODUCT_ID 0xA500 #define GEARVR_PRODUCT_ID_1 0xA501 diff --git a/include/linux/ccic/usbpd_msg.h b/include/linux/ccic/usbpd_msg.h index 3c2f3c4b6aa8..bc1c0a0a9fd2 100644 --- a/include/linux/ccic/usbpd_msg.h +++ b/include/linux/ccic/usbpd_msg.h @@ -6,13 +6,33 @@ #define PD_SID (0xFF00) #define PD_SID_1 (0xFF01) +#define MAX_INPUT_DATA (255) +#define SEC_UVDM_ALIGN (4) +#define SEC_UVDM_WAIT_MS (5000) +#define SEC_UVDM_MAXDATA_FIRST (12) +#define SEC_UVDM_MAXDATA_NORMAL (16) +#define SEC_UVDM_CHECKSUM_COUNT (20) + +enum uvdm_res_type { + RES_INIT = 0, + RES_ACK, + RES_NAK, + RES_BUSY, +}; + +enum uvdm_rx_type { + RX_ACK = 0, + RX_NAK, + RX_BUSY, +}; + typedef union { u16 word; u8 byte[2]; struct { unsigned msg_type:4; - unsigned:1; + unsigned rsvd:1; unsigned port_data_role:1; unsigned spec_revision:2; unsigned port_power_role:1; @@ -36,7 +56,7 @@ typedef union { unsigned max_current:10; /* 10mA units */ unsigned voltage:10; /* 50mV units */ unsigned peak_current:2; - unsigned:3; + unsigned rsvd:3; unsigned data_role_swap:1; unsigned usb_comm_capable:1; unsigned externally_powered:1; @@ -48,7 +68,7 @@ typedef union { struct { unsigned op_current:10; /* 10mA units */ unsigned voltage:10; /* 50mV units */ - unsigned:5; + unsigned rsvd:5; unsigned data_role_swap:1; unsigned usb_comm_capable:1; unsigned externally_powered:1; @@ -74,7 +94,7 @@ typedef union { struct { unsigned min_current:10; /* 10mA units */ unsigned op_current:10; /* 10mA units */ - unsigned:4; + unsigned rsvd:4; unsigned no_usb_suspend:1; unsigned usb_comm_capable:1; unsigned capability_mismatch:1; @@ -86,7 +106,7 @@ typedef union { struct { unsigned max_power:10; /* 250mW units */ unsigned op_power:10; /* 250mW units */ - unsigned:4; + unsigned rsvd:4; unsigned no_usb_suspend:1; unsigned usb_comm_capable:1; unsigned capability_mismatch:1; @@ -112,10 +132,10 @@ typedef union { struct { unsigned command:5; - unsigned:1; + unsigned reserved:1; unsigned command_type:2; unsigned obj_pos:3; - unsigned:2; + unsigned rsvd:2; unsigned version:2; unsigned vdm_type:1; unsigned svid:16; @@ -195,7 +215,7 @@ typedef union { unsigned pid:16; }; } s_uvdm_header; - + typedef union { u32 object; u16 word[2]; @@ -285,6 +305,13 @@ enum usbpd_port_vconn_role { USBPD_VCONN_ON, }; +enum usbpd_power_role_swap { + USBPD_SINK_OFF, + USBPD_SINK_ON, + USBPD_SOURCE_OFF, + USBPD_SOURCE_ON, +}; + enum usbpd_port_role { USBPD_Rp = 0x01, USBPD_Rd = 0x01 << 1, @@ -292,9 +319,9 @@ enum usbpd_port_role { }; enum usbpd_port_rp_level { - USBPD_56k = 1, - USBPD_22k = 3, - USBPD_10k = 7, + USBPD_56k = 1, + USBPD_22k = 3, + USBPD_10k = 7, }; enum { @@ -302,12 +329,6 @@ enum { USBPD_CC_ON, }; -enum usbpd_connect_type { - USBPD_UP_SIDE = 1, - USBPD_DOWN_SIDE = 2, - USBPD_UNDEFFINED_SIDE = 3, -}; - enum vdm_command_type{ Initiator = 0, Responder_ACK = 1, @@ -358,6 +379,13 @@ enum vdm_command_msg { DisplayPort_Configure = 0x11, }; +enum usbpd_connect_type { + USBPD_UP_SIDE = 1, + USBPD_DOWN_SIDE = 2, + USBPD_UNDEFFINED_SIDE = 3, +}; + + enum usbpd_data_msg_type { USBPD_Source_Capabilities = 0x1, USBPD_Request = 0x2, diff --git a/include/linux/power/s2mu106_pmeter.h b/include/linux/power/s2mu106_pmeter.h index a2d8bdcfccd0..38dba2de5747 100755 --- a/include/linux/power/s2mu106_pmeter.h +++ b/include/linux/power/s2mu106_pmeter.h @@ -21,15 +21,131 @@ #ifndef S2MU106_PMETER_H #define S2MU106_PMETER_H #include -#include +#include +#include +#include +#include + +#define S2MU106_PM_VALUP1 0x03 +#define S2MU106_PM_VALUP2 0x04 +#define S2MU106_PM_INT1 0x05 +#define S2MU106_PM_INT2 0x06 +#define S2MU106_PM_VALUP1_MASK 0x0B +#define S2MU106_PM_VALUP2_MASK 0x0C +#define S2MU106_PM_INT1_MASK 0x0D +#define S2MU106_PM_INT2_MASK 0x0E + +#define S2MU106_PM_CO_MASK1 0x59 +#define S2MU106_PM_CO_MASK2 0x5A +#define S2MU106_PM_CAL_DIS1 0x5B +#define S2MU106_PM_CAL_DIS2 0x5C +#define S2MU106_PM_REQ_BOX_RR1 0x5D +#define S2MU106_PM_REQ_BOX_RR2 0x5E +#define S2MU106_PM_REQ_BOX_CO1 0x5F +#define S2MU106_PM_REQ_BOX_CO2 0x60 +#define S2MU106_PM_CTRL1 0x61 +#define S2MU106_PM_CTRL2 0x62 +#define S2MU106_PM_CTRL3 0x63 +#define S2MU106_PM_CTRL4 0x64 + +#define S2MU106_PM_VAL1_VCHGIN 0x12 +#define S2MU106_PM_VAL2_VCHGIN 0x13 +#define S2MU106_PM_VAL1_VWCIN 0x14 +#define S2MU106_PM_VAL2_VWCIN 0x15 +#define S2MU106_PM_VAL1_VBYP 0x16 +#define S2MU106_PM_VAL2_VBYP 0x17 +#define S2MU106_PM_VAL1_VSYS 0x18 +#define S2MU106_PM_VAL2_VSYS 0x19 +#define S2MU106_PM_VAL1_VBAT 0x1A +#define S2MU106_PM_VAL2_VBAT 0x1B +#define S2MU106_PM_VAL1_VCC1 0x1C +#define S2MU106_PM_VAL2_VCC1 0x1D +#define S2MU106_PM_VAL1_VGPADC 0x1E +#define S2MU106_PM_VAL2_VGPADC 0x1F +#define S2MU106_PM_VAL1_ICHGIN 0x20 +#define S2MU106_PM_VAL2_ICHGIN 0x21 +#define S2MU106_PM_VAL1_IWCIN 0x22 +#define S2MU106_PM_VAL2_IWCIN 0x23 +#define S2MU106_PM_VAL1_VCC2 0x24 +#define S2MU106_PM_VAL2_VCC2 0x25 +#define S2MU106_PM_VAL1_IOTG 0x26 +#define S2MU106_PM_VAL2_IOTG 0x27 +#define S2MU106_PM_VAL1_ITX 0x28 +#define S2MU106_PM_VAL2_ITX 0x29 +#define S2MU106_PM_HYST_LEVEL1 0xA3 +#define S2MU106_PM_HYST_CONTI1 0xA9 + +enum pm_type { + PM_TYPE_VCHGIN = 0, + PM_TYPE_VWCIN, + PM_TYPE_VBYP, + PM_TYPE_VSYS, + PM_TYPE_VBAT, + PM_TYPE_VCC1, + PM_TYPE_VGPADC, + PM_TYPE_ICHGIN, + PM_TYPE_IWCIN, + PM_TYPE_VCC2, + PM_TYPE_IOTG, + PM_TYPE_ITX, + PM_TYPE_MAX, +}; + +enum { + CONTINUOUS_MODE = 0, + REQUEST_RESPONSE_MODE, +}; +#if 0 +enum power_supply_pm_property { + POWER_SUPPLY_PROP_VWCIN, + POWER_SUPPLY_PROP_VBYP, + POWER_SUPPLY_PROP_VSYS, + POWER_SUPPLY_PROP_VBAT, + POWER_SUPPLY_PROP_VGPADC, + POWER_SUPPLY_PROP_VCC1, + POWER_SUPPLY_PROP_VCC2, + POWER_SUPPLY_PROP_ICHGIN, + POWER_SUPPLY_PROP_IWCIN, + POWER_SUPPLY_PROP_IOTG, + POWER_SUPPLY_PROP_ITX, + POWER_SUPPLY_PROP_CO_ENABLE, + POWER_SUPPLY_PROP_RR_ENABLE, +}; +#endif + +#define HYST_LEV_VCHGIN_SHIFT 4 +#define HYST_LEV_VCHGIN_MASK 0x70 + +enum { + HYST_LEV_VCHGIN_80mV = 0x1, + HYST_LEV_VCHGIN_160mV = 0x2, + HYST_LEV_VCHGIN_320mV = 0x3, + HYST_LEV_VCHGIN_640mV = 0x4, + HYST_LEV_VCHGIN_1280mV = 0x5, + HYST_LEV_VCHGIN_2560mV = 0x6, + HYST_LEV_VCHGIN_5120mV = 0x7, +}; + +#define HYST_CON_VCHGIN_SHIFT 6 +#define HYST_CON_VCHGIN_MASK 0xC0 +enum { + HYST_CON_VCHGIN_1 = 0x1, + HYST_CON_VCHGIN_4 = 0x2, + HYST_CON_VCHGIN_16 = 0x3, + HYST_CON_VCHGIN_32 = 0x4, +}; struct s2mu106_pmeter_data { struct i2c_client *i2c; struct device *dev; struct s2mu106_platform_data *s2mu106_pdata; -}; -int s2mu106_powermeter_get_vchg_voltage(void); -int s2mu106_powermeter_get_vchg_current(void); + int irq_vchgin; + + struct power_supply *psy_pm; + struct power_supply_desc psy_pm_desc; + + struct mutex pmeter_mutex; +}; #endif /*S2MU106_PMETER_H*/ diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index ac5d4a4a3820..e6d70fcff400 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -169,6 +169,21 @@ enum power_supply_property { POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_SERIAL_NUMBER, + + POWER_SUPPLY_PROP_VCHGIN, + POWER_SUPPLY_PROP_VWCIN, + POWER_SUPPLY_PROP_VBYP, + POWER_SUPPLY_PROP_VSYS, + POWER_SUPPLY_PROP_VBAT, + POWER_SUPPLY_PROP_VGPADC, + POWER_SUPPLY_PROP_VCC1, + POWER_SUPPLY_PROP_VCC2, + POWER_SUPPLY_PROP_ICHGIN, + POWER_SUPPLY_PROP_IWCIN, + POWER_SUPPLY_PROP_IOTG, + POWER_SUPPLY_PROP_ITX, + POWER_SUPPLY_PROP_CO_ENABLE, + POWER_SUPPLY_PROP_RR_ENABLE, POWER_SUPPLY_PROP_USBPD_RESET, };