File Index
Files and directories
Sign in
FILE

pwm-tiehrpwm.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pwm/pwm-tiehrpwm.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * EHRPWM PWM driver
  4 *
  5 * Copyright (C) 2012 Texas Instruments, Inc. - https://www.ti.com/
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/platform_device.h>
 10#include <linux/pwm.h>
 11#include <linux/io.h>
 12#include <linux/err.h>
 13#include <linux/clk.h>
 14#include <linux/pm_runtime.h>
 15#include <linux/of.h>
 16
 17/* EHRPWM registers and bits definitions */
 18
 19/* Time base module registers */
 20#define TBCTL			0x00
 21#define TBPRD			0x0A
 22
 23#define TBCTL_PRDLD_MASK	BIT(3)
 24#define TBCTL_PRDLD_SHDW	0
 25#define TBCTL_PRDLD_IMDT	BIT(3)
 26#define TBCTL_CLKDIV_MASK	(BIT(12) | BIT(11) | BIT(10) | BIT(9) | \
 27				BIT(8) | BIT(7))
 28#define TBCTL_CTRMODE_MASK	(BIT(1) | BIT(0))
 29#define TBCTL_CTRMODE_UP	0
 30#define TBCTL_CTRMODE_DOWN	BIT(0)
 31#define TBCTL_CTRMODE_UPDOWN	BIT(1)
 32#define TBCTL_CTRMODE_FREEZE	(BIT(1) | BIT(0))
 33
 34#define TBCTL_HSPCLKDIV_SHIFT	7
 35#define TBCTL_CLKDIV_SHIFT	10
 36
 37#define CLKDIV_MAX		7
 38#define HSPCLKDIV_MAX		7
 39#define PERIOD_MAX		0x10000
 40
 41/* compare module registers */
 42#define CMPA			0x12
 43#define CMPB			0x14
 44
 45/* Action qualifier module registers */
 46#define AQCTLA			0x16
 47#define AQCTLB			0x18
 48#define AQSFRC			0x1A
 49#define AQCSFRC			0x1C
 50
 51#define AQCTL_CBU_MASK		(BIT(9) | BIT(8))
 52#define AQCTL_CBU_FRCLOW	BIT(8)
 53#define AQCTL_CBU_FRCHIGH	BIT(9)
 54#define AQCTL_CBU_FRCTOGGLE	(BIT(9) | BIT(8))
 55#define AQCTL_CAU_MASK		(BIT(5) | BIT(4))
 56#define AQCTL_CAU_FRCLOW	BIT(4)
 57#define AQCTL_CAU_FRCHIGH	BIT(5)
 58#define AQCTL_CAU_FRCTOGGLE	(BIT(5) | BIT(4))
 59#define AQCTL_PRD_MASK		(BIT(3) | BIT(2))
 60#define AQCTL_PRD_FRCLOW	BIT(2)
 61#define AQCTL_PRD_FRCHIGH	BIT(3)
 62#define AQCTL_PRD_FRCTOGGLE	(BIT(3) | BIT(2))
 63#define AQCTL_ZRO_MASK		(BIT(1) | BIT(0))
 64#define AQCTL_ZRO_FRCLOW	BIT(0)
 65#define AQCTL_ZRO_FRCHIGH	BIT(1)
 66#define AQCTL_ZRO_FRCTOGGLE	(BIT(1) | BIT(0))
 67
 68#define AQCTL_CHANA_POLNORMAL	(AQCTL_CAU_FRCLOW | AQCTL_ZRO_FRCHIGH)
 69#define AQCTL_CHANA_POLINVERSED	(AQCTL_CAU_FRCHIGH | AQCTL_ZRO_FRCLOW)
 70#define AQCTL_CHANB_POLNORMAL	(AQCTL_CBU_FRCLOW | AQCTL_ZRO_FRCHIGH)
 71#define AQCTL_CHANB_POLINVERSED	(AQCTL_CBU_FRCHIGH | AQCTL_ZRO_FRCLOW)
 72
 73#define AQSFRC_RLDCSF_MASK	(BIT(7) | BIT(6))
 74#define AQSFRC_RLDCSF_ZRO	0
 75#define AQSFRC_RLDCSF_PRD	BIT(6)
 76#define AQSFRC_RLDCSF_ZROPRD	BIT(7)
 77#define AQSFRC_RLDCSF_IMDT	(BIT(7) | BIT(6))
 78
 79#define AQCSFRC_CSFB_MASK	(BIT(3) | BIT(2))
 80#define AQCSFRC_CSFB_FRCDIS	0
 81#define AQCSFRC_CSFB_FRCLOW	BIT(2)
 82#define AQCSFRC_CSFB_FRCHIGH	BIT(3)
 83#define AQCSFRC_CSFB_DISSWFRC	(BIT(3) | BIT(2))
 84#define AQCSFRC_CSFA_MASK	(BIT(1) | BIT(0))
 85#define AQCSFRC_CSFA_FRCDIS	0
 86#define AQCSFRC_CSFA_FRCLOW	BIT(0)
 87#define AQCSFRC_CSFA_FRCHIGH	BIT(1)
 88#define AQCSFRC_CSFA_DISSWFRC	(BIT(1) | BIT(0))
 89
 90#define NUM_PWM_CHANNEL		2	/* EHRPWM channels */
 91
 92struct ehrpwm_context {
 93	u16 tbctl;
 94	u16 tbprd;
 95	u16 cmpa;
 96	u16 cmpb;
 97	u16 aqctla;
 98	u16 aqctlb;
 99	u16 aqsfrc;
100	u16 aqcsfrc;
101};
102
103struct ehrpwm_pwm_chip {
104	unsigned long clk_rate;
105	void __iomem *mmio_base;
106	unsigned long period_cycles[NUM_PWM_CHANNEL];
107	struct clk *tbclk;
108	struct ehrpwm_context ctx;
109};
110
111static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
112{
113	return pwmchip_get_drvdata(chip);
114}
115
116static inline u16 ehrpwm_read(void __iomem *base, unsigned int offset)
117{
118	return readw(base + offset);
119}
120
121static inline void ehrpwm_write(void __iomem *base, unsigned int offset,
122				u16 value)
123{
124	writew(value, base + offset);
125}
126
127static void ehrpwm_modify(void __iomem *base, unsigned int offset, u16 mask,
128			  u16 value)
129{
130	unsigned short val;
131
132	val = readw(base + offset);
133	val &= ~mask;
134	val |= value & mask;
135	writew(val, base + offset);
136}
137
138/**
139 * set_prescale_div -	Set up the prescaler divider function
140 * @rqst_prescaler:	prescaler value min
141 * @prescale_div:	prescaler value set
142 * @tb_clk_div:		Time Base Control prescaler bits
143 */
144static int set_prescale_div(unsigned long rqst_prescaler, u16 *prescale_div,
145			    u16 *tb_clk_div)
146{
147	unsigned int clkdiv, hspclkdiv;
148
149	for (clkdiv = 0; clkdiv <= CLKDIV_MAX; clkdiv++) {
150		for (hspclkdiv = 0; hspclkdiv <= HSPCLKDIV_MAX; hspclkdiv++) {
151			/*
152			 * calculations for prescaler value :
153			 * prescale_div = HSPCLKDIVIDER * CLKDIVIDER.
154			 * HSPCLKDIVIDER =  2 ** hspclkdiv
155			 * CLKDIVIDER = (1),		if clkdiv == 0 *OR*
156			 *		(2 * clkdiv),	if clkdiv != 0
157			 *
158			 * Configure prescale_div value such that period
159			 * register value is less than 65535.
160			 */
161
162			*prescale_div = (1 << clkdiv) *
163					(hspclkdiv ? (hspclkdiv * 2) : 1);
164			if (*prescale_div >= rqst_prescaler) {
165				*tb_clk_div = (clkdiv << TBCTL_CLKDIV_SHIFT) |
166					(hspclkdiv << TBCTL_HSPCLKDIV_SHIFT);
167				return 0;
168			}
169		}
170	}
171
172	return 1;
173}
174
175/*
176 * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE
177 * duty_ns   = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE
178 */
179static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
180			     u64 duty_ns, u64 period_ns, enum pwm_polarity polarity)
181{
182	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
183	u32 period_cycles, duty_cycles;
184	u16 ps_divval, tb_divval;
185	unsigned int i, cmp_reg;
186	unsigned long long c;
187	u16 aqctl_val, aqctl_mask;
188	unsigned int aqctl_reg;
189
190	if (period_ns > NSEC_PER_SEC)
191		return -ERANGE;
192
193	c = pc->clk_rate;
194	c = c * period_ns;
195	do_div(c, NSEC_PER_SEC);
196	period_cycles = (unsigned long)c;
197
198	c = pc->clk_rate;
199	c = c * duty_ns;
200	do_div(c, NSEC_PER_SEC);
201	duty_cycles = (unsigned long)c;
202
203	/*
204	 * Period values should be same for multiple PWM channels as IP uses
205	 * same period register for multiple channels.
206	 */
207	for (i = 0; i < NUM_PWM_CHANNEL; i++) {
208		if (pc->period_cycles[i] &&
209				(pc->period_cycles[i] != period_cycles)) {
210			/*
211			 * Allow channel to reconfigure period if no other
212			 * channels being configured.
213			 */
214			if (i == pwm->hwpwm)
215				continue;
216
217			dev_err(pwmchip_parent(chip),
218				"period value conflicts with channel %u\n",
219				i);
220			return -EINVAL;
221		}
222	}
223
224	pc->period_cycles[pwm->hwpwm] = period_cycles;
225
226	/* Configure clock prescaler to support Low frequency PWM wave */
227	if (set_prescale_div(DIV_ROUND_UP(period_cycles, PERIOD_MAX), &ps_divval,
228			     &tb_divval)) {
229		dev_err(pwmchip_parent(chip), "Unsupported values\n");
230		return -EINVAL;
231	}
232
233	/* Update period & duty cycle with presacler division */
234	period_cycles = period_cycles / ps_divval;
235	duty_cycles = duty_cycles / ps_divval;
236
237	if (period_cycles < 1)
238		period_cycles = 1;
239
240	/* Update clock prescaler values */
241	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval);
242
243	if (pwm->hwpwm == 1) {
244		/* Channel 1 configured with compare B register */
245		cmp_reg = CMPB;
246
247		aqctl_reg = AQCTLB;
248		aqctl_mask = AQCTL_CBU_MASK;
249
250		if (polarity == PWM_POLARITY_INVERSED)
251			aqctl_val = AQCTL_CHANB_POLINVERSED;
252		else
253			aqctl_val = AQCTL_CHANB_POLNORMAL;
254
255		/* if duty_cycle is big, don't toggle on CBU */
256		if (duty_cycles > period_cycles)
257			aqctl_val &= ~AQCTL_CBU_MASK;
258
259	} else {
260		/* Channel 0 configured with compare A register */
261		cmp_reg = CMPA;
262
263		aqctl_reg = AQCTLA;
264		aqctl_mask = AQCTL_CAU_MASK;
265
266		if (polarity == PWM_POLARITY_INVERSED)
267			aqctl_val = AQCTL_CHANA_POLINVERSED;
268		else
269			aqctl_val = AQCTL_CHANA_POLNORMAL;
270
271		/* if duty_cycle is big, don't toggle on CAU */
272		if (duty_cycles > period_cycles)
273			aqctl_val &= ~AQCTL_CAU_MASK;
274	}
275
276	aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
277	ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
278
279	/* Configure shadow loading on Period register */
280	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW);
281
282	ehrpwm_write(pc->mmio_base, TBPRD, period_cycles - 1);
283
284	/* Configure ehrpwm counter for up-count mode */
285	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
286		      TBCTL_CTRMODE_UP);
287
288	if (!(duty_cycles > period_cycles))
289		ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
290
291	return 0;
292}
293
294static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
295{
296	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
297	u16 aqcsfrc_val, aqcsfrc_mask;
298	int ret;
299
300	/* Leave clock enabled on enabling PWM */
301	pm_runtime_get_sync(pwmchip_parent(chip));
302
303	/* Disabling Action Qualifier on PWM output */
304	if (pwm->hwpwm) {
305		aqcsfrc_val = AQCSFRC_CSFB_FRCDIS;
306		aqcsfrc_mask = AQCSFRC_CSFB_MASK;
307	} else {
308		aqcsfrc_val = AQCSFRC_CSFA_FRCDIS;
309		aqcsfrc_mask = AQCSFRC_CSFA_MASK;
310	}
311
312	/* Changes to shadow mode */
313	ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
314		      AQSFRC_RLDCSF_ZRO);
315
316	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
317
318	/* Enable TBCLK */
319	ret = clk_enable(pc->tbclk);
320	if (ret) {
321		dev_err(pwmchip_parent(chip), "Failed to enable TBCLK for %s: %d\n",
322			dev_name(pwmchip_parent(chip)), ret);
323		return ret;
324	}
325
326	return 0;
327}
328
329static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
330{
331	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
332	u16 aqcsfrc_val, aqcsfrc_mask;
333
334	/* Action Qualifier puts PWM output low forcefully */
335	if (pwm->hwpwm) {
336		aqcsfrc_val = AQCSFRC_CSFB_FRCLOW;
337		aqcsfrc_mask = AQCSFRC_CSFB_MASK;
338	} else {
339		aqcsfrc_val = AQCSFRC_CSFA_FRCLOW;
340		aqcsfrc_mask = AQCSFRC_CSFA_MASK;
341	}
342
343	/* Update shadow register first before modifying active register */
344	ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
345		      AQSFRC_RLDCSF_ZRO);
346	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
347	/*
348	 * Changes to immediate action on Action Qualifier. This puts
349	 * Action Qualifier control on PWM output from next TBCLK
350	 */
351	ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
352		      AQSFRC_RLDCSF_IMDT);
353
354	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
355
356	/* Disabling TBCLK on PWM disable */
357	clk_disable(pc->tbclk);
358
359	/* Disable clock on PWM disable */
360	pm_runtime_put_sync(pwmchip_parent(chip));
361}
362
363static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
364{
365	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
366
367	/* Don't let a pwm without consumer block requests to the other channel */
368	pc->period_cycles[pwm->hwpwm] = 0;
369}
370
371static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
372			    const struct pwm_state *state)
373{
374	int err;
375	bool enabled = pwm->state.enabled;
376
377	guard(pm_runtime_active)(pwmchip_parent(chip));
378
379	if (state->polarity != pwm->state.polarity) {
380		if (enabled) {
381			ehrpwm_pwm_disable(chip, pwm);
382			enabled = false;
383		}
384	}
385
386	if (!state->enabled) {
387		if (enabled)
388			ehrpwm_pwm_disable(chip, pwm);
389		return 0;
390	}
391
392	err = ehrpwm_pwm_config(chip, pwm, state->duty_cycle, state->period, state->polarity);
393	if (err)
394		return err;
395
396	if (!enabled)
397		err = ehrpwm_pwm_enable(chip, pwm);
398
399	return err;
400}
401
402static const struct pwm_ops ehrpwm_pwm_ops = {
403	.free = ehrpwm_pwm_free,
404	.apply = ehrpwm_pwm_apply,
405};
406
407static const struct of_device_id ehrpwm_of_match[] = {
408	{ .compatible = "ti,am3352-ehrpwm" },
409	{ .compatible = "ti,am33xx-ehrpwm" },
410	{},
411};
412MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
413
414static int ehrpwm_pwm_probe(struct platform_device *pdev)
415{
416	struct device_node *np = pdev->dev.of_node;
417	struct ehrpwm_pwm_chip *pc;
418	struct pwm_chip *chip;
419	struct clk *clk;
420	int ret;
421
422	chip = devm_pwmchip_alloc(&pdev->dev, NUM_PWM_CHANNEL, sizeof(*pc));
423	if (IS_ERR(chip))
424		return PTR_ERR(chip);
425	pc = to_ehrpwm_pwm_chip(chip);
426
427	clk = devm_clk_get(&pdev->dev, "fck");
428	if (IS_ERR(clk)) {
429		if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
430			dev_warn(&pdev->dev, "Binding is obsolete.\n");
431			clk = devm_clk_get(pdev->dev.parent, "fck");
432		}
433	}
434
435	if (IS_ERR(clk))
436		return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Failed to get fck\n");
437
438	pc->clk_rate = clk_get_rate(clk);
439	if (!pc->clk_rate) {
440		dev_err(&pdev->dev, "failed to get clock rate\n");
441		return -EINVAL;
442	}
443
444	chip->ops = &ehrpwm_pwm_ops;
445
446	pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
447	if (IS_ERR(pc->mmio_base))
448		return PTR_ERR(pc->mmio_base);
449
450	/* Acquire tbclk for Time Base EHRPWM submodule */
451	pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
452	if (IS_ERR(pc->tbclk))
453		return dev_err_probe(&pdev->dev, PTR_ERR(pc->tbclk), "Failed to get tbclk\n");
454
455	ret = clk_prepare(pc->tbclk);
456	if (ret < 0) {
457		dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret);
458		return ret;
459	}
460
461	ret = pwmchip_add(chip);
462	if (ret < 0) {
463		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
464		goto err_clk_unprepare;
465	}
466
467	platform_set_drvdata(pdev, chip);
468	pm_runtime_enable(&pdev->dev);
469
470	return 0;
471
472err_clk_unprepare:
473	clk_unprepare(pc->tbclk);
474
475	return ret;
476}
477
478static void ehrpwm_pwm_remove(struct platform_device *pdev)
479{
480	struct pwm_chip *chip = platform_get_drvdata(pdev);
481	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
482
483	pwmchip_remove(chip);
484
485	clk_unprepare(pc->tbclk);
486
487	pm_runtime_disable(&pdev->dev);
488}
489
490static void ehrpwm_pwm_save_context(struct pwm_chip *chip)
491{
492	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
493
494	pm_runtime_get_sync(pwmchip_parent(chip));
495
496	pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL);
497	pc->ctx.tbprd = ehrpwm_read(pc->mmio_base, TBPRD);
498	pc->ctx.cmpa = ehrpwm_read(pc->mmio_base, CMPA);
499	pc->ctx.cmpb = ehrpwm_read(pc->mmio_base, CMPB);
500	pc->ctx.aqctla = ehrpwm_read(pc->mmio_base, AQCTLA);
501	pc->ctx.aqctlb = ehrpwm_read(pc->mmio_base, AQCTLB);
502	pc->ctx.aqsfrc = ehrpwm_read(pc->mmio_base, AQSFRC);
503	pc->ctx.aqcsfrc = ehrpwm_read(pc->mmio_base, AQCSFRC);
504
505	pm_runtime_put_sync(pwmchip_parent(chip));
506}
507
508static void ehrpwm_pwm_restore_context(struct pwm_chip *chip)
509{
510	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
511
512	ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd);
513	ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa);
514	ehrpwm_write(pc->mmio_base, CMPB, pc->ctx.cmpb);
515	ehrpwm_write(pc->mmio_base, AQCTLA, pc->ctx.aqctla);
516	ehrpwm_write(pc->mmio_base, AQCTLB, pc->ctx.aqctlb);
517	ehrpwm_write(pc->mmio_base, AQSFRC, pc->ctx.aqsfrc);
518	ehrpwm_write(pc->mmio_base, AQCSFRC, pc->ctx.aqcsfrc);
519	ehrpwm_write(pc->mmio_base, TBCTL, pc->ctx.tbctl);
520}
521
522static int ehrpwm_pwm_suspend(struct device *dev)
523{
524	struct pwm_chip *chip = dev_get_drvdata(dev);
525	unsigned int i;
526
527	ehrpwm_pwm_save_context(chip);
528
529	for (i = 0; i < chip->npwm; i++) {
530		struct pwm_device *pwm = &chip->pwms[i];
531
532		if (!pwm_is_enabled(pwm))
533			continue;
534
535		/* Disable explicitly if PWM is running */
536		pm_runtime_put_sync(dev);
537	}
538
539	return 0;
540}
541
542static int ehrpwm_pwm_resume(struct device *dev)
543{
544	struct pwm_chip *chip = dev_get_drvdata(dev);
545	unsigned int i;
546
547	for (i = 0; i < chip->npwm; i++) {
548		struct pwm_device *pwm = &chip->pwms[i];
549
550		if (!pwm_is_enabled(pwm))
551			continue;
552
553		/* Enable explicitly if PWM was running */
554		pm_runtime_get_sync(dev);
555	}
556
557	ehrpwm_pwm_restore_context(chip);
558
559	return 0;
560}
561
562static DEFINE_SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
563				ehrpwm_pwm_resume);
564
565static struct platform_driver ehrpwm_pwm_driver = {
566	.driver = {
567		.name = "ehrpwm",
568		.of_match_table = ehrpwm_of_match,
569		.pm = pm_ptr(&ehrpwm_pwm_pm_ops),
570	},
571	.probe = ehrpwm_pwm_probe,
572	.remove = ehrpwm_pwm_remove,
573};
574module_platform_driver(ehrpwm_pwm_driver);
575
576MODULE_DESCRIPTION("EHRPWM PWM driver");
577MODULE_AUTHOR("Texas Instruments");
578MODULE_LICENSE("GPL");
~/ Read-only file preview.