hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/pwm/pwm-tegra.c
....@@ -1,24 +1,39 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * drivers/pwm/pwm-tegra.c
34 *
45 * Tegra pulse-width-modulation controller driver
56 *
6
- * Copyright (c) 2010, NVIDIA Corporation.
7
+ * Copyright (c) 2010-2020, NVIDIA Corporation.
78 * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de>
89 *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
10
+ * Overview of Tegra Pulse Width Modulator Register:
11
+ * 1. 13-bit: Frequency division (SCALE)
12
+ * 2. 8-bit : Pulse division (DUTY)
13
+ * 3. 1-bit : Enable bit
1314 *
14
- * This program is distributed in the hope that it will be useful, but WITHOUT
15
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
- * more details.
15
+ * The PWM clock frequency is divided by 256 before subdividing it based
16
+ * on the programmable frequency division value to generate the required
17
+ * frequency for PWM output. The maximum output frequency that can be
18
+ * achieved is (max rate of source clock) / 256.
19
+ * e.g. if source clock rate is 408 MHz, maximum output frequency can be:
20
+ * 408 MHz/256 = 1.6 MHz.
21
+ * This 1.6 MHz frequency can further be divided using SCALE value in PWM.
1822 *
19
- * You should have received a copy of the GNU General Public License along
20
- * with this program; if not, write to the Free Software Foundation, Inc.,
21
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
+ * PWM pulse width: 8 bits are usable [23:16] for varying pulse width.
24
+ * To achieve 100% duty cycle, program Bit [24] of this register to
25
+ * 1’b1. In which case the other bits [23:16] are set to don't care.
26
+ *
27
+ * Limitations:
28
+ * - When PWM is disabled, the output is driven to inactive.
29
+ * - It does not allow the current PWM period to complete and
30
+ * stops abruptly.
31
+ *
32
+ * - If the register is reconfigured while PWM is running,
33
+ * it does not complete the currently running period.
34
+ *
35
+ * - If the user input duty is beyond acceptible limits,
36
+ * -EINVAL is returned.
2237 */
2338
2439 #include <linux/clk.h>
....@@ -54,6 +69,7 @@
5469 struct reset_control*rst;
5570
5671 unsigned long clk_rate;
72
+ unsigned long min_period_ns;
5773
5874 void __iomem *regs;
5975
....@@ -81,7 +97,7 @@
8197 {
8298 struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
8399 unsigned long long c = duty_ns, hz;
84
- unsigned long rate;
100
+ unsigned long rate, required_clk_rate;
85101 u32 val = 0;
86102 int err;
87103
....@@ -96,9 +112,47 @@
96112 val = (u32)c << PWM_DUTY_SHIFT;
97113
98114 /*
115
+ * min period = max clock limit >> PWM_DUTY_WIDTH
116
+ */
117
+ if (period_ns < pc->min_period_ns)
118
+ return -EINVAL;
119
+
120
+ /*
99121 * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
100122 * cycles at the PWM clock rate will take period_ns nanoseconds.
123
+ *
124
+ * num_channels: If single instance of PWM controller has multiple
125
+ * channels (e.g. Tegra210 or older) then it is not possible to
126
+ * configure separate clock rates to each of the channels, in such
127
+ * case the value stored during probe will be referred.
128
+ *
129
+ * If every PWM controller instance has one channel respectively, i.e.
130
+ * nums_channels == 1 then only the clock rate can be modified
131
+ * dynamically (e.g. Tegra186 or Tegra194).
101132 */
133
+ if (pc->soc->num_channels == 1) {
134
+ /*
135
+ * Rate is multiplied with 2^PWM_DUTY_WIDTH so that it matches
136
+ * with the maximum possible rate that the controller can
137
+ * provide. Any further lower value can be derived by setting
138
+ * PFM bits[0:12].
139
+ *
140
+ * required_clk_rate is a reference rate for source clock and
141
+ * it is derived based on user requested period. By setting the
142
+ * source clock rate as required_clk_rate, PWM controller will
143
+ * be able to configure the requested period.
144
+ */
145
+ required_clk_rate = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC << PWM_DUTY_WIDTH,
146
+ period_ns);
147
+
148
+ err = clk_set_rate(pc->clk, required_clk_rate);
149
+ if (err < 0)
150
+ return -EINVAL;
151
+
152
+ /* Store the new rate for further references */
153
+ pc->clk_rate = clk_get_rate(pc->clk);
154
+ }
155
+
102156 rate = pc->clk_rate >> PWM_DUTY_WIDTH;
103157
104158 /* Consider precision in PWM_SCALE_WIDTH rate calculation */
....@@ -107,7 +161,7 @@
107161
108162 /*
109163 * Since the actual PWM divider is the register's frequency divider
110
- * field minus 1, we need to decrement to get the correct value to
164
+ * field plus 1, we need to decrement to get the correct value to
111165 * write to the register.
112166 */
113167 if (rate > 0)
....@@ -218,6 +272,10 @@
218272 */
219273 pwm->clk_rate = clk_get_rate(pwm->clk);
220274
275
+ /* Set minimum limit of PWM period for the IP */
276
+ pwm->min_period_ns =
277
+ (NSEC_PER_SEC / (pwm->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1;
278
+
221279 pwm->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm");
222280 if (IS_ERR(pwm->rst)) {
223281 ret = PTR_ERR(pwm->rst);
....@@ -282,12 +340,17 @@
282340 .max_frequency = 102000000UL,
283341 };
284342
343
+static const struct tegra_pwm_soc tegra194_pwm_soc = {
344
+ .num_channels = 1,
345
+ .max_frequency = 408000000UL,
346
+};
347
+
285348 static const struct of_device_id tegra_pwm_of_match[] = {
286349 { .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc },
287350 { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc },
351
+ { .compatible = "nvidia,tegra194-pwm", .data = &tegra194_pwm_soc },
288352 { }
289353 };
290
-
291354 MODULE_DEVICE_TABLE(of, tegra_pwm_of_match);
292355
293356 static const struct dev_pm_ops tegra_pwm_pm_ops = {
....@@ -307,5 +370,6 @@
307370 module_platform_driver(tegra_pwm_driver);
308371
309372 MODULE_LICENSE("GPL");
310
-MODULE_AUTHOR("NVIDIA Corporation");
373
+MODULE_AUTHOR("Sandipan Patra <spatra@nvidia.com>");
374
+MODULE_DESCRIPTION("Tegra PWM controller driver");
311375 MODULE_ALIAS("platform:tegra-pwm");