diff options
-rw-r--r-- | drivers/spi/spi-omap-100k.c | 101 |
1 files changed, 77 insertions, 24 deletions
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index d890d309dff9..35b332dacb13 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/pm_runtime.h> | ||
27 | #include <linux/err.h> | 28 | #include <linux/err.h> |
28 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
29 | #include <linux/io.h> | 30 | #include <linux/io.h> |
@@ -294,16 +295,6 @@ static int omap1_spi100k_setup(struct spi_device *spi) | |||
294 | return ret; | 295 | return ret; |
295 | } | 296 | } |
296 | 297 | ||
297 | static int omap1_spi100k_prepare_hardware(struct spi_master *master) | ||
298 | { | ||
299 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
300 | |||
301 | clk_prepare_enable(spi100k->ick); | ||
302 | clk_prepare_enable(spi100k->fck); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int omap1_spi100k_transfer_one_message(struct spi_master *master, | 298 | static int omap1_spi100k_transfer_one_message(struct spi_master *master, |
308 | struct spi_message *m) | 299 | struct spi_message *m) |
309 | { | 300 | { |
@@ -372,16 +363,6 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master, | |||
372 | return status; | 363 | return status; |
373 | } | 364 | } |
374 | 365 | ||
375 | static int omap1_spi100k_unprepare_hardware(struct spi_master *master) | ||
376 | { | ||
377 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
378 | |||
379 | clk_disable_unprepare(spi100k->ick); | ||
380 | clk_disable_unprepare(spi100k->fck); | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int omap1_spi100k_probe(struct platform_device *pdev) | 366 | static int omap1_spi100k_probe(struct platform_device *pdev) |
386 | { | 367 | { |
387 | struct spi_master *master; | 368 | struct spi_master *master; |
@@ -402,14 +383,12 @@ static int omap1_spi100k_probe(struct platform_device *pdev) | |||
402 | 383 | ||
403 | master->setup = omap1_spi100k_setup; | 384 | master->setup = omap1_spi100k_setup; |
404 | master->transfer_one_message = omap1_spi100k_transfer_one_message; | 385 | master->transfer_one_message = omap1_spi100k_transfer_one_message; |
405 | master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware; | ||
406 | master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware; | ||
407 | master->cleanup = NULL; | ||
408 | master->num_chipselect = 2; | 386 | master->num_chipselect = 2; |
409 | master->mode_bits = MODEBITS; | 387 | master->mode_bits = MODEBITS; |
410 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); | 388 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); |
411 | master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16); | 389 | master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16); |
412 | master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ; | 390 | master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ; |
391 | master->auto_runtime_pm = true; | ||
413 | 392 | ||
414 | spi100k = spi_master_get_devdata(master); | 393 | spi100k = spi_master_get_devdata(master); |
415 | 394 | ||
@@ -434,22 +413,96 @@ static int omap1_spi100k_probe(struct platform_device *pdev) | |||
434 | goto err; | 413 | goto err; |
435 | } | 414 | } |
436 | 415 | ||
416 | status = clk_prepare_enable(spi100k->ick); | ||
417 | if (status != 0) { | ||
418 | dev_err(&pdev->dev, "failed to enable ick: %d\n", status); | ||
419 | goto err; | ||
420 | } | ||
421 | |||
422 | status = clk_prepare_enable(spi100k->fck); | ||
423 | if (status != 0) { | ||
424 | dev_err(&pdev->dev, "failed to enable fck: %d\n", status); | ||
425 | goto err_ick; | ||
426 | } | ||
427 | |||
428 | pm_runtime_enable(&pdev->dev); | ||
429 | pm_runtime_set_active(&pdev->dev); | ||
430 | |||
437 | status = devm_spi_register_master(&pdev->dev, master); | 431 | status = devm_spi_register_master(&pdev->dev, master); |
438 | if (status < 0) | 432 | if (status < 0) |
439 | goto err; | 433 | goto err_fck; |
440 | 434 | ||
441 | return status; | 435 | return status; |
442 | 436 | ||
437 | err_fck: | ||
438 | clk_disable_unprepare(spi100k->fck); | ||
439 | err_ick: | ||
440 | clk_disable_unprepare(spi100k->ick); | ||
443 | err: | 441 | err: |
444 | spi_master_put(master); | 442 | spi_master_put(master); |
445 | return status; | 443 | return status; |
446 | } | 444 | } |
447 | 445 | ||
446 | static int omap1_spi100k_remove(struct platform_device *pdev) | ||
447 | { | ||
448 | struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); | ||
449 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
450 | |||
451 | pm_runtime_disable(&pdev->dev); | ||
452 | |||
453 | clk_disable_unprepare(spi100k->fck); | ||
454 | clk_disable_unprepare(spi100k->ick); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | #ifdef CONFIG_PM | ||
460 | static int omap1_spi100k_runtime_suspend(struct device *dev) | ||
461 | { | ||
462 | struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); | ||
463 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
464 | |||
465 | clk_disable_unprepare(spi100k->ick); | ||
466 | clk_disable_unprepare(spi100k->fck); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int omap1_spi100k_runtime_resume(struct device *dev) | ||
472 | { | ||
473 | struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); | ||
474 | struct omap1_spi100k *spi100k = spi_master_get_devdata(master); | ||
475 | int ret; | ||
476 | |||
477 | ret = clk_prepare_enable(spi100k->ick); | ||
478 | if (ret != 0) { | ||
479 | dev_err(dev, "Failed to enable ick: %d\n", ret); | ||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | ret = clk_prepare_enable(spi100k->fck); | ||
484 | if (ret != 0) { | ||
485 | dev_err(dev, "Failed to enable fck: %d\n", ret); | ||
486 | clk_disable_unprepare(spi100k->ick); | ||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | #endif | ||
493 | |||
494 | static const struct dev_pm_ops omap1_spi100k_pm = { | ||
495 | SET_RUNTIME_PM_OPS(omap1_spi100k_runtime_suspend, | ||
496 | omap1_spi100k_runtime_resume, NULL) | ||
497 | }; | ||
498 | |||
448 | static struct platform_driver omap1_spi100k_driver = { | 499 | static struct platform_driver omap1_spi100k_driver = { |
449 | .driver = { | 500 | .driver = { |
450 | .name = "omap1_spi100k", | 501 | .name = "omap1_spi100k", |
502 | .pm = &omap1_spi100k_pm, | ||
451 | }, | 503 | }, |
452 | .probe = omap1_spi100k_probe, | 504 | .probe = omap1_spi100k_probe, |
505 | .remove = omap1_spi100k_remove, | ||
453 | }; | 506 | }; |
454 | 507 | ||
455 | module_platform_driver(omap1_spi100k_driver); | 508 | module_platform_driver(omap1_spi100k_driver); |