* 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
#include <linux/ccic/usbpd.h>
#include <linux/ccic/usbpd-s2mu106.h>
+#if defined(CONFIG_PM_S2MU106)
+#include <linux/power/s2mu106_pmeter.h>
+#endif
+
#include <linux/muic/muic.h>
#if defined(CONFIG_MUIC_NOTIFIER)
#include <linux/muic/muic_notifier.h>
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) {
}
+#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)
{
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;
} 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;
}
#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;
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) {
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) {
#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)) {
#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)) {
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;
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;
| 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;
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;
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;
}
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)
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;
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;
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;
}
{
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)
/* 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);
}
#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;
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);
}
}
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;
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
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,
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);
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);
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);
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);
#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);
}
}
#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);
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
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);
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);
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 */
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;
}
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) {
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;
_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
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 =
.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,
.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
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++;
{
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)
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;
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)
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);
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
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;
{
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;
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);
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)
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__);
}
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,
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);
}
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__);
}
}
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);
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");
ifconn_event_work(pdic_data, IFCONN_NOTIFY_MANAGER,
IFCONN_NOTIFY_ID_DP_LINK_CONF,
IFCONN_NOTIFY_EVENT_ATTACH, manager);
-
+
return 0;
}
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");
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");
}
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;
#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;
#include <linux/ccic/usbpd.h>
#include <linux/delay.h>
#include <linux/completion.h>
-#include <linux/time.h>
#include <linux/muic/muic.h>
#if defined(CONFIG_MUIC_NOTIFIER)
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
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)
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);
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);
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);
*/
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;
}
{
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;
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;
}
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
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;
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;
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) {
}
}
#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)
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);
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);
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)
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) {
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) {
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);
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);
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);
{
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)
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);
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);
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);
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);
{
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)
{
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
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;
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
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;
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,
{
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);
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;
}
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)
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);
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)
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__);
{
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);
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);
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);
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;
}
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);
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);
{
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
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);
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);
{
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
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);
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);
{
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
*/
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);
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
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);
{
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)) {
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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,
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);
{
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,
{
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,
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);
{
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,
{
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,
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);
{
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,
{
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,
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);
{
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);
{
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);
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);
{
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);
{
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);
{
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);
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);
{
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);
{
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);
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);
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 */
/* 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,
{
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);
{
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);
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);
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);
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;
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);
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);
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);
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);
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;
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);
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);
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);
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);
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:
next_state = PE_SRC_Startup;
}
}
+
break;
}
dev_info(pd_data->dev, "%s saved state %x next_state %x \n", __func__, saved_state, next_state);
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;
{
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);
+}
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;
}
#include <linux/mfd/samsung/s2mu106.h>
#include <linux/of_gpio.h>
-#if defined(CONFIG_CHARGER_S2MU106)
-#define CONFIG_PM_S2MU106
-#endif
-
static struct mfd_cell s2mu106_devs[] = {
#if defined(CONFIG_CHARGER_S2MU106)
{ .name = "s2mu106-charger", },
#if defined(CONFIG_MUIC_S2MU106)
#include <linux/muic/s2mu106-muic.h>
#endif
+#if defined(CONFIG_PM_S2MU106)
+#include <linux/power/s2mu106_pmeter.h>
+#endif
/* TODO : add IP Header file include*/
static const u8 s2mu106_mask_reg[] = {
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)
#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)
#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;
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;
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__);
}
/* powermeter */
#if defined(CONFIG_PM_S2MU106)
-#include "../battery_v2/include/s2mu106_pmeter.h"
+#include <linux/power/s2mu106_pmeter.h>
#endif
static struct s2mu106_muic_data *static_data;
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
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
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;
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;
#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)
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__);
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__);
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__);
#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;
}
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;
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;
battery->input_current = 0;
battery->charging_current = 0;
battery->topoff_current = 0;
+ battery->small_input_flag = 0;
break;
case POWER_SUPPLY_STATUS_FULL:
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,
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;
}
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);
}
}
+ 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;
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";
#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";
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__);
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__);
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
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%%)"
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");
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;
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)
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;
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,
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:
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");
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;
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;
if (charger->otg_on) {
pr_info("[DEBUG] %s: skipped set(%d) : OTG is on\n", __func__, onoff);
+ charger->is_charging = false;
return;
}
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);
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);
#include <linux/mfd/samsung/s2mu106.h>
#include <linux/power/s2mu106_pmeter.h>
#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#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;
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;
}
static int __init s2mu106_pmeter_init(void)
{
int ret = 0;
-
+ pr_info("%s\n", __func__);
ret = platform_driver_register(&s2mu106_pmeter_driver);
return ret;
static int otg_accessory_power(bool enable)
{
-#if !defined(CONFIG_CCIC_S2MM005)
+#if 0
u8 on = (u8)!!enable;
union power_supply_propval val;
/*****************************************/
/***********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)
#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 \
(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 */
(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 \
(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 */
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 \
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 */
(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 */
#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)
/*****************************************/
#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 {
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;
bool is_muic_attached;
bool vbus_short_check;
bool vbus_short;
+ bool vbus_access;
#ifndef CONFIG_SEC_FACTORY
bool lpcharge_water;
#endif
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;
#include <linux/ccic/usbpd_msg.h>
#include <linux/muic/muic.h>
+
#ifdef CONFIG_IFCONN_NOTIFIER
#include <linux/ifconn/ifconn_notifier.h>
#endif
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ktime.h>
+
#define MAX_CHARGING_VOLT 12000 /* 12V */
#define USBPD_VOLT_UNIT 50 /* 50mV */
#define USBPD_CURRENT_UNIT 10 /* 10mA */
#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 */
#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 {
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;
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 {
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);
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 {
bool abnormal_state;
bool sink_cap_received;
bool send_sink_cap;
+ bool txhardresetflag;
+ bool pd_support;
};
struct protocol_data {
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 */
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 {
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)
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 *);
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);
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
#include <linux/usb/class-dual-role.h>
#endif
-
#ifndef __USBPD_EXT_H__
#define __USBPD_EXT_H__
/* 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
#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;
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;
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;
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;
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;
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;
unsigned pid:16;
};
} s_uvdm_header;
-
+
typedef union {
u32 object;
u16 word[2];
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,
};
enum usbpd_port_rp_level {
- USBPD_56k = 1,
- USBPD_22k = 3,
- USBPD_10k = 7,
+ USBPD_56k = 1,
+ USBPD_22k = 3,
+ USBPD_10k = 7,
};
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,
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,
#ifndef S2MU106_PMETER_H
#define S2MU106_PMETER_H
#include <linux/mfd/samsung/s2mu106.h>
-#include <linux/power/s2mu00x_battery.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+
+#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*/
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,
};