.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * drivers/pwm/pwm-tegra.c |
---|
3 | 4 | * |
---|
4 | 5 | * Tegra pulse-width-modulation controller driver |
---|
5 | 6 | * |
---|
6 | | - * Copyright (c) 2010, NVIDIA Corporation. |
---|
| 7 | + * Copyright (c) 2010-2020, NVIDIA Corporation. |
---|
7 | 8 | * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de> |
---|
8 | 9 | * |
---|
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 |
---|
13 | 14 | * |
---|
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. |
---|
18 | 22 | * |
---|
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. |
---|
22 | 37 | */ |
---|
23 | 38 | |
---|
24 | 39 | #include <linux/clk.h> |
---|
.. | .. |
---|
54 | 69 | struct reset_control*rst; |
---|
55 | 70 | |
---|
56 | 71 | unsigned long clk_rate; |
---|
| 72 | + unsigned long min_period_ns; |
---|
57 | 73 | |
---|
58 | 74 | void __iomem *regs; |
---|
59 | 75 | |
---|
.. | .. |
---|
81 | 97 | { |
---|
82 | 98 | struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); |
---|
83 | 99 | unsigned long long c = duty_ns, hz; |
---|
84 | | - unsigned long rate; |
---|
| 100 | + unsigned long rate, required_clk_rate; |
---|
85 | 101 | u32 val = 0; |
---|
86 | 102 | int err; |
---|
87 | 103 | |
---|
.. | .. |
---|
96 | 112 | val = (u32)c << PWM_DUTY_SHIFT; |
---|
97 | 113 | |
---|
98 | 114 | /* |
---|
| 115 | + * min period = max clock limit >> PWM_DUTY_WIDTH |
---|
| 116 | + */ |
---|
| 117 | + if (period_ns < pc->min_period_ns) |
---|
| 118 | + return -EINVAL; |
---|
| 119 | + |
---|
| 120 | + /* |
---|
99 | 121 | * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH) |
---|
100 | 122 | * 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). |
---|
101 | 132 | */ |
---|
| 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 | + |
---|
102 | 156 | rate = pc->clk_rate >> PWM_DUTY_WIDTH; |
---|
103 | 157 | |
---|
104 | 158 | /* Consider precision in PWM_SCALE_WIDTH rate calculation */ |
---|
.. | .. |
---|
107 | 161 | |
---|
108 | 162 | /* |
---|
109 | 163 | * 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 |
---|
111 | 165 | * write to the register. |
---|
112 | 166 | */ |
---|
113 | 167 | if (rate > 0) |
---|
.. | .. |
---|
218 | 272 | */ |
---|
219 | 273 | pwm->clk_rate = clk_get_rate(pwm->clk); |
---|
220 | 274 | |
---|
| 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 | + |
---|
221 | 279 | pwm->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm"); |
---|
222 | 280 | if (IS_ERR(pwm->rst)) { |
---|
223 | 281 | ret = PTR_ERR(pwm->rst); |
---|
.. | .. |
---|
282 | 340 | .max_frequency = 102000000UL, |
---|
283 | 341 | }; |
---|
284 | 342 | |
---|
| 343 | +static const struct tegra_pwm_soc tegra194_pwm_soc = { |
---|
| 344 | + .num_channels = 1, |
---|
| 345 | + .max_frequency = 408000000UL, |
---|
| 346 | +}; |
---|
| 347 | + |
---|
285 | 348 | static const struct of_device_id tegra_pwm_of_match[] = { |
---|
286 | 349 | { .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc }, |
---|
287 | 350 | { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, |
---|
| 351 | + { .compatible = "nvidia,tegra194-pwm", .data = &tegra194_pwm_soc }, |
---|
288 | 352 | { } |
---|
289 | 353 | }; |
---|
290 | | - |
---|
291 | 354 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); |
---|
292 | 355 | |
---|
293 | 356 | static const struct dev_pm_ops tegra_pwm_pm_ops = { |
---|
.. | .. |
---|
307 | 370 | module_platform_driver(tegra_pwm_driver); |
---|
308 | 371 | |
---|
309 | 372 | MODULE_LICENSE("GPL"); |
---|
310 | | -MODULE_AUTHOR("NVIDIA Corporation"); |
---|
| 373 | +MODULE_AUTHOR("Sandipan Patra <spatra@nvidia.com>"); |
---|
| 374 | +MODULE_DESCRIPTION("Tegra PWM controller driver"); |
---|
311 | 375 | MODULE_ALIAS("platform:tegra-pwm"); |
---|