aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ohci-omap.c113
1 files changed, 71 insertions, 42 deletions
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 47f1c9bbef8..160cd4c58a0 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -4,7 +4,7 @@
4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
5 * (C) Copyright 2000-2005 David Brownell 5 * (C) Copyright 2000-2005 David Brownell
6 * (C) Copyright 2002 Hewlett-Packard Company 6 * (C) Copyright 2002 Hewlett-Packard Company
7 * 7 *
8 * OMAP Bus Glue 8 * OMAP Bus Glue
9 * 9 *
10 * Modified for OMAP by Tony Lindgren <tony@atomide.com> 10 * Modified for OMAP by Tony Lindgren <tony@atomide.com>
@@ -66,15 +66,20 @@ extern int usb_disabled(void);
66extern int ocpi_enable(void); 66extern int ocpi_enable(void);
67 67
68static struct clk *usb_host_ck; 68static struct clk *usb_host_ck;
69static struct clk *usb_dc_ck;
70static int host_enabled;
71static int host_initialized;
69 72
70static void omap_ohci_clock_power(int on) 73static void omap_ohci_clock_power(int on)
71{ 74{
72 if (on) { 75 if (on) {
76 clk_enable(usb_dc_ck);
73 clk_enable(usb_host_ck); 77 clk_enable(usb_host_ck);
74 /* guesstimate for T5 == 1x 32K clock + APLL lock time */ 78 /* guesstimate for T5 == 1x 32K clock + APLL lock time */
75 udelay(100); 79 udelay(100);
76 } else { 80 } else {
77 clk_disable(usb_host_ck); 81 clk_disable(usb_host_ck);
82 clk_disable(usb_dc_ck);
78 } 83 }
79} 84}
80 85
@@ -87,14 +92,14 @@ static int omap_ohci_transceiver_power(int on)
87 if (on) { 92 if (on) {
88 if (machine_is_omap_innovator() && cpu_is_omap1510()) 93 if (machine_is_omap_innovator() && cpu_is_omap1510())
89 fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) 94 fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
90 | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 95 | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
91 INNOVATOR_FPGA_CAM_USB_CONTROL); 96 INNOVATOR_FPGA_CAM_USB_CONTROL);
92 else if (machine_is_omap_osk()) 97 else if (machine_is_omap_osk())
93 tps65010_set_gpio_out_value(GPIO1, LOW); 98 tps65010_set_gpio_out_value(GPIO1, LOW);
94 } else { 99 } else {
95 if (machine_is_omap_innovator() && cpu_is_omap1510()) 100 if (machine_is_omap_innovator() && cpu_is_omap1510())
96 fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) 101 fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
97 & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 102 & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
98 INNOVATOR_FPGA_CAM_USB_CONTROL); 103 INNOVATOR_FPGA_CAM_USB_CONTROL);
99 else if (machine_is_omap_osk()) 104 else if (machine_is_omap_osk())
100 tps65010_set_gpio_out_value(GPIO1, HIGH); 105 tps65010_set_gpio_out_value(GPIO1, HIGH);
@@ -103,6 +108,7 @@ static int omap_ohci_transceiver_power(int on)
103 return 0; 108 return 0;
104} 109}
105 110
111#ifdef CONFIG_ARCH_OMAP15XX
106/* 112/*
107 * OMAP-1510 specific Local Bus clock on/off 113 * OMAP-1510 specific Local Bus clock on/off
108 */ 114 */
@@ -121,8 +127,8 @@ static int omap_1510_local_bus_power(int on)
121/* 127/*
122 * OMAP-1510 specific Local Bus initialization 128 * OMAP-1510 specific Local Bus initialization
123 * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE. 129 * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
124 * See also arch/mach-omap/memory.h for __virt_to_dma() and 130 * See also arch/mach-omap/memory.h for __virt_to_dma() and
125 * __dma_to_virt() which need to match with the physical 131 * __dma_to_virt() which need to match with the physical
126 * Local Bus address below. 132 * Local Bus address below.
127 */ 133 */
128static int omap_1510_local_bus_init(void) 134static int omap_1510_local_bus_init(void)
@@ -130,7 +136,7 @@ static int omap_1510_local_bus_init(void)
130 unsigned int tlb; 136 unsigned int tlb;
131 unsigned long lbaddr, physaddr; 137 unsigned long lbaddr, physaddr;
132 138
133 omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 139 omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
134 OMAP1510_LB_CLOCK_DIV); 140 OMAP1510_LB_CLOCK_DIV);
135 141
136 /* Configure the Local Bus MMU table */ 142 /* Configure the Local Bus MMU table */
@@ -138,7 +144,7 @@ static int omap_1510_local_bus_init(void)
138 lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET; 144 lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
139 physaddr = tlb * 0x00100000 + PHYS_OFFSET; 145 physaddr = tlb * 0x00100000 + PHYS_OFFSET;
140 omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H); 146 omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
141 omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 147 omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
142 OMAP1510_LB_MMU_CAM_L); 148 OMAP1510_LB_MMU_CAM_L);
143 omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H); 149 omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
144 omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L); 150 omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
@@ -152,6 +158,10 @@ static int omap_1510_local_bus_init(void)
152 158
153 return 0; 159 return 0;
154} 160}
161#else
162#define omap_1510_local_bus_power(x) {}
163#define omap_1510_local_bus_init() {}
164#endif
155 165
156#ifdef CONFIG_USB_OTG 166#ifdef CONFIG_USB_OTG
157 167
@@ -173,13 +183,14 @@ static void start_hnp(struct ohci_hcd *ohci)
173 183
174/*-------------------------------------------------------------------------*/ 184/*-------------------------------------------------------------------------*/
175 185
176static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) 186static int ohci_omap_init(struct usb_hcd *hcd)
177{ 187{
178 struct omap_usb_config *config = pdev->dev.platform_data; 188 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
189 struct omap_usb_config *config = hcd->self.controller->platform_data;
179 int need_transceiver = (config->otg != 0); 190 int need_transceiver = (config->otg != 0);
180 int ret; 191 int ret;
181 192
182 dev_dbg(&pdev->dev, "starting USB Controller\n"); 193 dev_dbg(hcd->self.controller, "starting USB Controller\n");
183 194
184 if (config->otg) { 195 if (config->otg) {
185 ohci_to_hcd(ohci)->self.otg_port = config->otg; 196 ohci_to_hcd(ohci)->self.otg_port = config->otg;
@@ -200,7 +211,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
200 if (ohci->transceiver) { 211 if (ohci->transceiver) {
201 int status = otg_set_host(ohci->transceiver, 212 int status = otg_set_host(ohci->transceiver,
202 &ohci_to_hcd(ohci)->self); 213 &ohci_to_hcd(ohci)->self);
203 dev_dbg(&pdev->dev, "init %s transceiver, status %d\n", 214 dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
204 ohci->transceiver->label, status); 215 ohci->transceiver->label, status);
205 if (status) { 216 if (status) {
206 if (ohci->transceiver) 217 if (ohci->transceiver)
@@ -208,7 +219,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
208 return status; 219 return status;
209 } 220 }
210 } else { 221 } else {
211 dev_err(&pdev->dev, "can't find transceiver\n"); 222 dev_err(hcd->self.controller, "can't find transceiver\n");
212 return -ENODEV; 223 return -ENODEV;
213 } 224 }
214 } 225 }
@@ -247,6 +258,10 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
247 } 258 }
248 ohci_writel(ohci, rh, &ohci->regs->roothub.a); 259 ohci_writel(ohci, rh, &ohci->regs->roothub.a);
249 distrust_firmware = 0; 260 distrust_firmware = 0;
261 } else if (machine_is_nokia770()) {
262 /* We require a self-powered hub, which should have
263 * plenty of power. */
264 ohci_to_hcd(ohci)->power_budget = 0;
250 } 265 }
251 266
252 /* FIXME khubd hub requests should manage power switching */ 267 /* FIXME khubd hub requests should manage power switching */
@@ -260,21 +275,15 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
260 return 0; 275 return 0;
261} 276}
262 277
263static void omap_stop_hc(struct platform_device *pdev) 278static void ohci_omap_stop(struct usb_hcd *hcd)
264{ 279{
265 dev_dbg(&pdev->dev, "stopping USB Controller\n"); 280 dev_dbg(hcd->self.controller, "stopping USB Controller\n");
266 omap_ohci_clock_power(0); 281 omap_ohci_clock_power(0);
267} 282}
268 283
269 284
270/*-------------------------------------------------------------------------*/ 285/*-------------------------------------------------------------------------*/
271 286
272void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
273
274/* configure so an HC device and id are always provided */
275/* always called with process context; sleeping is OK */
276
277
278/** 287/**
279 * usb_hcd_omap_probe - initialize OMAP-based HCDs 288 * usb_hcd_omap_probe - initialize OMAP-based HCDs
280 * Context: !in_interrupt() 289 * Context: !in_interrupt()
@@ -283,7 +292,7 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
283 * then invokes the start() method for the HCD associated with it 292 * then invokes the start() method for the HCD associated with it
284 * through the hotplug entry's driver_data. 293 * through the hotplug entry's driver_data.
285 */ 294 */
286int usb_hcd_omap_probe (const struct hc_driver *driver, 295static int usb_hcd_omap_probe (const struct hc_driver *driver,
287 struct platform_device *pdev) 296 struct platform_device *pdev)
288{ 297{
289 int retval, irq; 298 int retval, irq;
@@ -291,12 +300,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
291 struct ohci_hcd *ohci; 300 struct ohci_hcd *ohci;
292 301
293 if (pdev->num_resources != 2) { 302 if (pdev->num_resources != 2) {
294 printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 303 printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
295 pdev->num_resources); 304 pdev->num_resources);
296 return -ENODEV; 305 return -ENODEV;
297 } 306 }
298 307
299 if (pdev->resource[0].flags != IORESOURCE_MEM 308 if (pdev->resource[0].flags != IORESOURCE_MEM
300 || pdev->resource[1].flags != IORESOURCE_IRQ) { 309 || pdev->resource[1].flags != IORESOURCE_IRQ) {
301 printk(KERN_ERR "hcd probe: invalid resource type\n"); 310 printk(KERN_ERR "hcd probe: invalid resource type\n");
302 return -ENODEV; 311 return -ENODEV;
@@ -306,6 +315,17 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
306 if (IS_ERR(usb_host_ck)) 315 if (IS_ERR(usb_host_ck))
307 return PTR_ERR(usb_host_ck); 316 return PTR_ERR(usb_host_ck);
308 317
318 if (!cpu_is_omap1510())
319 usb_dc_ck = clk_get(0, "usb_dc_ck");
320 else
321 usb_dc_ck = clk_get(0, "lb_ck");
322
323 if (IS_ERR(usb_dc_ck)) {
324 clk_put(usb_host_ck);
325 return PTR_ERR(usb_dc_ck);
326 }
327
328
309 hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); 329 hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
310 if (!hcd) { 330 if (!hcd) {
311 retval = -ENOMEM; 331 retval = -ENOMEM;
@@ -325,9 +345,8 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
325 ohci = hcd_to_ohci(hcd); 345 ohci = hcd_to_ohci(hcd);
326 ohci_hcd_init(ohci); 346 ohci_hcd_init(ohci);
327 347
328 retval = omap_start_hc(ohci, pdev); 348 host_initialized = 0;
329 if (retval < 0) 349 host_enabled = 1;
330 goto err2;
331 350
332 irq = platform_get_irq(pdev, 0); 351 irq = platform_get_irq(pdev, 0);
333 if (irq < 0) { 352 if (irq < 0) {
@@ -335,15 +354,21 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
335 goto err2; 354 goto err2;
336 } 355 }
337 retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); 356 retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
338 if (retval == 0) 357 if (retval)
339 return retval; 358 goto err2;
359
360 host_initialized = 1;
361
362 if (!host_enabled)
363 omap_ohci_clock_power(0);
340 364
341 omap_stop_hc(pdev); 365 return 0;
342err2: 366err2:
343 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 367 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
344err1: 368err1:
345 usb_put_hcd(hcd); 369 usb_put_hcd(hcd);
346err0: 370err0:
371 clk_put(usb_dc_ck);
347 clk_put(usb_host_ck); 372 clk_put(usb_host_ck);
348 return retval; 373 return retval;
349} 374}
@@ -359,28 +384,36 @@ err0:
359 * Reverses the effect of usb_hcd_omap_probe(), first invoking 384 * Reverses the effect of usb_hcd_omap_probe(), first invoking
360 * the HCD's stop() method. It is always called from a thread 385 * the HCD's stop() method. It is always called from a thread
361 * context, normally "rmmod", "apmd", or something similar. 386 * context, normally "rmmod", "apmd", or something similar.
362 *
363 */ 387 */
364void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) 388static inline void
389usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
365{ 390{
391 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
392
366 usb_remove_hcd(hcd); 393 usb_remove_hcd(hcd);
394 if (ohci->transceiver) {
395 (void) otg_set_host(ohci->transceiver, 0);
396 put_device(ohci->transceiver->dev);
397 }
367 if (machine_is_omap_osk()) 398 if (machine_is_omap_osk())
368 omap_free_gpio(9); 399 omap_free_gpio(9);
369 omap_stop_hc(pdev);
370 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 400 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
371 usb_put_hcd(hcd); 401 usb_put_hcd(hcd);
402 clk_put(usb_dc_ck);
372 clk_put(usb_host_ck); 403 clk_put(usb_host_ck);
373} 404}
374 405
375/*-------------------------------------------------------------------------*/ 406/*-------------------------------------------------------------------------*/
376 407
377static int __devinit 408static int
378ohci_omap_start (struct usb_hcd *hcd) 409ohci_omap_start (struct usb_hcd *hcd)
379{ 410{
380 struct omap_usb_config *config; 411 struct omap_usb_config *config;
381 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 412 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
382 int ret; 413 int ret;
383 414
415 if (!host_enabled)
416 return 0;
384 config = hcd->self.controller->platform_data; 417 config = hcd->self.controller->platform_data;
385 if (config->otg || config->rwc) { 418 if (config->otg || config->rwc) {
386 ohci->hc_control = OHCI_CTRL_RWC; 419 ohci->hc_control = OHCI_CTRL_RWC;
@@ -411,8 +444,9 @@ static const struct hc_driver ohci_omap_hc_driver = {
411 /* 444 /*
412 * basic lifecycle operations 445 * basic lifecycle operations
413 */ 446 */
447 .reset = ohci_omap_init,
414 .start = ohci_omap_start, 448 .start = ohci_omap_start,
415 .stop = ohci_stop, 449 .stop = ohci_omap_stop,
416 450
417 /* 451 /*
418 * managing i/o requests and associated device resources 452 * managing i/o requests and associated device resources
@@ -449,13 +483,8 @@ static int ohci_hcd_omap_drv_probe(struct platform_device *dev)
449static int ohci_hcd_omap_drv_remove(struct platform_device *dev) 483static int ohci_hcd_omap_drv_remove(struct platform_device *dev)
450{ 484{
451 struct usb_hcd *hcd = platform_get_drvdata(dev); 485 struct usb_hcd *hcd = platform_get_drvdata(dev);
452 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
453 486
454 usb_hcd_omap_remove(hcd, dev); 487 usb_hcd_omap_remove(hcd, dev);
455 if (ohci->transceiver) {
456 (void) otg_set_host(ohci->transceiver, 0);
457 put_device(ohci->transceiver->dev);
458 }
459 platform_set_drvdata(dev, NULL); 488 platform_set_drvdata(dev, NULL);
460 489
461 return 0; 490 return 0;
@@ -475,7 +504,7 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
475 504
476 omap_ohci_clock_power(0); 505 omap_ohci_clock_power(0);
477 ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; 506 ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
478 dev->power.power_state = PMSG_SUSPEND; 507 dev->dev.power.power_state = PMSG_SUSPEND;
479 return 0; 508 return 0;
480} 509}
481 510
@@ -488,8 +517,8 @@ static int ohci_omap_resume(struct platform_device *dev)
488 ohci->next_statechange = jiffies; 517 ohci->next_statechange = jiffies;
489 518
490 omap_ohci_clock_power(1); 519 omap_ohci_clock_power(1);
491 dev->power.power_state = PMSG_ON; 520 dev->dev.power.power_state = PMSG_ON;
492 usb_hcd_resume_root_hub(dev_get_drvdata(dev)); 521 usb_hcd_resume_root_hub(platform_get_drvdata(dev));
493 return 0; 522 return 0;
494} 523}
495 524