Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Generic platform ohci driver
0004  *
0005  * Copyright 2007 Michael Buesch <m@bues.ch>
0006  * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
0007  * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
0008  *
0009  * Derived from the OCHI-SSB driver
0010  * Derived from the OHCI-PCI driver
0011  * Copyright 1999 Roman Weissgaerber
0012  * Copyright 2000-2002 David Brownell
0013  * Copyright 1999 Linus Torvalds
0014  * Copyright 1999 Gregory P. Smith
0015  */
0016 
0017 #include <linux/clk.h>
0018 #include <linux/dma-mapping.h>
0019 #include <linux/hrtimer.h>
0020 #include <linux/io.h>
0021 #include <linux/kernel.h>
0022 #include <linux/module.h>
0023 #include <linux/err.h>
0024 #include <linux/of.h>
0025 #include <linux/platform_device.h>
0026 #include <linux/pm_runtime.h>
0027 #include <linux/reset.h>
0028 #include <linux/usb/ohci_pdriver.h>
0029 #include <linux/usb.h>
0030 #include <linux/usb/hcd.h>
0031 #include <linux/usb/of.h>
0032 
0033 #include "ohci.h"
0034 
0035 #define DRIVER_DESC "OHCI generic platform driver"
0036 #define OHCI_MAX_CLKS 3
0037 #define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
0038 
0039 struct ohci_platform_priv {
0040     struct clk *clks[OHCI_MAX_CLKS];
0041     struct reset_control *resets;
0042 };
0043 
0044 static const char hcd_name[] = "ohci-platform";
0045 
0046 static int ohci_platform_power_on(struct platform_device *dev)
0047 {
0048     struct usb_hcd *hcd = platform_get_drvdata(dev);
0049     struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
0050     int clk, ret;
0051 
0052     for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
0053         ret = clk_prepare_enable(priv->clks[clk]);
0054         if (ret)
0055             goto err_disable_clks;
0056     }
0057 
0058     return 0;
0059 
0060 err_disable_clks:
0061     while (--clk >= 0)
0062         clk_disable_unprepare(priv->clks[clk]);
0063 
0064     return ret;
0065 }
0066 
0067 static void ohci_platform_power_off(struct platform_device *dev)
0068 {
0069     struct usb_hcd *hcd = platform_get_drvdata(dev);
0070     struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
0071     int clk;
0072 
0073     for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
0074         if (priv->clks[clk])
0075             clk_disable_unprepare(priv->clks[clk]);
0076 }
0077 
0078 static struct hc_driver __read_mostly ohci_platform_hc_driver;
0079 
0080 static const struct ohci_driver_overrides platform_overrides __initconst = {
0081     .product_desc =     "Generic Platform OHCI controller",
0082     .extra_priv_size =  sizeof(struct ohci_platform_priv),
0083 };
0084 
0085 static struct usb_ohci_pdata ohci_platform_defaults = {
0086     .power_on =     ohci_platform_power_on,
0087     .power_suspend =    ohci_platform_power_off,
0088     .power_off =        ohci_platform_power_off,
0089 };
0090 
0091 static int ohci_platform_probe(struct platform_device *dev)
0092 {
0093     struct usb_hcd *hcd;
0094     struct resource *res_mem;
0095     struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
0096     struct ohci_platform_priv *priv;
0097     struct ohci_hcd *ohci;
0098     int err, irq, clk = 0;
0099 
0100     if (usb_disabled())
0101         return -ENODEV;
0102 
0103     /*
0104      * Use reasonable defaults so platforms don't have to provide these
0105      * with DT probing on ARM.
0106      */
0107     if (!pdata)
0108         pdata = &ohci_platform_defaults;
0109 
0110     err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
0111     if (err)
0112         return err;
0113 
0114     irq = platform_get_irq(dev, 0);
0115     if (irq < 0)
0116         return irq;
0117 
0118     hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
0119             dev_name(&dev->dev));
0120     if (!hcd)
0121         return -ENOMEM;
0122 
0123     platform_set_drvdata(dev, hcd);
0124     dev->dev.platform_data = pdata;
0125     priv = hcd_to_ohci_priv(hcd);
0126     ohci = hcd_to_ohci(hcd);
0127 
0128     if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
0129         if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
0130             ohci->flags |= OHCI_QUIRK_BE_MMIO;
0131 
0132         if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
0133             ohci->flags |= OHCI_QUIRK_BE_DESC;
0134 
0135         if (of_property_read_bool(dev->dev.of_node, "big-endian"))
0136             ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
0137 
0138         if (of_property_read_bool(dev->dev.of_node, "no-big-frame-no"))
0139             ohci->flags |= OHCI_QUIRK_FRAME_NO;
0140 
0141         if (of_property_read_bool(dev->dev.of_node,
0142                       "remote-wakeup-connected"))
0143             ohci->hc_control = OHCI_CTRL_RWC;
0144 
0145         of_property_read_u32(dev->dev.of_node, "num-ports",
0146                      &ohci->num_ports);
0147 
0148         for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
0149             priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
0150             if (IS_ERR(priv->clks[clk])) {
0151                 err = PTR_ERR(priv->clks[clk]);
0152                 if (err == -EPROBE_DEFER)
0153                     goto err_put_clks;
0154                 priv->clks[clk] = NULL;
0155                 break;
0156             }
0157         }
0158 
0159         priv->resets = devm_reset_control_array_get_optional_shared(
0160                                 &dev->dev);
0161         if (IS_ERR(priv->resets)) {
0162             err = PTR_ERR(priv->resets);
0163             goto err_put_clks;
0164         }
0165 
0166         err = reset_control_deassert(priv->resets);
0167         if (err)
0168             goto err_put_clks;
0169     }
0170 
0171     if (pdata->big_endian_desc)
0172         ohci->flags |= OHCI_QUIRK_BE_DESC;
0173     if (pdata->big_endian_mmio)
0174         ohci->flags |= OHCI_QUIRK_BE_MMIO;
0175     if (pdata->no_big_frame_no)
0176         ohci->flags |= OHCI_QUIRK_FRAME_NO;
0177     if (pdata->num_ports)
0178         ohci->num_ports = pdata->num_ports;
0179 
0180 #ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
0181     if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
0182         dev_err(&dev->dev,
0183             "Error: CONFIG_USB_OHCI_BIG_ENDIAN_MMIO not set\n");
0184         err = -EINVAL;
0185         goto err_reset;
0186     }
0187 #endif
0188 #ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
0189     if (ohci->flags & OHCI_QUIRK_BE_DESC) {
0190         dev_err(&dev->dev,
0191             "Error: CONFIG_USB_OHCI_BIG_ENDIAN_DESC not set\n");
0192         err = -EINVAL;
0193         goto err_reset;
0194     }
0195 #endif
0196 
0197     pm_runtime_set_active(&dev->dev);
0198     pm_runtime_enable(&dev->dev);
0199     if (pdata->power_on) {
0200         err = pdata->power_on(dev);
0201         if (err < 0)
0202             goto err_reset;
0203     }
0204 
0205     res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
0206     hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
0207     if (IS_ERR(hcd->regs)) {
0208         err = PTR_ERR(hcd->regs);
0209         goto err_power;
0210     }
0211     hcd->rsrc_start = res_mem->start;
0212     hcd->rsrc_len = resource_size(res_mem);
0213 
0214     hcd->tpl_support = of_usb_host_tpl_support(dev->dev.of_node);
0215 
0216     err = usb_add_hcd(hcd, irq, IRQF_SHARED);
0217     if (err)
0218         goto err_power;
0219 
0220     device_wakeup_enable(hcd->self.controller);
0221 
0222     platform_set_drvdata(dev, hcd);
0223 
0224     return err;
0225 
0226 err_power:
0227     if (pdata->power_off)
0228         pdata->power_off(dev);
0229 err_reset:
0230     pm_runtime_disable(&dev->dev);
0231     reset_control_assert(priv->resets);
0232 err_put_clks:
0233     while (--clk >= 0)
0234         clk_put(priv->clks[clk]);
0235 
0236     if (pdata == &ohci_platform_defaults)
0237         dev->dev.platform_data = NULL;
0238 
0239     usb_put_hcd(hcd);
0240 
0241     return err;
0242 }
0243 
0244 static int ohci_platform_remove(struct platform_device *dev)
0245 {
0246     struct usb_hcd *hcd = platform_get_drvdata(dev);
0247     struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
0248     struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
0249     int clk;
0250 
0251     pm_runtime_get_sync(&dev->dev);
0252     usb_remove_hcd(hcd);
0253 
0254     if (pdata->power_off)
0255         pdata->power_off(dev);
0256 
0257     reset_control_assert(priv->resets);
0258 
0259     for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
0260         clk_put(priv->clks[clk]);
0261 
0262     usb_put_hcd(hcd);
0263 
0264     pm_runtime_put_sync(&dev->dev);
0265     pm_runtime_disable(&dev->dev);
0266 
0267     if (pdata == &ohci_platform_defaults)
0268         dev->dev.platform_data = NULL;
0269 
0270     return 0;
0271 }
0272 
0273 #ifdef CONFIG_PM_SLEEP
0274 static int ohci_platform_suspend(struct device *dev)
0275 {
0276     struct usb_hcd *hcd = dev_get_drvdata(dev);
0277     struct usb_ohci_pdata *pdata = dev->platform_data;
0278     struct platform_device *pdev = to_platform_device(dev);
0279     bool do_wakeup = device_may_wakeup(dev);
0280     int ret;
0281 
0282     ret = ohci_suspend(hcd, do_wakeup);
0283     if (ret)
0284         return ret;
0285 
0286     if (pdata->power_suspend)
0287         pdata->power_suspend(pdev);
0288 
0289     return ret;
0290 }
0291 
0292 static int ohci_platform_resume(struct device *dev)
0293 {
0294     struct usb_hcd *hcd = dev_get_drvdata(dev);
0295     struct usb_ohci_pdata *pdata = dev_get_platdata(dev);
0296     struct platform_device *pdev = to_platform_device(dev);
0297 
0298     if (pdata->power_on) {
0299         int err = pdata->power_on(pdev);
0300         if (err < 0)
0301             return err;
0302     }
0303 
0304     ohci_resume(hcd, false);
0305 
0306     pm_runtime_disable(dev);
0307     pm_runtime_set_active(dev);
0308     pm_runtime_enable(dev);
0309 
0310     return 0;
0311 }
0312 #endif /* CONFIG_PM_SLEEP */
0313 
0314 static const struct of_device_id ohci_platform_ids[] = {
0315     { .compatible = "generic-ohci", },
0316     { .compatible = "cavium,octeon-6335-ohci", },
0317     { .compatible = "ti,ohci-omap3", },
0318     { }
0319 };
0320 MODULE_DEVICE_TABLE(of, ohci_platform_ids);
0321 
0322 static const struct platform_device_id ohci_platform_table[] = {
0323     { "ohci-platform", 0 },
0324     { }
0325 };
0326 MODULE_DEVICE_TABLE(platform, ohci_platform_table);
0327 
0328 static SIMPLE_DEV_PM_OPS(ohci_platform_pm_ops, ohci_platform_suspend,
0329     ohci_platform_resume);
0330 
0331 static struct platform_driver ohci_platform_driver = {
0332     .id_table   = ohci_platform_table,
0333     .probe      = ohci_platform_probe,
0334     .remove     = ohci_platform_remove,
0335     .shutdown   = usb_hcd_platform_shutdown,
0336     .driver     = {
0337         .name   = "ohci-platform",
0338         .pm = &ohci_platform_pm_ops,
0339         .of_match_table = ohci_platform_ids,
0340         .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0341     }
0342 };
0343 
0344 static int __init ohci_platform_init(void)
0345 {
0346     if (usb_disabled())
0347         return -ENODEV;
0348 
0349     pr_info("%s: " DRIVER_DESC "\n", hcd_name);
0350 
0351     ohci_init_driver(&ohci_platform_hc_driver, &platform_overrides);
0352     return platform_driver_register(&ohci_platform_driver);
0353 }
0354 module_init(ohci_platform_init);
0355 
0356 static void __exit ohci_platform_cleanup(void)
0357 {
0358     platform_driver_unregister(&ohci_platform_driver);
0359 }
0360 module_exit(ohci_platform_cleanup);
0361 
0362 MODULE_DESCRIPTION(DRIVER_DESC);
0363 MODULE_AUTHOR("Hauke Mehrtens");
0364 MODULE_AUTHOR("Alan Stern");
0365 MODULE_LICENSE("GPL");