Merge "usb: pd: Increment MessageID only on successful TX"
This commit is contained in:
commit
3f35f049e7
2 changed files with 60 additions and 16 deletions
|
@ -488,13 +488,12 @@ static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data,
|
||||||
ret = pd_phy_write(hdr, (u8 *)data, num_data * sizeof(u32), type, 15);
|
ret = pd_phy_write(hdr, (u8 *)data, num_data * sizeof(u32), type, 15);
|
||||||
/* TODO figure out timeout. based on tReceive=1.1ms x nRetryCount? */
|
/* TODO figure out timeout. based on tReceive=1.1ms x nRetryCount? */
|
||||||
|
|
||||||
/* MessageID incremented regardless of Tx error */
|
|
||||||
pd->tx_msgid = (pd->tx_msgid + 1) & PD_MAX_MSG_ID;
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
else if (ret != num_data * sizeof(u32))
|
else if (ret != num_data * sizeof(u32))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
pd->tx_msgid = (pd->tx_msgid + 1) & PD_MAX_MSG_ID;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,6 +585,8 @@ static int pd_eval_src_caps(struct usbpd *pd)
|
||||||
|
|
||||||
static void pd_send_hard_reset(struct usbpd *pd)
|
static void pd_send_hard_reset(struct usbpd *pd)
|
||||||
{
|
{
|
||||||
|
union power_supply_propval val = {0};
|
||||||
|
|
||||||
usbpd_dbg(&pd->dev, "send hard reset");
|
usbpd_dbg(&pd->dev, "send hard reset");
|
||||||
|
|
||||||
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
|
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
|
||||||
|
@ -593,6 +594,7 @@ static void pd_send_hard_reset(struct usbpd *pd)
|
||||||
pd->hard_reset_count++;
|
pd->hard_reset_count++;
|
||||||
pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
|
pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
|
||||||
pd->in_pr_swap = false;
|
pd->in_pr_swap = false;
|
||||||
|
power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kick_sm(struct usbpd *pd, int ms)
|
static void kick_sm(struct usbpd *pd, int ms)
|
||||||
|
@ -608,6 +610,8 @@ static void kick_sm(struct usbpd *pd, int ms)
|
||||||
|
|
||||||
static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
|
static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
|
||||||
{
|
{
|
||||||
|
union power_supply_propval val = {1};
|
||||||
|
|
||||||
if (type != HARD_RESET_SIG) {
|
if (type != HARD_RESET_SIG) {
|
||||||
usbpd_err(&pd->dev, "invalid signal (%d) received\n", type);
|
usbpd_err(&pd->dev, "invalid signal (%d) received\n", type);
|
||||||
return;
|
return;
|
||||||
|
@ -618,6 +622,9 @@ static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
|
||||||
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
|
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
|
||||||
set_power_role(pd, pd->current_pr);
|
set_power_role(pd, pd->current_pr);
|
||||||
pd->hard_reset_recvd = true;
|
pd->hard_reset_recvd = true;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
||||||
|
|
||||||
kick_sm(pd, 0);
|
kick_sm(pd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,6 +790,9 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
|
||||||
if (pd->in_pr_swap) {
|
if (pd->in_pr_swap) {
|
||||||
kick_sm(pd, SWAP_SOURCE_START_TIME);
|
kick_sm(pd, SWAP_SOURCE_START_TIME);
|
||||||
pd->in_pr_swap = false;
|
pd->in_pr_swap = false;
|
||||||
|
val.intval = 0;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1572,7 +1582,6 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
memset(&pd->received_pdos, 0, sizeof(pd->received_pdos));
|
memset(&pd->received_pdos, 0, sizeof(pd->received_pdos));
|
||||||
rx_msg_cleanup(pd);
|
rx_msg_cleanup(pd);
|
||||||
|
|
||||||
val.intval = 0;
|
|
||||||
power_supply_set_property(pd->usb_psy,
|
power_supply_set_property(pd->usb_psy,
|
||||||
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
||||||
|
|
||||||
|
@ -1603,6 +1612,10 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
usleep_range(ERROR_RECOVERY_TIME * USEC_PER_MSEC,
|
usleep_range(ERROR_RECOVERY_TIME * USEC_PER_MSEC,
|
||||||
(ERROR_RECOVERY_TIME + 5) * USEC_PER_MSEC);
|
(ERROR_RECOVERY_TIME + 5) * USEC_PER_MSEC);
|
||||||
|
|
||||||
|
val.intval = 0;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
|
|
||||||
/* set due to dual_role class "mode" change */
|
/* set due to dual_role class "mode" change */
|
||||||
if (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE)
|
if (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE)
|
||||||
val.intval = pd->forced_pr;
|
val.intval = pd->forced_pr;
|
||||||
|
@ -1626,11 +1639,22 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
if (pd->hard_reset_recvd) {
|
if (pd->hard_reset_recvd) {
|
||||||
pd->hard_reset_recvd = false;
|
pd->hard_reset_recvd = false;
|
||||||
|
|
||||||
val.intval = 1;
|
if (pd->requested_current) {
|
||||||
|
val.intval = pd->requested_current = 0;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->requested_voltage = 5000000;
|
||||||
|
val.intval = pd->requested_voltage;
|
||||||
power_supply_set_property(pd->usb_psy,
|
power_supply_set_property(pd->usb_psy,
|
||||||
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
|
POWER_SUPPLY_PROP_VOLTAGE_MIN, &val);
|
||||||
|
|
||||||
pd->in_pr_swap = false;
|
pd->in_pr_swap = false;
|
||||||
|
val.intval = 0;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
|
|
||||||
pd->in_explicit_contract = false;
|
pd->in_explicit_contract = false;
|
||||||
pd->selected_pdo = pd->requested_pdo = 0;
|
pd->selected_pdo = pd->requested_pdo = 0;
|
||||||
pd->rdo = 0;
|
pd->rdo = 0;
|
||||||
|
@ -1891,6 +1915,9 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
|
|
||||||
case PE_SNK_WAIT_FOR_CAPABILITIES:
|
case PE_SNK_WAIT_FOR_CAPABILITIES:
|
||||||
pd->in_pr_swap = false;
|
pd->in_pr_swap = false;
|
||||||
|
val.intval = 0;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
|
|
||||||
if (IS_DATA(rx_msg, MSG_SOURCE_CAPABILITIES)) {
|
if (IS_DATA(rx_msg, MSG_SOURCE_CAPABILITIES)) {
|
||||||
val.intval = 0;
|
val.intval = 0;
|
||||||
|
@ -1910,15 +1937,6 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
|
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
|
||||||
} else if (pd->hard_reset_count < 3) {
|
} else if (pd->hard_reset_count < 3) {
|
||||||
usbpd_set_state(pd, PE_SNK_HARD_RESET);
|
usbpd_set_state(pd, PE_SNK_HARD_RESET);
|
||||||
} else if (pd->pd_connected) {
|
|
||||||
usbpd_info(&pd->dev, "Sink hard reset count exceeded, forcing reconnect\n");
|
|
||||||
|
|
||||||
val.intval = 0;
|
|
||||||
power_supply_set_property(pd->usb_psy,
|
|
||||||
POWER_SUPPLY_PROP_PD_IN_HARD_RESET,
|
|
||||||
&val);
|
|
||||||
|
|
||||||
usbpd_set_state(pd, PE_ERROR_RECOVERY);
|
|
||||||
} else {
|
} else {
|
||||||
usbpd_dbg(&pd->dev, "Sink hard reset count exceeded, disabling PD\n");
|
usbpd_dbg(&pd->dev, "Sink hard reset count exceeded, disabling PD\n");
|
||||||
|
|
||||||
|
@ -2069,6 +2087,9 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
}
|
}
|
||||||
|
|
||||||
pd->in_pr_swap = true;
|
pd->in_pr_swap = true;
|
||||||
|
val.intval = 1;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
|
usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
|
||||||
break;
|
break;
|
||||||
} else if (IS_CTRL(rx_msg, MSG_VCONN_SWAP)) {
|
} else if (IS_CTRL(rx_msg, MSG_VCONN_SWAP)) {
|
||||||
|
@ -2212,6 +2233,9 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
|
|
||||||
case PE_PRS_SRC_SNK_TRANSITION_TO_OFF:
|
case PE_PRS_SRC_SNK_TRANSITION_TO_OFF:
|
||||||
pd->in_pr_swap = true;
|
pd->in_pr_swap = true;
|
||||||
|
val.intval = 1;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
pd->in_explicit_contract = false;
|
pd->in_explicit_contract = false;
|
||||||
|
|
||||||
if (pd->vbus_enabled) {
|
if (pd->vbus_enabled) {
|
||||||
|
@ -2252,6 +2276,9 @@ static void usbpd_sm(struct work_struct *w)
|
||||||
}
|
}
|
||||||
|
|
||||||
pd->in_pr_swap = true;
|
pd->in_pr_swap = true;
|
||||||
|
val.intval = 1;
|
||||||
|
power_supply_set_property(pd->usb_psy,
|
||||||
|
POWER_SUPPLY_PROP_PR_SWAP, &val);
|
||||||
usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
|
usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@ struct usb_pdphy {
|
||||||
int tx_status;
|
int tx_status;
|
||||||
u8 frame_filter_val;
|
u8 frame_filter_val;
|
||||||
bool in_test_data_mode;
|
bool in_test_data_mode;
|
||||||
|
bool rx_busy;
|
||||||
|
|
||||||
enum data_role data_role;
|
enum data_role data_role;
|
||||||
enum power_role power_role;
|
enum power_role power_role;
|
||||||
|
@ -485,6 +486,12 @@ int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = pdphy_reg_read(pdphy, &val, USB_PDPHY_RX_ACKNOWLEDGE, 1);
|
||||||
|
if (ret || val || pdphy->rx_busy) {
|
||||||
|
dev_err(pdphy->dev, "%s: RX message pending\n", __func__);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
pdphy->tx_status = -EINPROGRESS;
|
pdphy->tx_status = -EINPROGRESS;
|
||||||
|
|
||||||
/* write 2 byte SOP message header */
|
/* write 2 byte SOP message header */
|
||||||
|
@ -657,6 +664,15 @@ static int pd_phy_bist_mode(u8 bist_mode)
|
||||||
BIST_MODE_MASK | BIST_ENABLE, bist_mode | BIST_ENABLE);
|
BIST_MODE_MASK | BIST_ENABLE, bist_mode | BIST_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static irqreturn_t pdphy_msg_rx_irq(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct usb_pdphy *pdphy = data;
|
||||||
|
|
||||||
|
pdphy->rx_busy = true;
|
||||||
|
|
||||||
|
return IRQ_WAKE_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data)
|
static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data)
|
||||||
{
|
{
|
||||||
u8 size, rx_status, frame_type;
|
u8 size, rx_status, frame_type;
|
||||||
|
@ -713,6 +729,7 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data)
|
||||||
false);
|
false);
|
||||||
pdphy->rx_bytes += size + 1;
|
pdphy->rx_bytes += size + 1;
|
||||||
done:
|
done:
|
||||||
|
pdphy->rx_busy = false;
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -798,7 +815,7 @@ static int pdphy_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = pdphy_request_irq(pdphy, pdev->dev.of_node,
|
ret = pdphy_request_irq(pdphy, pdev->dev.of_node,
|
||||||
&pdphy->msg_rx_irq, "msg-rx", NULL,
|
&pdphy->msg_rx_irq, "msg-rx", pdphy_msg_rx_irq,
|
||||||
pdphy_msg_rx_irq_thread, (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
|
pdphy_msg_rx_irq_thread, (IRQF_TRIGGER_RISING | IRQF_ONESHOT));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Add table
Reference in a new issue