linux/drivers/usb/host/ohci-ppc-soc.c
<<
>>
Prefs
   1/*
   2 * OHCI HCD (Host Controller Driver) for USB.
   3 *
   4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
   5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
   6 * (C) Copyright 2002 Hewlett-Packard Company
   7 * (C) Copyright 2003-2005 MontaVista Software Inc.
   8 *
   9 * Bus Glue for PPC On-Chip OHCI driver
  10 * Tested on Freescale MPC5200 and IBM STB04xxx
  11 *
  12 * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
  13 *
  14 * This file is licenced under the GPL.
  15 */
  16
  17#include <linux/platform_device.h>
  18#include <linux/signal.h>
  19
  20/* configure so an HC device and id are always provided */
  21/* always called with process context; sleeping is OK */
  22
  23/**
  24 * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
  25 * Context: !in_interrupt()
  26 *
  27 * Allocates basic resources for this USB host controller.
  28 *
  29 * Store this function in the HCD's struct pci_driver as probe().
  30 */
  31static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
  32                          struct platform_device *pdev)
  33{
  34        int retval;
  35        struct usb_hcd *hcd;
  36        struct ohci_hcd *ohci;
  37        struct resource *res;
  38        int irq;
  39
  40        pr_debug("initializing PPC-SOC USB Controller\n");
  41
  42        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  43        if (!res) {
  44                pr_debug(__FILE__ ": no irq\n");
  45                return -ENODEV;
  46        }
  47        irq = res->start;
  48
  49        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  50        if (!res) {
  51                pr_debug(__FILE__ ": no reg addr\n");
  52                return -ENODEV;
  53        }
  54
  55        hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
  56        if (!hcd)
  57                return -ENOMEM;
  58        hcd->rsrc_start = res->start;
  59        hcd->rsrc_len = res->end - res->start + 1;
  60
  61        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
  62                pr_debug(__FILE__ ": request_mem_region failed\n");
  63                retval = -EBUSY;
  64                goto err1;
  65        }
  66
  67        hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
  68        if (!hcd->regs) {
  69                pr_debug(__FILE__ ": ioremap failed\n");
  70                retval = -ENOMEM;
  71                goto err2;
  72        }
  73
  74        ohci = hcd_to_ohci(hcd);
  75        ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
  76
  77#ifdef CONFIG_PPC_MPC52xx
  78        /* MPC52xx doesn't need frame_no shift */
  79        ohci->flags |= OHCI_QUIRK_FRAME_NO;
  80#endif
  81        ohci_hcd_init(ohci);
  82
  83        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
  84        if (retval == 0)
  85                return retval;
  86
  87        pr_debug("Removing PPC-SOC USB Controller\n");
  88
  89        iounmap(hcd->regs);
  90 err2:
  91        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  92 err1:
  93        usb_put_hcd(hcd);
  94        return retval;
  95}
  96
  97
  98/* may be called without controller electrically present */
  99/* may be called with controller, bus, and devices active */
 100
 101/**
 102 * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
 103 * @pdev: USB Host Controller being removed
 104 * Context: !in_interrupt()
 105 *
 106 * Reverses the effect of usb_hcd_ppc_soc_probe().
 107 * It is always called from a thread
 108 * context, normally "rmmod", "apmd", or something similar.
 109 *
 110 */
 111static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
 112                struct platform_device *pdev)
 113{
 114        usb_remove_hcd(hcd);
 115
 116        pr_debug("stopping PPC-SOC USB Controller\n");
 117
 118        iounmap(hcd->regs);
 119        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 120        usb_put_hcd(hcd);
 121}
 122
 123static int __devinit
 124ohci_ppc_soc_start(struct usb_hcd *hcd)
 125{
 126        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 127        int             ret;
 128
 129        if ((ret = ohci_init(ohci)) < 0)
 130                return ret;
 131
 132        if ((ret = ohci_run(ohci)) < 0) {
 133                err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
 134                ohci_stop(hcd);
 135                return ret;
 136        }
 137
 138        return 0;
 139}
 140
 141static const struct hc_driver ohci_ppc_soc_hc_driver = {
 142        .description =          hcd_name,
 143        .hcd_priv_size =        sizeof(struct ohci_hcd),
 144
 145        /*
 146         * generic hardware linkage
 147         */
 148        .irq =                  ohci_irq,
 149        .flags =                HCD_USB11 | HCD_MEMORY,
 150
 151        /*
 152         * basic lifecycle operations
 153         */
 154        .start =                ohci_ppc_soc_start,
 155        .stop =                 ohci_stop,
 156        .shutdown =             ohci_shutdown,
 157
 158        /*
 159         * managing i/o requests and associated device resources
 160         */
 161        .urb_enqueue =          ohci_urb_enqueue,
 162        .urb_dequeue =          ohci_urb_dequeue,
 163        .endpoint_disable =     ohci_endpoint_disable,
 164
 165        /*
 166         * scheduling support
 167         */
 168        .get_frame_number =     ohci_get_frame,
 169
 170        /*
 171         * root hub support
 172         */
 173        .hub_status_data =      ohci_hub_status_data,
 174        .hub_control =          ohci_hub_control,
 175#ifdef  CONFIG_PM
 176        .bus_suspend =          ohci_bus_suspend,
 177        .bus_resume =           ohci_bus_resume,
 178#endif
 179        .start_port_reset =     ohci_start_port_reset,
 180};
 181
 182static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
 183{
 184        int ret;
 185
 186        if (usb_disabled())
 187                return -ENODEV;
 188
 189        ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
 190        return ret;
 191}
 192
 193static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
 194{
 195        struct usb_hcd *hcd = platform_get_drvdata(pdev);
 196
 197        usb_hcd_ppc_soc_remove(hcd, pdev);
 198        return 0;
 199}
 200
 201static struct platform_driver ohci_hcd_ppc_soc_driver = {
 202        .probe          = ohci_hcd_ppc_soc_drv_probe,
 203        .remove         = ohci_hcd_ppc_soc_drv_remove,
 204        .shutdown       = usb_hcd_platform_shutdown,
 205#ifdef  CONFIG_PM
 206        /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
 207        /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
 208#endif
 209        .driver         = {
 210                .name   = "ppc-soc-ohci",
 211                .owner  = THIS_MODULE,
 212        },
 213};
 214
 215MODULE_ALIAS("platform:ppc-soc-ohci");
 216