pwm-lpss-platform.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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/kernel.h>
  10. #include <linux/mod_devicetable.h>
  11. #include <linux/module.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/pm_runtime.h>
  14. #include <linux/property.h>
  15. #include "pwm-lpss.h"
  16. static int pwm_lpss_probe_platform(struct platform_device *pdev)
  17. {
  18. const struct pwm_lpss_boardinfo *info;
  19. struct pwm_chip *chip;
  20. void __iomem *base;
  21. info = device_get_match_data(&pdev->dev);
  22. if (!info)
  23. return -ENODEV;
  24. base = devm_platform_ioremap_resource(pdev, 0);
  25. if (IS_ERR(base))
  26. return PTR_ERR(base);
  27. chip = devm_pwm_lpss_probe(&pdev->dev, base, info);
  28. if (IS_ERR(chip))
  29. return PTR_ERR(chip);
  30. /*
  31. * On Cherry Trail devices the GFX0._PS0 AML checks if the controller
  32. * is on and if it is not on it turns it on and restores what it
  33. * believes is the correct state to the PWM controller.
  34. * Because of this we must disallow direct-complete, which keeps the
  35. * controller (runtime)suspended on resume, to avoid 2 issues:
  36. * 1. The controller getting turned on without the linux-pm code
  37. * knowing about this. On devices where the controller is unused
  38. * this causes it to stay on during the next suspend causing high
  39. * battery drain (because S0i3 is not reached)
  40. * 2. The state restoring code unexpectedly messing with the controller
  41. *
  42. * Leaving the controller runtime-suspended (skipping runtime-resume +
  43. * normal-suspend) during suspend is fine.
  44. */
  45. if (info->other_devices_aml_touches_pwm_regs)
  46. dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE|
  47. DPM_FLAG_SMART_SUSPEND);
  48. pm_runtime_set_active(&pdev->dev);
  49. return devm_pm_runtime_enable(&pdev->dev);
  50. }
  51. static const struct acpi_device_id pwm_lpss_acpi_match[] = {
  52. { "80860F09", (unsigned long)&pwm_lpss_byt_info },
  53. { "80862288", (unsigned long)&pwm_lpss_bsw_info },
  54. { "80862289", (unsigned long)&pwm_lpss_bsw_info },
  55. { "80865AC8", (unsigned long)&pwm_lpss_bxt_info },
  56. { },
  57. };
  58. MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
  59. static struct platform_driver pwm_lpss_driver_platform = {
  60. .driver = {
  61. .name = "pwm-lpss",
  62. .acpi_match_table = pwm_lpss_acpi_match,
  63. },
  64. .probe = pwm_lpss_probe_platform,
  65. };
  66. module_platform_driver(pwm_lpss_driver_platform);
  67. MODULE_DESCRIPTION("PWM platform driver for Intel LPSS");
  68. MODULE_LICENSE("GPL v2");
  69. MODULE_IMPORT_NS(PWM_LPSS);
  70. MODULE_ALIAS("platform:pwm-lpss");