hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/pwm/pwm-hibvt.c
....@@ -1,20 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * PWM Controller Driver for HiSilicon BVT SoCs
34 *
45 * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
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, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
186 */
197
208 #include <linux/bitops.h>
....@@ -49,15 +37,30 @@
4937 struct clk *clk;
5038 void __iomem *base;
5139 struct reset_control *rstc;
40
+ const struct hibvt_pwm_soc *soc;
5241 };
5342
5443 struct hibvt_pwm_soc {
5544 u32 num_pwms;
45
+ bool quirk_force_enable;
5646 };
5747
58
-static const struct hibvt_pwm_soc pwm_soc[2] = {
59
- { .num_pwms = 4 },
60
- { .num_pwms = 8 },
48
+static const struct hibvt_pwm_soc hi3516cv300_soc_info = {
49
+ .num_pwms = 4,
50
+};
51
+
52
+static const struct hibvt_pwm_soc hi3519v100_soc_info = {
53
+ .num_pwms = 8,
54
+};
55
+
56
+static const struct hibvt_pwm_soc hi3559v100_shub_soc_info = {
57
+ .num_pwms = 8,
58
+ .quirk_force_enable = true,
59
+};
60
+
61
+static const struct hibvt_pwm_soc hi3559v100_soc_info = {
62
+ .num_pwms = 2,
63
+ .quirk_force_enable = true,
6164 };
6265
6366 static inline struct hibvt_pwm_chip *to_hibvt_pwm_chip(struct pwm_chip *chip)
....@@ -143,17 +146,28 @@
143146
144147 value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
145148 state->enabled = (PWM_ENABLE_MASK & value);
149
+ state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
146150 }
147151
148152 static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
149
- struct pwm_state *state)
153
+ const struct pwm_state *state)
150154 {
155
+ struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);
156
+
151157 if (state->polarity != pwm->state.polarity)
152158 hibvt_pwm_set_polarity(chip, pwm, state->polarity);
153159
154160 if (state->period != pwm->state.period ||
155
- state->duty_cycle != pwm->state.duty_cycle)
161
+ state->duty_cycle != pwm->state.duty_cycle) {
156162 hibvt_pwm_config(chip, pwm, state->duty_cycle, state->period);
163
+
164
+ /*
165
+ * Some implementations require the PWM to be enabled twice
166
+ * each time the duty cycle is refreshed.
167
+ */
168
+ if (hi_pwm_chip->soc->quirk_force_enable && state->enabled)
169
+ hibvt_pwm_enable(chip, pwm);
170
+ }
157171
158172 if (state->enabled != pwm->state.enabled) {
159173 if (state->enabled)
....@@ -198,6 +212,7 @@
198212 pwm_chip->chip.npwm = soc->num_pwms;
199213 pwm_chip->chip.of_xlate = of_pwm_xlate_with_flags;
200214 pwm_chip->chip.of_pwm_n_cells = 3;
215
+ pwm_chip->soc = soc;
201216
202217 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
203218 pwm_chip->base = devm_ioremap_resource(&pdev->dev, res);
....@@ -250,8 +265,14 @@
250265 }
251266
252267 static const struct of_device_id hibvt_pwm_of_match[] = {
253
- { .compatible = "hisilicon,hi3516cv300-pwm", .data = &pwm_soc[0] },
254
- { .compatible = "hisilicon,hi3519v100-pwm", .data = &pwm_soc[1] },
268
+ { .compatible = "hisilicon,hi3516cv300-pwm",
269
+ .data = &hi3516cv300_soc_info },
270
+ { .compatible = "hisilicon,hi3519v100-pwm",
271
+ .data = &hi3519v100_soc_info },
272
+ { .compatible = "hisilicon,hi3559v100-shub-pwm",
273
+ .data = &hi3559v100_shub_soc_info },
274
+ { .compatible = "hisilicon,hi3559v100-pwm",
275
+ .data = &hi3559v100_soc_info },
255276 { }
256277 };
257278 MODULE_DEVICE_TABLE(of, hibvt_pwm_of_match);