Loading Documentation/devicetree/bindings/usb/msm-ssusb.txt +0 −2 Original line number Diff line number Diff line Loading @@ -31,8 +31,6 @@ Optional properties : regulator node to the USB controller. - qcom,dwc-usb3-msm-tx-fifo-size: If present, represents RAM size available for TX fifo allocation in bytes - qcom,utmi-clk-rate: Indicates refclk frequency (in Hz) to the core. If not specified, default of 19.2MHz is assumed. - qcom,usb-dbm : phandle for the DBM device - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform power collapse when cable is disconencted. Loading drivers/usb/common/common.c +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ const char *usb_otg_state_string(enum usb_otg_state state) { static const char *const names[] = { [OTG_STATE_UNDEFINED] = "undefined", [OTG_STATE_A_IDLE] = "a_idle", [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise", [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon", Loading drivers/usb/dwc3/core.c +63 −70 Original line number Diff line number Diff line Loading @@ -683,41 +683,16 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) static int dwc3_core_init_mode(struct dwc3 *dwc) { struct device *dev = dwc->dev; int ret; switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); return ret; } break; case USB_DR_MODE_HOST: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); return ret; } break; case USB_DR_MODE_OTG: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); dwc->is_drd = true; ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); return ret; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); dwc3_host_exit(dwc); return ret; } break; default: dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); Loading Loading @@ -774,6 +749,49 @@ int dwc3_notify_event(struct dwc3 *dwc, unsigned event) } EXPORT_SYMBOL(dwc3_notify_event); int dwc3_core_pre_init(struct dwc3 *dwc) { int ret; dwc3_cache_hwparams(dwc); if (!dwc->ev_buffs) { ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err_alloc; } } ret = dwc3_core_init(dwc); if (ret) { dev_err(dwc->dev, "failed to initialize core\n"); goto err0; } ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err0; } ret = dwc3_core_init_mode(dwc); if (ret) { dev_err(dwc->dev, "failed to set mode with dwc3 core\n"); goto err1; } return ret; err1: dwc3_event_buffers_cleanup(dwc); err0: dwc3_core_exit(dwc); dwc3_free_event_buffers(dwc); err_alloc: return ret; } #define DWC3_ALIGN_MASK (16 - 1) static int dwc3_probe(struct platform_device *pdev) Loading Loading @@ -915,81 +933,58 @@ static int dwc3_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); dwc3_cache_hwparams(dwc); if (!dwc->ev_buffs) { ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err0; } } if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) dwc->dr_mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) dwc->dr_mode = USB_DR_MODE_PERIPHERAL; if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) { dwc->dr_mode = USB_DR_MODE_OTG; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err0; dwc->is_drd = true; } usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err1; goto err; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err_usb2phy_power; ret = dwc3_event_buffers_setup(dwc); ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); dev_err(dev, "failed to initialize debugfs\n"); goto err_usb3phy_power; } ret = dwc3_core_init_mode(dwc); if (ret) goto err2; /* Hardcode number of eps */ dwc->num_in_eps = 16; dwc->num_out_eps = 16; ret = dwc3_debugfs_init(dwc); ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); goto err3; dev_err(dev, "failed to initialize gadget\n"); goto err_usb3phy_power; } ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); goto err_gadget_exit; } dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_INITIALIZATION_EVENT); return 0; err3: dwc3_core_exit_mode(dwc); err2: dwc3_event_buffers_cleanup(dwc); err_gadget_exit: dwc3_gadget_exit(dwc); err_usb3phy_power: phy_power_off(dwc->usb3_generic_phy); err_usb2phy_power: phy_power_off(dwc->usb2_generic_phy); err1: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); dwc3_core_exit(dwc); err0: dwc3_free_event_buffers(dwc); err: return ret; } Loading @@ -1002,8 +997,6 @@ static int dwc3_remove(struct platform_device *pdev) dwc3_event_buffers_cleanup(dwc); dwc3_free_event_buffers(dwc); usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy); Loading drivers/usb/dwc3/core.h +1 −0 Original line number Diff line number Diff line Loading @@ -1183,6 +1183,7 @@ static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) { } #endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ int dwc3_core_init(struct dwc3 *dwc); int dwc3_core_pre_init(struct dwc3 *dwc); void dwc3_post_host_reset_core_init(struct dwc3 *dwc); int dwc3_event_buffers_setup(struct dwc3 *dwc); Loading drivers/usb/dwc3/dwc3-msm.c +239 −187 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ #define DWC3_IDEV_CHG_MAX 1500 #define DWC3_HVDCP_CHG_MAX 1800 /* time out to wait for USB cable status notification (in ms)*/ #define SM_INIT_TIMEOUT 30000 /* cpu to fix usb interrupt */ static int cpu_to_affin; module_param(cpu_to_affin, int, S_IRUGO|S_IWUSR); Loading Loading @@ -937,17 +940,10 @@ EXPORT_SYMBOL(msm_dwc3_reset_ep_after_lpm); */ static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on) { int ret = 0; if (IS_ERR(mdwc->dwc3_gdsc)) return 0; int ret; if (!mdwc->dwc3_gdsc) { mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev, "USB3_GDSC"); if (IS_ERR(mdwc->dwc3_gdsc)) return 0; } if (IS_ERR_OR_NULL(mdwc->dwc3_gdsc)) return -EPERM; if (on) { ret = regulator_enable(mdwc->dwc3_gdsc); Loading @@ -956,10 +952,14 @@ static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on) return ret; } } else { regulator_disable(mdwc->dwc3_gdsc); ret = regulator_disable(mdwc->dwc3_gdsc); if (ret) { dev_err(mdwc->dev, "unable to disable usb3 gdsc\n"); return ret; } } return 0; return ret; } static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert) Loading Loading @@ -1637,13 +1637,6 @@ static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc) struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); u32 irq_stat, irq_clear = 0; /* * Increment the PM count to prevent suspend from happening * during this routine. noresume is fine, since this function * should only be called when not in LPM. */ pm_runtime_get_noresume(mdwc->dev); irq_stat = dwc3_msm_read_reg(mdwc->base, PWR_EVNT_IRQ_STAT_REG); dev_dbg(mdwc->dev, "%s irq_stat=%X\n", __func__, irq_stat); Loading Loading @@ -1693,7 +1686,6 @@ static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc) __func__, irq_stat); dwc3_msm_write_reg(mdwc->base, PWR_EVNT_IRQ_STAT_REG, irq_clear); pm_runtime_put(mdwc->dev); } static irqreturn_t msm_dwc3_pwr_irq_thread(int irq, void *_mdwc) Loading Loading @@ -1801,9 +1793,23 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, break; /* Process PMIC notification in PRESENT prop */ case POWER_SUPPLY_PROP_PRESENT: dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__); dev_dbg(mdwc->dev, "%s: notify xceiv event with val:%d\n", __func__, val->intval); /* * Now otg_sm_work() state machine waits for USB cable status. * Hence here it makes sure that schedule resume work only if * there is change in USB cable also if there is no USB cable * notification. */ if (mdwc->otg_state == OTG_STATE_UNDEFINED) { mdwc->vbus_active = val->intval; dwc3_ext_event_notify(mdwc); break; } if (mdwc->vbus_active == val->intval) break; mdwc->vbus_active = val->intval; if (dwc->is_drd && !mdwc->ext_inuse && !mdwc->in_restart) { /* Loading Loading @@ -2013,85 +2019,40 @@ static int dwc3_cpu_notifier_cb(struct notifier_block *nfb, static void dwc3_otg_sm_work(struct work_struct *w); static int dwc3_msm_probe(struct platform_device *pdev) static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) { struct device_node *node = pdev->dev.of_node, *dwc3_node; struct device *dev = &pdev->dev; struct dwc3_msm *mdwc; struct dwc3 *dwc; struct resource *res; void __iomem *tcsr; unsigned long flags; u32 tmp; bool host_mode; int ret = 0; int ext_hub_reset_gpio; mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL); if (!mdwc) { dev_err(&pdev->dev, "not enough memory\n"); return -ENOMEM; } if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { dev_err(&pdev->dev, "setting DMA mask to 64 failed.\n"); if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { dev_err(&pdev->dev, "setting DMA mask to 32 failed.\n"); return -EOPNOTSUPP; } } platform_set_drvdata(pdev, mdwc); mdwc->dev = &pdev->dev; INIT_LIST_HEAD(&mdwc->req_complete_list); INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work); INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work); INIT_WORK(&mdwc->id_work, dwc3_id_work); INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w); init_completion(&mdwc->dwc3_xcvr_vbus_init); INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work); int ret; ret = dwc3_msm_config_gdsc(mdwc, 1); if (ret) { dev_err(&pdev->dev, "unable to configure usb3 gdsc\n"); return ret; } mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev, "USB3_GDSC"); if (IS_ERR(mdwc->dwc3_gdsc)) mdwc->dwc3_gdsc = NULL; mdwc->xo_clk = clk_get(&pdev->dev, "xo"); mdwc->xo_clk = devm_clk_get(mdwc->dev, "xo"); if (IS_ERR(mdwc->xo_clk)) { dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n", dev_err(mdwc->dev, "%s unable to get TCXO buffer handle\n", __func__); ret = PTR_ERR(mdwc->xo_clk); goto disable_dwc3_gdsc; return ret; } clk_set_rate(mdwc->xo_clk, 19200000); ret = clk_prepare_enable(mdwc->xo_clk); if (ret) { dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n", __func__, ret); goto put_xo; } mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk"); mdwc->iface_clk = devm_clk_get(mdwc->dev, "iface_clk"); if (IS_ERR(mdwc->iface_clk)) { dev_err(&pdev->dev, "failed to get iface_clk\n"); dev_err(mdwc->dev, "failed to get iface_clk\n"); ret = PTR_ERR(mdwc->iface_clk); goto disable_xo; return ret; } clk_prepare_enable(mdwc->iface_clk); /* * DWC3 Core requires its CORE CLK (aka master / bus clk) to * run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode. * On newer platform it can run at 150MHz as well. */ mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk"); mdwc->core_clk = devm_clk_get(mdwc->dev, "core_clk"); if (IS_ERR(mdwc->core_clk)) { dev_err(&pdev->dev, "failed to get core_clk\n"); dev_err(mdwc->dev, "failed to get core_clk\n"); ret = PTR_ERR(mdwc->core_clk); goto disable_iface_clk; return ret; } /* Loading @@ -2100,61 +2061,80 @@ static int dwc3_msm_probe(struct platform_device *pdev) */ mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX); if (IS_ERR_VALUE(mdwc->core_clk_rate)) { dev_err(&pdev->dev, "fail to get core clk max freq.\n"); dev_err(mdwc->dev, "fail to get core clk max freq.\n"); } else { ret = clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); if (ret) dev_err(&pdev->dev, "fail to set core_clk freq:%d\n", dev_err(mdwc->dev, "fail to set core_clk freq:%d\n", ret); } clk_prepare_enable(mdwc->core_clk); mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk"); mdwc->sleep_clk = devm_clk_get(mdwc->dev, "sleep_clk"); if (IS_ERR(mdwc->sleep_clk)) { dev_err(&pdev->dev, "failed to get sleep_clk\n"); dev_err(mdwc->dev, "failed to get sleep_clk\n"); ret = PTR_ERR(mdwc->sleep_clk); goto disable_core_clk; return ret; } clk_set_rate(mdwc->sleep_clk, 32000); clk_prepare_enable(mdwc->sleep_clk); ret = of_property_read_u32(node, "qcom,utmi-clk-rate", (u32 *)&mdwc->utmi_clk_rate); if (ret) clk_set_rate(mdwc->sleep_clk, 32000); mdwc->utmi_clk_rate = 19200000; mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk"); mdwc->utmi_clk = devm_clk_get(mdwc->dev, "utmi_clk"); if (IS_ERR(mdwc->utmi_clk)) { dev_err(&pdev->dev, "failed to get utmi_clk\n"); dev_err(mdwc->dev, "failed to get utmi_clk\n"); ret = PTR_ERR(mdwc->utmi_clk); goto disable_sleep_clk; return ret; } if (mdwc->utmi_clk_rate == 24000000) { /* * For setting utmi clock to 24MHz, first set 48MHz on parent * clock "utmi_clk_src" and then set divider 2 on child branch * "utmi_clk". */ mdwc->utmi_clk_src = devm_clk_get(&pdev->dev, "utmi_clk_src"); if (IS_ERR(mdwc->utmi_clk_src)) { dev_err(&pdev->dev, "failed to get utmi_clk_src\n"); ret = PTR_ERR(mdwc->utmi_clk_src); goto disable_sleep_clk; } clk_set_rate(mdwc->utmi_clk_src, 48000000); /* 1 means divide utmi_clk_src by 2 */ clk_set_rate(mdwc->utmi_clk, 1); } else { clk_set_rate(mdwc->utmi_clk, mdwc->utmi_clk_rate); } clk_prepare_enable(mdwc->utmi_clk); mdwc->bus_aggr_clk = devm_clk_get(&pdev->dev, "bus_aggr_clk"); mdwc->bus_aggr_clk = devm_clk_get(mdwc->dev, "bus_aggr_clk"); if (IS_ERR(mdwc->bus_aggr_clk)) mdwc->bus_aggr_clk = NULL; else clk_prepare_enable(mdwc->bus_aggr_clk); return 0; } static int dwc3_msm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node, *dwc3_node; struct device *dev = &pdev->dev; struct dwc3_msm *mdwc; struct dwc3 *dwc; struct resource *res; void __iomem *tcsr; unsigned long flags; bool host_mode; int ret = 0; int ext_hub_reset_gpio; mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL); if (!mdwc) return -ENOMEM; if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { dev_err(&pdev->dev, "setting DMA mask to 64 failed.\n"); if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { dev_err(&pdev->dev, "setting DMA mask to 32 failed.\n"); return -EOPNOTSUPP; } } platform_set_drvdata(pdev, mdwc); mdwc->dev = &pdev->dev; INIT_LIST_HEAD(&mdwc->req_complete_list); INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work); INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work); INIT_WORK(&mdwc->id_work, dwc3_id_work); INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w); init_completion(&mdwc->dwc3_xcvr_vbus_init); INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work); /* Get all clks and gdsc reference */ ret = dwc3_msm_get_clk_gdsc(mdwc); if (ret) { dev_err(&pdev->dev, "error getting clock or gdsc.\n"); return ret; } mdwc->id_state = DWC3_ID_FLOAT; mdwc->charging_disabled = of_property_read_bool(node, Loading Loading @@ -2183,7 +2163,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq"); if (mdwc->hs_phy_irq < 0) { dev_err(&pdev->dev, "pget_irq for hs_phy_irq failed\n"); goto disable_aggr_clk; ret = -EINVAL; goto err; } else { irq_set_status_flags(mdwc->hs_phy_irq, IRQ_NOAUTOEN); ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq, Loading @@ -2191,7 +2172,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) "msm_hs_phy_irq", mdwc); if (ret) { dev_err(&pdev->dev, "irqreq HSPHYINT failed\n"); goto disable_aggr_clk; goto err; } } Loading @@ -2202,7 +2183,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->pwr_event_irq = platform_get_irq_byname(pdev, "pwr_event_irq"); if (mdwc->pwr_event_irq < 0) { dev_err(&pdev->dev, "pget_irq for pwr_event_irq failed\n"); goto disable_aggr_clk; ret = -EINVAL; goto err; } else { /* * enable pwr event irq early during PM resume to meet bus Loading @@ -2216,7 +2198,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "irqreq pwr_event_irq failed: %d\n", ret); goto disable_aggr_clk; goto err; } } Loading @@ -2232,7 +2214,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc); if (ret) { dev_err(&pdev->dev, "irqreq IDINT failed\n"); goto disable_aggr_clk; goto err; } } Loading @@ -2259,7 +2241,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "missing memory base resource\n"); ret = -ENODEV; goto disable_aggr_clk; goto err; } mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start, Loading @@ -2267,7 +2249,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (!mdwc->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENODEV; goto disable_aggr_clk; goto err; } mdwc->io_res = res; /* used to calculate chg block offset */ Loading @@ -2278,7 +2260,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (IS_ERR(mdwc->dbm)) { dev_err(&pdev->dev, "unable to get dbm device\n"); ret = -EPROBE_DEFER; goto disable_aggr_clk; goto err; } /* * Add power event if the dbm indicates coming out of L1 Loading @@ -2289,7 +2271,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "need pwr_event_irq exiting L1\n"); ret = -EINVAL; goto disable_aggr_clk; goto err; } } } Loading Loading @@ -2321,7 +2303,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) dwc3_node = of_get_next_available_child(node, NULL); if (!dwc3_node) { dev_err(&pdev->dev, "failed to find dwc3 child\n"); goto put_psupply; ret = -ENODEV; goto err; } host_mode = of_usb_get_dr_mode(dwc3_node) == USB_DR_MODE_HOST; Loading @@ -2332,14 +2315,14 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to get vbus regulator\n"); ret = PTR_ERR(mdwc->vbus_reg); of_node_put(dwc3_node); goto put_psupply; goto err; } ret = regulator_enable(mdwc->vbus_reg); if (ret) { mdwc->vbus_reg = 0; dev_err(&pdev->dev, "Failed to enable vbus_reg\n"); of_node_put(dwc3_node); goto put_psupply; goto err; } } Loading @@ -2365,21 +2348,16 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s:power_supply_register usb failed\n", __func__); goto disable_aggr_clk; goto err; } } /* Perform controller GCC reset */ dwc3_msm_link_clk_reset(mdwc, 1); msleep(20); dwc3_msm_link_clk_reset(mdwc, 0); ret = of_platform_populate(node, NULL, NULL, &pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to add create dwc3 core\n"); of_node_put(dwc3_node); goto disable_vbus; goto put_psupply; } mdwc->dwc3 = of_find_device_by_node(dwc3_node); Loading Loading @@ -2444,17 +2422,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) device_init_wakeup(mdwc->dev, 1); pm_stay_awake(mdwc->dev); pm_runtime_set_active(mdwc->dev); pm_runtime_enable(mdwc->dev); /* Get initial P3 status and enable IN_P3 event */ tmp = dwc3_msm_read_reg_field(mdwc->base, DWC3_GDBGLTSSM, DWC3_GDBGLTSSM_LINKSTATE_MASK); atomic_set(&mdwc->in_p3, tmp == DWC3_LINK_STATE_U3); dwc3_msm_write_reg_field(mdwc->base, PWR_EVNT_IRQ_MASK_REG, PWR_EVNT_POWERDOWN_IN_P3_MASK, 1); enable_irq(mdwc->hs_phy_irq); schedule_delayed_work(&mdwc->sm_work, 0); /* Update initial ID state */ if (mdwc->pmic_id_irq) { Loading @@ -2466,38 +2434,16 @@ static int dwc3_msm_probe(struct platform_device *pdev) local_irq_restore(flags); enable_irq_wake(mdwc->pmic_id_irq); } return 0; put_dwc3: platform_device_put(mdwc->dwc3); if (mdwc->bus_perf_client) msm_bus_scale_unregister_client(mdwc->bus_perf_client); disable_vbus: if (!IS_ERR_OR_NULL(mdwc->vbus_reg)) regulator_disable(mdwc->vbus_reg); put_psupply: if (mdwc->usb_psy.dev) power_supply_unregister(&mdwc->usb_psy); disable_aggr_clk: if (mdwc->bus_aggr_clk) clk_disable_unprepare(mdwc->bus_aggr_clk); clk_disable_unprepare(mdwc->utmi_clk); disable_sleep_clk: clk_disable_unprepare(mdwc->sleep_clk); disable_core_clk: clk_set_rate(mdwc->core_clk, 19200000); clk_disable_unprepare(mdwc->core_clk); disable_iface_clk: clk_disable_unprepare(mdwc->iface_clk); disable_xo: clk_disable_unprepare(mdwc->xo_clk); put_xo: clk_put(mdwc->xo_clk); disable_dwc3_gdsc: dwc3_msm_config_gdsc(mdwc, 0); err: return ret; } Loading Loading @@ -2795,20 +2741,82 @@ psy_error: return -ENXIO; } void dwc3_otg_init_sm(struct dwc3_msm *mdwc) void dwc3_init_sm(struct dwc3_msm *mdwc) { int ret; static bool sm_initialized; /* * dwc3_init_sm() can be called multiple times in undefined state. * example: QC charger connected during boot up sequeunce, and * performing charger disconnect. */ if (sm_initialized) { pr_debug("%s(): Already sm_initialized.\n", __func__); return; } /* * VBUS initial state is reported after PMIC * driver initialization. Wait for it. */ ret = wait_for_completion_timeout(&mdwc->dwc3_xcvr_vbus_init, HZ * 5); ret = wait_for_completion_timeout(&mdwc->dwc3_xcvr_vbus_init, msecs_to_jiffies(SM_INIT_TIMEOUT)); if (!ret) { dev_err(mdwc->dev, "%s: completion timeout\n", __func__); /* We can safely assume no cable connected */ set_bit(ID, &mdwc->inputs); } sm_initialized = true; } static void dwc3_initialize(struct dwc3_msm *mdwc) { u32 tmp; int ret; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dbg_event(0xFF, "Initialized Start", atomic_read(&mdwc->dev->power.usage_count)); if (mdwc->bus_perf_client) { mdwc->bus_vote = 1; schedule_work(&mdwc->bus_vote_w); } /* enable USB GDSC */ dwc3_msm_config_gdsc(mdwc, 1); /* enable all clocks */ ret = clk_prepare_enable(mdwc->xo_clk); clk_prepare_enable(mdwc->iface_clk); clk_prepare_enable(mdwc->core_clk); clk_prepare_enable(mdwc->sleep_clk); clk_prepare_enable(mdwc->utmi_clk); if (mdwc->bus_aggr_clk) clk_prepare_enable(mdwc->bus_aggr_clk); /* Perform controller GCC reset */ dwc3_msm_link_clk_reset(mdwc, 1); msleep(20); dwc3_msm_link_clk_reset(mdwc, 0); /* * Get core configuration and initialized * Set Event buffers * Reset both USB PHYs and initialized */ dwc3_core_pre_init(dwc); /* Get initial P3 status and enable IN_P3 event */ tmp = dwc3_msm_read_reg_field(mdwc->base, DWC3_GDBGLTSSM, DWC3_GDBGLTSSM_LINKSTATE_MASK); atomic_set(&mdwc->in_p3, tmp == DWC3_LINK_STATE_U3); dwc3_msm_write_reg_field(mdwc->base, PWR_EVNT_IRQ_MASK_REG, PWR_EVNT_POWERDOWN_IN_P3_MASK, 1); enable_irq(mdwc->hs_phy_irq); } /** Loading @@ -2825,28 +2833,64 @@ static void dwc3_otg_sm_work(struct work_struct *w) bool work = 0; int ret = 0; unsigned long delay = 0; const char *state; if (mdwc->dwc3) dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s state\n", usb_otg_state_string(mdwc->otg_state)); if (!dwc) { dev_err(mdwc->dev, "dwc is NULL.\n"); return; } state = usb_otg_state_string(mdwc->otg_state); dev_dbg(mdwc->dev, "%s state\n", state); dbg_event(0xFF, state, 0); /* Check OTG state */ switch (mdwc->otg_state) { case OTG_STATE_UNDEFINED: dwc3_otg_init_sm(mdwc); /* Switch to A or B-Device according to ID / BSV */ if (!test_bit(ID, &mdwc->inputs)) { dev_dbg(mdwc->dev, "!id\n"); mdwc->otg_state = OTG_STATE_A_IDLE; work = 1; } else { mdwc->otg_state = OTG_STATE_B_IDLE; dwc3_init_sm(mdwc); if (test_bit(B_SESS_VLD, &mdwc->inputs)) { dev_dbg(mdwc->dev, "b_sess_vld\n"); work = 1; switch (mdwc->chg_type) { case DWC3_DCP_CHARGER: case DWC3_PROPRIETARY_CHARGER: dev_dbg(mdwc->dev, "DCP charger\n"); dwc3_msm_gadget_vbus_draw(mdwc, dcp_max_current); atomic_set(&dwc->in_lpm, 1); pm_relax(mdwc->dev); break; case DWC3_CDP_CHARGER: case DWC3_SDP_CHARGER: atomic_set(&dwc->in_lpm, 0); pm_runtime_set_active(mdwc->dev); pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; dbg_event(0xFF, "Undef SDP", atomic_read( &mdwc->dev->power.usage_count)); break; default: WARN_ON(1); break; } } if (!test_bit(B_SESS_VLD, &mdwc->inputs)) { atomic_set(&dwc->in_lpm, 0); pm_runtime_set_active(mdwc->dev); pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); pm_runtime_put_sync(mdwc->dev); dbg_event(0xFF, "Undef NoUSB", atomic_read(&mdwc->dev->power.usage_count)); mdwc->otg_state = OTG_STATE_B_IDLE; } break; Loading Loading @@ -3056,6 +3100,14 @@ static int dwc3_msm_pm_resume(struct device *dev) #endif #ifdef CONFIG_PM_RUNTIME static int dwc3_msm_runtime_idle(struct device *dev) { dev_dbg(dev, "DWC3-msm runtime idle\n"); dbg_event(0xFF, "RT Idle", 0); return 0; } static int dwc3_msm_runtime_suspend(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); Loading @@ -3080,7 +3132,7 @@ static int dwc3_msm_runtime_resume(struct device *dev) static const struct dev_pm_ops dwc3_msm_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_msm_pm_suspend, dwc3_msm_pm_resume) SET_RUNTIME_PM_OPS(dwc3_msm_runtime_suspend, dwc3_msm_runtime_resume, NULL) dwc3_msm_runtime_idle) }; static const struct of_device_id of_dwc3_matach[] = { Loading Loading
Documentation/devicetree/bindings/usb/msm-ssusb.txt +0 −2 Original line number Diff line number Diff line Loading @@ -31,8 +31,6 @@ Optional properties : regulator node to the USB controller. - qcom,dwc-usb3-msm-tx-fifo-size: If present, represents RAM size available for TX fifo allocation in bytes - qcom,utmi-clk-rate: Indicates refclk frequency (in Hz) to the core. If not specified, default of 19.2MHz is assumed. - qcom,usb-dbm : phandle for the DBM device - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform power collapse when cable is disconencted. Loading
drivers/usb/common/common.c +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ const char *usb_otg_state_string(enum usb_otg_state state) { static const char *const names[] = { [OTG_STATE_UNDEFINED] = "undefined", [OTG_STATE_A_IDLE] = "a_idle", [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise", [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon", Loading
drivers/usb/dwc3/core.c +63 −70 Original line number Diff line number Diff line Loading @@ -683,41 +683,16 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) static int dwc3_core_init_mode(struct dwc3 *dwc) { struct device *dev = dwc->dev; int ret; switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); return ret; } break; case USB_DR_MODE_HOST: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); return ret; } break; case USB_DR_MODE_OTG: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); dwc->is_drd = true; ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); return ret; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); dwc3_host_exit(dwc); return ret; } break; default: dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); Loading Loading @@ -774,6 +749,49 @@ int dwc3_notify_event(struct dwc3 *dwc, unsigned event) } EXPORT_SYMBOL(dwc3_notify_event); int dwc3_core_pre_init(struct dwc3 *dwc) { int ret; dwc3_cache_hwparams(dwc); if (!dwc->ev_buffs) { ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err_alloc; } } ret = dwc3_core_init(dwc); if (ret) { dev_err(dwc->dev, "failed to initialize core\n"); goto err0; } ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err0; } ret = dwc3_core_init_mode(dwc); if (ret) { dev_err(dwc->dev, "failed to set mode with dwc3 core\n"); goto err1; } return ret; err1: dwc3_event_buffers_cleanup(dwc); err0: dwc3_core_exit(dwc); dwc3_free_event_buffers(dwc); err_alloc: return ret; } #define DWC3_ALIGN_MASK (16 - 1) static int dwc3_probe(struct platform_device *pdev) Loading Loading @@ -915,81 +933,58 @@ static int dwc3_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); dwc3_cache_hwparams(dwc); if (!dwc->ev_buffs) { ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err0; } } if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) dwc->dr_mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) dwc->dr_mode = USB_DR_MODE_PERIPHERAL; if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) { dwc->dr_mode = USB_DR_MODE_OTG; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err0; dwc->is_drd = true; } usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err1; goto err; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err_usb2phy_power; ret = dwc3_event_buffers_setup(dwc); ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); dev_err(dev, "failed to initialize debugfs\n"); goto err_usb3phy_power; } ret = dwc3_core_init_mode(dwc); if (ret) goto err2; /* Hardcode number of eps */ dwc->num_in_eps = 16; dwc->num_out_eps = 16; ret = dwc3_debugfs_init(dwc); ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); goto err3; dev_err(dev, "failed to initialize gadget\n"); goto err_usb3phy_power; } ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); goto err_gadget_exit; } dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_INITIALIZATION_EVENT); return 0; err3: dwc3_core_exit_mode(dwc); err2: dwc3_event_buffers_cleanup(dwc); err_gadget_exit: dwc3_gadget_exit(dwc); err_usb3phy_power: phy_power_off(dwc->usb3_generic_phy); err_usb2phy_power: phy_power_off(dwc->usb2_generic_phy); err1: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); dwc3_core_exit(dwc); err0: dwc3_free_event_buffers(dwc); err: return ret; } Loading @@ -1002,8 +997,6 @@ static int dwc3_remove(struct platform_device *pdev) dwc3_event_buffers_cleanup(dwc); dwc3_free_event_buffers(dwc); usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy); Loading
drivers/usb/dwc3/core.h +1 −0 Original line number Diff line number Diff line Loading @@ -1183,6 +1183,7 @@ static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) { } #endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ int dwc3_core_init(struct dwc3 *dwc); int dwc3_core_pre_init(struct dwc3 *dwc); void dwc3_post_host_reset_core_init(struct dwc3 *dwc); int dwc3_event_buffers_setup(struct dwc3 *dwc); Loading
drivers/usb/dwc3/dwc3-msm.c +239 −187 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ #define DWC3_IDEV_CHG_MAX 1500 #define DWC3_HVDCP_CHG_MAX 1800 /* time out to wait for USB cable status notification (in ms)*/ #define SM_INIT_TIMEOUT 30000 /* cpu to fix usb interrupt */ static int cpu_to_affin; module_param(cpu_to_affin, int, S_IRUGO|S_IWUSR); Loading Loading @@ -937,17 +940,10 @@ EXPORT_SYMBOL(msm_dwc3_reset_ep_after_lpm); */ static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on) { int ret = 0; if (IS_ERR(mdwc->dwc3_gdsc)) return 0; int ret; if (!mdwc->dwc3_gdsc) { mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev, "USB3_GDSC"); if (IS_ERR(mdwc->dwc3_gdsc)) return 0; } if (IS_ERR_OR_NULL(mdwc->dwc3_gdsc)) return -EPERM; if (on) { ret = regulator_enable(mdwc->dwc3_gdsc); Loading @@ -956,10 +952,14 @@ static int dwc3_msm_config_gdsc(struct dwc3_msm *mdwc, int on) return ret; } } else { regulator_disable(mdwc->dwc3_gdsc); ret = regulator_disable(mdwc->dwc3_gdsc); if (ret) { dev_err(mdwc->dev, "unable to disable usb3 gdsc\n"); return ret; } } return 0; return ret; } static int dwc3_msm_link_clk_reset(struct dwc3_msm *mdwc, bool assert) Loading Loading @@ -1637,13 +1637,6 @@ static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc) struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); u32 irq_stat, irq_clear = 0; /* * Increment the PM count to prevent suspend from happening * during this routine. noresume is fine, since this function * should only be called when not in LPM. */ pm_runtime_get_noresume(mdwc->dev); irq_stat = dwc3_msm_read_reg(mdwc->base, PWR_EVNT_IRQ_STAT_REG); dev_dbg(mdwc->dev, "%s irq_stat=%X\n", __func__, irq_stat); Loading Loading @@ -1693,7 +1686,6 @@ static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc) __func__, irq_stat); dwc3_msm_write_reg(mdwc->base, PWR_EVNT_IRQ_STAT_REG, irq_clear); pm_runtime_put(mdwc->dev); } static irqreturn_t msm_dwc3_pwr_irq_thread(int irq, void *_mdwc) Loading Loading @@ -1801,9 +1793,23 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, break; /* Process PMIC notification in PRESENT prop */ case POWER_SUPPLY_PROP_PRESENT: dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__); dev_dbg(mdwc->dev, "%s: notify xceiv event with val:%d\n", __func__, val->intval); /* * Now otg_sm_work() state machine waits for USB cable status. * Hence here it makes sure that schedule resume work only if * there is change in USB cable also if there is no USB cable * notification. */ if (mdwc->otg_state == OTG_STATE_UNDEFINED) { mdwc->vbus_active = val->intval; dwc3_ext_event_notify(mdwc); break; } if (mdwc->vbus_active == val->intval) break; mdwc->vbus_active = val->intval; if (dwc->is_drd && !mdwc->ext_inuse && !mdwc->in_restart) { /* Loading Loading @@ -2013,85 +2019,40 @@ static int dwc3_cpu_notifier_cb(struct notifier_block *nfb, static void dwc3_otg_sm_work(struct work_struct *w); static int dwc3_msm_probe(struct platform_device *pdev) static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) { struct device_node *node = pdev->dev.of_node, *dwc3_node; struct device *dev = &pdev->dev; struct dwc3_msm *mdwc; struct dwc3 *dwc; struct resource *res; void __iomem *tcsr; unsigned long flags; u32 tmp; bool host_mode; int ret = 0; int ext_hub_reset_gpio; mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL); if (!mdwc) { dev_err(&pdev->dev, "not enough memory\n"); return -ENOMEM; } if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { dev_err(&pdev->dev, "setting DMA mask to 64 failed.\n"); if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { dev_err(&pdev->dev, "setting DMA mask to 32 failed.\n"); return -EOPNOTSUPP; } } platform_set_drvdata(pdev, mdwc); mdwc->dev = &pdev->dev; INIT_LIST_HEAD(&mdwc->req_complete_list); INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work); INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work); INIT_WORK(&mdwc->id_work, dwc3_id_work); INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w); init_completion(&mdwc->dwc3_xcvr_vbus_init); INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work); int ret; ret = dwc3_msm_config_gdsc(mdwc, 1); if (ret) { dev_err(&pdev->dev, "unable to configure usb3 gdsc\n"); return ret; } mdwc->dwc3_gdsc = devm_regulator_get(mdwc->dev, "USB3_GDSC"); if (IS_ERR(mdwc->dwc3_gdsc)) mdwc->dwc3_gdsc = NULL; mdwc->xo_clk = clk_get(&pdev->dev, "xo"); mdwc->xo_clk = devm_clk_get(mdwc->dev, "xo"); if (IS_ERR(mdwc->xo_clk)) { dev_err(&pdev->dev, "%s unable to get TCXO buffer handle\n", dev_err(mdwc->dev, "%s unable to get TCXO buffer handle\n", __func__); ret = PTR_ERR(mdwc->xo_clk); goto disable_dwc3_gdsc; return ret; } clk_set_rate(mdwc->xo_clk, 19200000); ret = clk_prepare_enable(mdwc->xo_clk); if (ret) { dev_err(&pdev->dev, "%s failed to vote for TCXO buffer%d\n", __func__, ret); goto put_xo; } mdwc->iface_clk = devm_clk_get(&pdev->dev, "iface_clk"); mdwc->iface_clk = devm_clk_get(mdwc->dev, "iface_clk"); if (IS_ERR(mdwc->iface_clk)) { dev_err(&pdev->dev, "failed to get iface_clk\n"); dev_err(mdwc->dev, "failed to get iface_clk\n"); ret = PTR_ERR(mdwc->iface_clk); goto disable_xo; return ret; } clk_prepare_enable(mdwc->iface_clk); /* * DWC3 Core requires its CORE CLK (aka master / bus clk) to * run at 125Mhz in SSUSB mode and >60MHZ for HSUSB mode. * On newer platform it can run at 150MHz as well. */ mdwc->core_clk = devm_clk_get(&pdev->dev, "core_clk"); mdwc->core_clk = devm_clk_get(mdwc->dev, "core_clk"); if (IS_ERR(mdwc->core_clk)) { dev_err(&pdev->dev, "failed to get core_clk\n"); dev_err(mdwc->dev, "failed to get core_clk\n"); ret = PTR_ERR(mdwc->core_clk); goto disable_iface_clk; return ret; } /* Loading @@ -2100,61 +2061,80 @@ static int dwc3_msm_probe(struct platform_device *pdev) */ mdwc->core_clk_rate = clk_round_rate(mdwc->core_clk, LONG_MAX); if (IS_ERR_VALUE(mdwc->core_clk_rate)) { dev_err(&pdev->dev, "fail to get core clk max freq.\n"); dev_err(mdwc->dev, "fail to get core clk max freq.\n"); } else { ret = clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); if (ret) dev_err(&pdev->dev, "fail to set core_clk freq:%d\n", dev_err(mdwc->dev, "fail to set core_clk freq:%d\n", ret); } clk_prepare_enable(mdwc->core_clk); mdwc->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk"); mdwc->sleep_clk = devm_clk_get(mdwc->dev, "sleep_clk"); if (IS_ERR(mdwc->sleep_clk)) { dev_err(&pdev->dev, "failed to get sleep_clk\n"); dev_err(mdwc->dev, "failed to get sleep_clk\n"); ret = PTR_ERR(mdwc->sleep_clk); goto disable_core_clk; return ret; } clk_set_rate(mdwc->sleep_clk, 32000); clk_prepare_enable(mdwc->sleep_clk); ret = of_property_read_u32(node, "qcom,utmi-clk-rate", (u32 *)&mdwc->utmi_clk_rate); if (ret) clk_set_rate(mdwc->sleep_clk, 32000); mdwc->utmi_clk_rate = 19200000; mdwc->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk"); mdwc->utmi_clk = devm_clk_get(mdwc->dev, "utmi_clk"); if (IS_ERR(mdwc->utmi_clk)) { dev_err(&pdev->dev, "failed to get utmi_clk\n"); dev_err(mdwc->dev, "failed to get utmi_clk\n"); ret = PTR_ERR(mdwc->utmi_clk); goto disable_sleep_clk; return ret; } if (mdwc->utmi_clk_rate == 24000000) { /* * For setting utmi clock to 24MHz, first set 48MHz on parent * clock "utmi_clk_src" and then set divider 2 on child branch * "utmi_clk". */ mdwc->utmi_clk_src = devm_clk_get(&pdev->dev, "utmi_clk_src"); if (IS_ERR(mdwc->utmi_clk_src)) { dev_err(&pdev->dev, "failed to get utmi_clk_src\n"); ret = PTR_ERR(mdwc->utmi_clk_src); goto disable_sleep_clk; } clk_set_rate(mdwc->utmi_clk_src, 48000000); /* 1 means divide utmi_clk_src by 2 */ clk_set_rate(mdwc->utmi_clk, 1); } else { clk_set_rate(mdwc->utmi_clk, mdwc->utmi_clk_rate); } clk_prepare_enable(mdwc->utmi_clk); mdwc->bus_aggr_clk = devm_clk_get(&pdev->dev, "bus_aggr_clk"); mdwc->bus_aggr_clk = devm_clk_get(mdwc->dev, "bus_aggr_clk"); if (IS_ERR(mdwc->bus_aggr_clk)) mdwc->bus_aggr_clk = NULL; else clk_prepare_enable(mdwc->bus_aggr_clk); return 0; } static int dwc3_msm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node, *dwc3_node; struct device *dev = &pdev->dev; struct dwc3_msm *mdwc; struct dwc3 *dwc; struct resource *res; void __iomem *tcsr; unsigned long flags; bool host_mode; int ret = 0; int ext_hub_reset_gpio; mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL); if (!mdwc) return -ENOMEM; if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { dev_err(&pdev->dev, "setting DMA mask to 64 failed.\n"); if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { dev_err(&pdev->dev, "setting DMA mask to 32 failed.\n"); return -EOPNOTSUPP; } } platform_set_drvdata(pdev, mdwc); mdwc->dev = &pdev->dev; INIT_LIST_HEAD(&mdwc->req_complete_list); INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work); INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work); INIT_WORK(&mdwc->id_work, dwc3_id_work); INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w); init_completion(&mdwc->dwc3_xcvr_vbus_init); INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work); /* Get all clks and gdsc reference */ ret = dwc3_msm_get_clk_gdsc(mdwc); if (ret) { dev_err(&pdev->dev, "error getting clock or gdsc.\n"); return ret; } mdwc->id_state = DWC3_ID_FLOAT; mdwc->charging_disabled = of_property_read_bool(node, Loading Loading @@ -2183,7 +2163,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->hs_phy_irq = platform_get_irq_byname(pdev, "hs_phy_irq"); if (mdwc->hs_phy_irq < 0) { dev_err(&pdev->dev, "pget_irq for hs_phy_irq failed\n"); goto disable_aggr_clk; ret = -EINVAL; goto err; } else { irq_set_status_flags(mdwc->hs_phy_irq, IRQ_NOAUTOEN); ret = devm_request_irq(&pdev->dev, mdwc->hs_phy_irq, Loading @@ -2191,7 +2172,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) "msm_hs_phy_irq", mdwc); if (ret) { dev_err(&pdev->dev, "irqreq HSPHYINT failed\n"); goto disable_aggr_clk; goto err; } } Loading @@ -2202,7 +2183,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->pwr_event_irq = platform_get_irq_byname(pdev, "pwr_event_irq"); if (mdwc->pwr_event_irq < 0) { dev_err(&pdev->dev, "pget_irq for pwr_event_irq failed\n"); goto disable_aggr_clk; ret = -EINVAL; goto err; } else { /* * enable pwr event irq early during PM resume to meet bus Loading @@ -2216,7 +2198,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "irqreq pwr_event_irq failed: %d\n", ret); goto disable_aggr_clk; goto err; } } Loading @@ -2232,7 +2214,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc); if (ret) { dev_err(&pdev->dev, "irqreq IDINT failed\n"); goto disable_aggr_clk; goto err; } } Loading @@ -2259,7 +2241,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "missing memory base resource\n"); ret = -ENODEV; goto disable_aggr_clk; goto err; } mdwc->base = devm_ioremap_nocache(&pdev->dev, res->start, Loading @@ -2267,7 +2249,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (!mdwc->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENODEV; goto disable_aggr_clk; goto err; } mdwc->io_res = res; /* used to calculate chg block offset */ Loading @@ -2278,7 +2260,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (IS_ERR(mdwc->dbm)) { dev_err(&pdev->dev, "unable to get dbm device\n"); ret = -EPROBE_DEFER; goto disable_aggr_clk; goto err; } /* * Add power event if the dbm indicates coming out of L1 Loading @@ -2289,7 +2271,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "need pwr_event_irq exiting L1\n"); ret = -EINVAL; goto disable_aggr_clk; goto err; } } } Loading Loading @@ -2321,7 +2303,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) dwc3_node = of_get_next_available_child(node, NULL); if (!dwc3_node) { dev_err(&pdev->dev, "failed to find dwc3 child\n"); goto put_psupply; ret = -ENODEV; goto err; } host_mode = of_usb_get_dr_mode(dwc3_node) == USB_DR_MODE_HOST; Loading @@ -2332,14 +2315,14 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to get vbus regulator\n"); ret = PTR_ERR(mdwc->vbus_reg); of_node_put(dwc3_node); goto put_psupply; goto err; } ret = regulator_enable(mdwc->vbus_reg); if (ret) { mdwc->vbus_reg = 0; dev_err(&pdev->dev, "Failed to enable vbus_reg\n"); of_node_put(dwc3_node); goto put_psupply; goto err; } } Loading @@ -2365,21 +2348,16 @@ static int dwc3_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s:power_supply_register usb failed\n", __func__); goto disable_aggr_clk; goto err; } } /* Perform controller GCC reset */ dwc3_msm_link_clk_reset(mdwc, 1); msleep(20); dwc3_msm_link_clk_reset(mdwc, 0); ret = of_platform_populate(node, NULL, NULL, &pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to add create dwc3 core\n"); of_node_put(dwc3_node); goto disable_vbus; goto put_psupply; } mdwc->dwc3 = of_find_device_by_node(dwc3_node); Loading Loading @@ -2444,17 +2422,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) device_init_wakeup(mdwc->dev, 1); pm_stay_awake(mdwc->dev); pm_runtime_set_active(mdwc->dev); pm_runtime_enable(mdwc->dev); /* Get initial P3 status and enable IN_P3 event */ tmp = dwc3_msm_read_reg_field(mdwc->base, DWC3_GDBGLTSSM, DWC3_GDBGLTSSM_LINKSTATE_MASK); atomic_set(&mdwc->in_p3, tmp == DWC3_LINK_STATE_U3); dwc3_msm_write_reg_field(mdwc->base, PWR_EVNT_IRQ_MASK_REG, PWR_EVNT_POWERDOWN_IN_P3_MASK, 1); enable_irq(mdwc->hs_phy_irq); schedule_delayed_work(&mdwc->sm_work, 0); /* Update initial ID state */ if (mdwc->pmic_id_irq) { Loading @@ -2466,38 +2434,16 @@ static int dwc3_msm_probe(struct platform_device *pdev) local_irq_restore(flags); enable_irq_wake(mdwc->pmic_id_irq); } return 0; put_dwc3: platform_device_put(mdwc->dwc3); if (mdwc->bus_perf_client) msm_bus_scale_unregister_client(mdwc->bus_perf_client); disable_vbus: if (!IS_ERR_OR_NULL(mdwc->vbus_reg)) regulator_disable(mdwc->vbus_reg); put_psupply: if (mdwc->usb_psy.dev) power_supply_unregister(&mdwc->usb_psy); disable_aggr_clk: if (mdwc->bus_aggr_clk) clk_disable_unprepare(mdwc->bus_aggr_clk); clk_disable_unprepare(mdwc->utmi_clk); disable_sleep_clk: clk_disable_unprepare(mdwc->sleep_clk); disable_core_clk: clk_set_rate(mdwc->core_clk, 19200000); clk_disable_unprepare(mdwc->core_clk); disable_iface_clk: clk_disable_unprepare(mdwc->iface_clk); disable_xo: clk_disable_unprepare(mdwc->xo_clk); put_xo: clk_put(mdwc->xo_clk); disable_dwc3_gdsc: dwc3_msm_config_gdsc(mdwc, 0); err: return ret; } Loading Loading @@ -2795,20 +2741,82 @@ psy_error: return -ENXIO; } void dwc3_otg_init_sm(struct dwc3_msm *mdwc) void dwc3_init_sm(struct dwc3_msm *mdwc) { int ret; static bool sm_initialized; /* * dwc3_init_sm() can be called multiple times in undefined state. * example: QC charger connected during boot up sequeunce, and * performing charger disconnect. */ if (sm_initialized) { pr_debug("%s(): Already sm_initialized.\n", __func__); return; } /* * VBUS initial state is reported after PMIC * driver initialization. Wait for it. */ ret = wait_for_completion_timeout(&mdwc->dwc3_xcvr_vbus_init, HZ * 5); ret = wait_for_completion_timeout(&mdwc->dwc3_xcvr_vbus_init, msecs_to_jiffies(SM_INIT_TIMEOUT)); if (!ret) { dev_err(mdwc->dev, "%s: completion timeout\n", __func__); /* We can safely assume no cable connected */ set_bit(ID, &mdwc->inputs); } sm_initialized = true; } static void dwc3_initialize(struct dwc3_msm *mdwc) { u32 tmp; int ret; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dbg_event(0xFF, "Initialized Start", atomic_read(&mdwc->dev->power.usage_count)); if (mdwc->bus_perf_client) { mdwc->bus_vote = 1; schedule_work(&mdwc->bus_vote_w); } /* enable USB GDSC */ dwc3_msm_config_gdsc(mdwc, 1); /* enable all clocks */ ret = clk_prepare_enable(mdwc->xo_clk); clk_prepare_enable(mdwc->iface_clk); clk_prepare_enable(mdwc->core_clk); clk_prepare_enable(mdwc->sleep_clk); clk_prepare_enable(mdwc->utmi_clk); if (mdwc->bus_aggr_clk) clk_prepare_enable(mdwc->bus_aggr_clk); /* Perform controller GCC reset */ dwc3_msm_link_clk_reset(mdwc, 1); msleep(20); dwc3_msm_link_clk_reset(mdwc, 0); /* * Get core configuration and initialized * Set Event buffers * Reset both USB PHYs and initialized */ dwc3_core_pre_init(dwc); /* Get initial P3 status and enable IN_P3 event */ tmp = dwc3_msm_read_reg_field(mdwc->base, DWC3_GDBGLTSSM, DWC3_GDBGLTSSM_LINKSTATE_MASK); atomic_set(&mdwc->in_p3, tmp == DWC3_LINK_STATE_U3); dwc3_msm_write_reg_field(mdwc->base, PWR_EVNT_IRQ_MASK_REG, PWR_EVNT_POWERDOWN_IN_P3_MASK, 1); enable_irq(mdwc->hs_phy_irq); } /** Loading @@ -2825,28 +2833,64 @@ static void dwc3_otg_sm_work(struct work_struct *w) bool work = 0; int ret = 0; unsigned long delay = 0; const char *state; if (mdwc->dwc3) dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s state\n", usb_otg_state_string(mdwc->otg_state)); if (!dwc) { dev_err(mdwc->dev, "dwc is NULL.\n"); return; } state = usb_otg_state_string(mdwc->otg_state); dev_dbg(mdwc->dev, "%s state\n", state); dbg_event(0xFF, state, 0); /* Check OTG state */ switch (mdwc->otg_state) { case OTG_STATE_UNDEFINED: dwc3_otg_init_sm(mdwc); /* Switch to A or B-Device according to ID / BSV */ if (!test_bit(ID, &mdwc->inputs)) { dev_dbg(mdwc->dev, "!id\n"); mdwc->otg_state = OTG_STATE_A_IDLE; work = 1; } else { mdwc->otg_state = OTG_STATE_B_IDLE; dwc3_init_sm(mdwc); if (test_bit(B_SESS_VLD, &mdwc->inputs)) { dev_dbg(mdwc->dev, "b_sess_vld\n"); work = 1; switch (mdwc->chg_type) { case DWC3_DCP_CHARGER: case DWC3_PROPRIETARY_CHARGER: dev_dbg(mdwc->dev, "DCP charger\n"); dwc3_msm_gadget_vbus_draw(mdwc, dcp_max_current); atomic_set(&dwc->in_lpm, 1); pm_relax(mdwc->dev); break; case DWC3_CDP_CHARGER: case DWC3_SDP_CHARGER: atomic_set(&dwc->in_lpm, 0); pm_runtime_set_active(mdwc->dev); pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; dbg_event(0xFF, "Undef SDP", atomic_read( &mdwc->dev->power.usage_count)); break; default: WARN_ON(1); break; } } if (!test_bit(B_SESS_VLD, &mdwc->inputs)) { atomic_set(&dwc->in_lpm, 0); pm_runtime_set_active(mdwc->dev); pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); pm_runtime_put_sync(mdwc->dev); dbg_event(0xFF, "Undef NoUSB", atomic_read(&mdwc->dev->power.usage_count)); mdwc->otg_state = OTG_STATE_B_IDLE; } break; Loading Loading @@ -3056,6 +3100,14 @@ static int dwc3_msm_pm_resume(struct device *dev) #endif #ifdef CONFIG_PM_RUNTIME static int dwc3_msm_runtime_idle(struct device *dev) { dev_dbg(dev, "DWC3-msm runtime idle\n"); dbg_event(0xFF, "RT Idle", 0); return 0; } static int dwc3_msm_runtime_suspend(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); Loading @@ -3080,7 +3132,7 @@ static int dwc3_msm_runtime_resume(struct device *dev) static const struct dev_pm_ops dwc3_msm_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_msm_pm_suspend, dwc3_msm_pm_resume) SET_RUNTIME_PM_OPS(dwc3_msm_runtime_suspend, dwc3_msm_runtime_resume, NULL) dwc3_msm_runtime_idle) }; static const struct of_device_id of_dwc3_matach[] = { Loading