aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-04-19 09:37:48 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2006-06-30 16:09:12 -0400
commit0db6095d4ff8918350797dfe299d572980e82fa0 (patch)
tree72d42bc165a382fe82a279222efc1c5c4cb7addb
parent5040cb8b7e61b7a03e8837920b9eb2c839bb1947 (diff)
[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>
-rw-r--r--drivers/pcmcia/at91_cf.c75
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
217static int __init at91_cf_probe(struct device *dev) 217static 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);
324fail0a: 324fail0a:
325 free_irq(board->det_pin, cf); 325 free_irq(board->det_pin, cf);
326 device_init_wakeup(&pdev->dev, 0);
326fail0: 327fail0:
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
332static int __exit at91_cf_remove(struct device *dev) 333static 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
351static struct device_driver at91_cf_driver = { 355#ifdef CONFIG_PM
352 .name = (char *) driver_name, 356
353 .bus = &platform_bus_type, 357static 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
374static 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
392static 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
362static int __init at91_cf_init(void) 405static 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}
366module_init(at91_cf_init); 409module_init(at91_cf_init);
367 410
368static void __exit at91_cf_exit(void) 411static void __exit at91_cf_exit(void)
369{ 412{
370 driver_unregister(&at91_cf_driver); 413 platform_driver_unregister(&at91_cf_driver);
371} 414}
372module_exit(at91_cf_exit); 415module_exit(at91_cf_exit);
373 416