Commit 0db6095d4ff8918350797dfe299d572980e82fa0

Authored by David Brownell
Committed by Dominik Brodowski
1 parent 5040cb8b7e

[PATCH] pcmcia: at91_cf suspend/resume/wakeup

AT91 CF updates, mostly for power management:

 - Add suspend/resume methods to the AT91 CF driver, disabling
   non-wakeup IRQs during system suspend.  The card detect IRQ
   serves as a wakeup event source.

 - Convert the driver to the more-current "platform_driver" style.

So inserting or removing a CF card will wake the system, unless that
has been disabled by updating the sysfs file; and there will be no
more warnings about spurious IRQs during suspend/resume cycles.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

Showing 1 changed file with 59 additions and 16 deletions Side-by-side Diff

drivers/pcmcia/at91_cf.c
... ... @@ -214,11 +214,10 @@
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 219 struct at91_cf_socket *cf;
220   - struct at91_cf_data *board = dev->platform_data;
221   - struct platform_device *pdev = to_platform_device(dev);
  220 + struct at91_cf_data *board = pdev->dev.platform_data;
222 221 struct resource *io;
223 222 unsigned int csa;
224 223 int status;
... ... @@ -236,7 +235,7 @@
236 235  
237 236 cf->board = board;
238 237 cf->pdev = pdev;
239   - dev_set_drvdata(dev, cf);
  238 + platform_set_drvdata(pdev, cf);
240 239  
241 240 /* CF takes over CS4, CS5, CS6 */
242 241 csa = at91_sys_read(AT91_EBI_CSA);
... ... @@ -271,6 +270,7 @@
271 270 SA_SAMPLE_RANDOM, driver_name, cf);
272 271 if (status < 0)
273 272 goto fail0;
  273 + device_init_wakeup(&pdev->dev, 1);
274 274  
275 275 /*
276 276 * The card driver will request this irq later as needed.
... ... @@ -301,7 +301,7 @@
301 301 board->det_pin, board->irq_pin);
302 302  
303 303 cf->socket.owner = THIS_MODULE;
304   - cf->socket.dev.dev = dev;
  304 + cf->socket.dev.dev = &pdev->dev;
305 305 cf->socket.ops = &at91_cf_ops;
306 306 cf->socket.resource_ops = &pccard_static_ops;
307 307 cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
308 308  
309 309  
310 310  
... ... @@ -323,21 +323,25 @@
323 323 free_irq(board->irq_pin, cf);
324 324 fail0a:
325 325 free_irq(board->det_pin, cf);
  326 + device_init_wakeup(&pdev->dev, 0);
326 327 fail0:
327 328 at91_sys_write(AT91_EBI_CSA, csa);
328 329 kfree(cf);
329 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 337 struct resource *io = cf->socket.io[0].res;
336 338 unsigned int csa;
337 339  
338 340 pcmcia_unregister_socket(&cf->socket);
339   - free_irq(cf->board->irq_pin, cf);
340   - free_irq(cf->board->det_pin, cf);
  341 + if (board->irq_pin)
  342 + free_irq(board->irq_pin, cf);
  343 + free_irq(board->det_pin, cf);
  344 + device_init_wakeup(&pdev->dev, 0);
341 345 iounmap((void __iomem *) cf->socket.io_offset);
342 346 release_mem_region(io->start, io->end + 1 - io->start);
343 347  
344 348  
345 349  
346 350  
... ... @@ -348,26 +352,65 @@
348 352 return 0;
349 353 }
350 354  
351   -static struct device_driver at91_cf_driver = {
352   - .name = (char *) driver_name,
353   - .bus = &platform_bus_type,
  355 +#ifdef CONFIG_PM
  356 +
  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 397 .probe = at91_cf_probe,
355 398 .remove = __exit_p(at91_cf_remove),
356   - .suspend = pcmcia_socket_dev_suspend,
357   - .resume = pcmcia_socket_dev_resume,
  399 + .suspend = at91_cf_suspend,
  400 + .resume = at91_cf_resume,
358 401 };
359 402  
360 403 /*--------------------------------------------------------------------------*/
361 404  
362 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 409 module_init(at91_cf_init);
367 410  
368 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 415 module_exit(at91_cf_exit);
373 416