xref: /openbmc/linux/drivers/pwm/pwm-sun4i.c (revision 4f3db074)
1 /*
2  * Driver for Allwinner sun4i Pulse Width Modulation Controller
3  *
4  * Copyright (C) 2014 Alexandre Belloni <alexandre.belloni@free-electrons.com>
5  *
6  * Licensed under GPLv2.
7  */
8 
9 #include <linux/bitops.h>
10 #include <linux/clk.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/of_device.h>
16 #include <linux/platform_device.h>
17 #include <linux/pwm.h>
18 #include <linux/slab.h>
19 #include <linux/spinlock.h>
20 #include <linux/time.h>
21 
22 #define PWM_CTRL_REG		0x0
23 
24 #define PWM_CH_PRD_BASE		0x4
25 #define PWM_CH_PRD_OFFSET	0x4
26 #define PWM_CH_PRD(ch)		(PWM_CH_PRD_BASE + PWM_CH_PRD_OFFSET * (ch))
27 
28 #define PWMCH_OFFSET		15
29 #define PWM_PRESCAL_MASK	GENMASK(3, 0)
30 #define PWM_PRESCAL_OFF		0
31 #define PWM_EN			BIT(4)
32 #define PWM_ACT_STATE		BIT(5)
33 #define PWM_CLK_GATING		BIT(6)
34 #define PWM_MODE		BIT(7)
35 #define PWM_PULSE		BIT(8)
36 #define PWM_BYPASS		BIT(9)
37 
38 #define PWM_RDY_BASE		28
39 #define PWM_RDY_OFFSET		1
40 #define PWM_RDY(ch)		BIT(PWM_RDY_BASE + PWM_RDY_OFFSET * (ch))
41 
42 #define PWM_PRD(prd)		(((prd) - 1) << 16)
43 #define PWM_PRD_MASK		GENMASK(15, 0)
44 
45 #define PWM_DTY_MASK		GENMASK(15, 0)
46 
47 #define BIT_CH(bit, chan)	((bit) << ((chan) * PWMCH_OFFSET))
48 
49 static const u32 prescaler_table[] = {
50 	120,
51 	180,
52 	240,
53 	360,
54 	480,
55 	0,
56 	0,
57 	0,
58 	12000,
59 	24000,
60 	36000,
61 	48000,
62 	72000,
63 	0,
64 	0,
65 	0, /* Actually 1 but tested separately */
66 };
67 
68 struct sun4i_pwm_data {
69 	bool has_prescaler_bypass;
70 	bool has_rdy;
71 };
72 
73 struct sun4i_pwm_chip {
74 	struct pwm_chip chip;
75 	struct clk *clk;
76 	void __iomem *base;
77 	spinlock_t ctrl_lock;
78 	const struct sun4i_pwm_data *data;
79 };
80 
81 static inline struct sun4i_pwm_chip *to_sun4i_pwm_chip(struct pwm_chip *chip)
82 {
83 	return container_of(chip, struct sun4i_pwm_chip, chip);
84 }
85 
86 static inline u32 sun4i_pwm_readl(struct sun4i_pwm_chip *chip,
87 				  unsigned long offset)
88 {
89 	return readl(chip->base + offset);
90 }
91 
92 static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *chip,
93 				    u32 val, unsigned long offset)
94 {
95 	writel(val, chip->base + offset);
96 }
97 
98 static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
99 			    int duty_ns, int period_ns)
100 {
101 	struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
102 	u32 prd, dty, val, clk_gate;
103 	u64 clk_rate, div = 0;
104 	unsigned int prescaler = 0;
105 	int err;
106 
107 	clk_rate = clk_get_rate(sun4i_pwm->clk);
108 
109 	if (sun4i_pwm->data->has_prescaler_bypass) {
110 		/* First, test without any prescaler when available */
111 		prescaler = PWM_PRESCAL_MASK;
112 		/*
113 		 * When not using any prescaler, the clock period in nanoseconds
114 		 * is not an integer so round it half up instead of
115 		 * truncating to get less surprising values.
116 		 */
117 		div = clk_rate * period_ns + NSEC_PER_SEC/2;
118 		do_div(div, NSEC_PER_SEC);
119 		if (div - 1 > PWM_PRD_MASK)
120 			prescaler = 0;
121 	}
122 
123 	if (prescaler == 0) {
124 		/* Go up from the first divider */
125 		for (prescaler = 0; prescaler < PWM_PRESCAL_MASK; prescaler++) {
126 			if (!prescaler_table[prescaler])
127 				continue;
128 			div = clk_rate;
129 			do_div(div, prescaler_table[prescaler]);
130 			div = div * period_ns;
131 			do_div(div, NSEC_PER_SEC);
132 			if (div - 1 <= PWM_PRD_MASK)
133 				break;
134 		}
135 
136 		if (div - 1 > PWM_PRD_MASK) {
137 			dev_err(chip->dev, "period exceeds the maximum value\n");
138 			return -EINVAL;
139 		}
140 	}
141 
142 	prd = div;
143 	div *= duty_ns;
144 	do_div(div, period_ns);
145 	dty = div;
146 
147 	err = clk_prepare_enable(sun4i_pwm->clk);
148 	if (err) {
149 		dev_err(chip->dev, "failed to enable PWM clock\n");
150 		return err;
151 	}
152 
153 	spin_lock(&sun4i_pwm->ctrl_lock);
154 	val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
155 
156 	if (sun4i_pwm->data->has_rdy && (val & PWM_RDY(pwm->hwpwm))) {
157 		spin_unlock(&sun4i_pwm->ctrl_lock);
158 		clk_disable_unprepare(sun4i_pwm->clk);
159 		return -EBUSY;
160 	}
161 
162 	clk_gate = val & BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
163 	if (clk_gate) {
164 		val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
165 		sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
166 	}
167 
168 	val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
169 	val &= ~BIT_CH(PWM_PRESCAL_MASK, pwm->hwpwm);
170 	val |= BIT_CH(prescaler, pwm->hwpwm);
171 	sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
172 
173 	val = (dty & PWM_DTY_MASK) | PWM_PRD(prd);
174 	sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm));
175 
176 	if (clk_gate) {
177 		val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
178 		val |= clk_gate;
179 		sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
180 	}
181 
182 	spin_unlock(&sun4i_pwm->ctrl_lock);
183 	clk_disable_unprepare(sun4i_pwm->clk);
184 
185 	return 0;
186 }
187 
188 static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
189 				  enum pwm_polarity polarity)
190 {
191 	struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
192 	u32 val;
193 	int ret;
194 
195 	ret = clk_prepare_enable(sun4i_pwm->clk);
196 	if (ret) {
197 		dev_err(chip->dev, "failed to enable PWM clock\n");
198 		return ret;
199 	}
200 
201 	spin_lock(&sun4i_pwm->ctrl_lock);
202 	val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
203 
204 	if (polarity != PWM_POLARITY_NORMAL)
205 		val &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm);
206 	else
207 		val |= BIT_CH(PWM_ACT_STATE, pwm->hwpwm);
208 
209 	sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
210 
211 	spin_unlock(&sun4i_pwm->ctrl_lock);
212 	clk_disable_unprepare(sun4i_pwm->clk);
213 
214 	return 0;
215 }
216 
217 static int sun4i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
218 {
219 	struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
220 	u32 val;
221 	int ret;
222 
223 	ret = clk_prepare_enable(sun4i_pwm->clk);
224 	if (ret) {
225 		dev_err(chip->dev, "failed to enable PWM clock\n");
226 		return ret;
227 	}
228 
229 	spin_lock(&sun4i_pwm->ctrl_lock);
230 	val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
231 	val |= BIT_CH(PWM_EN, pwm->hwpwm);
232 	val |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
233 	sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
234 	spin_unlock(&sun4i_pwm->ctrl_lock);
235 
236 	return 0;
237 }
238 
239 static void sun4i_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
240 {
241 	struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
242 	u32 val;
243 
244 	spin_lock(&sun4i_pwm->ctrl_lock);
245 	val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
246 	val &= ~BIT_CH(PWM_EN, pwm->hwpwm);
247 	val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
248 	sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG);
249 	spin_unlock(&sun4i_pwm->ctrl_lock);
250 
251 	clk_disable_unprepare(sun4i_pwm->clk);
252 }
253 
254 static const struct pwm_ops sun4i_pwm_ops = {
255 	.config = sun4i_pwm_config,
256 	.set_polarity = sun4i_pwm_set_polarity,
257 	.enable = sun4i_pwm_enable,
258 	.disable = sun4i_pwm_disable,
259 	.owner = THIS_MODULE,
260 };
261 
262 static const struct sun4i_pwm_data sun4i_pwm_data_a10 = {
263 	.has_prescaler_bypass = false,
264 	.has_rdy = false,
265 };
266 
267 static const struct sun4i_pwm_data sun4i_pwm_data_a20 = {
268 	.has_prescaler_bypass = true,
269 	.has_rdy = true,
270 };
271 
272 static const struct of_device_id sun4i_pwm_dt_ids[] = {
273 	{
274 		.compatible = "allwinner,sun4i-a10-pwm",
275 		.data = &sun4i_pwm_data_a10,
276 	}, {
277 		.compatible = "allwinner,sun7i-a20-pwm",
278 		.data = &sun4i_pwm_data_a20,
279 	}, {
280 		/* sentinel */
281 	},
282 };
283 MODULE_DEVICE_TABLE(of, sun4i_pwm_dt_ids);
284 
285 static int sun4i_pwm_probe(struct platform_device *pdev)
286 {
287 	struct sun4i_pwm_chip *pwm;
288 	struct resource *res;
289 	u32 val;
290 	int i, ret;
291 	const struct of_device_id *match;
292 
293 	match = of_match_device(sun4i_pwm_dt_ids, &pdev->dev);
294 
295 	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
296 	if (!pwm)
297 		return -ENOMEM;
298 
299 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
300 	pwm->base = devm_ioremap_resource(&pdev->dev, res);
301 	if (IS_ERR(pwm->base))
302 		return PTR_ERR(pwm->base);
303 
304 	pwm->clk = devm_clk_get(&pdev->dev, NULL);
305 	if (IS_ERR(pwm->clk))
306 		return PTR_ERR(pwm->clk);
307 
308 	pwm->chip.dev = &pdev->dev;
309 	pwm->chip.ops = &sun4i_pwm_ops;
310 	pwm->chip.base = -1;
311 	pwm->chip.npwm = 2;
312 	pwm->chip.can_sleep = true;
313 	pwm->chip.of_xlate = of_pwm_xlate_with_flags;
314 	pwm->chip.of_pwm_n_cells = 3;
315 	pwm->data = match->data;
316 
317 	spin_lock_init(&pwm->ctrl_lock);
318 
319 	ret = pwmchip_add(&pwm->chip);
320 	if (ret < 0) {
321 		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
322 		return ret;
323 	}
324 
325 	platform_set_drvdata(pdev, pwm);
326 
327 	ret = clk_prepare_enable(pwm->clk);
328 	if (ret) {
329 		dev_err(&pdev->dev, "failed to enable PWM clock\n");
330 		goto clk_error;
331 	}
332 
333 	val = sun4i_pwm_readl(pwm, PWM_CTRL_REG);
334 	for (i = 0; i < pwm->chip.npwm; i++)
335 		if (!(val & BIT_CH(PWM_ACT_STATE, i)))
336 			pwm->chip.pwms[i].polarity = PWM_POLARITY_INVERSED;
337 	clk_disable_unprepare(pwm->clk);
338 
339 	return 0;
340 
341 clk_error:
342 	pwmchip_remove(&pwm->chip);
343 	return ret;
344 }
345 
346 static int sun4i_pwm_remove(struct platform_device *pdev)
347 {
348 	struct sun4i_pwm_chip *pwm = platform_get_drvdata(pdev);
349 
350 	return pwmchip_remove(&pwm->chip);
351 }
352 
353 static struct platform_driver sun4i_pwm_driver = {
354 	.driver = {
355 		.name = "sun4i-pwm",
356 		.of_match_table = sun4i_pwm_dt_ids,
357 	},
358 	.probe = sun4i_pwm_probe,
359 	.remove = sun4i_pwm_remove,
360 };
361 module_platform_driver(sun4i_pwm_driver);
362 
363 MODULE_ALIAS("platform:sun4i-pwm");
364 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
365 MODULE_DESCRIPTION("Allwinner sun4i PWM driver");
366 MODULE_LICENSE("GPL v2");
367