Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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  */
 31 static 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  */
111 static 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 
123 static int __devinit
124 ohci_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 
141 static 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         .hub_irq_enable =       ohci_rhsc_enable,
176 #ifdef  CONFIG_PM
177         .bus_suspend =          ohci_bus_suspend,
178         .bus_resume =           ohci_bus_resume,
179 #endif
180         .start_port_reset =     ohci_start_port_reset,
181 };
182 
183 static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
184 {
185         int ret;
186 
187         if (usb_disabled())
188                 return -ENODEV;
189 
190         ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
191         return ret;
192 }
193 
194 static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
195 {
196         struct usb_hcd *hcd = platform_get_drvdata(pdev);
197 
198         usb_hcd_ppc_soc_remove(hcd, pdev);
199         return 0;
200 }
201 
202 static struct platform_driver ohci_hcd_ppc_soc_driver = {
203         .probe          = ohci_hcd_ppc_soc_drv_probe,
204         .remove         = ohci_hcd_ppc_soc_drv_remove,
205         .shutdown       = usb_hcd_platform_shutdown,
206 #ifdef  CONFIG_PM
207         /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
208         /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
209 #endif
210         .driver         = {
211                 .name   = "ppc-soc-ohci",
212                 .owner  = THIS_MODULE,
213         },
214 };
215 
216 MODULE_ALIAS("platform:ppc-soc-ohci");
217 
  This page was automatically generated by the LXR engine.