linux/drivers/usb/host/ohci-platform.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Generic platform ohci driver
   4 *
   5 * Copyright 2007 Michael Buesch <m@bues.ch>
   6 * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
   7 * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
   8 *
   9 * Derived from the OCHI-SSB driver
  10 * Derived from the OHCI-PCI driver
  11 * Copyright 1999 Roman Weissgaerber
  12 * Copyright 2000-2002 David Brownell
  13 * Copyright 1999 Linus Torvalds
  14 * Copyright 1999 Gregory P. Smith
  15 */
  16
  17#include <linux/clk.h>
  18#include <linux/dma-mapping.h>
  19#include <linux/hrtimer.h>
  20#include <linux/io.h>
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/err.h>
  24#include <linux/of.h>
  25#include <linux/platform_device.h>
  26#include <linux/pm_runtime.h>
  27#include <linux/reset.h>
  28#include <linux/usb/ohci_pdriver.h>
  29#include <linux/usb.h>
  30#include <linux/usb/hcd.h>
  31
  32#include "ohci.h"
  33
  34#define DRIVER_DESC "OHCI generic platform driver"
  35#define OHCI_MAX_CLKS 3
  36#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
  37
  38struct ohci_platform_priv {
  39        struct clk *clks[OHCI_MAX_CLKS];
  40        struct reset_control *resets;
  41};
  42
  43static const char hcd_name[] = "ohci-platform";
  44
  45static int ohci_platform_power_on(struct platform_device *dev)
  46{
  47        struct usb_hcd *hcd = platform_get_drvdata(dev);
  48        struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
  49        int clk, ret;
  50
  51        for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
  52                ret = clk_prepare_enable(priv->clks[clk]);
  53                if (ret)
  54                        goto err_disable_clks;
  55        }
  56
  57        return 0;
  58
  59err_disable_clks:
  60        while (--clk >= 0)
  61                clk_disable_unprepare(priv->clks[clk]);
  62
  63        return ret;
  64}
  65
  66static void ohci_platform_power_off(struct platform_device *dev)
  67{
  68        struct usb_hcd *hcd = platform_get_drvdata(dev);
  69        struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
  70        int clk;
  71
  72        for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
  73                if (priv->clks[clk])
  74                        clk_disable_unprepare(priv->clks[clk]);
  75}
  76
  77static struct hc_driver __read_mostly ohci_platform_hc_driver;
  78
  79static const struct ohci_driver_overrides platform_overrides __initconst = {
  80        .product_desc =         "Generic Platform OHCI controller",
  81        .extra_priv_size =      sizeof(struct ohci_platform_priv),
  82};
  83
  84static struct usb_ohci_pdata ohci_platform_defaults = {
  85        .power_on =             ohci_platform_power_on,
  86        .power_suspend =        ohci_platform_power_off,
  87        .power_off =            ohci_platform_power_off,
  88};
  89
  90static int ohci_platform_probe(struct platform_device *dev)
  91{
  92        struct usb_hcd *hcd;
  93        struct resource *res_mem;
  94        struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
  95        struct ohci_platform_priv *priv;
  96        struct ohci_hcd *ohci;
  97        int err, irq, clk = 0;
  98
  99        if (usb_disabled())
 100                return -ENODEV;
 101
 102        /*
 103         * Use reasonable defaults so platforms don't have to provide these
 104         * with DT probing on ARM.
 105         */
 106        if (!pdata)
 107                pdata = &ohci_platform_defaults;
 108
 109        err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
 110        if (err)
 111                return err;
 112
 113        irq = platform_get_irq(dev, 0);
 114        if (irq < 0)
 115                return irq;
 116
 117        hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
 118                        dev_name(&dev->dev));
 119        if (!hcd)
 120                return -ENOMEM;
 121
 122        platform_set_drvdata(dev, hcd);
 123        dev->dev.platform_data = pdata;
 124        priv = hcd_to_ohci_priv(hcd);
 125        ohci = hcd_to_ohci(hcd);
 126
 127        if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
 128                if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
 129                        ohci->flags |= OHCI_QUIRK_BE_MMIO;
 130
 131                if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
 132                        ohci->flags |= OHCI_QUIRK_BE_DESC;
 133
 134                if (of_property_read_bool(dev->dev.of_node, "big-endian"))
 135                        ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
 136
 137                if (of_property_read_bool(dev->dev.of_node, "no-big-frame-no"))
 138                        ohci->flags |= OHCI_QUIRK_FRAME_NO;
 139
 140                if (of_property_read_bool(dev->dev.of_node,
 141                                          "remote-wakeup-connected"))
 142                        ohci->hc_control = OHCI_CTRL_RWC;
 143
 144                of_property_read_u32(dev->dev.of_node, "num-ports",
 145                                     &ohci->num_ports);
 146
 147                for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
 148                        priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
 149                        if (IS_ERR(priv->clks[clk])) {
 150                                err = PTR_ERR(priv->clks[clk]);
 151                                if (err == -EPROBE_DEFER)
 152                                        goto err_put_clks;
 153                                priv->clks[clk] = NULL;
 154                                break;
 155                        }
 156                }
 157
 158                priv->resets = devm_reset_control_array_get_optional_shared(
 159                                                                &dev->dev);
 160                if (IS_ERR(priv->resets)) {
 161                        err = PTR_ERR(priv->resets);
 162                        goto err_put_clks;
 163                }
 164
 165                err = reset_control_deassert(priv->resets);
 166                if (err)
 167                        goto err_put_clks;
 168        }
 169
 170        if (pdata->big_endian_desc)
 171                ohci->flags |= OHCI_QUIRK_BE_DESC;
 172        if (pdata->big_endian_mmio)
 173                ohci->flags |= OHCI_QUIRK_BE_MMIO;
 174        if (pdata->no_big_frame_no)
 175                ohci->flags |= OHCI_QUIRK_FRAME_NO;
 176        if (pdata->num_ports)
 177                ohci->num_ports = pdata->num_ports;
 178
 179#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
 180        if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
 181                dev_err(&dev->dev,
 182                        "Error: CONFIG_USB_OHCI_BIG_ENDIAN_MMIO not set\n");
 183                err = -EINVAL;
 184                goto err_reset;
 185        }
 186#endif
 187#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
 188        if (ohci->flags & OHCI_QUIRK_BE_DESC) {
 189                dev_err(&dev->dev,
 190                        "Error: CONFIG_USB_OHCI_BIG_ENDIAN_DESC not set\n");
 191                err = -EINVAL;
 192                goto err_reset;
 193        }
 194#endif
 195
 196        pm_runtime_set_active(&dev->dev);
 197        pm_runtime_enable(&dev->dev);
 198        if (pdata->power_on) {
 199                err = pdata->power_on(dev);
 200                if (err < 0)
 201                        goto err_reset;
 202        }
 203
 204        res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 205        hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
 206        if (IS_ERR(hcd->regs)) {
 207                err = PTR_ERR(hcd->regs);
 208                goto err_power;
 209        }
 210        hcd->rsrc_start = res_mem->start;
 211        hcd->rsrc_len = resource_size(res_mem);
 212
 213        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 214        if (err)
 215                goto err_power;
 216
 217        device_wakeup_enable(hcd->self.controller);
 218
 219        platform_set_drvdata(dev, hcd);
 220
 221        return err;
 222
 223err_power:
 224        if (pdata->power_off)
 225                pdata->power_off(dev);
 226err_reset:
 227        pm_runtime_disable(&dev->dev);
 228        reset_control_assert(priv->resets);
 229err_put_clks:
 230        while (--clk >= 0)
 231                clk_put(priv->clks[clk]);
 232
 233        if (pdata == &ohci_platform_defaults)
 234                dev->dev.platform_data = NULL;
 235
 236        usb_put_hcd(hcd);
 237
 238        return err;
 239}
 240
 241static int ohci_platform_remove(struct platform_device *dev)
 242{
 243        struct usb_hcd *hcd = platform_get_drvdata(dev);
 244        struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
 245        struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
 246        int clk;
 247
 248        pm_runtime_get_sync(&dev->dev);
 249        usb_remove_hcd(hcd);
 250
 251        if (pdata->power_off)
 252                pdata->power_off(dev);
 253
 254        reset_control_assert(priv->resets);
 255
 256        for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
 257                clk_put(priv->clks[clk]);
 258
 259        usb_put_hcd(hcd);
 260
 261        pm_runtime_put_sync(&dev->dev);
 262        pm_runtime_disable(&dev->dev);
 263
 264        if (pdata == &ohci_platform_defaults)
 265                dev->dev.platform_data = NULL;
 266
 267        return 0;
 268}
 269
 270#ifdef CONFIG_PM_SLEEP
 271static int ohci_platform_suspend(struct device *dev)
 272{
 273        struct usb_hcd *hcd = dev_get_drvdata(dev);
 274        struct usb_ohci_pdata *pdata = dev->platform_data;
 275        struct platform_device *pdev = to_platform_device(dev);
 276        bool do_wakeup = device_may_wakeup(dev);
 277        int ret;
 278
 279        ret = ohci_suspend(hcd, do_wakeup);
 280        if (ret)
 281                return ret;
 282
 283        if (pdata->power_suspend)
 284                pdata->power_suspend(pdev);
 285
 286        return ret;
 287}
 288
 289static int ohci_platform_resume(struct device *dev)
 290{
 291        struct usb_hcd *hcd = dev_get_drvdata(dev);
 292        struct usb_ohci_pdata *pdata = dev_get_platdata(dev);
 293        struct platform_device *pdev = to_platform_device(dev);
 294
 295        if (pdata->power_on) {
 296                int err = pdata->power_on(pdev);
 297                if (err < 0)
 298                        return err;
 299        }
 300
 301        ohci_resume(hcd, false);
 302        return 0;
 303}
 304#endif /* CONFIG_PM_SLEEP */
 305
 306static const struct of_device_id ohci_platform_ids[] = {
 307        { .compatible = "generic-ohci", },
 308        { .compatible = "cavium,octeon-6335-ohci", },
 309        { .compatible = "ti,ohci-omap3", },
 310        { }
 311};
 312MODULE_DEVICE_TABLE(of, ohci_platform_ids);
 313
 314static const struct platform_device_id ohci_platform_table[] = {
 315        { "ohci-platform", 0 },
 316        { }
 317};
 318MODULE_DEVICE_TABLE(platform, ohci_platform_table);
 319
 320static SIMPLE_DEV_PM_OPS(ohci_platform_pm_ops, ohci_platform_suspend,
 321        ohci_platform_resume);
 322
 323static struct platform_driver ohci_platform_driver = {
 324        .id_table       = ohci_platform_table,
 325        .probe          = ohci_platform_probe,
 326        .remove         = ohci_platform_remove,
 327        .shutdown       = usb_hcd_platform_shutdown,
 328        .driver         = {
 329                .name   = "ohci-platform",
 330                .pm     = &ohci_platform_pm_ops,
 331                .of_match_table = ohci_platform_ids,
 332        }
 333};
 334
 335static int __init ohci_platform_init(void)
 336{
 337        if (usb_disabled())
 338                return -ENODEV;
 339
 340        pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 341
 342        ohci_init_driver(&ohci_platform_hc_driver, &platform_overrides);
 343        return platform_driver_register(&ohci_platform_driver);
 344}
 345module_init(ohci_platform_init);
 346
 347static void __exit ohci_platform_cleanup(void)
 348{
 349        platform_driver_unregister(&ohci_platform_driver);
 350}
 351module_exit(ohci_platform_cleanup);
 352
 353MODULE_DESCRIPTION(DRIVER_DESC);
 354MODULE_AUTHOR("Hauke Mehrtens");
 355MODULE_AUTHOR("Alan Stern");
 356MODULE_LICENSE("GPL");
 357