pwm-lpss-platform.c 2.9 KB

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