File Index
Files and directories
Sign in
FILE

pwm-lpc18xx-sct.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pwm/pwm-lpc18xx-sct.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * NXP LPC18xx State Configurable Timer - Pulse Width Modulator driver
  4 *
  5 * Copyright (c) 2015 Ariel D'Alessandro <ariel@vanguardiasur.com>
  6 *
  7 * Notes
  8 * =====
  9 * NXP LPC18xx provides a State Configurable Timer (SCT) which can be configured
 10 * as a Pulse Width Modulator.
 11 *
 12 * SCT supports 16 outputs, 16 events and 16 registers. Each event will be
 13 * triggered when its related register matches the SCT counter value, and it
 14 * will set or clear a selected output.
 15 *
 16 * One of the events is preselected to generate the period, thus the maximum
 17 * number of simultaneous channels is limited to 15. Notice that period is
 18 * global to all the channels, thus PWM driver will refuse setting different
 19 * values to it, unless there's only one channel requested.
 20 */
 21
 22#include <linux/clk.h>
 23#include <linux/err.h>
 24#include <linux/io.h>
 25#include <linux/mod_devicetable.h>
 26#include <linux/module.h>
 27#include <linux/platform_device.h>
 28#include <linux/pwm.h>
 29
 30/* LPC18xx SCT registers */
 31#define LPC18XX_PWM_CONFIG		0x000
 32#define LPC18XX_PWM_CONFIG_UNIFY	BIT(0)
 33#define LPC18XX_PWM_CONFIG_NORELOAD	BIT(7)
 34
 35#define LPC18XX_PWM_CTRL		0x004
 36#define LPC18XX_PWM_CTRL_HALT		BIT(2)
 37#define LPC18XX_PWM_BIDIR		BIT(4)
 38#define LPC18XX_PWM_PRE_SHIFT		5
 39#define LPC18XX_PWM_PRE_MASK		(0xff << LPC18XX_PWM_PRE_SHIFT)
 40#define LPC18XX_PWM_PRE(x)		(x << LPC18XX_PWM_PRE_SHIFT)
 41
 42#define LPC18XX_PWM_LIMIT		0x008
 43
 44#define LPC18XX_PWM_RES_BASE		0x058
 45#define LPC18XX_PWM_RES_SHIFT(_ch)	(_ch * 2)
 46#define LPC18XX_PWM_RES(_ch, _action)	(_action << LPC18XX_PWM_RES_SHIFT(_ch))
 47#define LPC18XX_PWM_RES_MASK(_ch)	(0x3 << LPC18XX_PWM_RES_SHIFT(_ch))
 48
 49#define LPC18XX_PWM_MATCH_BASE		0x100
 50#define LPC18XX_PWM_MATCH(_ch)		(LPC18XX_PWM_MATCH_BASE + _ch * 4)
 51
 52#define LPC18XX_PWM_MATCHREL_BASE	0x200
 53#define LPC18XX_PWM_MATCHREL(_ch)	(LPC18XX_PWM_MATCHREL_BASE + _ch * 4)
 54
 55#define LPC18XX_PWM_EVSTATEMSK_BASE	0x300
 56#define LPC18XX_PWM_EVSTATEMSK(_ch)	(LPC18XX_PWM_EVSTATEMSK_BASE + _ch * 8)
 57#define LPC18XX_PWM_EVSTATEMSK_ALL	0xffffffff
 58
 59#define LPC18XX_PWM_EVCTRL_BASE		0x304
 60#define LPC18XX_PWM_EVCTRL(_ev)		(LPC18XX_PWM_EVCTRL_BASE + _ev * 8)
 61
 62#define LPC18XX_PWM_EVCTRL_MATCH(_ch)	_ch
 63
 64#define LPC18XX_PWM_EVCTRL_COMB_SHIFT	12
 65#define LPC18XX_PWM_EVCTRL_COMB_MATCH	(0x1 << LPC18XX_PWM_EVCTRL_COMB_SHIFT)
 66
 67#define LPC18XX_PWM_OUTPUTSET_BASE	0x500
 68#define LPC18XX_PWM_OUTPUTSET(_ch)	(LPC18XX_PWM_OUTPUTSET_BASE + _ch * 8)
 69
 70#define LPC18XX_PWM_OUTPUTCL_BASE	0x504
 71#define LPC18XX_PWM_OUTPUTCL(_ch)	(LPC18XX_PWM_OUTPUTCL_BASE + _ch * 8)
 72
 73/* LPC18xx SCT unified counter */
 74#define LPC18XX_PWM_TIMER_MAX		0xffffffff
 75
 76/* LPC18xx SCT events */
 77#define LPC18XX_PWM_EVENT_PERIOD	0
 78#define LPC18XX_PWM_EVENT_MAX		16
 79
 80#define LPC18XX_NUM_PWMS		16
 81
 82/* SCT conflict resolution */
 83enum lpc18xx_pwm_res_action {
 84	LPC18XX_PWM_RES_NONE,
 85	LPC18XX_PWM_RES_SET,
 86	LPC18XX_PWM_RES_CLEAR,
 87	LPC18XX_PWM_RES_TOGGLE,
 88};
 89
 90struct lpc18xx_pwm_data {
 91	unsigned int duty_event;
 92};
 93
 94struct lpc18xx_pwm_chip {
 95	void __iomem *base;
 96	struct clk *pwm_clk;
 97	unsigned long clk_rate;
 98	unsigned int period_ns;
 99	unsigned int min_period_ns;
100	u64 max_period_ns;
101	unsigned int period_event;
102	unsigned long event_map;
103	struct lpc18xx_pwm_data channeldata[LPC18XX_NUM_PWMS];
104};
105
106static inline struct lpc18xx_pwm_chip *
107to_lpc18xx_pwm_chip(struct pwm_chip *chip)
108{
109	return pwmchip_get_drvdata(chip);
110}
111
112static inline void lpc18xx_pwm_writel(struct lpc18xx_pwm_chip *lpc18xx_pwm,
113				      u32 reg, u32 val)
114{
115	writel(val, lpc18xx_pwm->base + reg);
116}
117
118static inline u32 lpc18xx_pwm_readl(struct lpc18xx_pwm_chip *lpc18xx_pwm,
119				    u32 reg)
120{
121	return readl(lpc18xx_pwm->base + reg);
122}
123
124static void lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip *lpc18xx_pwm,
125					 struct pwm_device *pwm,
126					 enum lpc18xx_pwm_res_action action)
127{
128	u32 val;
129
130	/*
131	 * Simultaneous set and clear may happen on an output, that is the case
132	 * when duty_ns == period_ns. LPC18xx SCT allows to set a conflict
133	 * resolution action to be taken in such a case.
134	 */
135	val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_RES_BASE);
136	val &= ~LPC18XX_PWM_RES_MASK(pwm->hwpwm);
137	val |= LPC18XX_PWM_RES(pwm->hwpwm, action);
138	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_RES_BASE, val);
139}
140
141static void lpc18xx_pwm_config_period(struct pwm_chip *chip, u64 period_ns)
142{
143	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
144	u32 val;
145
146	/*
147	 * With clk_rate < NSEC_PER_SEC this cannot overflow.
148	 * With period_ns < max_period_ns this also fits into an u32.
149	 * As period_ns >= min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, lpc18xx_pwm->clk_rate);
150	 * we have val >= 1.
151	 */
152	val = mul_u64_u64_div_u64(period_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC);
153
154	lpc18xx_pwm_writel(lpc18xx_pwm,
155			   LPC18XX_PWM_MATCH(lpc18xx_pwm->period_event),
156			   val - 1);
157
158	lpc18xx_pwm_writel(lpc18xx_pwm,
159			   LPC18XX_PWM_MATCHREL(lpc18xx_pwm->period_event),
160			   val - 1);
161}
162
163static void lpc18xx_pwm_config_duty(struct pwm_chip *chip,
164				    struct pwm_device *pwm, u64 duty_ns)
165{
166	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
167	struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
168	u32 val;
169
170	/*
171	 * With clk_rate <= NSEC_PER_SEC this cannot overflow.
172	 * With duty_ns <= period_ns < max_period_ns this also fits into an u32.
173	 */
174	val = mul_u64_u64_div_u64(duty_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC);
175
176	lpc18xx_pwm_writel(lpc18xx_pwm,
177			   LPC18XX_PWM_MATCH(lpc18xx_data->duty_event),
178			   val);
179
180	lpc18xx_pwm_writel(lpc18xx_pwm,
181			   LPC18XX_PWM_MATCHREL(lpc18xx_data->duty_event),
182			   val);
183}
184
185static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
186			      int duty_ns, int period_ns)
187{
188	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
189	int requested_events;
190
191	if (period_ns < lpc18xx_pwm->min_period_ns ||
192	    period_ns > lpc18xx_pwm->max_period_ns) {
193		dev_err(pwmchip_parent(chip), "period %d not in range\n", period_ns);
194		return -ERANGE;
195	}
196
197	requested_events = bitmap_weight(&lpc18xx_pwm->event_map,
198					 LPC18XX_PWM_EVENT_MAX);
199
200	/*
201	 * The PWM supports only a single period for all PWM channels.
202	 * Once the period is set, it can only be changed if no more than one
203	 * channel is requested at that moment.
204	 */
205	if (requested_events > 2 && lpc18xx_pwm->period_ns != period_ns &&
206	    lpc18xx_pwm->period_ns) {
207		dev_err(pwmchip_parent(chip), "conflicting period requested for PWM %u\n",
208			pwm->hwpwm);
209		return -EBUSY;
210	}
211
212	if ((requested_events <= 2 && lpc18xx_pwm->period_ns != period_ns) ||
213	    !lpc18xx_pwm->period_ns) {
214		lpc18xx_pwm->period_ns = period_ns;
215		lpc18xx_pwm_config_period(chip, period_ns);
216	}
217
218	lpc18xx_pwm_config_duty(chip, pwm, duty_ns);
219
220	return 0;
221}
222
223static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, enum pwm_polarity polarity)
224{
225	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
226	struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
227	enum lpc18xx_pwm_res_action res_action;
228	unsigned int set_event, clear_event;
229
230	lpc18xx_pwm_writel(lpc18xx_pwm,
231			   LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event),
232			   LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_data->duty_event) |
233			   LPC18XX_PWM_EVCTRL_COMB_MATCH);
234
235	lpc18xx_pwm_writel(lpc18xx_pwm,
236			   LPC18XX_PWM_EVSTATEMSK(lpc18xx_data->duty_event),
237			   LPC18XX_PWM_EVSTATEMSK_ALL);
238
239	if (polarity == PWM_POLARITY_NORMAL) {
240		set_event = lpc18xx_pwm->period_event;
241		clear_event = lpc18xx_data->duty_event;
242		res_action = LPC18XX_PWM_RES_SET;
243	} else {
244		set_event = lpc18xx_data->duty_event;
245		clear_event = lpc18xx_pwm->period_event;
246		res_action = LPC18XX_PWM_RES_CLEAR;
247	}
248
249	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm),
250			   BIT(set_event));
251	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm),
252			   BIT(clear_event));
253	lpc18xx_pwm_set_conflict_res(lpc18xx_pwm, pwm, res_action);
254
255	return 0;
256}
257
258static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
259{
260	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
261	struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
262
263	lpc18xx_pwm_writel(lpc18xx_pwm,
264			   LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0);
265	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm), 0);
266	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm), 0);
267}
268
269static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
270{
271	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
272	struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
273	unsigned long event;
274
275	event = find_first_zero_bit(&lpc18xx_pwm->event_map,
276				    LPC18XX_PWM_EVENT_MAX);
277
278	if (event >= LPC18XX_PWM_EVENT_MAX) {
279		dev_err(pwmchip_parent(chip),
280			"maximum number of simultaneous channels reached\n");
281		return -EBUSY;
282	}
283
284	set_bit(event, &lpc18xx_pwm->event_map);
285	lpc18xx_data->duty_event = event;
286
287	return 0;
288}
289
290static void lpc18xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
291{
292	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
293	struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
294
295	clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map);
296}
297
298static int lpc18xx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
299			     const struct pwm_state *state)
300{
301	int err;
302	bool enabled = pwm->state.enabled;
303
304	if (state->polarity != pwm->state.polarity && pwm->state.enabled) {
305		lpc18xx_pwm_disable(chip, pwm);
306		enabled = false;
307	}
308
309	if (!state->enabled) {
310		if (enabled)
311			lpc18xx_pwm_disable(chip, pwm);
312
313		return 0;
314	}
315
316	err = lpc18xx_pwm_config(chip, pwm, state->duty_cycle, state->period);
317	if (err)
318		return err;
319
320	if (!enabled)
321		err = lpc18xx_pwm_enable(chip, pwm, state->polarity);
322
323	return err;
324}
325static const struct pwm_ops lpc18xx_pwm_ops = {
326	.apply = lpc18xx_pwm_apply,
327	.request = lpc18xx_pwm_request,
328	.free = lpc18xx_pwm_free,
329};
330
331static const struct of_device_id lpc18xx_pwm_of_match[] = {
332	{ .compatible = "nxp,lpc1850-sct-pwm" },
333	{}
334};
335MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match);
336
337static int lpc18xx_pwm_probe(struct platform_device *pdev)
338{
339	struct pwm_chip *chip;
340	struct lpc18xx_pwm_chip *lpc18xx_pwm;
341	int ret;
342	u64 val;
343
344	chip = devm_pwmchip_alloc(&pdev->dev, LPC18XX_NUM_PWMS, sizeof(*lpc18xx_pwm));
345	if (IS_ERR(chip))
346		return PTR_ERR(chip);
347	lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
348
349	lpc18xx_pwm->base = devm_platform_ioremap_resource(pdev, 0);
350	if (IS_ERR(lpc18xx_pwm->base))
351		return PTR_ERR(lpc18xx_pwm->base);
352
353	lpc18xx_pwm->pwm_clk = devm_clk_get_enabled(&pdev->dev, "pwm");
354	if (IS_ERR(lpc18xx_pwm->pwm_clk))
355		return dev_err_probe(&pdev->dev, PTR_ERR(lpc18xx_pwm->pwm_clk),
356				     "failed to get pwm clock\n");
357
358	lpc18xx_pwm->clk_rate = clk_get_rate(lpc18xx_pwm->pwm_clk);
359	if (!lpc18xx_pwm->clk_rate)
360		return dev_err_probe(&pdev->dev,
361				     -EINVAL, "pwm clock has no frequency\n");
362
363	/*
364	 * If clkrate is too fast, the calculations in .apply() might overflow.
365	 */
366	if (lpc18xx_pwm->clk_rate > NSEC_PER_SEC)
367		return dev_err_probe(&pdev->dev, -EINVAL, "pwm clock to fast\n");
368
369	lpc18xx_pwm->max_period_ns =
370		mul_u64_u64_div_u64(NSEC_PER_SEC, LPC18XX_PWM_TIMER_MAX, lpc18xx_pwm->clk_rate);
371
372	lpc18xx_pwm->min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC,
373						  lpc18xx_pwm->clk_rate);
374
375	chip->ops = &lpc18xx_pwm_ops;
376
377	/* SCT counter must be in unify (32 bit) mode */
378	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG,
379			   LPC18XX_PWM_CONFIG_UNIFY);
380
381	/*
382	 * Everytime the timer counter reaches the period value, the related
383	 * event will be triggered and the counter reset to 0.
384	 */
385	set_bit(LPC18XX_PWM_EVENT_PERIOD, &lpc18xx_pwm->event_map);
386	lpc18xx_pwm->period_event = LPC18XX_PWM_EVENT_PERIOD;
387
388	lpc18xx_pwm_writel(lpc18xx_pwm,
389			   LPC18XX_PWM_EVSTATEMSK(lpc18xx_pwm->period_event),
390			   LPC18XX_PWM_EVSTATEMSK_ALL);
391
392	val = LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_pwm->period_event) |
393	      LPC18XX_PWM_EVCTRL_COMB_MATCH;
394	lpc18xx_pwm_writel(lpc18xx_pwm,
395			   LPC18XX_PWM_EVCTRL(lpc18xx_pwm->period_event), val);
396
397	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT,
398			   BIT(lpc18xx_pwm->period_event));
399
400	val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
401	val &= ~LPC18XX_PWM_BIDIR;
402	val &= ~LPC18XX_PWM_CTRL_HALT;
403	val &= ~LPC18XX_PWM_PRE_MASK;
404	val |= LPC18XX_PWM_PRE(0);
405	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val);
406
407	ret = pwmchip_add(chip);
408	if (ret < 0)
409		return dev_err_probe(&pdev->dev, ret, "pwmchip_add failed\n");
410
411	platform_set_drvdata(pdev, chip);
412
413	return 0;
414}
415
416static void lpc18xx_pwm_remove(struct platform_device *pdev)
417{
418	struct pwm_chip *chip = platform_get_drvdata(pdev);
419	struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
420	u32 val;
421
422	pwmchip_remove(chip);
423
424	val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
425	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL,
426			   val | LPC18XX_PWM_CTRL_HALT);
427}
428
429static struct platform_driver lpc18xx_pwm_driver = {
430	.driver = {
431		.name = "lpc18xx-sct-pwm",
432		.of_match_table = lpc18xx_pwm_of_match,
433	},
434	.probe = lpc18xx_pwm_probe,
435	.remove = lpc18xx_pwm_remove,
436};
437module_platform_driver(lpc18xx_pwm_driver);
438
439MODULE_AUTHOR("Ariel D'Alessandro <ariel@vanguardiasur.com.ar>");
440MODULE_DESCRIPTION("NXP LPC18xx PWM driver");
441MODULE_LICENSE("GPL v2");
~/ Read-only file preview.