diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-02 14:22:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-11-02 14:22:45 -0400 |
commit | fcc37f76a995cc08546b88b83f9bb5da11307a0b (patch) | |
tree | fcb04dbf8d476070dbaadc5cbd72106e6ec0a2b6 | |
parent | 0b21f21ae0d746b385a827aceb84cb26c551eb94 (diff) | |
parent | 2153bbc12f77fb2203276befc0f0dddbfb023bb1 (diff) |
Merge tag 'pwm/for-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm updates from Thierry Reding:
"This series contains a number of improvements to existing drivers,
such as LPSS. Some drivers, such as renesas-tpu and rcar get support
for more SoC generations. To round things off this fixes an issue with
the sysfs interface"
* tag 'pwm/for-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
pwm: lpss: Only set update bit if we are actually changing the settings
pwm: lpss: Force runtime-resume on suspend on Cherry Trail
pwm: Enable TI ECAP driver for ARCH_K3
dt-bindings: pwm: tiecap: Add TI AM654 SoC specific compatible
dt-bindings: pwm: rcar: Add r8a774a1 support
pwm: Send a uevent on the pwmchip device upon channel sysfs (un)export
Revert "pwm: Set class for exported channels in sysfs"
dt-bindings: pwm: renesas-tpu: Document r8a7744 support
dt-bindings: pwm: rcar: Add r8a7744 support
dt-bindings: pwm: renesas: tpu: Document R8A779{7|8}0 bindings
dt-bindings: pwm: renesas: pwm-rcar: Document R8A779{7|8}0 bindings
dt-bindings: pwm: renesas: tpu: Fix "compatible" prop description
pwm: Use SPDX identifier for Renesas drivers
pwm: lpss: Add get_state callback
pwm: lpss: Release runtime-pm reference from the driver's remove callback
pwm: lpss: Check PWM powerstate after resume on Cherry Trail devices
pwm: lpss: Move struct pwm_lpss_chip definition to the header file
pwm: lpss: Add ACPI HID for second PWM controller on Cherry Trail devices
ACPI / PM: Export acpi_device_get_power() for use by modular build drivers
pwm: tegra: Remove gratuituous blank line
-rw-r--r-- | Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 10 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 1 | ||||
-rw-r--r-- | drivers/pwm/Kconfig | 5 | ||||
-rw-r--r-- | drivers/pwm/pwm-lpss-platform.c | 24 | ||||
-rw-r--r-- | drivers/pwm/pwm-lpss.c | 61 | ||||
-rw-r--r-- | drivers/pwm/pwm-lpss.h | 14 | ||||
-rw-r--r-- | drivers/pwm/pwm-rcar.c | 5 | ||||
-rw-r--r-- | drivers/pwm/pwm-renesas-tpu.c | 10 | ||||
-rw-r--r-- | drivers/pwm/pwm-tegra.c | 1 | ||||
-rw-r--r-- | drivers/pwm/sysfs.c | 12 |
12 files changed, 110 insertions, 38 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt index 06a363d9ccef..b9a1d7402128 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | |||
@@ -7,6 +7,7 @@ Required properties: | |||
7 | for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap"; | 7 | for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap"; |
8 | for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap"; | 8 | for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap"; |
9 | for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap"; | 9 | for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap"; |
10 | for am654 - compatible = "ti,am654-ecap", "ti,am3352-ecap"; | ||
10 | - #pwm-cells: should be 3. See pwm.txt in this directory for a description of | 11 | - #pwm-cells: should be 3. See pwm.txt in this directory for a description of |
11 | the cells format. The PWM channel index ranges from 0 to 4. The only third | 12 | the cells format. The PWM channel index ranges from 0 to 4. The only third |
12 | cell flag supported by this binding is PWM_POLARITY_INVERTED. | 13 | cell flag supported by this binding is PWM_POLARITY_INVERTED. |
diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index e1ef6afbe3a7..7f31fe7e2093 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | |||
@@ -3,7 +3,9 @@ | |||
3 | Required Properties: | 3 | Required Properties: |
4 | - compatible: should be "renesas,pwm-rcar" and one of the following. | 4 | - compatible: should be "renesas,pwm-rcar" and one of the following. |
5 | - "renesas,pwm-r8a7743": for RZ/G1M | 5 | - "renesas,pwm-r8a7743": for RZ/G1M |
6 | - "renesas,pwm-r8a7744": for RZ/G1N | ||
6 | - "renesas,pwm-r8a7745": for RZ/G1E | 7 | - "renesas,pwm-r8a7745": for RZ/G1E |
8 | - "renesas,pwm-r8a774a1": for RZ/G2M | ||
7 | - "renesas,pwm-r8a7778": for R-Car M1A | 9 | - "renesas,pwm-r8a7778": for R-Car M1A |
8 | - "renesas,pwm-r8a7779": for R-Car H1 | 10 | - "renesas,pwm-r8a7779": for R-Car H1 |
9 | - "renesas,pwm-r8a7790": for R-Car H2 | 11 | - "renesas,pwm-r8a7790": for R-Car H2 |
@@ -12,6 +14,8 @@ Required Properties: | |||
12 | - "renesas,pwm-r8a7795": for R-Car H3 | 14 | - "renesas,pwm-r8a7795": for R-Car H3 |
13 | - "renesas,pwm-r8a7796": for R-Car M3-W | 15 | - "renesas,pwm-r8a7796": for R-Car M3-W |
14 | - "renesas,pwm-r8a77965": for R-Car M3-N | 16 | - "renesas,pwm-r8a77965": for R-Car M3-N |
17 | - "renesas,pwm-r8a77970": for R-Car V3M | ||
18 | - "renesas,pwm-r8a77980": for R-Car V3H | ||
15 | - "renesas,pwm-r8a77990": for R-Car E3 | 19 | - "renesas,pwm-r8a77990": for R-Car E3 |
16 | - "renesas,pwm-r8a77995": for R-Car D3 | 20 | - "renesas,pwm-r8a77995": for R-Car D3 |
17 | - reg: base address and length of the registers block for the PWM. | 21 | - reg: base address and length of the registers block for the PWM. |
diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index d53a16715da6..848a92b53d81 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | |||
@@ -2,13 +2,19 @@ | |||
2 | 2 | ||
3 | Required Properties: | 3 | Required Properties: |
4 | 4 | ||
5 | - compatible: should be one of the following. | 5 | - compatible: must contain one or more of the following: |
6 | - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. | 6 | - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. |
7 | - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. | 7 | - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. |
8 | - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. | 8 | - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. |
9 | - "renesas,tpu-r8a7744": for R8A7744 (RZ/G1N) compatible PWM controller. | ||
9 | - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. | 10 | - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. |
10 | - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. | 11 | - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. |
11 | - "renesas,tpu": for generic R-Car and RZ/G1 TPU PWM controller. | 12 | - "renesas,tpu-r8a77970": for R8A77970 (R-Car V3M) compatible PWM |
13 | controller. | ||
14 | - "renesas,tpu-r8a77980": for R8A77980 (R-Car V3H) compatible PWM | ||
15 | controller. | ||
16 | - "renesas,tpu": for the generic TPU PWM controller; this is a fallback for | ||
17 | the entries listed above. | ||
12 | 18 | ||
13 | - reg: Base address and length of each memory resource used by the PWM | 19 | - reg: Base address and length of each memory resource used by the PWM |
14 | controller hardware module. | 20 | controller hardware module. |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index a7c2673ffd36..824ae985ad93 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -126,6 +126,7 @@ int acpi_device_get_power(struct acpi_device *device, int *state) | |||
126 | 126 | ||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | EXPORT_SYMBOL(acpi_device_get_power); | ||
129 | 130 | ||
130 | static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) | 131 | static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) |
131 | { | 132 | { |
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 504d252716f2..27e5dd47a01f 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
@@ -447,10 +447,9 @@ config PWM_TEGRA | |||
447 | 447 | ||
448 | config PWM_TIECAP | 448 | config PWM_TIECAP |
449 | tristate "ECAP PWM support" | 449 | tristate "ECAP PWM support" |
450 | depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE | 450 | depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 |
451 | help | 451 | help |
452 | PWM driver support for the ECAP APWM controller found on AM33XX | 452 | PWM driver support for the ECAP APWM controller found on TI SOCs |
453 | TI SOC | ||
454 | 453 | ||
455 | To compile this driver as a module, choose M here: the module | 454 | To compile this driver as a module, choose M here: the module |
456 | will be called pwm-tiecap. | 455 | will be called pwm-tiecap. |
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 5561b9e190f8..757230e1f575 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c | |||
@@ -30,6 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { | |||
30 | .clk_rate = 19200000, | 30 | .clk_rate = 19200000, |
31 | .npwm = 1, | 31 | .npwm = 1, |
32 | .base_unit_bits = 16, | 32 | .base_unit_bits = 16, |
33 | .other_devices_aml_touches_pwm_regs = true, | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | /* Broxton */ | 36 | /* Broxton */ |
@@ -60,6 +61,7 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) | |||
60 | 61 | ||
61 | platform_set_drvdata(pdev, lpwm); | 62 | platform_set_drvdata(pdev, lpwm); |
62 | 63 | ||
64 | dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE); | ||
63 | pm_runtime_set_active(&pdev->dev); | 65 | pm_runtime_set_active(&pdev->dev); |
64 | pm_runtime_enable(&pdev->dev); | 66 | pm_runtime_enable(&pdev->dev); |
65 | 67 | ||
@@ -74,13 +76,29 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev) | |||
74 | return pwm_lpss_remove(lpwm); | 76 | return pwm_lpss_remove(lpwm); |
75 | } | 77 | } |
76 | 78 | ||
77 | static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops, | 79 | static int pwm_lpss_prepare(struct device *dev) |
78 | pwm_lpss_suspend, | 80 | { |
79 | pwm_lpss_resume); | 81 | struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); |
82 | |||
83 | /* | ||
84 | * If other device's AML code touches the PWM regs on suspend/resume | ||
85 | * force runtime-resume the PWM controller to allow this. | ||
86 | */ | ||
87 | if (lpwm->info->other_devices_aml_touches_pwm_regs) | ||
88 | return 0; /* Force runtime-resume */ | ||
89 | |||
90 | return 1; /* If runtime-suspended leave as is */ | ||
91 | } | ||
92 | |||
93 | static const struct dev_pm_ops pwm_lpss_platform_pm_ops = { | ||
94 | .prepare = pwm_lpss_prepare, | ||
95 | SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume) | ||
96 | }; | ||
80 | 97 | ||
81 | static const struct acpi_device_id pwm_lpss_acpi_match[] = { | 98 | static const struct acpi_device_id pwm_lpss_acpi_match[] = { |
82 | { "80860F09", (unsigned long)&pwm_lpss_byt_info }, | 99 | { "80860F09", (unsigned long)&pwm_lpss_byt_info }, |
83 | { "80862288", (unsigned long)&pwm_lpss_bsw_info }, | 100 | { "80862288", (unsigned long)&pwm_lpss_bsw_info }, |
101 | { "80862289", (unsigned long)&pwm_lpss_bsw_info }, | ||
84 | { "80865AC8", (unsigned long)&pwm_lpss_bxt_info }, | 102 | { "80865AC8", (unsigned long)&pwm_lpss_bxt_info }, |
85 | { }, | 103 | { }, |
86 | }; | 104 | }; |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 4721a264bac2..2ac3a2aa9e53 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c | |||
@@ -32,15 +32,6 @@ | |||
32 | /* Size of each PWM register space if multiple */ | 32 | /* Size of each PWM register space if multiple */ |
33 | #define PWM_SIZE 0x400 | 33 | #define PWM_SIZE 0x400 |
34 | 34 | ||
35 | #define MAX_PWMS 4 | ||
36 | |||
37 | struct pwm_lpss_chip { | ||
38 | struct pwm_chip chip; | ||
39 | void __iomem *regs; | ||
40 | const struct pwm_lpss_boardinfo *info; | ||
41 | u32 saved_ctrl[MAX_PWMS]; | ||
42 | }; | ||
43 | |||
44 | static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) | 35 | static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) |
45 | { | 36 | { |
46 | return container_of(chip, struct pwm_lpss_chip, chip); | 37 | return container_of(chip, struct pwm_lpss_chip, chip); |
@@ -97,7 +88,7 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, | |||
97 | unsigned long long on_time_div; | 88 | unsigned long long on_time_div; |
98 | unsigned long c = lpwm->info->clk_rate, base_unit_range; | 89 | unsigned long c = lpwm->info->clk_rate, base_unit_range; |
99 | unsigned long long base_unit, freq = NSEC_PER_SEC; | 90 | unsigned long long base_unit, freq = NSEC_PER_SEC; |
100 | u32 ctrl; | 91 | u32 orig_ctrl, ctrl; |
101 | 92 | ||
102 | do_div(freq, period_ns); | 93 | do_div(freq, period_ns); |
103 | 94 | ||
@@ -114,13 +105,17 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, | |||
114 | do_div(on_time_div, period_ns); | 105 | do_div(on_time_div, period_ns); |
115 | on_time_div = 255ULL - on_time_div; | 106 | on_time_div = 255ULL - on_time_div; |
116 | 107 | ||
117 | ctrl = pwm_lpss_read(pwm); | 108 | orig_ctrl = ctrl = pwm_lpss_read(pwm); |
118 | ctrl &= ~PWM_ON_TIME_DIV_MASK; | 109 | ctrl &= ~PWM_ON_TIME_DIV_MASK; |
119 | ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT); | 110 | ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT); |
120 | base_unit &= base_unit_range; | 111 | base_unit &= base_unit_range; |
121 | ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; | 112 | ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; |
122 | ctrl |= on_time_div; | 113 | ctrl |= on_time_div; |
123 | pwm_lpss_write(pwm, ctrl); | 114 | |
115 | if (orig_ctrl != ctrl) { | ||
116 | pwm_lpss_write(pwm, ctrl); | ||
117 | pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); | ||
118 | } | ||
124 | } | 119 | } |
125 | 120 | ||
126 | static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) | 121 | static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) |
@@ -144,7 +139,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
144 | return ret; | 139 | return ret; |
145 | } | 140 | } |
146 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); | 141 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); |
147 | pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); | ||
148 | pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); | 142 | pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); |
149 | ret = pwm_lpss_wait_for_update(pwm); | 143 | ret = pwm_lpss_wait_for_update(pwm); |
150 | if (ret) { | 144 | if (ret) { |
@@ -157,7 +151,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
157 | if (ret) | 151 | if (ret) |
158 | return ret; | 152 | return ret; |
159 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); | 153 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); |
160 | pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); | ||
161 | return pwm_lpss_wait_for_update(pwm); | 154 | return pwm_lpss_wait_for_update(pwm); |
162 | } | 155 | } |
163 | } else if (pwm_is_enabled(pwm)) { | 156 | } else if (pwm_is_enabled(pwm)) { |
@@ -168,8 +161,42 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
168 | return 0; | 161 | return 0; |
169 | } | 162 | } |
170 | 163 | ||
164 | /* This function gets called once from pwmchip_add to get the initial state */ | ||
165 | static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | ||
166 | struct pwm_state *state) | ||
167 | { | ||
168 | struct pwm_lpss_chip *lpwm = to_lpwm(chip); | ||
169 | unsigned long base_unit_range; | ||
170 | unsigned long long base_unit, freq, on_time_div; | ||
171 | u32 ctrl; | ||
172 | |||
173 | base_unit_range = BIT(lpwm->info->base_unit_bits); | ||
174 | |||
175 | ctrl = pwm_lpss_read(pwm); | ||
176 | on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK); | ||
177 | base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1); | ||
178 | |||
179 | freq = base_unit * lpwm->info->clk_rate; | ||
180 | do_div(freq, base_unit_range); | ||
181 | if (freq == 0) | ||
182 | state->period = NSEC_PER_SEC; | ||
183 | else | ||
184 | state->period = NSEC_PER_SEC / (unsigned long)freq; | ||
185 | |||
186 | on_time_div *= state->period; | ||
187 | do_div(on_time_div, 255); | ||
188 | state->duty_cycle = on_time_div; | ||
189 | |||
190 | state->polarity = PWM_POLARITY_NORMAL; | ||
191 | state->enabled = !!(ctrl & PWM_ENABLE); | ||
192 | |||
193 | if (state->enabled) | ||
194 | pm_runtime_get(chip->dev); | ||
195 | } | ||
196 | |||
171 | static const struct pwm_ops pwm_lpss_ops = { | 197 | static const struct pwm_ops pwm_lpss_ops = { |
172 | .apply = pwm_lpss_apply, | 198 | .apply = pwm_lpss_apply, |
199 | .get_state = pwm_lpss_get_state, | ||
173 | .owner = THIS_MODULE, | 200 | .owner = THIS_MODULE, |
174 | }; | 201 | }; |
175 | 202 | ||
@@ -214,6 +241,12 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe); | |||
214 | 241 | ||
215 | int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) | 242 | int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) |
216 | { | 243 | { |
244 | int i; | ||
245 | |||
246 | for (i = 0; i < lpwm->info->npwm; i++) { | ||
247 | if (pwm_is_enabled(&lpwm->chip.pwms[i])) | ||
248 | pm_runtime_put(lpwm->chip.dev); | ||
249 | } | ||
217 | return pwmchip_remove(&lpwm->chip); | 250 | return pwmchip_remove(&lpwm->chip); |
218 | } | 251 | } |
219 | EXPORT_SYMBOL_GPL(pwm_lpss_remove); | 252 | EXPORT_SYMBOL_GPL(pwm_lpss_remove); |
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 7a4238ad1fcb..3236be835bd9 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h | |||
@@ -16,13 +16,25 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/pwm.h> | 17 | #include <linux/pwm.h> |
18 | 18 | ||
19 | struct pwm_lpss_chip; | 19 | #define MAX_PWMS 4 |
20 | |||
21 | struct pwm_lpss_chip { | ||
22 | struct pwm_chip chip; | ||
23 | void __iomem *regs; | ||
24 | const struct pwm_lpss_boardinfo *info; | ||
25 | u32 saved_ctrl[MAX_PWMS]; | ||
26 | }; | ||
20 | 27 | ||
21 | struct pwm_lpss_boardinfo { | 28 | struct pwm_lpss_boardinfo { |
22 | unsigned long clk_rate; | 29 | unsigned long clk_rate; |
23 | unsigned int npwm; | 30 | unsigned int npwm; |
24 | unsigned long base_unit_bits; | 31 | unsigned long base_unit_bits; |
25 | bool bypass; | 32 | bool bypass; |
33 | /* | ||
34 | * On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device | ||
35 | * messes with the PWM0 controllers state, | ||
36 | */ | ||
37 | bool other_devices_aml_touches_pwm_regs; | ||
26 | }; | 38 | }; |
27 | 39 | ||
28 | struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, | 40 | struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, |
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 748f614d5375..a41812fc6f95 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c | |||
@@ -1,11 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * R-Car PWM Timer driver | 3 | * R-Car PWM Timer driver |
3 | * | 4 | * |
4 | * Copyright (C) 2015 Renesas Electronics Corporation | 5 | * Copyright (C) 2015 Renesas Electronics Corporation |
5 | * | ||
6 | * This is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of version 2 of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | 6 | */ |
10 | 7 | ||
11 | #include <linux/clk.h> | 8 | #include <linux/clk.h> |
diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 29267d12fb4c..4a855a21b782 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c | |||
@@ -1,16 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * R-Mobile TPU PWM driver | 3 | * R-Mobile TPU PWM driver |
3 | * | 4 | * |
4 | * Copyright (C) 2012 Renesas Solutions Corp. | 5 | * Copyright (C) 2012 Renesas Solutions Corp. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | 6 | */ |
15 | 7 | ||
16 | #include <linux/clk.h> | 8 | #include <linux/clk.h> |
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index f8ebbece57b7..48c4595a0ffc 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c | |||
@@ -300,7 +300,6 @@ static const struct of_device_id tegra_pwm_of_match[] = { | |||
300 | { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, | 300 | { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, |
301 | { } | 301 | { } |
302 | }; | 302 | }; |
303 | |||
304 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); | 303 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); |
305 | 304 | ||
306 | static const struct dev_pm_ops tegra_pwm_pm_ops = { | 305 | static const struct dev_pm_ops tegra_pwm_pm_ops = { |
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 7c71cdb8a9d8..ceb233dd6048 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c | |||
@@ -249,6 +249,7 @@ static void pwm_export_release(struct device *child) | |||
249 | static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | 249 | static int pwm_export_child(struct device *parent, struct pwm_device *pwm) |
250 | { | 250 | { |
251 | struct pwm_export *export; | 251 | struct pwm_export *export; |
252 | char *pwm_prop[2]; | ||
252 | int ret; | 253 | int ret; |
253 | 254 | ||
254 | if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) | 255 | if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) |
@@ -263,7 +264,6 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | |||
263 | export->pwm = pwm; | 264 | export->pwm = pwm; |
264 | mutex_init(&export->lock); | 265 | mutex_init(&export->lock); |
265 | 266 | ||
266 | export->child.class = parent->class; | ||
267 | export->child.release = pwm_export_release; | 267 | export->child.release = pwm_export_release; |
268 | export->child.parent = parent; | 268 | export->child.parent = parent; |
269 | export->child.devt = MKDEV(0, 0); | 269 | export->child.devt = MKDEV(0, 0); |
@@ -277,6 +277,10 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | |||
277 | export = NULL; | 277 | export = NULL; |
278 | return ret; | 278 | return ret; |
279 | } | 279 | } |
280 | pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm); | ||
281 | pwm_prop[1] = NULL; | ||
282 | kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); | ||
283 | kfree(pwm_prop[0]); | ||
280 | 284 | ||
281 | return 0; | 285 | return 0; |
282 | } | 286 | } |
@@ -289,6 +293,7 @@ static int pwm_unexport_match(struct device *child, void *data) | |||
289 | static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) | 293 | static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) |
290 | { | 294 | { |
291 | struct device *child; | 295 | struct device *child; |
296 | char *pwm_prop[2]; | ||
292 | 297 | ||
293 | if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) | 298 | if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) |
294 | return -ENODEV; | 299 | return -ENODEV; |
@@ -297,6 +302,11 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) | |||
297 | if (!child) | 302 | if (!child) |
298 | return -ENODEV; | 303 | return -ENODEV; |
299 | 304 | ||
305 | pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm); | ||
306 | pwm_prop[1] = NULL; | ||
307 | kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); | ||
308 | kfree(pwm_prop[0]); | ||
309 | |||
300 | /* for device_find_child() */ | 310 | /* for device_find_child() */ |
301 | put_device(child); | 311 | put_device(child); |
302 | device_unregister(child); | 312 | device_unregister(child); |