]>
Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
c558e39e AS |
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 | |
c558e39e AS |
8 | */ |
9 | ||
c558e39e | 10 | #include <linux/kernel.h> |
7f8dd161 | 11 | #include <linux/mod_devicetable.h> |
c558e39e AS |
12 | #include <linux/module.h> |
13 | #include <linux/platform_device.h> | |
f080be27 | 14 | #include <linux/pm_runtime.h> |
7f8dd161 | 15 | #include <linux/property.h> |
c558e39e AS |
16 | |
17 | #include "pwm-lpss.h" | |
18 | ||
9900073c | 19 | |
c558e39e AS |
20 | static int pwm_lpss_probe_platform(struct platform_device *pdev) |
21 | { | |
22 | const struct pwm_lpss_boardinfo *info; | |
c558e39e | 23 | struct pwm_lpss_chip *lpwm; |
68af6fb0 | 24 | void __iomem *base; |
c558e39e | 25 | |
7f8dd161 AS |
26 | info = device_get_match_data(&pdev->dev); |
27 | if (!info) | |
c558e39e AS |
28 | return -ENODEV; |
29 | ||
68af6fb0 AS |
30 | base = devm_platform_ioremap_resource(pdev, 0); |
31 | if (IS_ERR(base)) | |
32 | return PTR_ERR(base); | |
33 | ||
f0f31de3 | 34 | lpwm = devm_pwm_lpss_probe(&pdev->dev, base, info); |
c558e39e AS |
35 | if (IS_ERR(lpwm)) |
36 | return PTR_ERR(lpwm); | |
37 | ||
38 | platform_set_drvdata(pdev, lpwm); | |
f080be27 | 39 | |
b9c90f15 HG |
40 | /* |
41 | * On Cherry Trail devices the GFX0._PS0 AML checks if the controller | |
42 | * is on and if it is not on it turns it on and restores what it | |
43 | * believes is the correct state to the PWM controller. | |
44 | * Because of this we must disallow direct-complete, which keeps the | |
45 | * controller (runtime)suspended on resume, to avoid 2 issues: | |
46 | * 1. The controller getting turned on without the linux-pm code | |
47 | * knowing about this. On devices where the controller is unused | |
48 | * this causes it to stay on during the next suspend causing high | |
49 | * battery drain (because S0i3 is not reached) | |
50 | * 2. The state restoring code unexpectedly messing with the controller | |
e3aa45f2 HG |
51 | * |
52 | * Leaving the controller runtime-suspended (skipping runtime-resume + | |
53 | * normal-suspend) during suspend is fine. | |
b9c90f15 HG |
54 | */ |
55 | if (info->other_devices_aml_touches_pwm_regs) | |
e3aa45f2 HG |
56 | dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE| |
57 | DPM_FLAG_SMART_SUSPEND); | |
b9c90f15 | 58 | |
f080be27 QZ |
59 | pm_runtime_set_active(&pdev->dev); |
60 | pm_runtime_enable(&pdev->dev); | |
61 | ||
c558e39e AS |
62 | return 0; |
63 | } | |
64 | ||
65 | static int pwm_lpss_remove_platform(struct platform_device *pdev) | |
66 | { | |
f080be27 | 67 | pm_runtime_disable(&pdev->dev); |
d1e487b7 | 68 | return 0; |
c558e39e AS |
69 | } |
70 | ||
71 | static const struct acpi_device_id pwm_lpss_acpi_match[] = { | |
72 | { "80860F09", (unsigned long)&pwm_lpss_byt_info }, | |
73 | { "80862288", (unsigned long)&pwm_lpss_bsw_info }, | |
1688c871 | 74 | { "80862289", (unsigned long)&pwm_lpss_bsw_info }, |
03f00e53 | 75 | { "80865AC8", (unsigned long)&pwm_lpss_bxt_info }, |
c558e39e AS |
76 | { }, |
77 | }; | |
78 | MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match); | |
79 | ||
80 | static struct platform_driver pwm_lpss_driver_platform = { | |
81 | .driver = { | |
82 | .name = "pwm-lpss", | |
83 | .acpi_match_table = pwm_lpss_acpi_match, | |
84 | }, | |
85 | .probe = pwm_lpss_probe_platform, | |
86 | .remove = pwm_lpss_remove_platform, | |
87 | }; | |
88 | module_platform_driver(pwm_lpss_driver_platform); | |
89 | ||
90 | MODULE_DESCRIPTION("PWM platform driver for Intel LPSS"); | |
91 | MODULE_LICENSE("GPL v2"); | |
a3682d2f | 92 | MODULE_IMPORT_NS(PWM_LPSS); |
c558e39e | 93 | MODULE_ALIAS("platform:pwm-lpss"); |