linux/drivers/usb/host/ohci-platform.c
<<
>>
Prefs
   1/*
   2 * Generic platform ohci driver
   3 *
   4 * Copyright 2007 Michael Buesch <m@bues.ch>
   5 * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
   6 *
   7 * Derived from the OCHI-SSB driver
   8 * Derived from the OHCI-PCI driver
   9 * Copyright 1999 Roman Weissgaerber
  10 * Copyright 2000-2002 David Brownell
  11 * Copyright 1999 Linus Torvalds
  12 * Copyright 1999 Gregory P. Smith
  13 *
  14 * Licensed under the GNU/GPL. See COPYING for details.
  15 */
  16#include <linux/err.h>
  17#include <linux/platform_device.h>
  18#include <linux/usb/ohci_pdriver.h>
  19
  20static int ohci_platform_reset(struct usb_hcd *hcd)
  21{
  22        struct platform_device *pdev = to_platform_device(hcd->self.controller);
  23        struct usb_ohci_pdata *pdata = pdev->dev.platform_data;
  24        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
  25        int err;
  26
  27        if (pdata->big_endian_desc)
  28                ohci->flags |= OHCI_QUIRK_BE_DESC;
  29        if (pdata->big_endian_mmio)
  30                ohci->flags |= OHCI_QUIRK_BE_MMIO;
  31        if (pdata->no_big_frame_no)
  32                ohci->flags |= OHCI_QUIRK_FRAME_NO;
  33
  34        ohci_hcd_init(ohci);
  35
  36        if (pdata->num_ports)
  37                ohci->num_ports = pdata->num_ports;
  38
  39        err = ohci_init(ohci);
  40
  41        return err;
  42}
  43
  44static int ohci_platform_start(struct usb_hcd *hcd)
  45{
  46        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
  47        int err;
  48
  49        err = ohci_run(ohci);
  50        if (err < 0) {
  51                ohci_err(ohci, "can't start\n");
  52                ohci_stop(hcd);
  53        }
  54
  55        return err;
  56}
  57
  58static const struct hc_driver ohci_platform_hc_driver = {
  59        .description            = hcd_name,
  60        .product_desc           = "Generic Platform OHCI Controller",
  61        .hcd_priv_size          = sizeof(struct ohci_hcd),
  62
  63        .irq                    = ohci_irq,
  64        .flags                  = HCD_MEMORY | HCD_USB11,
  65
  66        .reset                  = ohci_platform_reset,
  67        .start                  = ohci_platform_start,
  68        .stop                   = ohci_stop,
  69        .shutdown               = ohci_shutdown,
  70
  71        .urb_enqueue            = ohci_urb_enqueue,
  72        .urb_dequeue            = ohci_urb_dequeue,
  73        .endpoint_disable       = ohci_endpoint_disable,
  74
  75        .get_frame_number       = ohci_get_frame,
  76
  77        .hub_status_data        = ohci_hub_status_data,
  78        .hub_control            = ohci_hub_control,
  79#ifdef  CONFIG_PM
  80        .bus_suspend            = ohci_bus_suspend,
  81        .bus_resume             = ohci_bus_resume,
  82#endif
  83
  84        .start_port_reset       = ohci_start_port_reset,
  85};
  86
  87static int ohci_platform_probe(struct platform_device *dev)
  88{
  89        struct usb_hcd *hcd;
  90        struct resource *res_mem;
  91        struct usb_ohci_pdata *pdata = dev->dev.platform_data;
  92        int irq;
  93        int err = -ENOMEM;
  94
  95        if (!pdata) {
  96                WARN_ON(1);
  97                return -ENODEV;
  98        }
  99
 100        if (usb_disabled())
 101                return -ENODEV;
 102
 103        irq = platform_get_irq(dev, 0);
 104        if (irq < 0) {
 105                dev_err(&dev->dev, "no irq provided");
 106                return irq;
 107        }
 108
 109        res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 110        if (!res_mem) {
 111                dev_err(&dev->dev, "no memory resource provided");
 112                return -ENXIO;
 113        }
 114
 115        if (pdata->power_on) {
 116                err = pdata->power_on(dev);
 117                if (err < 0)
 118                        return err;
 119        }
 120
 121        hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
 122                        dev_name(&dev->dev));
 123        if (!hcd) {
 124                err = -ENOMEM;
 125                goto err_power;
 126        }
 127
 128        hcd->rsrc_start = res_mem->start;
 129        hcd->rsrc_len = resource_size(res_mem);
 130
 131        hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
 132        if (IS_ERR(hcd->regs)) {
 133                err = PTR_ERR(hcd->regs);
 134                goto err_put_hcd;
 135        }
 136        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 137        if (err)
 138                goto err_put_hcd;
 139
 140        platform_set_drvdata(dev, hcd);
 141
 142        return err;
 143
 144err_put_hcd:
 145        usb_put_hcd(hcd);
 146err_power:
 147        if (pdata->power_off)
 148                pdata->power_off(dev);
 149
 150        return err;
 151}
 152
 153static int ohci_platform_remove(struct platform_device *dev)
 154{
 155        struct usb_hcd *hcd = platform_get_drvdata(dev);
 156        struct usb_ohci_pdata *pdata = dev->dev.platform_data;
 157
 158        usb_remove_hcd(hcd);
 159        usb_put_hcd(hcd);
 160        platform_set_drvdata(dev, NULL);
 161
 162        if (pdata->power_off)
 163                pdata->power_off(dev);
 164
 165        return 0;
 166}
 167
 168#ifdef CONFIG_PM
 169
 170static int ohci_platform_suspend(struct device *dev)
 171{
 172        struct usb_ohci_pdata *pdata = dev->platform_data;
 173        struct platform_device *pdev =
 174                container_of(dev, struct platform_device, dev);
 175
 176        if (pdata->power_suspend)
 177                pdata->power_suspend(pdev);
 178
 179        return 0;
 180}
 181
 182static int ohci_platform_resume(struct device *dev)
 183{
 184        struct usb_hcd *hcd = dev_get_drvdata(dev);
 185        struct usb_ohci_pdata *pdata = dev->platform_data;
 186        struct platform_device *pdev =
 187                container_of(dev, struct platform_device, dev);
 188
 189        if (pdata->power_on) {
 190                int err = pdata->power_on(pdev);
 191                if (err < 0)
 192                        return err;
 193        }
 194
 195        ohci_resume(hcd, false);
 196        return 0;
 197}
 198
 199#else /* !CONFIG_PM */
 200#define ohci_platform_suspend   NULL
 201#define ohci_platform_resume    NULL
 202#endif /* CONFIG_PM */
 203
 204static const struct platform_device_id ohci_platform_table[] = {
 205        { "ohci-platform", 0 },
 206        { }
 207};
 208MODULE_DEVICE_TABLE(platform, ohci_platform_table);
 209
 210static const struct dev_pm_ops ohci_platform_pm_ops = {
 211        .suspend        = ohci_platform_suspend,
 212        .resume         = ohci_platform_resume,
 213};
 214
 215static struct platform_driver ohci_platform_driver = {
 216        .id_table       = ohci_platform_table,
 217        .probe          = ohci_platform_probe,
 218        .remove         = ohci_platform_remove,
 219        .shutdown       = usb_hcd_platform_shutdown,
 220        .driver         = {
 221                .owner  = THIS_MODULE,
 222                .name   = "ohci-platform",
 223                .pm     = &ohci_platform_pm_ops,
 224        }
 225};
 226