xref: /linux/drivers/pwm/pwm-tegra.c (revision e58e871becec2d3b04ed91c0c16fe8deac9c9dfa)
1 /*
2  * drivers/pwm/pwm-tegra.c
3  *
4  * Tegra pulse-width-modulation controller driver
5  *
6  * Copyright (c) 2010, NVIDIA Corporation.
7  * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de>
8  *
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.
13  *
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.
18  *
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.
22  */
23 
24 #include <linux/clk.h>
25 #include <linux/err.h>
26 #include <linux/io.h>
27 #include <linux/module.h>
28 #include <linux/of.h>
29 #include <linux/of_device.h>
30 #include <linux/pwm.h>
31 #include <linux/platform_device.h>
32 #include <linux/pinctrl/consumer.h>
33 #include <linux/slab.h>
34 #include <linux/reset.h>
35 
36 #define PWM_ENABLE	(1 << 31)
37 #define PWM_DUTY_WIDTH	8
38 #define PWM_DUTY_SHIFT	16
39 #define PWM_SCALE_WIDTH	13
40 #define PWM_SCALE_SHIFT	0
41 
42 struct tegra_pwm_soc {
43 	unsigned int num_channels;
44 };
45 
46 struct tegra_pwm_chip {
47 	struct pwm_chip chip;
48 	struct device *dev;
49 
50 	struct clk *clk;
51 	struct reset_control*rst;
52 
53 	unsigned long clk_rate;
54 
55 	void __iomem *regs;
56 
57 	const struct tegra_pwm_soc *soc;
58 };
59 
60 static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip)
61 {
62 	return container_of(chip, struct tegra_pwm_chip, chip);
63 }
64 
65 static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num)
66 {
67 	return readl(chip->regs + (num << 4));
68 }
69 
70 static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num,
71 			     unsigned long val)
72 {
73 	writel(val, chip->regs + (num << 4));
74 }
75 
76 static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
77 			    int duty_ns, int period_ns)
78 {
79 	struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
80 	unsigned long long c = duty_ns, hz;
81 	unsigned long rate;
82 	u32 val = 0;
83 	int err;
84 
85 	/*
86 	 * Convert from duty_ns / period_ns to a fixed number of duty ticks
87 	 * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the
88 	 * nearest integer during division.
89 	 */
90 	c *= (1 << PWM_DUTY_WIDTH);
91 	c = DIV_ROUND_CLOSEST_ULL(c, period_ns);
92 
93 	val = (u32)c << PWM_DUTY_SHIFT;
94 
95 	/*
96 	 * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
97 	 * cycles at the PWM clock rate will take period_ns nanoseconds.
98 	 */
99 	rate = pc->clk_rate >> PWM_DUTY_WIDTH;
100 
101 	/* Consider precision in PWM_SCALE_WIDTH rate calculation */
102 	hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns);
103 	rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz);
104 
105 	/*
106 	 * Since the actual PWM divider is the register's frequency divider
107 	 * field minus 1, we need to decrement to get the correct value to
108 	 * write to the register.
109 	 */
110 	if (rate > 0)
111 		rate--;
112 
113 	/*
114 	 * Make sure that the rate will fit in the register's frequency
115 	 * divider field.
116 	 */
117 	if (rate >> PWM_SCALE_WIDTH)
118 		return -EINVAL;
119 
120 	val |= rate << PWM_SCALE_SHIFT;
121 
122 	/*
123 	 * If the PWM channel is disabled, make sure to turn on the clock
124 	 * before writing the register. Otherwise, keep it enabled.
125 	 */
126 	if (!pwm_is_enabled(pwm)) {
127 		err = clk_prepare_enable(pc->clk);
128 		if (err < 0)
129 			return err;
130 	} else
131 		val |= PWM_ENABLE;
132 
133 	pwm_writel(pc, pwm->hwpwm, val);
134 
135 	/*
136 	 * If the PWM is not enabled, turn the clock off again to save power.
137 	 */
138 	if (!pwm_is_enabled(pwm))
139 		clk_disable_unprepare(pc->clk);
140 
141 	return 0;
142 }
143 
144 static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
145 {
146 	struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
147 	int rc = 0;
148 	u32 val;
149 
150 	rc = clk_prepare_enable(pc->clk);
151 	if (rc < 0)
152 		return rc;
153 
154 	val = pwm_readl(pc, pwm->hwpwm);
155 	val |= PWM_ENABLE;
156 	pwm_writel(pc, pwm->hwpwm, val);
157 
158 	return 0;
159 }
160 
161 static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
162 {
163 	struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
164 	u32 val;
165 
166 	val = pwm_readl(pc, pwm->hwpwm);
167 	val &= ~PWM_ENABLE;
168 	pwm_writel(pc, pwm->hwpwm, val);
169 
170 	clk_disable_unprepare(pc->clk);
171 }
172 
173 static const struct pwm_ops tegra_pwm_ops = {
174 	.config = tegra_pwm_config,
175 	.enable = tegra_pwm_enable,
176 	.disable = tegra_pwm_disable,
177 	.owner = THIS_MODULE,
178 };
179 
180 static int tegra_pwm_probe(struct platform_device *pdev)
181 {
182 	struct tegra_pwm_chip *pwm;
183 	struct resource *r;
184 	int ret;
185 
186 	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
187 	if (!pwm)
188 		return -ENOMEM;
189 
190 	pwm->soc = of_device_get_match_data(&pdev->dev);
191 	pwm->dev = &pdev->dev;
192 
193 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
194 	pwm->regs = devm_ioremap_resource(&pdev->dev, r);
195 	if (IS_ERR(pwm->regs))
196 		return PTR_ERR(pwm->regs);
197 
198 	platform_set_drvdata(pdev, pwm);
199 
200 	pwm->clk = devm_clk_get(&pdev->dev, NULL);
201 	if (IS_ERR(pwm->clk))
202 		return PTR_ERR(pwm->clk);
203 
204 	/* Read PWM clock rate from source */
205 	pwm->clk_rate = clk_get_rate(pwm->clk);
206 
207 	pwm->rst = devm_reset_control_get(&pdev->dev, "pwm");
208 	if (IS_ERR(pwm->rst)) {
209 		ret = PTR_ERR(pwm->rst);
210 		dev_err(&pdev->dev, "Reset control is not found: %d\n", ret);
211 		return ret;
212 	}
213 
214 	reset_control_deassert(pwm->rst);
215 
216 	pwm->chip.dev = &pdev->dev;
217 	pwm->chip.ops = &tegra_pwm_ops;
218 	pwm->chip.base = -1;
219 	pwm->chip.npwm = pwm->soc->num_channels;
220 
221 	ret = pwmchip_add(&pwm->chip);
222 	if (ret < 0) {
223 		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
224 		reset_control_assert(pwm->rst);
225 		return ret;
226 	}
227 
228 	return 0;
229 }
230 
231 static int tegra_pwm_remove(struct platform_device *pdev)
232 {
233 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
234 	unsigned int i;
235 	int err;
236 
237 	if (WARN_ON(!pc))
238 		return -ENODEV;
239 
240 	err = clk_prepare_enable(pc->clk);
241 	if (err < 0)
242 		return err;
243 
244 	for (i = 0; i < pc->chip.npwm; i++) {
245 		struct pwm_device *pwm = &pc->chip.pwms[i];
246 
247 		if (!pwm_is_enabled(pwm))
248 			if (clk_prepare_enable(pc->clk) < 0)
249 				continue;
250 
251 		pwm_writel(pc, i, 0);
252 
253 		clk_disable_unprepare(pc->clk);
254 	}
255 
256 	reset_control_assert(pc->rst);
257 	clk_disable_unprepare(pc->clk);
258 
259 	return pwmchip_remove(&pc->chip);
260 }
261 
262 #ifdef CONFIG_PM_SLEEP
263 static int tegra_pwm_suspend(struct device *dev)
264 {
265 	return pinctrl_pm_select_sleep_state(dev);
266 }
267 
268 static int tegra_pwm_resume(struct device *dev)
269 {
270 	return pinctrl_pm_select_default_state(dev);
271 }
272 #endif
273 
274 static const struct tegra_pwm_soc tegra20_pwm_soc = {
275 	.num_channels = 4,
276 };
277 
278 static const struct tegra_pwm_soc tegra186_pwm_soc = {
279 	.num_channels = 1,
280 };
281 
282 static const struct of_device_id tegra_pwm_of_match[] = {
283 	{ .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc },
284 	{ .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc },
285 	{ }
286 };
287 
288 MODULE_DEVICE_TABLE(of, tegra_pwm_of_match);
289 
290 static const struct dev_pm_ops tegra_pwm_pm_ops = {
291 	SET_SYSTEM_SLEEP_PM_OPS(tegra_pwm_suspend, tegra_pwm_resume)
292 };
293 
294 static struct platform_driver tegra_pwm_driver = {
295 	.driver = {
296 		.name = "tegra-pwm",
297 		.of_match_table = tegra_pwm_of_match,
298 		.pm = &tegra_pwm_pm_ops,
299 	},
300 	.probe = tegra_pwm_probe,
301 	.remove = tegra_pwm_remove,
302 };
303 
304 module_platform_driver(tegra_pwm_driver);
305 
306 MODULE_LICENSE("GPL");
307 MODULE_AUTHOR("NVIDIA Corporation");
308 MODULE_ALIAS("platform:tegra-pwm");
309