1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Generic software PWM for modulating GPIOs
4   *
5   * Copyright (C) 2020 Axis Communications AB
6   * Copyright (C) 2020 Nicola Di Lieto
7   * Copyright (C) 2024 Stefan Wahren
8   * Copyright (C) 2024 Linus Walleij
9   */
10  
11  #include <linux/cleanup.h>
12  #include <linux/container_of.h>
13  #include <linux/device.h>
14  #include <linux/err.h>
15  #include <linux/gpio/consumer.h>
16  #include <linux/hrtimer.h>
17  #include <linux/math.h>
18  #include <linux/module.h>
19  #include <linux/mod_devicetable.h>
20  #include <linux/platform_device.h>
21  #include <linux/property.h>
22  #include <linux/pwm.h>
23  #include <linux/spinlock.h>
24  #include <linux/time.h>
25  #include <linux/types.h>
26  
27  struct pwm_gpio {
28  	struct hrtimer gpio_timer;
29  	struct gpio_desc *gpio;
30  	struct pwm_state state;
31  	struct pwm_state next_state;
32  
33  	/* Protect internal state between pwm_ops and hrtimer */
34  	spinlock_t lock;
35  
36  	bool changing;
37  	bool running;
38  	bool level;
39  };
40  
pwm_gpio_round(struct pwm_state * dest,const struct pwm_state * src)41  static void pwm_gpio_round(struct pwm_state *dest, const struct pwm_state *src)
42  {
43  	u64 dividend;
44  	u32 remainder;
45  
46  	*dest = *src;
47  
48  	/* Round down to hrtimer resolution */
49  	dividend = dest->period;
50  	remainder = do_div(dividend, hrtimer_resolution);
51  	dest->period -= remainder;
52  
53  	dividend = dest->duty_cycle;
54  	remainder = do_div(dividend, hrtimer_resolution);
55  	dest->duty_cycle -= remainder;
56  }
57  
pwm_gpio_toggle(struct pwm_gpio * gpwm,bool level)58  static u64 pwm_gpio_toggle(struct pwm_gpio *gpwm, bool level)
59  {
60  	const struct pwm_state *state = &gpwm->state;
61  	bool invert = state->polarity == PWM_POLARITY_INVERSED;
62  
63  	gpwm->level = level;
64  	gpiod_set_value(gpwm->gpio, gpwm->level ^ invert);
65  
66  	if (!state->duty_cycle || state->duty_cycle == state->period) {
67  		gpwm->running = false;
68  		return 0;
69  	}
70  
71  	gpwm->running = true;
72  	return level ? state->duty_cycle : state->period - state->duty_cycle;
73  }
74  
pwm_gpio_timer(struct hrtimer * gpio_timer)75  static enum hrtimer_restart pwm_gpio_timer(struct hrtimer *gpio_timer)
76  {
77  	struct pwm_gpio *gpwm = container_of(gpio_timer, struct pwm_gpio,
78  					     gpio_timer);
79  	u64 next_toggle;
80  	bool new_level;
81  
82  	guard(spinlock_irqsave)(&gpwm->lock);
83  
84  	/* Apply new state at end of current period */
85  	if (!gpwm->level && gpwm->changing) {
86  		gpwm->changing = false;
87  		gpwm->state = gpwm->next_state;
88  		new_level = !!gpwm->state.duty_cycle;
89  	} else {
90  		new_level = !gpwm->level;
91  	}
92  
93  	next_toggle = pwm_gpio_toggle(gpwm, new_level);
94  	if (next_toggle)
95  		hrtimer_forward(gpio_timer, hrtimer_get_expires(gpio_timer),
96  				ns_to_ktime(next_toggle));
97  
98  	return next_toggle ? HRTIMER_RESTART : HRTIMER_NORESTART;
99  }
100  
pwm_gpio_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)101  static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm,
102  			  const struct pwm_state *state)
103  {
104  	struct pwm_gpio *gpwm = pwmchip_get_drvdata(chip);
105  	bool invert = state->polarity == PWM_POLARITY_INVERSED;
106  
107  	if (state->duty_cycle && state->duty_cycle < hrtimer_resolution)
108  		return -EINVAL;
109  
110  	if (state->duty_cycle != state->period &&
111  	    (state->period - state->duty_cycle < hrtimer_resolution))
112  		return -EINVAL;
113  
114  	if (!state->enabled) {
115  		hrtimer_cancel(&gpwm->gpio_timer);
116  	} else if (!gpwm->running) {
117  		int ret;
118  
119  		/*
120  		 * This just enables the output, but pwm_gpio_toggle()
121  		 * really starts the duty cycle.
122  		 */
123  		ret = gpiod_direction_output(gpwm->gpio, invert);
124  		if (ret)
125  			return ret;
126  	}
127  
128  	guard(spinlock_irqsave)(&gpwm->lock);
129  
130  	if (!state->enabled) {
131  		pwm_gpio_round(&gpwm->state, state);
132  		gpwm->running = false;
133  		gpwm->changing = false;
134  
135  		gpiod_set_value(gpwm->gpio, invert);
136  	} else if (gpwm->running) {
137  		pwm_gpio_round(&gpwm->next_state, state);
138  		gpwm->changing = true;
139  	} else {
140  		unsigned long next_toggle;
141  
142  		pwm_gpio_round(&gpwm->state, state);
143  		gpwm->changing = false;
144  
145  		next_toggle = pwm_gpio_toggle(gpwm, !!state->duty_cycle);
146  		if (next_toggle)
147  			hrtimer_start(&gpwm->gpio_timer, next_toggle,
148  				      HRTIMER_MODE_REL);
149  	}
150  
151  	return 0;
152  }
153  
pwm_gpio_get_state(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_state * state)154  static int pwm_gpio_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
155  			       struct pwm_state *state)
156  {
157  	struct pwm_gpio *gpwm = pwmchip_get_drvdata(chip);
158  
159  	guard(spinlock_irqsave)(&gpwm->lock);
160  
161  	if (gpwm->changing)
162  		*state = gpwm->next_state;
163  	else
164  		*state = gpwm->state;
165  
166  	return 0;
167  }
168  
169  static const struct pwm_ops pwm_gpio_ops = {
170  	.apply = pwm_gpio_apply,
171  	.get_state = pwm_gpio_get_state,
172  };
173  
pwm_gpio_disable_hrtimer(void * data)174  static void pwm_gpio_disable_hrtimer(void *data)
175  {
176  	struct pwm_gpio *gpwm = data;
177  
178  	hrtimer_cancel(&gpwm->gpio_timer);
179  }
180  
pwm_gpio_probe(struct platform_device * pdev)181  static int pwm_gpio_probe(struct platform_device *pdev)
182  {
183  	struct device *dev = &pdev->dev;
184  	struct pwm_chip *chip;
185  	struct pwm_gpio *gpwm;
186  	int ret;
187  
188  	chip = devm_pwmchip_alloc(dev, 1, sizeof(*gpwm));
189  	if (IS_ERR(chip))
190  		return PTR_ERR(chip);
191  
192  	gpwm = pwmchip_get_drvdata(chip);
193  
194  	spin_lock_init(&gpwm->lock);
195  
196  	gpwm->gpio = devm_gpiod_get(dev, NULL, GPIOD_ASIS);
197  	if (IS_ERR(gpwm->gpio))
198  		return dev_err_probe(dev, PTR_ERR(gpwm->gpio),
199  				     "%pfw: could not get gpio\n",
200  				     dev_fwnode(dev));
201  
202  	if (gpiod_cansleep(gpwm->gpio))
203  		return dev_err_probe(dev, -EINVAL,
204  				     "%pfw: sleeping GPIO not supported\n",
205  				     dev_fwnode(dev));
206  
207  	chip->ops = &pwm_gpio_ops;
208  	chip->atomic = true;
209  
210  	hrtimer_init(&gpwm->gpio_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
211  	ret = devm_add_action_or_reset(dev, pwm_gpio_disable_hrtimer, gpwm);
212  	if (ret)
213  		return ret;
214  
215  	gpwm->gpio_timer.function = pwm_gpio_timer;
216  
217  	ret = pwmchip_add(chip);
218  	if (ret < 0)
219  		return dev_err_probe(dev, ret, "could not add pwmchip\n");
220  
221  	return 0;
222  }
223  
224  static const struct of_device_id pwm_gpio_dt_ids[] = {
225  	{ .compatible = "pwm-gpio" },
226  	{ /* sentinel */ }
227  };
228  MODULE_DEVICE_TABLE(of, pwm_gpio_dt_ids);
229  
230  static struct platform_driver pwm_gpio_driver = {
231  	.driver = {
232  		.name = "pwm-gpio",
233  		.of_match_table = pwm_gpio_dt_ids,
234  	},
235  	.probe = pwm_gpio_probe,
236  };
237  module_platform_driver(pwm_gpio_driver);
238  
239  MODULE_DESCRIPTION("PWM GPIO driver");
240  MODULE_AUTHOR("Vincent Whitchurch");
241  MODULE_LICENSE("GPL");
242