diff options
Diffstat (limited to 'drivers/usb/host/ohci-omap.c')
| -rw-r--r-- | drivers/usb/host/ohci-omap.c | 120 |
1 files changed, 77 insertions, 43 deletions
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index c4c4babd4767..9c02177de50a 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); | |||
| 66 | extern int ocpi_enable(void); | 66 | extern int ocpi_enable(void); |
| 67 | 67 | ||
| 68 | static struct clk *usb_host_ck; | 68 | static struct clk *usb_host_ck; |
| 69 | static struct clk *usb_dc_ck; | ||
| 70 | static int host_enabled; | ||
| 71 | static int host_initialized; | ||
| 69 | 72 | ||
| 70 | static void omap_ohci_clock_power(int on) | 73 | static 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 | */ |
| 128 | static int omap_1510_local_bus_init(void) | 134 | static 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 | ||
| 176 | static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | 186 | static 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 | ||
| 263 | static void omap_stop_hc(struct platform_device *pdev) | 278 | static 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 | ||
| 272 | void 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 | */ |
| 286 | int usb_hcd_omap_probe (const struct hc_driver *driver, | 295 | static 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; |
| 342 | err2: | 366 | err2: |
| 343 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 367 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 344 | err1: | 368 | err1: |
| 345 | usb_put_hcd(hcd); | 369 | usb_put_hcd(hcd); |
| 346 | err0: | 370 | err0: |
| 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,31 +384,41 @@ 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 | */ |
| 364 | void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) | 388 | static inline void |
| 389 | usb_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 | ||
| 377 | static int __devinit | 408 | static int |
| 378 | ohci_omap_start (struct usb_hcd *hcd) | 409 | ohci_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) { |
| 419 | ohci->hc_control = OHCI_CTRL_RWC; | ||
| 386 | writel(OHCI_CTRL_RWC, &ohci->regs->control); | 420 | writel(OHCI_CTRL_RWC, &ohci->regs->control); |
| 421 | } | ||
| 387 | 422 | ||
| 388 | if ((ret = ohci_run (ohci)) < 0) { | 423 | if ((ret = ohci_run (ohci)) < 0) { |
| 389 | dev_err(hcd->self.controller, "can't start\n"); | 424 | dev_err(hcd->self.controller, "can't start\n"); |
| @@ -409,8 +444,10 @@ static const struct hc_driver ohci_omap_hc_driver = { | |||
| 409 | /* | 444 | /* |
| 410 | * basic lifecycle operations | 445 | * basic lifecycle operations |
| 411 | */ | 446 | */ |
| 447 | .reset = ohci_omap_init, | ||
| 412 | .start = ohci_omap_start, | 448 | .start = ohci_omap_start, |
| 413 | .stop = ohci_stop, | 449 | .stop = ohci_omap_stop, |
| 450 | .shutdown = ohci_shutdown, | ||
| 414 | 451 | ||
| 415 | /* | 452 | /* |
| 416 | * managing i/o requests and associated device resources | 453 | * managing i/o requests and associated device resources |
| @@ -429,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = { | |||
| 429 | */ | 466 | */ |
| 430 | .hub_status_data = ohci_hub_status_data, | 467 | .hub_status_data = ohci_hub_status_data, |
| 431 | .hub_control = ohci_hub_control, | 468 | .hub_control = ohci_hub_control, |
| 469 | .hub_irq_enable = ohci_rhsc_enable, | ||
| 432 | #ifdef CONFIG_PM | 470 | #ifdef CONFIG_PM |
| 433 | .bus_suspend = ohci_bus_suspend, | 471 | .bus_suspend = ohci_bus_suspend, |
| 434 | .bus_resume = ohci_bus_resume, | 472 | .bus_resume = ohci_bus_resume, |
| @@ -446,13 +484,8 @@ static int ohci_hcd_omap_drv_probe(struct platform_device *dev) | |||
| 446 | static int ohci_hcd_omap_drv_remove(struct platform_device *dev) | 484 | static int ohci_hcd_omap_drv_remove(struct platform_device *dev) |
| 447 | { | 485 | { |
| 448 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 486 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
| 449 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
| 450 | 487 | ||
| 451 | usb_hcd_omap_remove(hcd, dev); | 488 | usb_hcd_omap_remove(hcd, dev); |
| 452 | if (ohci->transceiver) { | ||
| 453 | (void) otg_set_host(ohci->transceiver, 0); | ||
| 454 | put_device(ohci->transceiver->dev); | ||
| 455 | } | ||
| 456 | platform_set_drvdata(dev, NULL); | 489 | platform_set_drvdata(dev, NULL); |
| 457 | 490 | ||
| 458 | return 0; | 491 | return 0; |
| @@ -472,7 +505,7 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message) | |||
| 472 | 505 | ||
| 473 | omap_ohci_clock_power(0); | 506 | omap_ohci_clock_power(0); |
| 474 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; | 507 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; |
| 475 | dev->power.power_state = PMSG_SUSPEND; | 508 | dev->dev.power.power_state = PMSG_SUSPEND; |
| 476 | return 0; | 509 | return 0; |
| 477 | } | 510 | } |
| 478 | 511 | ||
| @@ -485,8 +518,8 @@ static int ohci_omap_resume(struct platform_device *dev) | |||
| 485 | ohci->next_statechange = jiffies; | 518 | ohci->next_statechange = jiffies; |
| 486 | 519 | ||
| 487 | omap_ohci_clock_power(1); | 520 | omap_ohci_clock_power(1); |
| 488 | dev->power.power_state = PMSG_ON; | 521 | dev->dev.power.power_state = PMSG_ON; |
| 489 | usb_hcd_resume_root_hub(dev_get_drvdata(dev)); | 522 | usb_hcd_resume_root_hub(platform_get_drvdata(dev)); |
| 490 | return 0; | 523 | return 0; |
| 491 | } | 524 | } |
| 492 | 525 | ||
| @@ -500,6 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev) | |||
| 500 | static struct platform_driver ohci_hcd_omap_driver = { | 533 | static struct platform_driver ohci_hcd_omap_driver = { |
| 501 | .probe = ohci_hcd_omap_drv_probe, | 534 | .probe = ohci_hcd_omap_drv_probe, |
| 502 | .remove = ohci_hcd_omap_drv_remove, | 535 | .remove = ohci_hcd_omap_drv_remove, |
| 536 | .shutdown = usb_hcd_platform_shutdown, | ||
| 503 | #ifdef CONFIG_PM | 537 | #ifdef CONFIG_PM |
| 504 | .suspend = ohci_omap_suspend, | 538 | .suspend = ohci_omap_suspend, |
| 505 | .resume = ohci_omap_resume, | 539 | .resume = ohci_omap_resume, |
