simple-pm-bus.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Simple Power-Managed Bus Driver
  3. *
  4. * Copyright (C) 2014-2015 Glider bvba
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/of_platform.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/pm_runtime.h>
  14. static int simple_pm_bus_probe(struct platform_device *pdev)
  15. {
  16. const struct device *dev = &pdev->dev;
  17. const struct of_dev_auxdata *lookup = dev_get_platdata(dev);
  18. struct device_node *np = dev->of_node;
  19. const struct of_device_id *match;
  20. /*
  21. * Allow user to use driver_override to bind this driver to a
  22. * transparent bus device which has a different compatible string
  23. * that's not listed in simple_pm_bus_of_match. We don't want to do any
  24. * of the simple-pm-bus tasks for these devices, so return early.
  25. */
  26. if (pdev->driver_override)
  27. return 0;
  28. match = of_match_device(dev->driver->of_match_table, dev);
  29. /*
  30. * These are transparent bus devices (not simple-pm-bus matches) that
  31. * have their child nodes populated automatically. So, don't need to
  32. * do anything more. We only match with the device if this driver is
  33. * the most specific match because we don't want to incorrectly bind to
  34. * a device that has a more specific driver.
  35. */
  36. if (match && match->data) {
  37. if (of_property_match_string(np, "compatible", match->compatible) == 0)
  38. return 0;
  39. else
  40. return -ENODEV;
  41. }
  42. dev_dbg(&pdev->dev, "%s\n", __func__);
  43. pm_runtime_enable(&pdev->dev);
  44. if (np)
  45. of_platform_populate(np, NULL, lookup, &pdev->dev);
  46. return 0;
  47. }
  48. static int simple_pm_bus_remove(struct platform_device *pdev)
  49. {
  50. const void *data = of_device_get_match_data(&pdev->dev);
  51. if (pdev->driver_override || data)
  52. return 0;
  53. dev_dbg(&pdev->dev, "%s\n", __func__);
  54. pm_runtime_disable(&pdev->dev);
  55. return 0;
  56. }
  57. #define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */
  58. static const struct of_device_id simple_pm_bus_of_match[] = {
  59. { .compatible = "simple-pm-bus", },
  60. { .compatible = "simple-bus", .data = ONLY_BUS },
  61. { .compatible = "simple-mfd", .data = ONLY_BUS },
  62. { .compatible = "isa", .data = ONLY_BUS },
  63. { .compatible = "arm,amba-bus", .data = ONLY_BUS },
  64. { /* sentinel */ }
  65. };
  66. MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);
  67. static struct platform_driver simple_pm_bus_driver = {
  68. .probe = simple_pm_bus_probe,
  69. .remove = simple_pm_bus_remove,
  70. .driver = {
  71. .name = "simple-pm-bus",
  72. .of_match_table = simple_pm_bus_of_match,
  73. },
  74. };
  75. module_platform_driver(simple_pm_bus_driver);
  76. MODULE_DESCRIPTION("Simple Power-Managed Bus Driver");
  77. MODULE_AUTHOR("Geert Uytterhoeven <[email protected]>");
  78. MODULE_LICENSE("GPL v2");