Lines Matching +full:pwm +full:- +full:gpio
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Generic software PWM for modulating GPIOs
15 #include <linux/gpio/consumer.h>
22 #include <linux/pwm.h>
29 struct gpio_desc *gpio; member
49 dividend = dest->period; in pwm_gpio_round()
51 dest->period -= remainder; in pwm_gpio_round()
53 dividend = dest->duty_cycle; in pwm_gpio_round()
55 dest->duty_cycle -= remainder; in pwm_gpio_round()
60 const struct pwm_state *state = &gpwm->state; in pwm_gpio_toggle()
61 bool invert = state->polarity == PWM_POLARITY_INVERSED; in pwm_gpio_toggle()
63 gpwm->level = level; in pwm_gpio_toggle()
64 gpiod_set_value(gpwm->gpio, gpwm->level ^ invert); in pwm_gpio_toggle()
66 if (!state->duty_cycle || state->duty_cycle == state->period) { in pwm_gpio_toggle()
67 gpwm->running = false; in pwm_gpio_toggle()
71 gpwm->running = true; in pwm_gpio_toggle()
72 return level ? state->duty_cycle : state->period - state->duty_cycle; in pwm_gpio_toggle()
82 guard(spinlock_irqsave)(&gpwm->lock); in pwm_gpio_timer()
85 if (!gpwm->level && gpwm->changing) { in pwm_gpio_timer()
86 gpwm->changing = false; in pwm_gpio_timer()
87 gpwm->state = gpwm->next_state; in pwm_gpio_timer()
88 new_level = !!gpwm->state.duty_cycle; in pwm_gpio_timer()
90 new_level = !gpwm->level; in pwm_gpio_timer()
101 static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm, in pwm_gpio_apply() argument
105 bool invert = state->polarity == PWM_POLARITY_INVERSED; in pwm_gpio_apply()
107 if (state->duty_cycle && state->duty_cycle < hrtimer_resolution) in pwm_gpio_apply()
108 return -EINVAL; in pwm_gpio_apply()
110 if (state->duty_cycle != state->period && in pwm_gpio_apply()
111 (state->period - state->duty_cycle < hrtimer_resolution)) in pwm_gpio_apply()
112 return -EINVAL; in pwm_gpio_apply()
114 if (!state->enabled) { in pwm_gpio_apply()
115 hrtimer_cancel(&gpwm->gpio_timer); in pwm_gpio_apply()
116 } else if (!gpwm->running) { in pwm_gpio_apply()
123 ret = gpiod_direction_output(gpwm->gpio, invert); in pwm_gpio_apply()
128 guard(spinlock_irqsave)(&gpwm->lock); in pwm_gpio_apply()
130 if (!state->enabled) { in pwm_gpio_apply()
131 pwm_gpio_round(&gpwm->state, state); in pwm_gpio_apply()
132 gpwm->running = false; in pwm_gpio_apply()
133 gpwm->changing = false; in pwm_gpio_apply()
135 gpiod_set_value(gpwm->gpio, invert); in pwm_gpio_apply()
136 } else if (gpwm->running) { in pwm_gpio_apply()
137 pwm_gpio_round(&gpwm->next_state, state); in pwm_gpio_apply()
138 gpwm->changing = true; in pwm_gpio_apply()
142 pwm_gpio_round(&gpwm->state, state); in pwm_gpio_apply()
143 gpwm->changing = false; in pwm_gpio_apply()
145 next_toggle = pwm_gpio_toggle(gpwm, !!state->duty_cycle); in pwm_gpio_apply()
147 hrtimer_start(&gpwm->gpio_timer, next_toggle, in pwm_gpio_apply()
154 static int pwm_gpio_get_state(struct pwm_chip *chip, struct pwm_device *pwm, in pwm_gpio_get_state() argument
159 guard(spinlock_irqsave)(&gpwm->lock); in pwm_gpio_get_state()
161 if (gpwm->changing) in pwm_gpio_get_state()
162 *state = gpwm->next_state; in pwm_gpio_get_state()
164 *state = gpwm->state; in pwm_gpio_get_state()
178 hrtimer_cancel(&gpwm->gpio_timer); in pwm_gpio_disable_hrtimer()
183 struct device *dev = &pdev->dev; in pwm_gpio_probe()
194 spin_lock_init(&gpwm->lock); in pwm_gpio_probe()
196 gpwm->gpio = devm_gpiod_get(dev, NULL, GPIOD_ASIS); in pwm_gpio_probe()
197 if (IS_ERR(gpwm->gpio)) in pwm_gpio_probe()
198 return dev_err_probe(dev, PTR_ERR(gpwm->gpio), in pwm_gpio_probe()
199 "%pfw: could not get gpio\n", in pwm_gpio_probe()
202 if (gpiod_cansleep(gpwm->gpio)) in pwm_gpio_probe()
203 return dev_err_probe(dev, -EINVAL, in pwm_gpio_probe()
204 "%pfw: sleeping GPIO not supported\n", in pwm_gpio_probe()
207 chip->ops = &pwm_gpio_ops; in pwm_gpio_probe()
208 chip->atomic = true; in pwm_gpio_probe()
210 hrtimer_init(&gpwm->gpio_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); in pwm_gpio_probe()
215 gpwm->gpio_timer.function = pwm_gpio_timer; in pwm_gpio_probe()
225 { .compatible = "pwm-gpio" },
232 .name = "pwm-gpio",
239 MODULE_DESCRIPTION("PWM GPIO driver");