diff options
| -rw-r--r-- | drivers/pcmcia/at91_cf.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index a4d50940ebeb..5256342e8532 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c | |||
| @@ -214,11 +214,10 @@ static struct pccard_operations at91_cf_ops = { | |||
| 214 | 214 | ||
| 215 | /*--------------------------------------------------------------------------*/ | 215 | /*--------------------------------------------------------------------------*/ |
| 216 | 216 | ||
| 217 | static int __init at91_cf_probe(struct device *dev) | 217 | static int __init at91_cf_probe(struct platform_device *pdev) |
| 218 | { | 218 | { |
| 219 | struct at91_cf_socket *cf; | 219 | struct at91_cf_socket *cf; |
| 220 | struct at91_cf_data *board = dev->platform_data; | 220 | struct at91_cf_data *board = pdev->dev.platform_data; |
| 221 | struct platform_device *pdev = to_platform_device(dev); | ||
| 222 | struct resource *io; | 221 | struct resource *io; |
| 223 | unsigned int csa; | 222 | unsigned int csa; |
| 224 | int status; | 223 | int status; |
| @@ -236,7 +235,7 @@ static int __init at91_cf_probe(struct device *dev) | |||
| 236 | 235 | ||
| 237 | cf->board = board; | 236 | cf->board = board; |
| 238 | cf->pdev = pdev; | 237 | cf->pdev = pdev; |
| 239 | dev_set_drvdata(dev, cf); | 238 | platform_set_drvdata(pdev, cf); |
| 240 | 239 | ||
| 241 | /* CF takes over CS4, CS5, CS6 */ | 240 | /* CF takes over CS4, CS5, CS6 */ |
| 242 | csa = at91_sys_read(AT91_EBI_CSA); | 241 | csa = at91_sys_read(AT91_EBI_CSA); |
| @@ -271,6 +270,7 @@ static int __init at91_cf_probe(struct device *dev) | |||
| 271 | SA_SAMPLE_RANDOM, driver_name, cf); | 270 | SA_SAMPLE_RANDOM, driver_name, cf); |
| 272 | if (status < 0) | 271 | if (status < 0) |
| 273 | goto fail0; | 272 | goto fail0; |
| 273 | device_init_wakeup(&pdev->dev, 1); | ||
| 274 | 274 | ||
| 275 | /* | 275 | /* |
| 276 | * The card driver will request this irq later as needed. | 276 | * The card driver will request this irq later as needed. |
| @@ -301,7 +301,7 @@ static int __init at91_cf_probe(struct device *dev) | |||
| 301 | board->det_pin, board->irq_pin); | 301 | board->det_pin, board->irq_pin); |
| 302 | 302 | ||
| 303 | cf->socket.owner = THIS_MODULE; | 303 | cf->socket.owner = THIS_MODULE; |
| 304 | cf->socket.dev.dev = dev; | 304 | cf->socket.dev.dev = &pdev->dev; |
| 305 | cf->socket.ops = &at91_cf_ops; | 305 | cf->socket.ops = &at91_cf_ops; |
| 306 | cf->socket.resource_ops = &pccard_static_ops; | 306 | cf->socket.resource_ops = &pccard_static_ops; |
| 307 | cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | 307 | cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP |
| @@ -323,21 +323,25 @@ fail1: | |||
| 323 | free_irq(board->irq_pin, cf); | 323 | free_irq(board->irq_pin, cf); |
| 324 | fail0a: | 324 | fail0a: |
| 325 | free_irq(board->det_pin, cf); | 325 | free_irq(board->det_pin, cf); |
| 326 | device_init_wakeup(&pdev->dev, 0); | ||
| 326 | fail0: | 327 | fail0: |
| 327 | at91_sys_write(AT91_EBI_CSA, csa); | 328 | at91_sys_write(AT91_EBI_CSA, csa); |
| 328 | kfree(cf); | 329 | kfree(cf); |
| 329 | return status; | 330 | return status; |
| 330 | } | 331 | } |
| 331 | 332 | ||
| 332 | static int __exit at91_cf_remove(struct device *dev) | 333 | static int __exit at91_cf_remove(struct platform_device *pdev) |
| 333 | { | 334 | { |
| 334 | struct at91_cf_socket *cf = dev_get_drvdata(dev); | 335 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); |
| 336 | struct at91_cf_data *board = cf->board; | ||
| 335 | struct resource *io = cf->socket.io[0].res; | 337 | struct resource *io = cf->socket.io[0].res; |
| 336 | unsigned int csa; | 338 | unsigned int csa; |
| 337 | 339 | ||
| 338 | pcmcia_unregister_socket(&cf->socket); | 340 | pcmcia_unregister_socket(&cf->socket); |
| 339 | free_irq(cf->board->irq_pin, cf); | 341 | if (board->irq_pin) |
| 340 | free_irq(cf->board->det_pin, cf); | 342 | free_irq(board->irq_pin, cf); |
| 343 | free_irq(board->det_pin, cf); | ||
| 344 | device_init_wakeup(&pdev->dev, 0); | ||
| 341 | iounmap((void __iomem *) cf->socket.io_offset); | 345 | iounmap((void __iomem *) cf->socket.io_offset); |
| 342 | release_mem_region(io->start, io->end + 1 - io->start); | 346 | release_mem_region(io->start, io->end + 1 - io->start); |
| 343 | 347 | ||
| @@ -348,26 +352,65 @@ static int __exit at91_cf_remove(struct device *dev) | |||
| 348 | return 0; | 352 | return 0; |
| 349 | } | 353 | } |
| 350 | 354 | ||
| 351 | static struct device_driver at91_cf_driver = { | 355 | #ifdef CONFIG_PM |
| 352 | .name = (char *) driver_name, | 356 | |
| 353 | .bus = &platform_bus_type, | 357 | static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg) |
| 358 | { | ||
| 359 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); | ||
| 360 | struct at91_cf_data *board = cf->board; | ||
| 361 | |||
| 362 | pcmcia_socket_dev_suspend(&pdev->dev, mesg); | ||
| 363 | if (device_may_wakeup(&pdev->dev)) | ||
| 364 | enable_irq_wake(board->det_pin); | ||
| 365 | else { | ||
| 366 | disable_irq_wake(board->det_pin); | ||
| 367 | disable_irq(board->det_pin); | ||
| 368 | } | ||
| 369 | if (board->irq_pin) | ||
| 370 | disable_irq(board->irq_pin); | ||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | static int at91_cf_resume(struct platform_device *pdev) | ||
| 375 | { | ||
| 376 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); | ||
| 377 | struct at91_cf_data *board = cf->board; | ||
| 378 | |||
| 379 | if (board->irq_pin) | ||
| 380 | enable_irq(board->irq_pin); | ||
| 381 | if (!device_may_wakeup(&pdev->dev)) | ||
| 382 | enable_irq(board->det_pin); | ||
| 383 | pcmcia_socket_dev_resume(&pdev->dev); | ||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | #else | ||
| 388 | #define at91_cf_suspend NULL | ||
| 389 | #define at91_cf_resume NULL | ||
| 390 | #endif | ||
| 391 | |||
| 392 | static struct platform_driver at91_cf_driver = { | ||
| 393 | .driver = { | ||
| 394 | .name = (char *) driver_name, | ||
| 395 | .owner = THIS_MODULE, | ||
| 396 | }, | ||
| 354 | .probe = at91_cf_probe, | 397 | .probe = at91_cf_probe, |
| 355 | .remove = __exit_p(at91_cf_remove), | 398 | .remove = __exit_p(at91_cf_remove), |
| 356 | .suspend = pcmcia_socket_dev_suspend, | 399 | .suspend = at91_cf_suspend, |
| 357 | .resume = pcmcia_socket_dev_resume, | 400 | .resume = at91_cf_resume, |
| 358 | }; | 401 | }; |
| 359 | 402 | ||
| 360 | /*--------------------------------------------------------------------------*/ | 403 | /*--------------------------------------------------------------------------*/ |
| 361 | 404 | ||
| 362 | static int __init at91_cf_init(void) | 405 | static int __init at91_cf_init(void) |
| 363 | { | 406 | { |
| 364 | return driver_register(&at91_cf_driver); | 407 | return platform_driver_register(&at91_cf_driver); |
| 365 | } | 408 | } |
| 366 | module_init(at91_cf_init); | 409 | module_init(at91_cf_init); |
| 367 | 410 | ||
| 368 | static void __exit at91_cf_exit(void) | 411 | static void __exit at91_cf_exit(void) |
| 369 | { | 412 | { |
| 370 | driver_unregister(&at91_cf_driver); | 413 | platform_driver_unregister(&at91_cf_driver); |
| 371 | } | 414 | } |
| 372 | module_exit(at91_cf_exit); | 415 | module_exit(at91_cf_exit); |
| 373 | 416 | ||
