Lines Matching +full:generic +full:- +full:xhci
1 // SPDX-License-Identifier: GPL-2.0
3 * MediaTek xHCI Host Controller Driver
10 #include <linux/dma-mapping.h>
22 #include "xhci.h"
23 #include "xhci-mtk.h"
59 /* xHCI CSR */
117 struct device *dev = mtk->dev; in xhci_mtk_set_frame_interval()
118 struct usb_hcd *hcd = mtk->hcd; in xhci_mtk_set_frame_interval()
121 if (!of_device_is_compatible(dev->of_node, "mediatek,mt8195-xhci")) in xhci_mtk_set_frame_interval()
124 value = readl(hcd->regs + HFCNTR_CFG); in xhci_mtk_set_frame_interval()
127 writel(value, hcd->regs + HFCNTR_CFG); in xhci_mtk_set_frame_interval()
129 value = readl(hcd->regs + LS_EOF_CFG); in xhci_mtk_set_frame_interval()
132 writel(value, hcd->regs + LS_EOF_CFG); in xhci_mtk_set_frame_interval()
134 value = readl(hcd->regs + FS_EOF_CFG); in xhci_mtk_set_frame_interval()
137 writel(value, hcd->regs + FS_EOF_CFG); in xhci_mtk_set_frame_interval()
139 value = readl(hcd->regs + SS_GEN1_EOF_CFG); in xhci_mtk_set_frame_interval()
142 writel(value, hcd->regs + SS_GEN1_EOF_CFG); in xhci_mtk_set_frame_interval()
144 value = readl(hcd->regs + SS_GEN2_EOF_CFG); in xhci_mtk_set_frame_interval()
147 writel(value, hcd->regs + SS_GEN2_EOF_CFG); in xhci_mtk_set_frame_interval()
152 struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; in xhci_mtk_host_enable()
158 if (!mtk->has_ippc) in xhci_mtk_host_enable()
162 value = readl(&ippc->ip_pw_ctr1); in xhci_mtk_host_enable()
164 writel(value, &ippc->ip_pw_ctr1); in xhci_mtk_host_enable()
167 for (i = 0; i < mtk->num_u3_ports; i++) { in xhci_mtk_host_enable()
168 if ((0x1 << i) & mtk->u3p_dis_msk) { in xhci_mtk_host_enable()
173 value = readl(&ippc->u3_ctrl_p[i]); in xhci_mtk_host_enable()
176 writel(value, &ippc->u3_ctrl_p[i]); in xhci_mtk_host_enable()
180 for (i = 0; i < mtk->num_u2_ports; i++) { in xhci_mtk_host_enable()
181 if (BIT(i) & mtk->u2p_dis_msk) in xhci_mtk_host_enable()
184 value = readl(&ippc->u2_ctrl_p[i]); in xhci_mtk_host_enable()
187 writel(value, &ippc->u2_ctrl_p[i]); in xhci_mtk_host_enable()
197 if (mtk->num_u3_ports > u3_ports_disabled) in xhci_mtk_host_enable()
200 ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, in xhci_mtk_host_enable()
203 dev_err(mtk->dev, "clocks are not stable (0x%x)\n", value); in xhci_mtk_host_enable()
212 struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; in xhci_mtk_host_disable()
217 if (!mtk->has_ippc) in xhci_mtk_host_disable()
221 for (i = 0; i < mtk->num_u3_ports; i++) { in xhci_mtk_host_disable()
222 if ((0x1 << i) & mtk->u3p_dis_msk) in xhci_mtk_host_disable()
225 value = readl(&ippc->u3_ctrl_p[i]); in xhci_mtk_host_disable()
227 writel(value, &ippc->u3_ctrl_p[i]); in xhci_mtk_host_disable()
231 for (i = 0; i < mtk->num_u2_ports; i++) { in xhci_mtk_host_disable()
232 if (BIT(i) & mtk->u2p_dis_msk) in xhci_mtk_host_disable()
235 value = readl(&ippc->u2_ctrl_p[i]); in xhci_mtk_host_disable()
237 writel(value, &ippc->u2_ctrl_p[i]); in xhci_mtk_host_disable()
241 value = readl(&ippc->ip_pw_ctr1); in xhci_mtk_host_disable()
243 writel(value, &ippc->ip_pw_ctr1); in xhci_mtk_host_disable()
246 ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, in xhci_mtk_host_disable()
249 dev_err(mtk->dev, "ip sleep failed!!!\n"); in xhci_mtk_host_disable()
257 struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; in xhci_mtk_ssusb_config()
260 if (!mtk->has_ippc) in xhci_mtk_ssusb_config()
264 value = readl(&ippc->ip_pw_ctr0); in xhci_mtk_ssusb_config()
266 writel(value, &ippc->ip_pw_ctr0); in xhci_mtk_ssusb_config()
268 value = readl(&ippc->ip_pw_ctr0); in xhci_mtk_ssusb_config()
270 writel(value, &ippc->ip_pw_ctr0); in xhci_mtk_ssusb_config()
273 * device ip is default power-on in fact in xhci_mtk_ssusb_config()
274 * power down device ip, otherwise ip-sleep will fail in xhci_mtk_ssusb_config()
276 value = readl(&ippc->ip_pw_ctr2); in xhci_mtk_ssusb_config()
278 writel(value, &ippc->ip_pw_ctr2); in xhci_mtk_ssusb_config()
280 value = readl(&ippc->ip_xhci_cap); in xhci_mtk_ssusb_config()
281 mtk->num_u3_ports = CAP_U3_PORT_NUM(value); in xhci_mtk_ssusb_config()
282 mtk->num_u2_ports = CAP_U2_PORT_NUM(value); in xhci_mtk_ssusb_config()
283 dev_dbg(mtk->dev, "%s u2p:%d, u3p:%d\n", __func__, in xhci_mtk_ssusb_config()
284 mtk->num_u2_ports, mtk->num_u3_ports); in xhci_mtk_ssusb_config()
289 /* only clocks can be turn off for ip-sleep wakeup mode */
294 switch (mtk->uwk_vers) { in usb_wakeup_ip_sleep_set()
296 reg = mtk->uwk_reg_base + PERI_WK_CTRL1; in usb_wakeup_ip_sleep_set()
301 reg = mtk->uwk_reg_base + PERI_WK_CTRL0; in usb_wakeup_ip_sleep_set()
306 reg = mtk->uwk_reg_base + PERI_WK_CTRL0; in usb_wakeup_ip_sleep_set()
311 reg = mtk->uwk_reg_base + PERI_SSUSB_SPM_CTRL; in usb_wakeup_ip_sleep_set()
318 regmap_update_bits(mtk->uwk, reg, msk, val); in usb_wakeup_ip_sleep_set()
328 mtk->uwk_en = of_property_read_bool(dn, "wakeup-source"); in usb_wakeup_of_property_parse()
329 if (!mtk->uwk_en) in usb_wakeup_of_property_parse()
333 "mediatek,syscon-wakeup", 2, 0, &args); in usb_wakeup_of_property_parse()
337 mtk->uwk_reg_base = args.args[0]; in usb_wakeup_of_property_parse()
338 mtk->uwk_vers = args.args[1]; in usb_wakeup_of_property_parse()
339 mtk->uwk = syscon_node_to_regmap(args.np); in usb_wakeup_of_property_parse()
341 dev_info(mtk->dev, "uwk - reg:0x%x, version:%d\n", in usb_wakeup_of_property_parse()
342 mtk->uwk_reg_base, mtk->uwk_vers); in usb_wakeup_of_property_parse()
344 return PTR_ERR_OR_ZERO(mtk->uwk); in usb_wakeup_of_property_parse()
349 if (mtk->uwk_en) in usb_wakeup_set()
355 struct clk_bulk_data *clks = mtk->clks; in xhci_mtk_clks_get()
363 return devm_clk_bulk_get_optional(mtk->dev, BULK_CLKS_NUM, clks); in xhci_mtk_clks_get()
370 ret = regulator_enable(mtk->vbus); in xhci_mtk_ldos_enable()
372 dev_err(mtk->dev, "failed to enable vbus\n"); in xhci_mtk_ldos_enable()
376 ret = regulator_enable(mtk->vusb33); in xhci_mtk_ldos_enable()
378 dev_err(mtk->dev, "failed to enable vusb33\n"); in xhci_mtk_ldos_enable()
379 regulator_disable(mtk->vbus); in xhci_mtk_ldos_enable()
387 regulator_disable(mtk->vbus); in xhci_mtk_ldos_disable()
388 regulator_disable(mtk->vusb33); in xhci_mtk_ldos_disable()
391 static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) in xhci_mtk_quirks() argument
393 struct usb_hcd *hcd = xhci_to_hcd(xhci); in xhci_mtk_quirks()
398 * here that the generic code does not try to make a pci_dev from our in xhci_mtk_quirks()
401 xhci->quirks |= XHCI_PLAT; in xhci_mtk_quirks()
402 xhci->quirks |= XHCI_MTK_HOST; in xhci_mtk_quirks()
407 xhci->quirks |= XHCI_SPURIOUS_SUCCESS; in xhci_mtk_quirks()
408 if (mtk->lpm_support) in xhci_mtk_quirks()
409 xhci->quirks |= XHCI_LPM_SUPPORT; in xhci_mtk_quirks()
410 if (mtk->u2_lpm_disable) in xhci_mtk_quirks()
411 xhci->quirks |= XHCI_HW_LPM_DISABLE; in xhci_mtk_quirks()
414 * MTK xHCI 0.96: PSA is 1 by default even if doesn't support stream, in xhci_mtk_quirks()
417 if (xhci->hci_version < 0x100 && HCC_MAX_PSA(xhci->hcc_params) == 4) in xhci_mtk_quirks()
418 xhci->quirks |= XHCI_BROKEN_STREAMS; in xhci_mtk_quirks()
461 struct device *dev = &pdev->dev; in xhci_mtk_probe()
462 struct device_node *node = dev->of_node; in xhci_mtk_probe()
465 struct xhci_hcd *xhci; in xhci_mtk_probe() local
468 int ret = -ENODEV; in xhci_mtk_probe()
473 return -ENODEV; in xhci_mtk_probe()
478 return -ENOMEM; in xhci_mtk_probe()
480 mtk->dev = dev; in xhci_mtk_probe()
481 mtk->vbus = devm_regulator_get(dev, "vbus"); in xhci_mtk_probe()
482 if (IS_ERR(mtk->vbus)) { in xhci_mtk_probe()
484 return PTR_ERR(mtk->vbus); in xhci_mtk_probe()
487 mtk->vusb33 = devm_regulator_get(dev, "vusb33"); in xhci_mtk_probe()
488 if (IS_ERR(mtk->vusb33)) { in xhci_mtk_probe()
490 return PTR_ERR(mtk->vusb33); in xhci_mtk_probe()
499 if (irq == -EPROBE_DEFER) in xhci_mtk_probe()
509 if (wakeup_irq == -EPROBE_DEFER) in xhci_mtk_probe()
512 mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable"); in xhci_mtk_probe()
513 mtk->u2_lpm_disable = of_property_read_bool(node, "usb2-lpm-disable"); in xhci_mtk_probe()
515 of_property_read_u32(node, "mediatek,u3p-dis-msk", in xhci_mtk_probe()
516 &mtk->u3p_dis_msk); in xhci_mtk_probe()
517 of_property_read_u32(node, "mediatek,u2p-dis-msk", in xhci_mtk_probe()
518 &mtk->u2p_dis_msk); in xhci_mtk_probe()
536 ret = clk_bulk_prepare_enable(BULK_CLKS_NUM, mtk->clks); in xhci_mtk_probe()
542 ret = -ENOMEM; in xhci_mtk_probe()
550 mtk->hcd = platform_get_drvdata(pdev); in xhci_mtk_probe()
554 hcd->regs = devm_ioremap_resource(dev, res); in xhci_mtk_probe()
555 if (IS_ERR(hcd->regs)) { in xhci_mtk_probe()
556 ret = PTR_ERR(hcd->regs); in xhci_mtk_probe()
559 hcd->rsrc_start = res->start; in xhci_mtk_probe()
560 hcd->rsrc_len = resource_size(res); in xhci_mtk_probe()
564 mtk->ippc_regs = devm_ioremap_resource(dev, res); in xhci_mtk_probe()
565 if (IS_ERR(mtk->ippc_regs)) { in xhci_mtk_probe()
566 ret = PTR_ERR(mtk->ippc_regs); in xhci_mtk_probe()
569 mtk->has_ippc = true; in xhci_mtk_probe()
574 xhci = hcd_to_xhci(hcd); in xhci_mtk_probe()
575 xhci->main_hcd = hcd; in xhci_mtk_probe()
580 * the xHCI spec on MTK's controller. in xhci_mtk_probe()
582 xhci->imod_interval = 5000; in xhci_mtk_probe()
583 device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval); in xhci_mtk_probe()
585 xhci->shared_hcd = usb_create_shared_hcd(driver, dev, in xhci_mtk_probe()
587 if (!xhci->shared_hcd) { in xhci_mtk_probe()
588 ret = -ENOMEM; in xhci_mtk_probe()
596 if (HCC_MAX_PSA(xhci->hcc_params) >= 4 && in xhci_mtk_probe()
597 !(xhci->quirks & XHCI_BROKEN_STREAMS)) in xhci_mtk_probe()
598 xhci->shared_hcd->can_do_streams = 1; in xhci_mtk_probe()
600 ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); in xhci_mtk_probe()
621 usb_remove_hcd(xhci->shared_hcd); in xhci_mtk_probe()
622 xhci->shared_hcd = NULL; in xhci_mtk_probe()
629 usb_put_hcd(xhci->shared_hcd); in xhci_mtk_probe()
638 clk_bulk_disable_unprepare(BULK_CLKS_NUM, mtk->clks); in xhci_mtk_probe()
652 struct usb_hcd *hcd = mtk->hcd; in xhci_mtk_remove()
653 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in xhci_mtk_remove() local
654 struct usb_hcd *shared_hcd = xhci->shared_hcd; in xhci_mtk_remove()
655 struct device *dev = &pdev->dev; in xhci_mtk_remove()
658 xhci->xhc_state |= XHCI_STATE_REMOVING; in xhci_mtk_remove()
663 xhci->shared_hcd = NULL; in xhci_mtk_remove()
668 clk_bulk_disable_unprepare(BULK_CLKS_NUM, mtk->clks); in xhci_mtk_remove()
681 struct usb_hcd *hcd = mtk->hcd; in xhci_mtk_suspend()
682 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in xhci_mtk_suspend() local
685 xhci_dbg(xhci, "%s: stop port polling\n", __func__); in xhci_mtk_suspend()
686 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); in xhci_mtk_suspend()
687 del_timer_sync(&hcd->rh_timer); in xhci_mtk_suspend()
688 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); in xhci_mtk_suspend()
689 del_timer_sync(&xhci->shared_hcd->rh_timer); in xhci_mtk_suspend()
695 clk_bulk_disable_unprepare(BULK_CLKS_NUM, mtk->clks); in xhci_mtk_suspend()
700 xhci_dbg(xhci, "%s: restart port polling\n", __func__); in xhci_mtk_suspend()
701 set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); in xhci_mtk_suspend()
702 usb_hcd_poll_rh_status(xhci->shared_hcd); in xhci_mtk_suspend()
703 set_bit(HCD_FLAG_POLL_RH, &hcd->flags); in xhci_mtk_suspend()
711 struct usb_hcd *hcd = mtk->hcd; in xhci_mtk_resume()
712 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in xhci_mtk_resume() local
716 ret = clk_bulk_prepare_enable(BULK_CLKS_NUM, mtk->clks); in xhci_mtk_resume()
724 xhci_dbg(xhci, "%s: restart port polling\n", __func__); in xhci_mtk_resume()
725 set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); in xhci_mtk_resume()
726 usb_hcd_poll_rh_status(xhci->shared_hcd); in xhci_mtk_resume()
727 set_bit(HCD_FLAG_POLL_RH, &hcd->flags); in xhci_mtk_resume()
732 clk_bulk_disable_unprepare(BULK_CLKS_NUM, mtk->clks); in xhci_mtk_resume()
741 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in xhci_mtk_runtime_suspend() local
744 if (xhci->xhc_state) in xhci_mtk_runtime_suspend()
745 return -ESHUTDOWN; in xhci_mtk_runtime_suspend()
750 /* -EBUSY: let PM automatically reschedule another autosuspend */ in xhci_mtk_runtime_suspend()
751 return ret ? -EBUSY : 0; in xhci_mtk_runtime_suspend()
757 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in xhci_mtk_runtime_resume() local
760 if (xhci->xhc_state) in xhci_mtk_runtime_resume()
761 return -ESHUTDOWN; in xhci_mtk_runtime_resume()
778 { .compatible = "mediatek,mt8173-xhci"},
779 { .compatible = "mediatek,mt8195-xhci"},
780 { .compatible = "mediatek,mtk-xhci"},
789 .name = "xhci-mtk",
809 MODULE_DESCRIPTION("MediaTek xHCI Host Controller Driver");