Lines Matching +full:generic +full:- +full:ehci
1 // SPDX-License-Identifier: GPL-2.0
3 * Generic platform ehci driver
6 * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
9 * Derived from the ohci-ssb driver
12 * Derived from the EHCI-PCI driver
13 * Copyright (c) 2000-2004 by David Brownell
15 * Derived from the ohci-pci driver
17 * Copyright 2000-2002 David Brownell
23 #include <linux/dma-mapping.h>
40 #include "ehci.h"
42 #define DRIVER_DESC "EHCI generic platform driver"
44 #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
58 static const char hcd_name[] = "ehci-platform";
62 struct ehci_hcd *ehci = hcd_to_ehci(hcd); in ehci_rockchip_relinquish_port() local
63 u32 __iomem *status_reg = &ehci->regs->port_status[--portnum]; in ehci_rockchip_relinquish_port()
66 portsc = ehci_readl(ehci, status_reg); in ehci_rockchip_relinquish_port()
69 ehci_writel(ehci, portsc, status_reg); in ehci_rockchip_relinquish_port()
81 struct ehci_hcd *ehci = hcd_to_ehci(hcd); in ehci_usic_init() local
83 ehci_writel(ehci, USIC_ENABLE, in ehci_usic_init()
84 hcd->regs + USIC_ENABLE_OFFSET); in ehci_usic_init()
85 ehci_writel(ehci, USIC_MICROFRAME_COUNT, in ehci_usic_init()
86 hcd->regs + USIC_MICROFRAME_OFFSET); in ehci_usic_init()
87 ehci_writel(ehci, USIC_SCALE_DOWN, in ehci_usic_init()
88 hcd->regs + USIC_SCALE_DOWN_OFFSET); in ehci_usic_init()
93 struct platform_device *pdev = to_platform_device(hcd->self.controller); in ehci_platform_reset()
94 struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); in ehci_platform_reset()
95 struct ehci_hcd *ehci = hcd_to_ehci(hcd); in ehci_platform_reset() local
98 ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; in ehci_platform_reset()
100 if (pdata->pre_setup) { in ehci_platform_reset()
101 retval = pdata->pre_setup(hcd); in ehci_platform_reset()
106 ehci->caps = hcd->regs + pdata->caps_offset; in ehci_platform_reset()
111 if (pdata->no_io_watchdog) in ehci_platform_reset()
112 ehci->need_io_watchdog = 0; in ehci_platform_reset()
114 if (of_device_is_compatible(pdev->dev.of_node, "brcm,xgs-iproc-ehci")) in ehci_platform_reset()
115 ehci_writel(ehci, BCM_USB_FIFO_THRESHOLD, in ehci_platform_reset()
116 &ehci->regs->bcm_iproc_insnreg01); in ehci_platform_reset()
127 for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) { in ehci_platform_power_on()
128 ret = clk_prepare_enable(priv->clks[clk]); in ehci_platform_power_on()
136 while (--clk >= 0) in ehci_platform_power_on()
137 clk_disable_unprepare(priv->clks[clk]); in ehci_platform_power_on()
148 for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) in ehci_platform_power_off()
149 if (priv->clks[clk]) in ehci_platform_power_off()
150 clk_disable_unprepare(priv->clks[clk]); in ehci_platform_power_off()
167 * quirk_poll_check_port_status - Poll port_status if the device sticks
168 * @ehci: the ehci hcd pointer
170 * Since EHCI/OHCI controllers on R-Car Gen3 SoCs are possible to be getting
173 * the EHCI PORTSC register.
177 static bool quirk_poll_check_port_status(struct ehci_hcd *ehci) in quirk_poll_check_port_status() argument
179 u32 port_status = ehci_readl(ehci, &ehci->regs->port_status[0]); in quirk_poll_check_port_status()
191 * quirk_poll_rebind_companion - rebind comanion device to recover
192 * @ehci: the ehci hcd pointer
194 * Since EHCI/OHCI controllers on R-Car Gen3 SoCs are possible to be getting
199 static void quirk_poll_rebind_companion(struct ehci_hcd *ehci) in quirk_poll_rebind_companion() argument
202 struct usb_hcd *hcd = ehci_to_hcd(ehci); in quirk_poll_rebind_companion()
204 companion_dev = usb_of_get_companion_dev(hcd->self.controller); in quirk_poll_rebind_companion()
210 ehci_err(ehci, "%s: failed\n", __func__); in quirk_poll_rebind_companion()
220 struct ehci_hcd *ehci = container_of((void *)priv, struct ehci_hcd, in quirk_poll_work() local
224 if (!quirk_poll_check_port_status(ehci)) in quirk_poll_work()
227 if (!quirk_poll_check_port_status(ehci)) in quirk_poll_work()
230 ehci_dbg(ehci, "%s: detected getting stuck. rebind now!\n", __func__); in quirk_poll_work()
231 quirk_poll_rebind_companion(ehci); in quirk_poll_work()
237 struct ehci_hcd *ehci = container_of((void *)priv, struct ehci_hcd, in quirk_poll_timer() local
240 if (quirk_poll_check_port_status(ehci)) { in quirk_poll_timer()
247 schedule_delayed_work(&priv->poll_work, msecs_to_jiffies(5)); in quirk_poll_timer()
250 mod_timer(&priv->poll_timer, jiffies + HZ); in quirk_poll_timer()
255 INIT_DELAYED_WORK(&priv->poll_work, quirk_poll_work); in quirk_poll_init()
256 timer_setup(&priv->poll_timer, quirk_poll_timer, 0); in quirk_poll_init()
257 mod_timer(&priv->poll_timer, jiffies + HZ); in quirk_poll_init()
262 del_timer_sync(&priv->poll_timer); in quirk_poll_end()
263 cancel_delayed_work(&priv->poll_work); in quirk_poll_end()
267 { .family = "R-Car Gen3" },
275 struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); in ehci_platform_probe()
277 struct ehci_hcd *ehci; in ehci_platform_probe() local
283 return -ENODEV; in ehci_platform_probe()
292 err = dma_coerce_mask_and_coherent(&dev->dev, in ehci_platform_probe()
293 pdata->dma_mask_64 ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32)); in ehci_platform_probe()
295 dev_err(&dev->dev, "Error: DMA mask configuration failed\n"); in ehci_platform_probe()
303 hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, in ehci_platform_probe()
304 dev_name(&dev->dev)); in ehci_platform_probe()
306 return -ENOMEM; in ehci_platform_probe()
309 dev->dev.platform_data = pdata; in ehci_platform_probe()
311 ehci = hcd_to_ehci(hcd); in ehci_platform_probe()
313 if (pdata == &ehci_platform_defaults && dev->dev.of_node) { in ehci_platform_probe()
314 if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) in ehci_platform_probe()
315 ehci->big_endian_mmio = 1; in ehci_platform_probe()
317 if (of_property_read_bool(dev->dev.of_node, "big-endian-desc")) in ehci_platform_probe()
318 ehci->big_endian_desc = 1; in ehci_platform_probe()
320 if (of_property_read_bool(dev->dev.of_node, "big-endian")) in ehci_platform_probe()
321 ehci->big_endian_mmio = ehci->big_endian_desc = 1; in ehci_platform_probe()
323 if (of_property_read_bool(dev->dev.of_node, in ehci_platform_probe()
324 "needs-reset-on-resume")) in ehci_platform_probe()
325 priv->reset_on_resume = true; in ehci_platform_probe()
327 if (of_property_read_bool(dev->dev.of_node, in ehci_platform_probe()
328 "has-transaction-translator")) in ehci_platform_probe()
329 hcd->has_tt = 1; in ehci_platform_probe()
331 if (of_device_is_compatible(dev->dev.of_node, in ehci_platform_probe()
332 "aspeed,ast2500-ehci") || in ehci_platform_probe()
333 of_device_is_compatible(dev->dev.of_node, in ehci_platform_probe()
334 "aspeed,ast2600-ehci")) in ehci_platform_probe()
335 ehci->is_aspeed = 1; in ehci_platform_probe()
338 priv->quirk_poll = true; in ehci_platform_probe()
341 of_property_read_bool(dev->dev.of_node, in ehci_platform_probe()
342 "rockchip-relinquish-port")) in ehci_platform_probe()
347 priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); in ehci_platform_probe()
348 if (IS_ERR(priv->clks[clk])) { in ehci_platform_probe()
349 err = PTR_ERR(priv->clks[clk]); in ehci_platform_probe()
350 if (err == -EPROBE_DEFER) in ehci_platform_probe()
352 priv->clks[clk] = NULL; in ehci_platform_probe()
358 priv->rsts = devm_reset_control_array_get_optional_shared(&dev->dev); in ehci_platform_probe()
359 if (IS_ERR(priv->rsts)) { in ehci_platform_probe()
360 err = PTR_ERR(priv->rsts); in ehci_platform_probe()
364 err = reset_control_deassert(priv->rsts); in ehci_platform_probe()
368 if (pdata->big_endian_desc) in ehci_platform_probe()
369 ehci->big_endian_desc = 1; in ehci_platform_probe()
370 if (pdata->big_endian_mmio) in ehci_platform_probe()
371 ehci->big_endian_mmio = 1; in ehci_platform_probe()
372 if (pdata->has_tt) in ehci_platform_probe()
373 hcd->has_tt = 1; in ehci_platform_probe()
374 if (pdata->reset_on_resume) in ehci_platform_probe()
375 priv->reset_on_resume = true; in ehci_platform_probe()
378 if (ehci->big_endian_mmio) { in ehci_platform_probe()
379 dev_err(&dev->dev, in ehci_platform_probe()
381 err = -EINVAL; in ehci_platform_probe()
386 if (ehci->big_endian_desc) { in ehci_platform_probe()
387 dev_err(&dev->dev, in ehci_platform_probe()
389 err = -EINVAL; in ehci_platform_probe()
394 pm_runtime_set_active(&dev->dev); in ehci_platform_probe()
395 pm_runtime_enable(&dev->dev); in ehci_platform_probe()
396 pm_runtime_get_sync(&dev->dev); in ehci_platform_probe()
397 if (pdata->power_on) { in ehci_platform_probe()
398 err = pdata->power_on(dev); in ehci_platform_probe()
404 hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); in ehci_platform_probe()
405 if (IS_ERR(hcd->regs)) { in ehci_platform_probe()
406 err = PTR_ERR(hcd->regs); in ehci_platform_probe()
409 hcd->rsrc_start = res_mem->start; in ehci_platform_probe()
410 hcd->rsrc_len = resource_size(res_mem); in ehci_platform_probe()
416 if (of_usb_get_phy_mode(dev->dev.of_node) == USBPHY_INTERFACE_MODE_HSIC) in ehci_platform_probe()
419 if (of_device_is_compatible(dev->dev.of_node, in ehci_platform_probe()
420 "rockchip,rk3588-ehci")) { in ehci_platform_probe()
421 companion_dev = usb_of_get_companion_dev(hcd->self.controller); in ehci_platform_probe()
423 link = device_link_add(companion_dev, hcd->self.controller, in ehci_platform_probe()
427 dev_err(&dev->dev, "Unable to link %s\n", in ehci_platform_probe()
429 err = -EINVAL; in ehci_platform_probe()
435 device_wakeup_enable(hcd->self.controller); in ehci_platform_probe()
436 device_enable_async_suspend(hcd->self.controller); in ehci_platform_probe()
439 if (priv->quirk_poll) in ehci_platform_probe()
445 if (pdata->power_off) in ehci_platform_probe()
446 pdata->power_off(dev); in ehci_platform_probe()
448 pm_runtime_put_sync(&dev->dev); in ehci_platform_probe()
449 pm_runtime_disable(&dev->dev); in ehci_platform_probe()
450 reset_control_assert(priv->rsts); in ehci_platform_probe()
452 while (--clk >= 0) in ehci_platform_probe()
453 clk_put(priv->clks[clk]); in ehci_platform_probe()
456 dev->dev.platform_data = NULL; in ehci_platform_probe()
466 struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); in ehci_platform_remove()
471 if (priv->quirk_poll) in ehci_platform_remove()
474 if (of_device_is_compatible(dev->dev.of_node, in ehci_platform_remove()
475 "rockchip,rk3588-ehci")) { in ehci_platform_remove()
476 companion_dev = usb_of_get_companion_dev(hcd->self.controller); in ehci_platform_remove()
478 device_link_remove(companion_dev, hcd->self.controller); in ehci_platform_remove()
485 if (pdata->power_off) in ehci_platform_remove()
486 pdata->power_off(dev); in ehci_platform_remove()
488 reset_control_assert(priv->rsts); in ehci_platform_remove()
490 for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) in ehci_platform_remove()
491 clk_put(priv->clks[clk]); in ehci_platform_remove()
495 pm_runtime_put_sync(&dev->dev); in ehci_platform_remove()
496 pm_runtime_disable(&dev->dev); in ehci_platform_remove()
499 dev->dev.platform_data = NULL; in ehci_platform_remove()
513 if (priv->quirk_poll) in ehci_platform_suspend()
520 if (pdata->power_suspend) in ehci_platform_suspend()
521 pdata->power_suspend(pdev); in ehci_platform_suspend()
534 if (pdata->power_on) { in ehci_platform_resume()
535 int err = pdata->power_on(pdev); in ehci_platform_resume()
540 companion_dev = usb_of_get_companion_dev(hcd->self.controller); in ehci_platform_resume()
542 if (!device_is_dependent(hcd->self.controller, companion_dev)) in ehci_platform_resume()
543 device_pm_wait_for_dev(hcd->self.controller, companion_dev); in ehci_platform_resume()
547 ehci_resume(hcd, priv->reset_on_resume); in ehci_platform_resume()
553 if (priv->quirk_poll) in ehci_platform_resume()
560 { .compatible = "via,vt8500-ehci", },
561 { .compatible = "wm,prizm-ehci", },
562 { .compatible = "generic-ehci", },
563 { .compatible = "cavium,octeon-6335-ehci", },
570 { "PNP0D20", 0 }, /* EHCI controller without debug */
577 { "ehci-platform", 0 },
591 .name = "ehci-platform",
601 return -ENODEV; in ehci_platform_init()