Merge "usb: pd: Increment MessageID only on successful TX"

This commit is contained in:
Linux Build Service Account 2017-06-07 20:57:55 -07:00 committed by Gerrit - the friendly Code Review server
commit 3f35f049e7
2 changed files with 60 additions and 16 deletions

View file

@ -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);
/* 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)
return ret;
else if (ret != num_data * sizeof(u32))
return -EIO;
pd->tx_msgid = (pd->tx_msgid + 1) & PD_MAX_MSG_ID;
return 0;
}
@ -586,6 +585,8 @@ static int pd_eval_src_caps(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");
/* 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_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
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)
@ -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)
{
union power_supply_propval val = {1};
if (type != HARD_RESET_SIG) {
usbpd_err(&pd->dev, "invalid signal (%d) received\n", type);
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 */
set_power_role(pd, pd->current_pr);
pd->hard_reset_recvd = true;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
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) {
kick_sm(pd, SWAP_SOURCE_START_TIME);
pd->in_pr_swap = false;
val.intval = 0;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PR_SWAP, &val);
break;
}
@ -1572,7 +1582,6 @@ static void usbpd_sm(struct work_struct *w)
memset(&pd->received_pdos, 0, sizeof(pd->received_pdos));
rx_msg_cleanup(pd);
val.intval = 0;
power_supply_set_property(pd->usb_psy,
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,
(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 */
if (pd->forced_pr != POWER_SUPPLY_TYPEC_PR_NONE)
val.intval = pd->forced_pr;
@ -1626,11 +1639,22 @@ static void usbpd_sm(struct work_struct *w)
if (pd->hard_reset_recvd) {
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_IN_HARD_RESET, &val);
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_PROP_VOLTAGE_MIN, &val);
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->selected_pdo = pd->requested_pdo = 0;
pd->rdo = 0;
@ -1891,6 +1915,9 @@ static void usbpd_sm(struct work_struct *w)
case PE_SNK_WAIT_FOR_CAPABILITIES:
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)) {
val.intval = 0;
@ -1910,15 +1937,6 @@ static void usbpd_sm(struct work_struct *w)
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
} else if (pd->hard_reset_count < 3) {
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 {
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;
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);
break;
} 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:
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;
if (pd->vbus_enabled) {
@ -2252,6 +2276,9 @@ static void usbpd_sm(struct work_struct *w)
}
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);
break;

View file

@ -108,6 +108,7 @@ struct usb_pdphy {
int tx_status;
u8 frame_filter_val;
bool in_test_data_mode;
bool rx_busy;
enum data_role data_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;
}
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;
/* 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);
}
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)
{
u8 size, rx_status, frame_type;
@ -713,6 +729,7 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data)
false);
pdphy->rx_bytes += size + 1;
done:
pdphy->rx_busy = false;
return IRQ_HANDLED;
}
@ -798,7 +815,7 @@ static int pdphy_probe(struct platform_device *pdev)
return ret;
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));
if (ret < 0)
return ret;