Merge "ARM: dts: msm: Allow only wfi based on USB irq load for msmfalcon"
This commit is contained in:
commit
48a7875c4f
3 changed files with 96 additions and 0 deletions
|
@ -60,6 +60,8 @@ Optional properties :
|
|||
should point to external connector device, which provide "USB-HOST"
|
||||
cable events. A single phandle may be specified if a single connector
|
||||
device provides both "USB" and "USB-HOST" events.
|
||||
- qcom,pm-qos-latency: This represents max tolerable CPU latency in microsecs,
|
||||
which is used as a vote by driver to get max performance in perf mode.
|
||||
|
||||
Sub nodes:
|
||||
- Sub node for "DWC3- USB3 controller".
|
||||
|
@ -84,6 +86,7 @@ Example MSM USB3.0 controller device node :
|
|||
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
|
||||
qcom,usb-dbm = <&dbm_1p4>;
|
||||
qcom,lpm-to-suspend-delay-ms = <2>;
|
||||
qcom,pm-qos-latency = <2>;
|
||||
|
||||
qcom,msm_bus,name = "usb3";
|
||||
qcom,msm_bus,num_cases = <2>;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
|
||||
extcon = <&pmfalcon_pdphy>;
|
||||
qcom,pm-qos-latency = <41>; /* CPU-CLUSTER-WFI-LVL latency +1 */
|
||||
|
||||
clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
|
||||
<&clock_gcc GCC_CFG_NOC_USB3_AXI_CLK>,
|
||||
|
|
|
@ -143,6 +143,9 @@ enum plug_orientation {
|
|||
#define B_SESS_VLD 1
|
||||
#define B_SUSPEND 2
|
||||
|
||||
#define PM_QOS_SAMPLE_SEC 2
|
||||
#define PM_QOS_THRESHOLD 400
|
||||
|
||||
struct dwc3_msm {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
|
@ -219,6 +222,9 @@ struct dwc3_msm {
|
|||
unsigned int lpm_to_suspend_delay;
|
||||
bool init;
|
||||
enum plug_orientation typec_orientation;
|
||||
int pm_qos_latency;
|
||||
struct pm_qos_request pm_qos_req_dma;
|
||||
struct delayed_work perf_vote_work;
|
||||
};
|
||||
|
||||
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
|
||||
|
@ -1952,6 +1958,8 @@ static void dwc3_set_phy_speed_flags(struct dwc3_msm *mdwc)
|
|||
}
|
||||
}
|
||||
|
||||
static void msm_dwc3_perf_vote_update(struct dwc3_msm *mdwc,
|
||||
bool perf_mode);
|
||||
|
||||
static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
|
||||
{
|
||||
|
@ -1966,6 +1974,9 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&mdwc->perf_vote_work);
|
||||
msm_dwc3_perf_vote_update(mdwc, false);
|
||||
|
||||
if (!mdwc->in_host_mode) {
|
||||
/* pending device events unprocessed */
|
||||
for (i = 0; i < dwc->num_event_buffers; i++) {
|
||||
|
@ -2244,6 +2255,10 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
|
|||
*/
|
||||
dwc3_pwr_event_handler(mdwc);
|
||||
|
||||
if (pm_qos_request_active(&mdwc->pm_qos_req_dma))
|
||||
schedule_delayed_work(&mdwc->perf_vote_work,
|
||||
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
|
||||
|
||||
dbg_event(0xFF, "Ctl Res", atomic_read(&dwc->in_lpm));
|
||||
|
||||
return 0;
|
||||
|
@ -2702,6 +2717,7 @@ static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
|
|||
}
|
||||
|
||||
static DEVICE_ATTR_RW(mode);
|
||||
static void msm_dwc3_perf_vote_work(struct work_struct *w);
|
||||
|
||||
static int dwc3_msm_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -2737,6 +2753,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
|
|||
INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w);
|
||||
INIT_WORK(&mdwc->vbus_draw_work, dwc3_msm_vbus_draw_work);
|
||||
INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work);
|
||||
INIT_DELAYED_WORK(&mdwc->perf_vote_work, msm_dwc3_perf_vote_work);
|
||||
|
||||
mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0);
|
||||
if (!mdwc->dwc3_wq) {
|
||||
|
@ -3012,6 +3029,13 @@ static int dwc3_msm_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto put_dwc3;
|
||||
|
||||
ret = of_property_read_u32(node, "qcom,pm-qos-latency",
|
||||
&mdwc->pm_qos_latency);
|
||||
if (ret) {
|
||||
dev_dbg(&pdev->dev, "setting pm-qos-latency to zero.\n");
|
||||
mdwc->pm_qos_latency = 0;
|
||||
}
|
||||
|
||||
/* Update initial VBUS/ID state from extcon */
|
||||
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
|
||||
EXTCON_USB))
|
||||
|
@ -3077,6 +3101,7 @@ static int dwc3_msm_remove(struct platform_device *pdev)
|
|||
clk_prepare_enable(mdwc->xo_clk);
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&mdwc->perf_vote_work);
|
||||
cancel_delayed_work_sync(&mdwc->sm_work);
|
||||
|
||||
if (mdwc->hs_phy)
|
||||
|
@ -3162,6 +3187,45 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static void msm_dwc3_perf_vote_update(struct dwc3_msm *mdwc, bool perf_mode)
|
||||
{
|
||||
static bool curr_perf_mode;
|
||||
int latency = mdwc->pm_qos_latency;
|
||||
|
||||
if ((curr_perf_mode == perf_mode) || !latency)
|
||||
return;
|
||||
|
||||
if (perf_mode)
|
||||
pm_qos_update_request(&mdwc->pm_qos_req_dma, latency);
|
||||
else
|
||||
pm_qos_update_request(&mdwc->pm_qos_req_dma,
|
||||
PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
curr_perf_mode = perf_mode;
|
||||
pr_debug("%s: latency updated to: %d\n", __func__,
|
||||
perf_mode ? latency : PM_QOS_DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
static void msm_dwc3_perf_vote_work(struct work_struct *w)
|
||||
{
|
||||
struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
|
||||
perf_vote_work.work);
|
||||
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
|
||||
static unsigned long last_irq_cnt;
|
||||
bool in_perf_mode = false;
|
||||
|
||||
if (dwc->irq_cnt - last_irq_cnt >= PM_QOS_THRESHOLD)
|
||||
in_perf_mode = true;
|
||||
|
||||
pr_debug("%s: in_perf_mode:%u, interrupts in last sample:%lu\n",
|
||||
__func__, in_perf_mode, (dwc->irq_cnt - last_irq_cnt));
|
||||
|
||||
last_irq_cnt = dwc->irq_cnt;
|
||||
msm_dwc3_perf_vote_update(mdwc, in_perf_mode);
|
||||
schedule_delayed_work(&mdwc->perf_vote_work,
|
||||
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
|
||||
}
|
||||
|
||||
#define VBUS_REG_CHECK_DELAY (msecs_to_jiffies(1000))
|
||||
|
||||
/**
|
||||
|
@ -3267,6 +3331,16 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
|
|||
atomic_read(&mdwc->dev->power.usage_count));
|
||||
pm_runtime_mark_last_busy(mdwc->dev);
|
||||
pm_runtime_put_sync_autosuspend(mdwc->dev);
|
||||
#ifdef CONFIG_SMP
|
||||
mdwc->pm_qos_req_dma.type = PM_QOS_REQ_AFFINE_IRQ;
|
||||
mdwc->pm_qos_req_dma.irq = dwc->irq;
|
||||
#endif
|
||||
pm_qos_add_request(&mdwc->pm_qos_req_dma,
|
||||
PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
|
||||
/* start in perf mode for better performance initially */
|
||||
msm_dwc3_perf_vote_update(mdwc, true);
|
||||
schedule_delayed_work(&mdwc->perf_vote_work,
|
||||
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
|
||||
} else {
|
||||
dev_dbg(mdwc->dev, "%s: turn off host\n", __func__);
|
||||
|
||||
|
@ -3278,6 +3352,10 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
|
|||
return ret;
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&mdwc->perf_vote_work);
|
||||
msm_dwc3_perf_vote_update(mdwc, false);
|
||||
pm_qos_remove_request(&mdwc->pm_qos_req_dma);
|
||||
|
||||
pm_runtime_get_sync(mdwc->dev);
|
||||
dbg_event(0xFF, "StopHost gsync",
|
||||
atomic_read(&mdwc->dev->power.usage_count));
|
||||
|
@ -3359,9 +3437,23 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
|
|||
|
||||
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
|
||||
usb_gadget_vbus_connect(&dwc->gadget);
|
||||
#ifdef CONFIG_SMP
|
||||
mdwc->pm_qos_req_dma.type = PM_QOS_REQ_AFFINE_IRQ;
|
||||
mdwc->pm_qos_req_dma.irq = dwc->irq;
|
||||
#endif
|
||||
pm_qos_add_request(&mdwc->pm_qos_req_dma,
|
||||
PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
|
||||
/* start in perf mode for better performance initially */
|
||||
msm_dwc3_perf_vote_update(mdwc, true);
|
||||
schedule_delayed_work(&mdwc->perf_vote_work,
|
||||
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
|
||||
} else {
|
||||
dev_dbg(mdwc->dev, "%s: turn off gadget %s\n",
|
||||
__func__, dwc->gadget.name);
|
||||
cancel_delayed_work_sync(&mdwc->perf_vote_work);
|
||||
msm_dwc3_perf_vote_update(mdwc, false);
|
||||
pm_qos_remove_request(&mdwc->pm_qos_req_dma);
|
||||
|
||||
usb_gadget_vbus_disconnect(&dwc->gadget);
|
||||
usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH);
|
||||
usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER);
|
||||
|
|
Loading…
Add table
Reference in a new issue