pwm-lpss-platform.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Intel Low Power Subsystem PWM controller driver
  3. *
  4. * Copyright (C) 2014, Intel Corporation
  5. *
  6. * Derived from the original pwm-lpss.c
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/acpi.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/pm_runtime.h>
  17. #include "pwm-lpss.h"
  18. /* BayTrail */
  19. static const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
  20. .clk_rate = 25000000,
  21. .npwm = 1,
  22. .base_unit_bits = 16,
  23. };
  24. /* Braswell */
  25. static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
  26. .clk_rate = 19200000,
  27. .npwm = 1,
  28. .base_unit_bits = 16,
  29. .other_devices_aml_touches_pwm_regs = true,
  30. };
  31. /* Broxton */
  32. static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
  33. .clk_rate = 19200000,
  34. .npwm = 4,
  35. .base_unit_bits = 22,
  36. .bypass = true,
  37. };
  38. static int pwm_lpss_probe_platform(struct platform_device *pdev)
  39. {
  40. const struct pwm_lpss_boardinfo *info;
  41. const struct acpi_device_id *id;
  42. struct pwm_lpss_chip *lpwm;
  43. struct resource *r;
  44. id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
  45. if (!id)
  46. return -ENODEV;
  47. info = (const struct pwm_lpss_boardinfo *)id->driver_data;
  48. r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  49. lpwm = pwm_lpss_probe(&pdev->dev, r, info);
  50. if (IS_ERR(lpwm))
  51. return PTR_ERR(lpwm);
  52. platform_set_drvdata(pdev, lpwm);
  53. dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);
  54. pm_runtime_set_active(&pdev->dev);
  55. pm_runtime_enable(&pdev->dev);
  56. return 0;
  57. }
  58. static int pwm_lpss_remove_platform(struct platform_device *pdev)
  59. {
  60. struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
  61. pm_runtime_disable(&pdev->dev);
  62. return pwm_lpss_remove(lpwm);
  63. }
  64. static int pwm_lpss_prepare(struct device *dev)
  65. {
  66. struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
  67. /*
  68. * If other device's AML code touches the PWM regs on suspend/resume
  69. * force runtime-resume the PWM controller to allow this.
  70. */
  71. if (lpwm->info->other_devices_aml_touches_pwm_regs)
  72. return 0; /* Force runtime-resume */
  73. return 1; /* If runtime-suspended leave as is */
  74. }
  75. static const struct dev_pm_ops pwm_lpss_platform_pm_ops = {
  76. .prepare = pwm_lpss_prepare,
  77. SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume)
  78. };
  79. static const struct acpi_device_id pwm_lpss_acpi_match[] = {
  80. { "80860F09", (unsigned long)&pwm_lpss_byt_info },
  81. { "80862288", (unsigned long)&pwm_lpss_bsw_info },
  82. { "80862289", (unsigned long)&pwm_lpss_bsw_info },
  83. { "80865AC8", (unsigned long)&pwm_lpss_bxt_info },
  84. { },
  85. };
  86. MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
  87. static struct platform_driver pwm_lpss_driver_platform = {
  88. .driver = {
  89. .name = "pwm-lpss",
  90. .acpi_match_table = pwm_lpss_acpi_match,
  91. .pm = &pwm_lpss_platform_pm_ops,
  92. },
  93. .probe = pwm_lpss_probe_platform,
  94. .remove = pwm_lpss_remove_platform,
  95. };
  96. module_platform_driver(pwm_lpss_driver_platform);
  97. MODULE_DESCRIPTION("PWM platform driver for Intel LPSS");
  98. MODULE_LICENSE("GPL v2");
  99. MODULE_ALIAS("platform:pwm-lpss");