From 4bb80f02225446325bd62db954804e0d8f5a3c6d Mon Sep 17 00:00:00 2001 From: Junhan Bae Date: Tue, 12 Mar 2019 10:41:07 +0900 Subject: [PATCH] [RAMEN9610-13185][COMMON][9610] drivers : fix ccic driver for PD 2.0 communication Change-Id: I60371c71a841cbe58914bfc27d0db2303162b65d Signed-off-by: Junhan Bae --- drivers/ccic/s2mu106-usbpd.c | 349 ++++++++++++------------- drivers/ccic/usbpd.c | 8 +- drivers/ccic/usbpd_manager.c | 23 +- drivers/ccic/usbpd_policy.c | 68 ++--- drivers/power/supply/s2mu106_charger.c | 18 +- include/linux/ccic/usbpd-s2mu106.h | 42 ++- include/linux/ccic/usbpd.h | 8 +- include/linux/ccic/usbpd_msg.h | 5 + 8 files changed, 246 insertions(+), 275 deletions(-) diff --git a/drivers/ccic/s2mu106-usbpd.c b/drivers/ccic/s2mu106-usbpd.c index 2cf19c399627..1188c4096015 100644 --- a/drivers/ccic/s2mu106-usbpd.c +++ b/drivers/ccic/s2mu106-usbpd.c @@ -73,9 +73,7 @@ static int s2mu106_check_port_detect(struct s2mu106_usbpd_data *pdic_data); static int s2mu106_usbpd_reg_init(struct s2mu106_usbpd_data *_data); static void s2mu106_dfp(struct i2c_client *i2c); static void s2mu106_ufp(struct i2c_client *i2c); -#ifdef CONFIG_CCIC_VDM -static int s2mu106_usbpd_check_vdm_msg(void *_data, u64 *val); -#endif +static int s2mu106_usbpd_check_msg(void *_data, u64 *val); static void s2mu106_src(struct i2c_client *i2c); static void s2mu106_snk(struct i2c_client *i2c); static void s2mu106_assert_rd(void *_data); @@ -483,6 +481,16 @@ static int s2mu106_usbpd_update_bit(struct i2c_client *i2c, return ret; } +static int s2mu106_write_msg_all(struct i2c_client *i2c, int count, u8 *buf) +{ + int ret; + + ret = s2mu106_usbpd_bulk_write(i2c, S2MU106_REG_MSG_TX_HEADER_L, + 2 + (count * 4), buf); + + return ret; +} +#if 0 static int s2mu106_write_msg_header(struct i2c_client *i2c, u8 *buf) { int ret; @@ -509,7 +517,7 @@ static int s2mu106_write_msg_obj(struct i2c_client *i2c, int count, data_obj_typ return ret; } - +#endif static int s2mu106_send_msg(struct i2c_client *i2c) { int ret; @@ -519,7 +527,8 @@ static int s2mu106_send_msg(struct i2c_client *i2c) s2mu106_usbpd_write_reg(i2c, reg, val); - ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_REG_MSG_SEND_CON_OP_MODE); + ret = s2mu106_usbpd_write_reg(i2c, reg, S2MU106_REG_MSG_SEND_CON_OP_MODE | + S2MU106_REG_MSG_SEND_CON_HARD_EN); return ret; } @@ -704,13 +713,15 @@ static unsigned s2mu106_get_status(void *_data, unsigned flag) static bool s2mu106_poll_status(void *_data) { struct usbpd_data *data = (struct usbpd_data *) _data; - struct policy_data *policy = &data->policy; struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; struct i2c_client *i2c = pdic_data->i2c; struct device *dev = &i2c->dev; u8 intr[S2MU106_MAX_NUM_INT_STATUS] = {0}; int ret = 0, retry = 0; u64 status_reg_val = 0; + msg_header_type header; + int data_obj_num = 0; + int msg_id = 0; ret = s2mu106_usbpd_bulk_read(i2c, S2MU106_REG_INT_STATUS0, S2MU106_MAX_NUM_INT_STATUS, intr); @@ -718,19 +729,14 @@ static bool s2mu106_poll_status(void *_data) dev_info(dev, "%s status[0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x]\n", __func__, intr[0], intr[1], intr[2], intr[3], intr[4], intr[5], intr[6]); - if ((intr[0] | intr[1] | intr[2] | intr[3] | intr[4] | intr[5]) == 0) { - status_reg_val |= MSG_NONE; + if ((intr[0] | intr[1] | intr[2] | intr[3] | intr[4] | intr[5]) == 0) goto out; - } if ((intr[2] & S2MU106_REG_INT_STATUS2_WAKEUP) || (intr[4] & S2MU106_REG_INT_STATUS4_CC12_DET_IRQ)) 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) - status_reg_val |= MSG_HARDRESET; - /* when occur detach & attach atomic */ if (intr[4] & S2MU106_REG_INT_STATUS4_USB_DETACH) { status_reg_val |= PLUG_DETACH; @@ -755,112 +761,72 @@ static bool s2mu106_poll_status(void *_data) mutex_unlock(&pdic_data->lpm_mutex); } - pdic_data->check_msg_pass = 1; -#ifdef CONFIG_CCIC_VDM - /* function that support dp control */ - if (pdic_data->check_msg_pass) { - if (intr[4] & S2MU106_REG_INT_STATUS4_MSG_PASS) - status_reg_val |= MSG_PASS; - } -#endif -/* #if defined(CONFIG_CCIC_FACTORY) */ - if ((intr[4] & S2MU106_REG_INT_STATUS4_MSG_PASS) && - (intr[3] & S2MU106_REG_INT_STATUS3_UNS_CMD_DATA)) { - status_reg_val |= MSG_RID; - } -/* #endif */ + if (intr[5] & S2MU106_REG_INT_STATUS5_HARD_RESET) + status_reg_val |= MSG_HARDRESET; - if (intr[0] & S2MU106_REG_INT_STATUS0_MSG_GOODCRC - || intr[4] & S2MU106_REG_INT_STATUS4_MSG_SENT) + if (intr[0] & S2MU106_REG_INT_STATUS0_MSG_GOODCRC) status_reg_val |= MSG_GOODCRC; - if (intr[0] & S2MU106_REG_INT_STATUS0_MSG_ACCEPT) - status_reg_val |= MSG_ACCEPT; - - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PSRDY) - status_reg_val |= MSG_PSRDY; - - if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_REQUEST) - status_reg_val |= MSG_REQUEST; - - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_REJECT) - status_reg_val |= MSG_REJECT; - - if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_WAIT) - status_reg_val |= MSG_WAIT; - - if (intr[4] & S2MU106_REG_INT_STATUS4_MSG_ERROR) - status_reg_val |= MSG_ERROR; - - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PING) - status_reg_val |= MSG_PING; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PR_SWAP) + status_reg_val |= MSG_PR_SWAP; - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_GETSNKCAP) - status_reg_val |= MSG_GET_SNK_CAP; + if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_SOFTRESET) + status_reg_val |= MSG_SOFTRESET; - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_GETSRCCAP) - status_reg_val |= MSG_GET_SRC_CAP; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_DR_SWAP) + status_reg_val |= MSG_DR_SWAP; - if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_SRC_CAP) { - if (!policy->plug_valid) - pdic_data->status_reg |= PLUG_ATTACH; - status_reg_val |= MSG_SRC_CAP; - } + /* function that support dp control */ + if (intr[4] & S2MU106_REG_INT_STATUS4_MSG_PASS) { + if (intr[3] & S2MU106_REG_INT_STATUS3_UNS_CMD_DATA) + status_reg_val |= MSG_RID; + else { + usbpd_protocol_rx(data); + header = data->protocol_rx.msg_header; + data_obj_num = header.num_data_objs; + msg_id = header.msg_id; + pr_info("%s, prev msg_id =(%d), received msg_id =(%d)\n", __func__, + data->msg_id, msg_id); + + if (msg_id == data->msg_id) + goto out; + else + data->msg_id = msg_id; - if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_SNK_CAP) - status_reg_val |= MSG_SNK_CAP; + if (data_obj_num > 0) + s2mu106_usbpd_check_msg(data, &status_reg_val); - if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_SOFTRESET) - status_reg_val |= MSG_SOFTRESET; + if (intr[0] & S2MU106_REG_INT_STATUS0_MSG_ACCEPT) + status_reg_val |= MSG_ACCEPT; - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PR_SWAP) - status_reg_val |= MSG_PR_SWAP; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PSRDY) + status_reg_val |= MSG_PSRDY; - if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP) - status_reg_val |= MSG_VCONN_SWAP; + if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_REQUEST) + status_reg_val |= MSG_REQUEST; - if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_DR_SWAP) - status_reg_val |= MSG_DR_SWAP; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_REJECT) + status_reg_val |= MSG_REJECT; - if (intr[0] & S2MU106_REG_INT_STATUS0_VDM_DISCOVER_ID) - status_reg_val |= VDM_DISCOVER_IDENTITY; + if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_WAIT) + status_reg_val |= MSG_WAIT; - if (intr[0] & S2MU106_REG_INT_STATUS0_VDM_DISCOVER_SVID) - status_reg_val |= VDM_DISCOVER_SVID; + if (intr[4] & S2MU106_REG_INT_STATUS4_MSG_ERROR) + status_reg_val |= MSG_ERROR; - if (intr[0] & S2MU106_REG_INT_STATUS0_VDM_DISCOVER_MODE) - status_reg_val |= VDM_DISCOVER_MODE; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_PING) + status_reg_val |= MSG_PING; - if (intr[0] & S2MU106_REG_INT_STATUS0_VDM_ENTER) - status_reg_val |= VDM_ENTER_MODE; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_GETSNKCAP) + status_reg_val |= MSG_GET_SNK_CAP; - if (intr[0] & S2MU106_REG_INT_STATUS0_VDM_EXIT) - status_reg_val |= VDM_EXIT_MODE; + if (intr[1] & S2MU106_REG_INT_STATUS1_MSG_GETSRCCAP) + status_reg_val |= MSG_GET_SRC_CAP; - if (intr[0] & S2MU106_REG_INT_STATUS0_VDM_ATTENTION) - status_reg_val |= VDM_ATTENTION; -/* disable function that support dp control */ -#ifdef CONFIG_CCIC_VDM - /* read message if data object message */ - if (status_reg_val & - (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)) { - usbpd_protocol_rx(data); - if (status_reg_val & MSG_PASS) - s2mu106_usbpd_check_vdm_msg(data, &status_reg_val); - } -#else - /* read message if data object message */ - if (status_reg_val & - (MSG_PSRDY | MSG_REQUEST | MSG_SNK_CAP - | VDM_DISCOVER_IDENTITY | VDM_DISCOVER_SVID - | VDM_DISCOVER_MODE | VDM_ENTER_MODE | VDM_EXIT_MODE - | VDM_ATTENTION)) { - usbpd_protocol_rx(data); + if (intr[2] & S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP) + status_reg_val |= MSG_VCONN_SWAP; + } } -#endif out: pdic_data->status_reg |= status_reg_val; @@ -958,36 +924,41 @@ static int s2mu106_tx_msg(void *_data, struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data; struct i2c_client *i2c = pdic_data->i2c; int ret = 0; + int i = 0; int count = 0; - u8 reg_data = 0; - u8 msg_id = 0; + u8 send_msg[30]; + + pr_info("%s, \n", __func__); - mutex_lock(&pdic_data->cc_mutex); /* if there is no attach, skip tx msg */ if (pdic_data->detach_valid) goto done; +#if 0 /* using msg id counter at s2mu106 */ s2mu106_usbpd_read_reg(pdic_data->i2c, S2MU106_REG_ID_MONITOR, ®_data); msg_id = reg_data & S2MU106_REG_ID_MONITOR_MSG_ID_MASK; header->msg_id = msg_id; - - ret = s2mu106_write_msg_header(i2c, header->byte); - if (ret < 0) - goto done; +#endif + send_msg[0] = header->byte[0]; + send_msg[1] = header->byte[1]; count = header->num_data_objs; - if (count > 0) { - ret = s2mu106_write_msg_obj(i2c, count, obj); - if (ret < 0) - goto done; + for (i = 0; i < count; i++) { + send_msg[2 + (i * 4)] = obj[i].byte[0]; + send_msg[3 + (i * 4)] = obj[i].byte[1]; + send_msg[4 + (i * 4)] = obj[i].byte[2]; + send_msg[5 + (i * 4)] = obj[i].byte[3]; } + ret = s2mu106_write_msg_all(i2c, count, send_msg); + if (ret < 0) + goto done; + s2mu106_send_msg(i2c); done: - mutex_unlock(&pdic_data->cc_mutex); return ret; } @@ -1049,38 +1020,6 @@ static int s2mu106_vbus_on_check(void *_data) return s2mu106_usbpd_check_vbus(pdic_data, 4500, 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) static int s2mu106_get_side_check(void *_data) { @@ -1321,54 +1260,88 @@ static void s2mu106_usbpd_set_rp_scr_sel(struct s2mu106_usbpd_data *pdic_data, } #endif -#ifdef CONFIG_CCIC_VDM -int s2mu106_usbpd_check_vdm_msg(void *_data, u64 *val) +int s2mu106_usbpd_check_msg(void *_data, u64 *val) { struct usbpd_data *data = (struct usbpd_data *) _data; - int vdm_command = 0, vdm_type = 0; + int data_type = 0; + int msg_type = 0; + int vdm_type = 0; + int vdm_command = 0; - dev_info(data->dev, "%s ++\n", __func__); - if (data->protocol_rx.msg_header.num_data_objs == 0) { - dev_info(data->dev, "%s data_obj null\n", __func__); - return 0; - } + dev_info(data->dev, "%s\n", __func__); - if (data->protocol_rx.msg_header.msg_type == USBPD_Source_Capabilities) { - *val |= MSG_SRC_CAP; - return 0; - } + if (data->protocol_rx.msg_header.num_data_objs == 0) + data_type = USBPD_CTRL_MSG; + else + data_type = USBPD_DATA_MSG; - if (data->protocol_rx.msg_header.msg_type != USBPD_Vendor_Defined) { - dev_info(data->dev, "%s msg type is wrong\n", __func__); + msg_type = data->protocol_rx.msg_header.msg_type; + + if (data_type == USBPD_CTRL_MSG) return 0; - } - vdm_command = data->protocol_rx.data_obj[0].structured_vdm.command; - vdm_type = data->protocol_rx.data_obj[0].structured_vdm.vdm_type; + if (data_type == USBPD_DATA_MSG) { + switch (msg_type) { + case USBPD_Source_Capabilities: + *val |= MSG_SRC_CAP; + break; + case USBPD_Request: + *val |= MSG_REQUEST; + break; + case USBPD_Sink_Capabilities: + *val |= MSG_SNK_CAP; + break; + case USBPD_BIST: + *val |= MSG_BIST; + break; + case USBPD_Vendor_Defined: + vdm_command = data->protocol_rx.data_obj[0].structured_vdm.command; + vdm_type = data->protocol_rx.data_obj[0].structured_vdm.vdm_type; - if (vdm_type == Unstructured_VDM) { - dev_info(data->dev, "%s : uvdm msg received!\n", __func__); - *val |= UVDM_MSG; - return 0; - } + if (vdm_type == Unstructured_VDM) { + dev_info(data->dev, "%s : uvdm msg received!\n", __func__); + *val |= UVDM_MSG; + break; + } -#if 0 - switch (vdm_command) { - case DisplayPort_Status_Update: - *val |= VDM_DP_STATUS_UPDATE; - break; - case DisplayPort_Configure: - *val |= VDM_DP_CONFIGURE; - break; - default: - return 0; + switch (vdm_command) { + case DisplayPort_Status_Update: + *val |= VDM_DP_STATUS_UPDATE; + break; + case DisplayPort_Configure: + *val |= VDM_DP_CONFIGURE; + break; + case Attention: + *val |= VDM_ATTENTION; + break; + case Exit_Mode: + *val |= VDM_EXIT_MODE; + break; + case Enter_Mode: + *val |= VDM_ENTER_MODE; + break; + case Discover_Modes: + *val |= VDM_ENTER_MODE; + break; + case Discover_SVIDs: + *val |= VDM_DISCOVER_SVID; + break; + case Discover_Identity: + *val |= VDM_DISCOVER_IDENTITY; + break; + default: + break; + } + break; + default: + break; + } } -#endif - dev_info(data->dev, "%s: check vdm mag val(%d)\n", __func__, vdm_command); + + dev_info(data->dev, "%s: msg status(%lld)\n", __func__, *val); return 0; } -#endif static int s2mu106_usbpd_set_cc_control(struct s2mu106_usbpd_data *pdic_data, int val) { @@ -1575,9 +1548,8 @@ int s2mu106_set_normal_mode(struct s2mu106_usbpd_data *pdic_data) pdic_data->lpm_mode = false; - s2mu106_set_irq_enable(pdic_data, 0, 0, - S2MU106_REG_INT_STATUS2_MSG_SRC_CAP, ENABLED_INT_3, - ENABLED_INT_4, 0); + s2mu106_set_irq_enable(pdic_data, ENABLED_INT_0, ENABLED_INT_1, + ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5); dev_info(dev, "%s s2mu106 exit lpm mode\n", __func__); @@ -2455,6 +2427,9 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data) dev_info(dev, "%s\n", __func__); + mutex_lock(&pd_data->accept_mutex); + mutex_unlock(&pd_data->accept_mutex); + mutex_lock(&pdic_data->_mutex); s2mu106_poll_status(pd_data); @@ -2464,7 +2439,7 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data) goto out; #endif - if (s2mu106_get_status(pd_data, MSG_NONE)) + if (pdic_data->status_reg == 0) goto out; if (s2mu106_get_status(pd_data, MSG_SOFTRESET)) @@ -2512,6 +2487,10 @@ static irqreturn_t s2mu106_irq_thread(int irq, void *data) mutex_unlock(&pdic_data->cc_mutex); s2mu106_self_soft_reset(i2c); pdic_data->status_reg = 0; + if (pdic_data->power_role == PDIC_SOURCE) + s2mu106_dfp(i2c); + else + s2mu106_ufp(i2c); usbpd_rx_hard_reset(dev); usbpd_kick_policy_work(dev); goto out; @@ -2734,7 +2713,8 @@ static int s2mu106_usbpd_irq_init(struct s2mu106_usbpd_data *_data) if (_data->lpm_mode) s2mu106_set_irq_enable(_data, 0, 0, 0, 0, 0, 0); else - s2mu106_set_irq_enable(_data, 0, 0, 0, 0, ENABLED_INT_4, 0); + s2mu106_set_irq_enable(_data, ENABLED_INT_0, ENABLED_INT_1, + ENABLED_INT_2, ENABLED_INT_3, ENABLED_INT_4, ENABLED_INT_5); return ret; } @@ -3035,7 +3015,6 @@ static usbpd_phy_ops_type s2mu106_ops = { .get_side_check = s2mu106_get_side_check, .pr_swap = s2mu106_pr_swap, .vbus_on_check = s2mu106_vbus_on_check, - .check_bist_message = s2mu106_check_bist_message, }; #if defined CONFIG_PM diff --git a/drivers/ccic/usbpd.c b/drivers/ccic/usbpd.c index e1e8d5654c68..6d38a0867567 100644 --- a/drivers/ccic/usbpd.c +++ b/drivers/ccic/usbpd.c @@ -107,6 +107,7 @@ void usbpd_init_protocol(struct usbpd_data *pd_data) rx_layer_init(&pd_data->protocol_rx); tx_layer_init(&pd_data->protocol_tx); pd_data->id_matched = 0; + pd_data->msg_id = USBPD_nMessageIDCount + 1; } void usbpd_init_counters(struct usbpd_data *pd_data) @@ -331,7 +332,6 @@ void usbpd_set_ops(struct device *dev, usbpd_phy_ops_type *ops) pd_data->phy_ops.get_side_check = ops->get_side_check; pd_data->phy_ops.pr_swap = ops->pr_swap; pd_data->phy_ops.vbus_on_check = ops->vbus_on_check; - pd_data->phy_ops.check_bist_message = ops->check_bist_message; } protocol_state usbpd_protocol_rx_layer_reset_for_receive(struct protocol_data *rx) @@ -355,6 +355,8 @@ protocol_state usbpd_protocol_rx_wait_for_phy_message(struct protocol_data *rx) struct usbpd_data *pd_data = protocol_rx_to_usbpd(rx); protocol_state state = PRL_Rx_Wait_for_PHY_Message; + pd_data->msg_received = 0; + if (pd_data->phy_ops.rx_msg(pd_data, &rx->msg_header, rx->data_obj)) { dev_err(pd_data->dev, "%s IO Error\n", __func__); return state; @@ -372,6 +374,7 @@ protocol_state usbpd_protocol_rx_wait_for_phy_message(struct protocol_data *rx) } pd_data->id_matched = 1; + pd_data->msg_received = 1; dev_err(pd_data->dev, "[Rx] [0x%x] [0x%x]\n", rx->msg_header.word, rx->data_obj[0].object); @@ -394,6 +397,7 @@ protocol_state usbpd_protocol_rx_store_messageid(struct protocol_data *rx) rx->stored_message_id = rx->msg_header.msg_id; usbpd_read_msg(pd_data); + /* return PRL_Rx_Wait_for_PHY_Message; */ @@ -644,6 +648,8 @@ int usbpd_init(struct device *dev, void *phy_driver_data) usbpd_init_policy(pd_data); usbpd_init_manager(pd_data); + mutex_init(&pd_data->accept_mutex); + pd_data->policy_wqueue = create_singlethread_workqueue(dev_name(dev)); if (!pd_data->policy_wqueue) diff --git a/drivers/ccic/usbpd_manager.c b/drivers/ccic/usbpd_manager.c index 1aa4ab2f68f8..22a64049475b 100644 --- a/drivers/ccic/usbpd_manager.c +++ b/drivers/ccic/usbpd_manager.c @@ -160,7 +160,7 @@ static void init_source_cap_data(struct usbpd_manager_data *_data) data_obj->power_data_obj.data_role_swap = 1; data_obj->power_data_obj.dual_role_power = 1; data_obj->power_data_obj.usb_suspend_support = 1; - data_obj->power_data_obj.usb_comm_capable = 1; + data_obj->power_data_obj.usb_comm_capable = 0; } @@ -176,21 +176,22 @@ static void init_sink_cap_data(struct usbpd_manager_data *_data) msg_header->port_data_role = USBPD_UFP; msg_header->spec_revision = 1; msg_header->port_power_role = USBPD_SINK; - msg_header->num_data_objs = 2; + msg_header->num_data_objs = 1; data_obj->power_data_obj_sink.supply_type = POWER_TYPE_FIXED; data_obj->power_data_obj_sink.dual_role_power = 1; data_obj->power_data_obj_sink.higher_capability = 1; data_obj->power_data_obj_sink.externally_powered = 0; - data_obj->power_data_obj_sink.usb_comm_capable = 1; + data_obj->power_data_obj_sink.usb_comm_capable = 0; data_obj->power_data_obj_sink.data_role_swap = 1; data_obj->power_data_obj_sink.voltage = 5000/50; data_obj->power_data_obj_sink.op_current = 3000/10; - +#if 0 (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 = 3000 / 10; +#endif } void usbpd_manager_receive_samsung_uvdm_message(struct usbpd_data *pd_data) @@ -880,7 +881,7 @@ data_obj_type usbpd_manager_select_capability(struct usbpd_data *pd_data) int pdo_num = pd_noti.sink_status.selected_pdo_num; #endif obj.request_data_object.no_usb_suspend = 1; - obj.request_data_object.usb_comm_capable = 1; + obj.request_data_object.usb_comm_capable = 0; obj.request_data_object.capability_mismatch = 0; obj.request_data_object.give_back = 0; #ifdef CONFIG_IFCONN_NOTIFIER @@ -959,13 +960,11 @@ int usbpd_manager_match_request(struct usbpd_data *pd_data) = pd_data->source_request_obj.power_data_obj_supply_type.supply_type; unsigned src_max_current, mismatch, max_min, op, pos; - if (supply_type == POWER_TYPE_FIXED) { + if (supply_type == POWER_TYPE_FIXED) pr_info("REQUEST: FIXED\n"); - goto log_fixed_variable; - } else if (supply_type == POWER_TYPE_VARIABLE) { + else if (supply_type == POWER_TYPE_VARIABLE) pr_info("REQUEST: VARIABLE\n"); - goto log_fixed_variable; - } else if (supply_type == POWER_TYPE_BATTERY) { + else if (supply_type == POWER_TYPE_BATTERY) { pr_info("REQUEST: BATTERY\n"); goto log_battery; } else { @@ -973,7 +972,6 @@ int usbpd_manager_match_request(struct usbpd_data *pd_data) return -1; } -log_fixed_variable: /* Tx Source PDO */ src_max_current = pd_data->source_data_obj.power_data_obj.max_current; @@ -983,8 +981,9 @@ log_fixed_variable: op = pd_data->source_request_obj.request_data_object.op_current; pos = pd_data->source_request_obj.request_data_object.object_position; +#if 0 pr_info("%s %x\n", __func__, pd_data->source_request_obj.object); - +#endif /*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); diff --git a/drivers/ccic/usbpd_policy.c b/drivers/ccic/usbpd_policy.c index 39010cc07c4f..6cd419ed8895 100644 --- a/drivers/ccic/usbpd_policy.c +++ b/drivers/ccic/usbpd_policy.c @@ -162,7 +162,6 @@ policy_state usbpd_policy_src_send_capabilities(struct policy_data *policy) if (pd_data->phy_ops.get_status(pd_data, MSG_REQUEST)) { pd_data->counter.hard_reset_counter = 0; pd_data->counter.caps_counter = 0; - 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"); @@ -218,6 +217,7 @@ 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; + int data_role = 0; /********************************************** Actions on entry: @@ -233,13 +233,19 @@ policy_state usbpd_policy_src_negotiate_capability(struct policy_data *policy) /* 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); + + mutex_lock(&pd_data->accept_mutex); /* 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); + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, + data_role, USBPD_SOURCE); + dev_info(pd_data->dev, "%s sended accept\n", __func__); ret = PE_SRC_Transition_Supply; /* Accept */ } else { ret = PE_SRC_Capability_Response; /* Reject */ } + mutex_unlock(&pd_data->accept_mutex); return ret; } @@ -304,7 +310,7 @@ policy_state usbpd_policy_src_transition_supply(struct policy_data *policy) break; } - if (ms1 >= 5) { + if (ms1 >= 8) { ret = PE_SRC_Hard_Reset; break; } @@ -338,6 +344,7 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy) 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); + CHECK_MSG(pd_data, MSG_BIST, PE_BIST_Receive_Mode); #if 0 CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity); CHECK_MSG(pd_data, VDM_DISCOVER_SVID, PE_UFP_VDM_Get_SVIDs); @@ -366,14 +373,6 @@ policy_state usbpd_policy_src_ready(struct policy_data *policy) 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)) { @@ -968,9 +967,6 @@ policy_state usbpd_policy_snk_evaluate_capability(struct policy_data *policy) /* 1) PD State Inform to AP */ dev_info(pd_data->dev, "%s\n", __func__); - /* 3) Get Rx Buffer */ - usbpd_protocol_rx(pd_data); - /* 4) Select PDO */ #if defined(CONFIG_IFCONN_NOTIFIER) if (pd_noti.sink_status.selected_pdo_num == 0) { @@ -1152,6 +1148,7 @@ policy_state usbpd_policy_snk_ready(struct policy_data *policy) 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); + CHECK_MSG(pd_data, MSG_BIST, PE_BIST_Receive_Mode); #if 0 CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity); @@ -1181,14 +1178,6 @@ policy_state usbpd_policy_snk_ready(struct policy_data *policy) /* 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); @@ -1285,8 +1274,9 @@ policy_state usbpd_policy_snk_give_sink_cap(struct policy_data *policy) 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; +#if 0 policy->tx_data_obj[1].object = pd_data->sink_data_obj[1].object; - +#endif policy->sink_cap_received = 1; /* 4) Send Message */ @@ -1572,12 +1562,14 @@ policy_state usbpd_policy_drs_dfp_ufp_accept_dr_swap(struct policy_data *policy) pd_data->phy_ops.get_power_role(pd_data, &power_role); - if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, - USBPD_Accept, USBPD_DFP, power_role)) { - return PE_DRS_DFP_UFP_Change_to_UFP; - } + mutex_lock(&pd_data->accept_mutex); + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_Accept, USBPD_DFP, power_role); + + pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP); + mutex_unlock(&pd_data->accept_mutex); - return PE_DRS_DFP_UFP_Accept_DR_Swap; + return PE_DRS_DFP_UFP_Change_to_UFP; } policy_state usbpd_policy_drs_dfp_ufp_change_to_ufp(struct policy_data *policy) @@ -1593,7 +1585,6 @@ policy_state usbpd_policy_drs_dfp_ufp_change_to_ufp(struct policy_data *policy) dev_info(pd_data->dev, "%s\n", __func__); - pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP); pd_data->phy_ops.get_power_role(pd_data, &power_role); if (power_role == USBPD_SOURCE) @@ -1710,11 +1701,12 @@ policy_state usbpd_policy_drs_ufp_dfp_accept_dr_swap(struct policy_data *policy) 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_Accept, USBPD_UFP, power_role)) { - return PE_DRS_UFP_DFP_Change_to_DFP; - } - return PE_DRS_UFP_DFP_Accept_DR_Swap; + mutex_lock(&pd_data->accept_mutex); + usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, + USBPD_Accept, USBPD_UFP, power_role); + pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP); + mutex_unlock(&pd_data->accept_mutex); + return PE_DRS_UFP_DFP_Change_to_DFP; } policy_state usbpd_policy_drs_ufp_dfp_change_to_dfp(struct policy_data *policy) @@ -1729,7 +1721,6 @@ policy_state usbpd_policy_drs_ufp_dfp_change_to_dfp(struct policy_data *policy) dev_info(pd_data->dev, "%s\n", __func__); - pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP); pd_data->phy_ops.get_power_role(pd_data, &power_role); if (power_role == USBPD_SOURCE) @@ -2046,11 +2037,9 @@ policy_state usbpd_policy_prs_src_snk_wait_source_on(struct policy_data *policy) if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { dev_info(pd_data->dev, "got PSRDY.\n"); pd_data->counter.swap_hard_reset_counter = 0; - mdelay(15); - /* Self SoftReset for Message ID Clear */ pd_data->phy_ops.soft_reset(pd_data); - + mdelay(15); ret = PE_SNK_Startup; break; } @@ -2202,7 +2191,6 @@ policy_state usbpd_policy_prs_snk_src_transition_to_off(struct policy_data *poli 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); /* Start Timer 750ms */ usbpd_timer1_start(pd_data); @@ -4058,8 +4046,6 @@ policy_state usbpd_policy_dr_snk_give_source_cap(struct policy_data *policy) /* 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; diff --git a/drivers/power/supply/s2mu106_charger.c b/drivers/power/supply/s2mu106_charger.c index 79799e4063e6..2a8d6bb49325 100755 --- a/drivers/power/supply/s2mu106_charger.c +++ b/drivers/power/supply/s2mu106_charger.c @@ -72,18 +72,18 @@ static int s2mu106_charger_otg_control( pr_info("%s: called charger otg control : %s\n", __func__, enable ? "ON" : "OFF"); + mutex_lock(&charger->charger_mutex); if (charger->is_charging) { pr_info("%s: Charger is enabled and OTG noti received!!!\n", __func__); pr_info("%s: is_charging: %d, otg_on: %d", __func__, charger->is_charging, charger->otg_on); s2mu106_test_read(charger->i2c); - return 0; + goto out; } if (charger->otg_on == enable) - return 0; + goto out; - mutex_lock(&charger->charger_mutex); if (!enable) { s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL0, CHG_MODE, REG_MODE_MASK); @@ -92,12 +92,13 @@ static int s2mu106_charger_otg_control( S2MU106_CHG_CTRL3, S2MU106_SET_OTG_OCP_1500mA << SET_OTG_OCP_SHIFT, SET_OTG_OCP_MASK); -// msleep(30); s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL0, OTG_BST_MODE, REG_MODE_MASK); charger->cable_type = POWER_SUPPLY_TYPE_OTG; } charger->otg_on = enable; + +out: mutex_unlock(&charger->charger_mutex); s2mu106_read_reg(charger->i2c, S2MU106_CHG_STATUS2, &chg_sts2); @@ -113,10 +114,11 @@ static void s2mu106_enable_charger_switch( struct s2mu106_charger_data *charger, int onoff) { + mutex_lock(&charger->charger_mutex); if (charger->otg_on) { pr_info("[DEBUG] %s: skipped set(%d) : OTG is on\n", __func__, onoff); charger->is_charging = false; - return; + goto out; } if (onoff > 0) { @@ -133,6 +135,8 @@ static void s2mu106_enable_charger_switch( s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL0, BUCK_MODE, REG_MODE_MASK); } +out: + mutex_unlock(&charger->charger_mutex); } static void s2mu106_set_buck( @@ -196,7 +200,7 @@ static void s2mu106_set_input_current_limit( pr_info("[DEBUG]%s: current %d, 0x%x\n", __func__, charging_current, data); -#if EN_TEST_READ +#if 0 s2mu106_test_read(charger->i2c); #endif } @@ -236,7 +240,7 @@ static void s2mu106_set_fast_charging_current( pr_info("[DEBUG]%s: current %d, 0x%02x\n", __func__, charging_current, data); -#if EN_TEST_READ +#if 0 s2mu106_test_read(charger->i2c); #endif } diff --git a/include/linux/ccic/usbpd-s2mu106.h b/include/linux/ccic/usbpd-s2mu106.h index 613bbe3f9f3f..02adc3e4953f 100644 --- a/include/linux/ccic/usbpd-s2mu106.h +++ b/include/linux/ccic/usbpd-s2mu106.h @@ -328,32 +328,22 @@ #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 |\ - 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 |\ - 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_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 |\ - S2MU106_REG_INT_STATUS2_MSG_WAIT) +#define ENABLED_INT_0 (S2MU106_REG_INT_STATUS0_MSG_GOODCRC |\ + S2MU106_REG_INT_STATUS0_MSG_ACCEPT) +#define ENABLED_INT_1 (S2MU106_REG_INT_STATUS1_MSG_PING |\ + S2MU106_REG_INT_STATUS1_MSG_REJECT |\ + S2MU106_REG_INT_STATUS1_MSG_PSRDY |\ + S2MU106_REG_INT_STATUS1_MSG_GETSRCCAP |\ + S2MU106_REG_INT_STATUS1_MSG_GETSNKCAP |\ + S2MU106_REG_INT_STATUS1_MSG_DR_SWAP |\ + S2MU106_REG_INT_STATUS1_MSG_PR_SWAP) +#define ENABLED_INT_2 (S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP |\ + S2MU106_REG_INT_STATUS2_MSG_WAIT |\ + S2MU106_REG_INT_STATUS2_MSG_SOFTRESET) +#define ENABLED_INT_2_WAKEUP (S2MU106_REG_INT_STATUS2_MSG_VCONN_SWAP |\ + S2MU106_REG_INT_STATUS2_MSG_WAIT |\ + S2MU106_REG_INT_STATUS2_MSG_SOFTRESET |\ + 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_STATUS4_PLUG_IRQ |\ diff --git a/include/linux/ccic/usbpd.h b/include/linux/ccic/usbpd.h index ff9ab9c16d51..01658554a527 100644 --- a/include/linux/ccic/usbpd.h +++ b/include/linux/ccic/usbpd.h @@ -33,7 +33,7 @@ #define tSenderResponse (25) /* 24~30ms */ #define tSenderResponseSRC (300) /* 1000 ms */ #define tSendSourceCap (10) /* 1~2 s */ -#define tPSHardReset (25) /* 25~35 ms */ +#define tPSHardReset (17) /* 25~35 ms */ #define tSinkWaitCap (2500) /* 2.1~2.5 s */ #define tPSTransition (450) /* 450~550 ms */ #define tVCONNSourceOn (100) /* 24~30 ms */ @@ -288,7 +288,7 @@ enum usbpd_msg_status { UVDM_MSG = 1<<28, MSG_PASS = 1<<29, MSG_RID = 1<<30, - MSG_NONE = 1<<31, + MSG_BIST = 1<<31, }; /* Timer */ @@ -350,7 +350,6 @@ typedef struct usbpd_phy_ops { int (*set_cc_control)(void *, int); 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; @@ -488,6 +487,9 @@ struct usbpd_data { unsigned wait_for_msg_arrived; int lc_test; int id_matched; + bool msg_received; + int msg_id; + struct mutex accept_mutex; struct timeval time1; struct timeval time2; diff --git a/include/linux/ccic/usbpd_msg.h b/include/linux/ccic/usbpd_msg.h index bc1c0a0a9fd2..b7b6258c3123 100644 --- a/include/linux/ccic/usbpd_msg.h +++ b/include/linux/ccic/usbpd_msg.h @@ -394,5 +394,10 @@ enum usbpd_data_msg_type { USBPD_Vendor_Defined = 0xF, }; +enum usbpd_msg_type { + USBPD_CTRL_MSG = 0, + USBPD_DATA_MSG = 1, +}; + #endif -- 2.20.1