1 // SPDX-License-Identifier: GPL-2.0-only
3 * Generic software PWM for modulating GPIOs
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
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>
28 struct hrtimer gpio_timer
;
29 struct gpio_desc
*gpio
;
30 struct pwm_state state
;
31 struct pwm_state next_state
;
33 /* Protect internal state between pwm_ops and hrtimer */
41 static void pwm_gpio_round(struct pwm_state
*dest
, const struct pwm_state
*src
)
48 /* Round down to hrtimer resolution */
49 dividend
= dest
->period
;
50 remainder
= do_div(dividend
, hrtimer_resolution
);
51 dest
->period
-= remainder
;
53 dividend
= dest
->duty_cycle
;
54 remainder
= do_div(dividend
, hrtimer_resolution
);
55 dest
->duty_cycle
-= remainder
;
58 static u64
pwm_gpio_toggle(struct pwm_gpio
*gpwm
, bool level
)
60 const struct pwm_state
*state
= &gpwm
->state
;
61 bool invert
= state
->polarity
== PWM_POLARITY_INVERSED
;
64 gpiod_set_value(gpwm
->gpio
, gpwm
->level
^ invert
);
66 if (!state
->duty_cycle
|| state
->duty_cycle
== state
->period
) {
67 gpwm
->running
= false;
72 return level
? state
->duty_cycle
: state
->period
- state
->duty_cycle
;
75 static enum hrtimer_restart
pwm_gpio_timer(struct hrtimer
*gpio_timer
)
77 struct pwm_gpio
*gpwm
= container_of(gpio_timer
, struct pwm_gpio
,
82 guard(spinlock_irqsave
)(&gpwm
->lock
);
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
;
90 new_level
= !gpwm
->level
;
93 next_toggle
= pwm_gpio_toggle(gpwm
, new_level
);
95 hrtimer_forward(gpio_timer
, hrtimer_get_expires(gpio_timer
),
96 ns_to_ktime(next_toggle
));
98 return next_toggle
? HRTIMER_RESTART
: HRTIMER_NORESTART
;
101 static int pwm_gpio_apply(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
102 const struct pwm_state
*state
)
104 struct pwm_gpio
*gpwm
= pwmchip_get_drvdata(chip
);
105 bool invert
= state
->polarity
== PWM_POLARITY_INVERSED
;
107 if (state
->duty_cycle
&& state
->duty_cycle
< hrtimer_resolution
)
110 if (state
->duty_cycle
!= state
->period
&&
111 (state
->period
- state
->duty_cycle
< hrtimer_resolution
))
114 if (!state
->enabled
) {
115 hrtimer_cancel(&gpwm
->gpio_timer
);
116 } else if (!gpwm
->running
) {
120 * This just enables the output, but pwm_gpio_toggle()
121 * really starts the duty cycle.
123 ret
= gpiod_direction_output(gpwm
->gpio
, invert
);
128 guard(spinlock_irqsave
)(&gpwm
->lock
);
130 if (!state
->enabled
) {
131 pwm_gpio_round(&gpwm
->state
, state
);
132 gpwm
->running
= false;
133 gpwm
->changing
= false;
135 gpiod_set_value(gpwm
->gpio
, invert
);
136 } else if (gpwm
->running
) {
137 pwm_gpio_round(&gpwm
->next_state
, state
);
138 gpwm
->changing
= true;
140 unsigned long next_toggle
;
142 pwm_gpio_round(&gpwm
->state
, state
);
143 gpwm
->changing
= false;
145 next_toggle
= pwm_gpio_toggle(gpwm
, !!state
->duty_cycle
);
147 hrtimer_start(&gpwm
->gpio_timer
, next_toggle
,
154 static int pwm_gpio_get_state(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
155 struct pwm_state
*state
)
157 struct pwm_gpio
*gpwm
= pwmchip_get_drvdata(chip
);
159 guard(spinlock_irqsave
)(&gpwm
->lock
);
162 *state
= gpwm
->next_state
;
164 *state
= gpwm
->state
;
169 static const struct pwm_ops pwm_gpio_ops
= {
170 .apply
= pwm_gpio_apply
,
171 .get_state
= pwm_gpio_get_state
,
174 static void pwm_gpio_disable_hrtimer(void *data
)
176 struct pwm_gpio
*gpwm
= data
;
178 hrtimer_cancel(&gpwm
->gpio_timer
);
181 static int pwm_gpio_probe(struct platform_device
*pdev
)
183 struct device
*dev
= &pdev
->dev
;
184 struct pwm_chip
*chip
;
185 struct pwm_gpio
*gpwm
;
188 chip
= devm_pwmchip_alloc(dev
, 1, sizeof(*gpwm
));
190 return PTR_ERR(chip
);
192 gpwm
= pwmchip_get_drvdata(chip
);
194 spin_lock_init(&gpwm
->lock
);
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",
202 if (gpiod_cansleep(gpwm
->gpio
))
203 return dev_err_probe(dev
, -EINVAL
,
204 "%pfw: sleeping GPIO not supported\n",
207 chip
->ops
= &pwm_gpio_ops
;
210 hrtimer_init(&gpwm
->gpio_timer
, CLOCK_MONOTONIC
, HRTIMER_MODE_REL
);
211 ret
= devm_add_action_or_reset(dev
, pwm_gpio_disable_hrtimer
, gpwm
);
215 gpwm
->gpio_timer
.function
= pwm_gpio_timer
;
217 ret
= pwmchip_add(chip
);
219 return dev_err_probe(dev
, ret
, "could not add pwmchip\n");
224 static const struct of_device_id pwm_gpio_dt_ids
[] = {
225 { .compatible
= "pwm-gpio" },
228 MODULE_DEVICE_TABLE(of
, pwm_gpio_dt_ids
);
230 static struct platform_driver pwm_gpio_driver
= {
233 .of_match_table
= pwm_gpio_dt_ids
,
235 .probe
= pwm_gpio_probe
,
237 module_platform_driver(pwm_gpio_driver
);
239 MODULE_DESCRIPTION("PWM GPIO driver");
240 MODULE_AUTHOR("Vincent Whitchurch");
241 MODULE_LICENSE("GPL");