Loading drivers/usb/pd/policy_engine.c +81 −67 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ */ #include <linux/delay.h> #include <linux/hrtimer.h> #include <linux/ipc_logging.h> #include <linux/kernel.h> #include <linux/list.h> Loading Loading @@ -158,14 +159,15 @@ static void *usbpd_ipc_log; /* Timeouts (in ms) */ #define ERROR_RECOVERY_TIME 25 #define SENDER_RESPONSE_TIME 30 #define SENDER_RESPONSE_TIME 26 #define SINK_WAIT_CAP_TIME 620 #define PS_TRANSITION_TIME 550 #define PS_TRANSITION_TIME 450 #define SRC_CAP_TIME 120 #define SRC_TRANSITION_TIME 25 #define PS_HARD_RESET_TIME 35 #define SRC_RECOVER_TIME 660 #define PS_HARD_RESET_TIME 25 #define PS_SOURCE_ON 400 #define PS_SOURCE_OFF 900 #define PS_SOURCE_OFF 750 #define VDM_BUSY_TIME 50 #define PD_CAPS_COUNT 50 Loading Loading @@ -255,7 +257,8 @@ struct vdm_tx { struct usbpd { struct device dev; struct workqueue_struct *wq; struct delayed_work sm_work; struct work_struct sm_work; struct hrtimer timer; struct extcon_dev *extcon; Loading Loading @@ -483,7 +486,7 @@ 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 = true; mod_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type, Loading Loading @@ -531,7 +534,7 @@ static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type, pd->rx_msg_len = PD_MSG_HDR_COUNT(header); memcpy(&pd->rx_payload, buf, len); mod_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } static void phy_shutdown(struct usbpd *pd) Loading @@ -539,6 +542,16 @@ static void phy_shutdown(struct usbpd *pd) usbpd_dbg(&pd->dev, "shutdown"); } static enum hrtimer_restart pd_timeout(struct hrtimer *timer) { struct usbpd *pd = container_of(timer, struct usbpd, timer); usbpd_dbg(&pd->dev, "timeout"); queue_work(pd->wq, &pd->sm_work); return HRTIMER_NORESTART; } /* Enters new state and executes actions on entry */ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) { Loading @@ -562,8 +575,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_ERROR_RECOVERY: /* perform hard disconnect/reconnect */ pd->in_pr_swap = false; set_power_role(pd, PR_NONE); queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(ERROR_RECOVERY_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(ERROR_RECOVERY_TIME), HRTIMER_MODE_REL); break; /* Source states */ Loading Loading @@ -609,7 +622,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) /* fall-through */ case PE_SRC_SEND_CAPABILITIES: queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; case PE_SRC_NEGOTIATE_CAPABILITY: Loading @@ -636,16 +649,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) break; } /* * we only support VSafe5V so Aceept right away as there is * nothing more to prepare from the power supply */ pd->current_state = PE_SRC_TRANSITION_SUPPLY; usbpd_dbg(&pd->dev, "Enter %s\n", usbpd_state_strings[pd->current_state]); /* fall-through */ case PE_SRC_TRANSITION_SUPPLY: /* PE_SRC_TRANSITION_SUPPLY pseudo-state */ ret = pd_send_msg(pd, MSG_ACCEPT, NULL, 0, SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending Accept\n"); Loading @@ -653,8 +657,23 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) break; } queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SRC_TRANSITION_TIME)); /* tSrcTransition required after ACCEPT */ usleep_range(SRC_TRANSITION_TIME * USEC_PER_MSEC, (SRC_TRANSITION_TIME + 5) * USEC_PER_MSEC); /* * Normally a voltage change should occur within tSrcReady * but since we only support VSafe5V there is nothing more to * prepare from the power supply so send PS_RDY right away. */ ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending PS_RDY\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); break; } usbpd_set_state(pd, PE_SRC_READY); break; case PE_SRC_READY: Loading Loading @@ -683,7 +702,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) pd_phy_update_roles(pd->current_dr, pd->current_pr); } msleep(1000); /* tSrcRecover */ msleep(SRC_RECOVER_TIME); ret = regulator_enable(pd->vbus); if (ret) Loading @@ -703,7 +722,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SRC_HARD_RESET: case PE_SNK_HARD_RESET: /* hard reset may sleep; handle it in the workqueue */ queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; case PE_SRC_SEND_SOFT_RESET: Loading @@ -721,8 +740,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) } /* wait for ACCEPT */ queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SENDER_RESPONSE_TIME * 3)); hrtimer_start(&pd->timer, ms_to_ktime(SENDER_RESPONSE_TIME), HRTIMER_MODE_REL); break; /* Sink states */ Loading Loading @@ -771,8 +790,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) if (!pd->vbus_present) { /* can get here during a hard reset and we lost vbus */ pd->current_state = PE_SNK_DISCOVERY; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(2000)); hrtimer_start(&pd->timer, ms_to_ktime(2000), HRTIMER_MODE_REL); break; } Loading @@ -785,10 +804,11 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SNK_WAIT_FOR_CAPABILITIES: if (pd->rx_msg_len && pd->rx_msg_type) queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); else queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SINK_WAIT_CAP_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(SINK_WAIT_CAP_TIME), HRTIMER_MODE_REL); break; case PE_SNK_EVALUATE_CAPABILITY: Loading @@ -810,14 +830,14 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) usbpd_err(&pd->dev, "Error sending Request\n"); /* wait for ACCEPT */ queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SENDER_RESPONSE_TIME * 3)); hrtimer_start(&pd->timer, ms_to_ktime(SENDER_RESPONSE_TIME), HRTIMER_MODE_REL); break; case PE_SNK_TRANSITION_SINK: /* wait for PS_RDY */ queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_TRANSITION_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(PS_TRANSITION_TIME), HRTIMER_MODE_REL); break; case PE_SNK_READY: Loading Loading @@ -910,7 +930,7 @@ int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos, int num_vdos) /* VDM will get sent in PE_SRC/SNK_READY state handling */ list_add_tail(&vdm_tx->entry, &pd->vdm_tx_queue); queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); return 0; } Loading Loading @@ -1092,8 +1112,8 @@ static void handle_vdm_rx(struct usbpd *pd) /* wait tVDMBusy, then retry */ list_move(&pd->vdm_tx_retry->entry, &pd->vdm_tx_queue); pd->vdm_tx_retry = NULL; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(VDM_BUSY_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(VDM_BUSY_TIME), HRTIMER_MODE_REL); break; default: break; Loading Loading @@ -1195,7 +1215,7 @@ static void dr_swap(struct usbpd *pd) /* Handles current state and determines transitions */ static void usbpd_sm(struct work_struct *w) { struct usbpd *pd = container_of(w, struct usbpd, sm_work.work); struct usbpd *pd = container_of(w, struct usbpd, sm_work); union power_supply_propval val = {0}; int ret; enum usbpd_control_msg_type ctrl_recvd = 0; Loading @@ -1204,6 +1224,8 @@ static void usbpd_sm(struct work_struct *w) usbpd_dbg(&pd->dev, "handle state %s\n", usbpd_state_strings[pd->current_state]); hrtimer_cancel(&pd->timer); if (pd->rx_msg_len) data_recvd = pd->rx_msg_type; else Loading Loading @@ -1325,8 +1347,8 @@ static void usbpd_sm(struct work_struct *w) break; } queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SRC_CAP_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(SRC_CAP_TIME), HRTIMER_MODE_REL); break; } Loading @@ -1341,8 +1363,8 @@ static void usbpd_sm(struct work_struct *w) /* wait for REQUEST */ pd->current_state = PE_SRC_SEND_CAPABILITIES_WAIT; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SENDER_RESPONSE_TIME * 3)); hrtimer_start(&pd->timer, ms_to_ktime(SENDER_RESPONSE_TIME), HRTIMER_MODE_REL); break; case PE_SRC_SEND_CAPABILITIES_WAIT: Loading @@ -1354,17 +1376,6 @@ static void usbpd_sm(struct work_struct *w) } break; case PE_SRC_TRANSITION_SUPPLY: ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending PS_RDY\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); break; } usbpd_set_state(pd, PE_SRC_READY); break; case PE_SRC_READY: if (ctrl_recvd == MSG_GET_SOURCE_CAP) { ret = pd_send_msg(pd, MSG_SOURCE_CAPABILITIES, Loading Loading @@ -1403,7 +1414,7 @@ static void usbpd_sm(struct work_struct *w) } pd->current_state = PE_PRS_SRC_SNK_TRANSITION_TO_OFF; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; } else { if (data_recvd == MSG_VDM) Loading @@ -1418,7 +1429,8 @@ static void usbpd_sm(struct work_struct *w) pd->in_explicit_contract = false; reset_vdm_state(pd); msleep(PS_HARD_RESET_TIME); usleep_range(PS_HARD_RESET_TIME * USEC_PER_MSEC, (PS_HARD_RESET_TIME + 5) * USEC_PER_MSEC); usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT); break; Loading @@ -1429,7 +1441,7 @@ static void usbpd_sm(struct work_struct *w) POWER_SUPPLY_PROP_TYPE, &val); if (val.intval == POWER_SUPPLY_TYPEC_NONE) { pd->typec_mode = POWER_SUPPLY_TYPEC_NONE; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } break; } Loading Loading @@ -1557,8 +1569,8 @@ static void usbpd_sm(struct work_struct *w) pd->current_pr = PR_SRC; pd_phy_update_roles(pd->current_dr, pd->current_pr); queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_SOURCE_OFF)); hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF), HRTIMER_MODE_REL); break; } else { if (data_recvd == MSG_VDM) Loading Loading @@ -1659,8 +1671,8 @@ static void usbpd_sm(struct work_struct *w) } pd->current_state = PE_PRS_SRC_SNK_WAIT_SOURCE_ON; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_SOURCE_ON)); hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_ON), HRTIMER_MODE_REL); break; case PE_PRS_SRC_SNK_WAIT_SOURCE_ON: Loading Loading @@ -1688,8 +1700,8 @@ static void usbpd_sm(struct work_struct *w) pd->current_pr = PR_SRC; pd_phy_update_roles(pd->current_dr, pd->current_pr); queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_SOURCE_OFF)); hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF), HRTIMER_MODE_REL); break; case PE_PRS_SNK_SRC_TRANSITION_TO_OFF: Loading Loading @@ -1819,7 +1831,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) switch (typec_mode) { /* Disconnect */ case POWER_SUPPLY_TYPEC_NONE: queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; /* Sink states */ Loading @@ -1829,7 +1841,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) usbpd_info(&pd->dev, "Type-C Source connected\n"); if (pd->current_pr != PR_SINK) { pd->current_pr = PR_SINK; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } break; Loading @@ -1839,7 +1851,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) usbpd_info(&pd->dev, "Type-C Sink connected\n"); if (pd->current_pr != PR_SRC) { pd->current_pr = PR_SRC; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } break; Loading Loading @@ -2282,7 +2294,9 @@ struct usbpd *usbpd_create(struct device *parent) ret = -ENOMEM; goto del_pd; } INIT_DELAYED_WORK(&pd->sm_work, usbpd_sm); INIT_WORK(&pd->sm_work, usbpd_sm); hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->timer.function = pd_timeout; pd->usb_psy = power_supply_get_by_name("usb"); if (!pd->usb_psy) { Loading drivers/usb/pd/qpnp-pdphy.c +49 −13 Original line number Diff line number Diff line Loading @@ -58,6 +58,12 @@ #define USB_PDPHY_RX_ACKNOWLEDGE 0x4B #define RX_BUFFER_TOKEN BIT(0) #define USB_PDPHY_BIST_MODE 0x4E #define BIST_MODE_MASK 0xF #define BIST_ENABLE BIT(7) #define PD_MSG_BIST 0x3 #define PD_BIST_TEST_DATA_MODE 0x8 #define USB_PDPHY_TX_BUFFER_HDR 0x60 #define USB_PDPHY_TX_BUFFER_DATA 0x62 Loading Loading @@ -95,6 +101,7 @@ struct usb_pdphy { bool is_opened; int tx_status; u8 frame_filter_val; bool in_test_data_mode; enum data_role data_role; enum power_role power_role; Loading Loading @@ -233,6 +240,7 @@ void pdphy_enable_irq(struct usb_pdphy *pdphy, bool enable) enable_irq(pdphy->sig_tx_irq); enable_irq(pdphy->sig_rx_irq); enable_irq(pdphy->msg_tx_irq); if (!pdphy->in_test_data_mode) enable_irq(pdphy->msg_rx_irq); enable_irq(pdphy->msg_tx_failed_irq); enable_irq(pdphy->msg_tx_discarded_irq); Loading @@ -243,6 +251,7 @@ void pdphy_enable_irq(struct usb_pdphy *pdphy, bool enable) disable_irq(pdphy->sig_tx_irq); disable_irq(pdphy->sig_rx_irq); disable_irq(pdphy->msg_tx_irq); if (!pdphy->in_test_data_mode) disable_irq(pdphy->msg_rx_irq); disable_irq(pdphy->msg_tx_failed_irq); disable_irq(pdphy->msg_tx_discarded_irq); Loading Loading @@ -523,6 +532,9 @@ void pd_phy_close(void) wake_up_all(&pdphy->tx_waitq); pdphy_reg_write(pdphy, USB_PDPHY_BIST_MODE, 0); pdphy->in_test_data_mode = false; ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, 0); if (ret) return; Loading Loading @@ -600,6 +612,9 @@ static irqreturn_t pdphy_sig_tx_irq_thread(int irq, void *data) { struct usb_pdphy *pdphy = data; /* in case of exit from BIST Carrier Mode 2, clear BIST_MODE */ pdphy_reg_write(pdphy, USB_PDPHY_BIST_MODE, 0); pdphy->sig_tx_cnt++; pdphy->tx_status = 0; wake_up(&pdphy->tx_waitq); Loading @@ -607,10 +622,24 @@ static irqreturn_t pdphy_sig_tx_irq_thread(int irq, void *data) return IRQ_HANDLED; } static int pd_phy_bist_mode(u8 bist_mode) { struct usb_pdphy *pdphy = __pdphy; dev_dbg(pdphy->dev, "%s: enter BIST mode %d\n", __func__, bist_mode); pdphy_reg_write(pdphy, USB_PDPHY_BIST_MODE, 0); udelay(5); return pdphy_masked_write(pdphy, USB_PDPHY_BIST_MODE, BIST_MODE_MASK | BIST_ENABLE, bist_mode | BIST_ENABLE); } static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) { u8 size, rx_status, frame_type; u8 *buf = NULL; u8 buf[32]; int ret; struct usb_pdphy *pdphy = data; Loading @@ -620,9 +649,8 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) if (ret) goto done; if (!size) { dev_err(pdphy->dev, "%s: incorrect size 1byte\n", __func__); if (!size || size > 31) { dev_err(pdphy->dev, "%s: invalid size %d\n", __func__, size); goto done; } Loading @@ -637,25 +665,33 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) goto done; } buf = kmalloc(size + 1, GFP_KERNEL); if (!buf) goto done; ret = pdphy_reg_read(pdphy, buf, USB_PDPHY_RX_BUFFER, size + 1); if (ret) goto done; /* ack to change ownership of rx buffer back to PDPHY RX HW */ if (((buf[0] & 0xf) == PD_MSG_BIST) && size >= 5) { /* BIST */ u8 mode = buf[5] >> 4; /* [31:28] of 1st data object */ pd_phy_bist_mode(mode); pdphy_reg_write(pdphy, USB_PDPHY_RX_ACKNOWLEDGE, 0); if (mode == PD_BIST_TEST_DATA_MODE) { pdphy->in_test_data_mode = true; disable_irq_nosync(irq); } goto done; } if (pdphy->msg_rx_cb) pdphy->msg_rx_cb(pdphy->usbpd, frame_type, buf, size + 1); /* ack to change ownership of rx buffer back to PDPHY RX HW */ pdphy_reg_write(pdphy, USB_PDPHY_RX_ACKNOWLEDGE, 0); print_hex_dump_debug("rx msg:", DUMP_PREFIX_NONE, 32, 4, buf, size + 1, false); pdphy->rx_bytes += size + 1; done: kfree(buf); return IRQ_HANDLED; } Loading Loading
drivers/usb/pd/policy_engine.c +81 −67 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ */ #include <linux/delay.h> #include <linux/hrtimer.h> #include <linux/ipc_logging.h> #include <linux/kernel.h> #include <linux/list.h> Loading Loading @@ -158,14 +159,15 @@ static void *usbpd_ipc_log; /* Timeouts (in ms) */ #define ERROR_RECOVERY_TIME 25 #define SENDER_RESPONSE_TIME 30 #define SENDER_RESPONSE_TIME 26 #define SINK_WAIT_CAP_TIME 620 #define PS_TRANSITION_TIME 550 #define PS_TRANSITION_TIME 450 #define SRC_CAP_TIME 120 #define SRC_TRANSITION_TIME 25 #define PS_HARD_RESET_TIME 35 #define SRC_RECOVER_TIME 660 #define PS_HARD_RESET_TIME 25 #define PS_SOURCE_ON 400 #define PS_SOURCE_OFF 900 #define PS_SOURCE_OFF 750 #define VDM_BUSY_TIME 50 #define PD_CAPS_COUNT 50 Loading Loading @@ -255,7 +257,8 @@ struct vdm_tx { struct usbpd { struct device dev; struct workqueue_struct *wq; struct delayed_work sm_work; struct work_struct sm_work; struct hrtimer timer; struct extcon_dev *extcon; Loading Loading @@ -483,7 +486,7 @@ 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 = true; mod_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type, Loading Loading @@ -531,7 +534,7 @@ static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type, pd->rx_msg_len = PD_MSG_HDR_COUNT(header); memcpy(&pd->rx_payload, buf, len); mod_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } static void phy_shutdown(struct usbpd *pd) Loading @@ -539,6 +542,16 @@ static void phy_shutdown(struct usbpd *pd) usbpd_dbg(&pd->dev, "shutdown"); } static enum hrtimer_restart pd_timeout(struct hrtimer *timer) { struct usbpd *pd = container_of(timer, struct usbpd, timer); usbpd_dbg(&pd->dev, "timeout"); queue_work(pd->wq, &pd->sm_work); return HRTIMER_NORESTART; } /* Enters new state and executes actions on entry */ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) { Loading @@ -562,8 +575,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_ERROR_RECOVERY: /* perform hard disconnect/reconnect */ pd->in_pr_swap = false; set_power_role(pd, PR_NONE); queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(ERROR_RECOVERY_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(ERROR_RECOVERY_TIME), HRTIMER_MODE_REL); break; /* Source states */ Loading Loading @@ -609,7 +622,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) /* fall-through */ case PE_SRC_SEND_CAPABILITIES: queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; case PE_SRC_NEGOTIATE_CAPABILITY: Loading @@ -636,16 +649,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) break; } /* * we only support VSafe5V so Aceept right away as there is * nothing more to prepare from the power supply */ pd->current_state = PE_SRC_TRANSITION_SUPPLY; usbpd_dbg(&pd->dev, "Enter %s\n", usbpd_state_strings[pd->current_state]); /* fall-through */ case PE_SRC_TRANSITION_SUPPLY: /* PE_SRC_TRANSITION_SUPPLY pseudo-state */ ret = pd_send_msg(pd, MSG_ACCEPT, NULL, 0, SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending Accept\n"); Loading @@ -653,8 +657,23 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) break; } queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SRC_TRANSITION_TIME)); /* tSrcTransition required after ACCEPT */ usleep_range(SRC_TRANSITION_TIME * USEC_PER_MSEC, (SRC_TRANSITION_TIME + 5) * USEC_PER_MSEC); /* * Normally a voltage change should occur within tSrcReady * but since we only support VSafe5V there is nothing more to * prepare from the power supply so send PS_RDY right away. */ ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending PS_RDY\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); break; } usbpd_set_state(pd, PE_SRC_READY); break; case PE_SRC_READY: Loading Loading @@ -683,7 +702,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) pd_phy_update_roles(pd->current_dr, pd->current_pr); } msleep(1000); /* tSrcRecover */ msleep(SRC_RECOVER_TIME); ret = regulator_enable(pd->vbus); if (ret) Loading @@ -703,7 +722,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SRC_HARD_RESET: case PE_SNK_HARD_RESET: /* hard reset may sleep; handle it in the workqueue */ queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; case PE_SRC_SEND_SOFT_RESET: Loading @@ -721,8 +740,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) } /* wait for ACCEPT */ queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SENDER_RESPONSE_TIME * 3)); hrtimer_start(&pd->timer, ms_to_ktime(SENDER_RESPONSE_TIME), HRTIMER_MODE_REL); break; /* Sink states */ Loading Loading @@ -771,8 +790,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) if (!pd->vbus_present) { /* can get here during a hard reset and we lost vbus */ pd->current_state = PE_SNK_DISCOVERY; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(2000)); hrtimer_start(&pd->timer, ms_to_ktime(2000), HRTIMER_MODE_REL); break; } Loading @@ -785,10 +804,11 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SNK_WAIT_FOR_CAPABILITIES: if (pd->rx_msg_len && pd->rx_msg_type) queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); else queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SINK_WAIT_CAP_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(SINK_WAIT_CAP_TIME), HRTIMER_MODE_REL); break; case PE_SNK_EVALUATE_CAPABILITY: Loading @@ -810,14 +830,14 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) usbpd_err(&pd->dev, "Error sending Request\n"); /* wait for ACCEPT */ queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SENDER_RESPONSE_TIME * 3)); hrtimer_start(&pd->timer, ms_to_ktime(SENDER_RESPONSE_TIME), HRTIMER_MODE_REL); break; case PE_SNK_TRANSITION_SINK: /* wait for PS_RDY */ queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_TRANSITION_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(PS_TRANSITION_TIME), HRTIMER_MODE_REL); break; case PE_SNK_READY: Loading Loading @@ -910,7 +930,7 @@ int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos, int num_vdos) /* VDM will get sent in PE_SRC/SNK_READY state handling */ list_add_tail(&vdm_tx->entry, &pd->vdm_tx_queue); queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); return 0; } Loading Loading @@ -1092,8 +1112,8 @@ static void handle_vdm_rx(struct usbpd *pd) /* wait tVDMBusy, then retry */ list_move(&pd->vdm_tx_retry->entry, &pd->vdm_tx_queue); pd->vdm_tx_retry = NULL; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(VDM_BUSY_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(VDM_BUSY_TIME), HRTIMER_MODE_REL); break; default: break; Loading Loading @@ -1195,7 +1215,7 @@ static void dr_swap(struct usbpd *pd) /* Handles current state and determines transitions */ static void usbpd_sm(struct work_struct *w) { struct usbpd *pd = container_of(w, struct usbpd, sm_work.work); struct usbpd *pd = container_of(w, struct usbpd, sm_work); union power_supply_propval val = {0}; int ret; enum usbpd_control_msg_type ctrl_recvd = 0; Loading @@ -1204,6 +1224,8 @@ static void usbpd_sm(struct work_struct *w) usbpd_dbg(&pd->dev, "handle state %s\n", usbpd_state_strings[pd->current_state]); hrtimer_cancel(&pd->timer); if (pd->rx_msg_len) data_recvd = pd->rx_msg_type; else Loading Loading @@ -1325,8 +1347,8 @@ static void usbpd_sm(struct work_struct *w) break; } queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SRC_CAP_TIME)); hrtimer_start(&pd->timer, ms_to_ktime(SRC_CAP_TIME), HRTIMER_MODE_REL); break; } Loading @@ -1341,8 +1363,8 @@ static void usbpd_sm(struct work_struct *w) /* wait for REQUEST */ pd->current_state = PE_SRC_SEND_CAPABILITIES_WAIT; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(SENDER_RESPONSE_TIME * 3)); hrtimer_start(&pd->timer, ms_to_ktime(SENDER_RESPONSE_TIME), HRTIMER_MODE_REL); break; case PE_SRC_SEND_CAPABILITIES_WAIT: Loading @@ -1354,17 +1376,6 @@ static void usbpd_sm(struct work_struct *w) } break; case PE_SRC_TRANSITION_SUPPLY: ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending PS_RDY\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); break; } usbpd_set_state(pd, PE_SRC_READY); break; case PE_SRC_READY: if (ctrl_recvd == MSG_GET_SOURCE_CAP) { ret = pd_send_msg(pd, MSG_SOURCE_CAPABILITIES, Loading Loading @@ -1403,7 +1414,7 @@ static void usbpd_sm(struct work_struct *w) } pd->current_state = PE_PRS_SRC_SNK_TRANSITION_TO_OFF; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; } else { if (data_recvd == MSG_VDM) Loading @@ -1418,7 +1429,8 @@ static void usbpd_sm(struct work_struct *w) pd->in_explicit_contract = false; reset_vdm_state(pd); msleep(PS_HARD_RESET_TIME); usleep_range(PS_HARD_RESET_TIME * USEC_PER_MSEC, (PS_HARD_RESET_TIME + 5) * USEC_PER_MSEC); usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT); break; Loading @@ -1429,7 +1441,7 @@ static void usbpd_sm(struct work_struct *w) POWER_SUPPLY_PROP_TYPE, &val); if (val.intval == POWER_SUPPLY_TYPEC_NONE) { pd->typec_mode = POWER_SUPPLY_TYPEC_NONE; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } break; } Loading Loading @@ -1557,8 +1569,8 @@ static void usbpd_sm(struct work_struct *w) pd->current_pr = PR_SRC; pd_phy_update_roles(pd->current_dr, pd->current_pr); queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_SOURCE_OFF)); hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF), HRTIMER_MODE_REL); break; } else { if (data_recvd == MSG_VDM) Loading Loading @@ -1659,8 +1671,8 @@ static void usbpd_sm(struct work_struct *w) } pd->current_state = PE_PRS_SRC_SNK_WAIT_SOURCE_ON; queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_SOURCE_ON)); hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_ON), HRTIMER_MODE_REL); break; case PE_PRS_SRC_SNK_WAIT_SOURCE_ON: Loading Loading @@ -1688,8 +1700,8 @@ static void usbpd_sm(struct work_struct *w) pd->current_pr = PR_SRC; pd_phy_update_roles(pd->current_dr, pd->current_pr); queue_delayed_work(pd->wq, &pd->sm_work, msecs_to_jiffies(PS_SOURCE_OFF)); hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF), HRTIMER_MODE_REL); break; case PE_PRS_SNK_SRC_TRANSITION_TO_OFF: Loading Loading @@ -1819,7 +1831,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) switch (typec_mode) { /* Disconnect */ case POWER_SUPPLY_TYPEC_NONE: queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); break; /* Sink states */ Loading @@ -1829,7 +1841,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) usbpd_info(&pd->dev, "Type-C Source connected\n"); if (pd->current_pr != PR_SINK) { pd->current_pr = PR_SINK; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } break; Loading @@ -1839,7 +1851,7 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr) usbpd_info(&pd->dev, "Type-C Sink connected\n"); if (pd->current_pr != PR_SRC) { pd->current_pr = PR_SRC; queue_delayed_work(pd->wq, &pd->sm_work, 0); queue_work(pd->wq, &pd->sm_work); } break; Loading Loading @@ -2282,7 +2294,9 @@ struct usbpd *usbpd_create(struct device *parent) ret = -ENOMEM; goto del_pd; } INIT_DELAYED_WORK(&pd->sm_work, usbpd_sm); INIT_WORK(&pd->sm_work, usbpd_sm); hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->timer.function = pd_timeout; pd->usb_psy = power_supply_get_by_name("usb"); if (!pd->usb_psy) { Loading
drivers/usb/pd/qpnp-pdphy.c +49 −13 Original line number Diff line number Diff line Loading @@ -58,6 +58,12 @@ #define USB_PDPHY_RX_ACKNOWLEDGE 0x4B #define RX_BUFFER_TOKEN BIT(0) #define USB_PDPHY_BIST_MODE 0x4E #define BIST_MODE_MASK 0xF #define BIST_ENABLE BIT(7) #define PD_MSG_BIST 0x3 #define PD_BIST_TEST_DATA_MODE 0x8 #define USB_PDPHY_TX_BUFFER_HDR 0x60 #define USB_PDPHY_TX_BUFFER_DATA 0x62 Loading Loading @@ -95,6 +101,7 @@ struct usb_pdphy { bool is_opened; int tx_status; u8 frame_filter_val; bool in_test_data_mode; enum data_role data_role; enum power_role power_role; Loading Loading @@ -233,6 +240,7 @@ void pdphy_enable_irq(struct usb_pdphy *pdphy, bool enable) enable_irq(pdphy->sig_tx_irq); enable_irq(pdphy->sig_rx_irq); enable_irq(pdphy->msg_tx_irq); if (!pdphy->in_test_data_mode) enable_irq(pdphy->msg_rx_irq); enable_irq(pdphy->msg_tx_failed_irq); enable_irq(pdphy->msg_tx_discarded_irq); Loading @@ -243,6 +251,7 @@ void pdphy_enable_irq(struct usb_pdphy *pdphy, bool enable) disable_irq(pdphy->sig_tx_irq); disable_irq(pdphy->sig_rx_irq); disable_irq(pdphy->msg_tx_irq); if (!pdphy->in_test_data_mode) disable_irq(pdphy->msg_rx_irq); disable_irq(pdphy->msg_tx_failed_irq); disable_irq(pdphy->msg_tx_discarded_irq); Loading Loading @@ -523,6 +532,9 @@ void pd_phy_close(void) wake_up_all(&pdphy->tx_waitq); pdphy_reg_write(pdphy, USB_PDPHY_BIST_MODE, 0); pdphy->in_test_data_mode = false; ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, 0); if (ret) return; Loading Loading @@ -600,6 +612,9 @@ static irqreturn_t pdphy_sig_tx_irq_thread(int irq, void *data) { struct usb_pdphy *pdphy = data; /* in case of exit from BIST Carrier Mode 2, clear BIST_MODE */ pdphy_reg_write(pdphy, USB_PDPHY_BIST_MODE, 0); pdphy->sig_tx_cnt++; pdphy->tx_status = 0; wake_up(&pdphy->tx_waitq); Loading @@ -607,10 +622,24 @@ static irqreturn_t pdphy_sig_tx_irq_thread(int irq, void *data) return IRQ_HANDLED; } static int pd_phy_bist_mode(u8 bist_mode) { struct usb_pdphy *pdphy = __pdphy; dev_dbg(pdphy->dev, "%s: enter BIST mode %d\n", __func__, bist_mode); pdphy_reg_write(pdphy, USB_PDPHY_BIST_MODE, 0); udelay(5); return pdphy_masked_write(pdphy, USB_PDPHY_BIST_MODE, BIST_MODE_MASK | BIST_ENABLE, bist_mode | BIST_ENABLE); } static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) { u8 size, rx_status, frame_type; u8 *buf = NULL; u8 buf[32]; int ret; struct usb_pdphy *pdphy = data; Loading @@ -620,9 +649,8 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) if (ret) goto done; if (!size) { dev_err(pdphy->dev, "%s: incorrect size 1byte\n", __func__); if (!size || size > 31) { dev_err(pdphy->dev, "%s: invalid size %d\n", __func__, size); goto done; } Loading @@ -637,25 +665,33 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) goto done; } buf = kmalloc(size + 1, GFP_KERNEL); if (!buf) goto done; ret = pdphy_reg_read(pdphy, buf, USB_PDPHY_RX_BUFFER, size + 1); if (ret) goto done; /* ack to change ownership of rx buffer back to PDPHY RX HW */ if (((buf[0] & 0xf) == PD_MSG_BIST) && size >= 5) { /* BIST */ u8 mode = buf[5] >> 4; /* [31:28] of 1st data object */ pd_phy_bist_mode(mode); pdphy_reg_write(pdphy, USB_PDPHY_RX_ACKNOWLEDGE, 0); if (mode == PD_BIST_TEST_DATA_MODE) { pdphy->in_test_data_mode = true; disable_irq_nosync(irq); } goto done; } if (pdphy->msg_rx_cb) pdphy->msg_rx_cb(pdphy->usbpd, frame_type, buf, size + 1); /* ack to change ownership of rx buffer back to PDPHY RX HW */ pdphy_reg_write(pdphy, USB_PDPHY_RX_ACKNOWLEDGE, 0); print_hex_dump_debug("rx msg:", DUMP_PREFIX_NONE, 32, 4, buf, size + 1, false); pdphy->rx_bytes += size + 1; done: kfree(buf); return IRQ_HANDLED; } Loading