Lines Matching +full:timer +full:- +full:pwm
1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas RZ/G2L General PWM Timer (GPT) driver
8 …* https://www.renesas.com/eu/en/document/mah/rzg2l-group-rzg2lc-group-users-manual-hardware-0?lang…
11 * - Counter must be stopped before modifying Mode and Prescaler.
12 * - When PWM is disabled, the output is driven to inactive.
13 * - While the hardware supports both polarities, the driver (for now)
15 * - General PWM Timer (GPT) has 8 HW channels for PWM operations and
17 * - Each IO is modelled as an independent PWM channel.
18 * - When both channels are used, disabling the channel on one stops the
20 * - When both channels are used, the period of both IOs in the HW channel
31 #include <linux/pwm.h>
101 writel(data, rzg2l_gpt->mmio + reg); in rzg2l_gpt_write()
106 return readl(rzg2l_gpt->mmio + reg); in rzg2l_gpt_read()
131 static int rzg2l_gpt_request(struct pwm_chip *chip, struct pwm_device *pwm) in rzg2l_gpt_request() argument
134 u32 ch = RZG2L_GET_CH(pwm->hwpwm); in rzg2l_gpt_request()
136 guard(mutex)(&rzg2l_gpt->lock); in rzg2l_gpt_request()
137 rzg2l_gpt->channel_request_count[ch]++; in rzg2l_gpt_request()
142 static void rzg2l_gpt_free(struct pwm_chip *chip, struct pwm_device *pwm) in rzg2l_gpt_free() argument
145 u32 ch = RZG2L_GET_CH(pwm->hwpwm); in rzg2l_gpt_free()
147 guard(mutex)(&rzg2l_gpt->lock); in rzg2l_gpt_free()
148 rzg2l_gpt->channel_request_count[ch]--; in rzg2l_gpt_free()
167 struct pwm_device *pwm) in rzg2l_gpt_enable() argument
169 u8 sub_ch = rzg2l_gpt_subchannel(pwm->hwpwm); in rzg2l_gpt_enable()
171 u8 ch = RZG2L_GET_CH(pwm->hwpwm); in rzg2l_gpt_enable()
177 if (!rzg2l_gpt->channel_enable_count[ch]) in rzg2l_gpt_enable()
180 rzg2l_gpt->channel_enable_count[ch]++; in rzg2l_gpt_enable()
185 struct pwm_device *pwm) in rzg2l_gpt_disable() argument
187 u8 sub_ch = rzg2l_gpt_subchannel(pwm->hwpwm); in rzg2l_gpt_disable()
188 u8 ch = RZG2L_GET_CH(pwm->hwpwm); in rzg2l_gpt_disable()
191 rzg2l_gpt->channel_enable_count[ch]--; in rzg2l_gpt_disable()
193 if (!rzg2l_gpt->channel_enable_count[ch]) in rzg2l_gpt_disable()
215 return DIV64_U64_ROUND_UP(tmp, rzg2l_gpt->rate_khz); in rzg2l_gpt_calculate_period_or_duty()
218 static int rzg2l_gpt_get_state(struct pwm_chip *chip, struct pwm_device *pwm, in rzg2l_gpt_get_state() argument
223 state->enabled = rzg2l_gpt_is_ch_enabled(rzg2l_gpt, pwm->hwpwm); in rzg2l_gpt_get_state()
224 if (state->enabled) { in rzg2l_gpt_get_state()
225 u32 sub_ch = rzg2l_gpt_subchannel(pwm->hwpwm); in rzg2l_gpt_get_state()
226 u32 ch = RZG2L_GET_CH(pwm->hwpwm); in rzg2l_gpt_get_state()
234 state->period = rzg2l_gpt_calculate_period_or_duty(rzg2l_gpt, val, prescale); in rzg2l_gpt_get_state()
237 state->duty_cycle = rzg2l_gpt_calculate_period_or_duty(rzg2l_gpt, val, prescale); in rzg2l_gpt_get_state()
238 if (state->duty_cycle > state->period) in rzg2l_gpt_get_state()
239 state->duty_cycle = state->period; in rzg2l_gpt_get_state()
242 state->polarity = PWM_POLARITY_NORMAL; in rzg2l_gpt_get_state()
254 static int rzg2l_gpt_config(struct pwm_chip *chip, struct pwm_device *pwm, in rzg2l_gpt_config() argument
258 u8 sub_ch = rzg2l_gpt_subchannel(pwm->hwpwm); in rzg2l_gpt_config()
259 u8 ch = RZG2L_GET_CH(pwm->hwpwm); in rzg2l_gpt_config()
265 period_ticks = mul_u64_u64_div_u64(state->period, rzg2l_gpt->rate_khz, USEC_PER_SEC); in rzg2l_gpt_config()
273 if (rzg2l_gpt->channel_request_count[ch] > 1) { in rzg2l_gpt_config()
274 if (period_ticks < rzg2l_gpt->period_ticks[ch]) in rzg2l_gpt_config()
275 return -EBUSY; in rzg2l_gpt_config()
277 period_ticks = rzg2l_gpt->period_ticks[ch]; in rzg2l_gpt_config()
283 duty_ticks = mul_u64_u64_div_u64(state->duty_cycle, rzg2l_gpt->rate_khz, USEC_PER_SEC); in rzg2l_gpt_config()
293 rzg2l_gpt->period_ticks[ch] = period_ticks; in rzg2l_gpt_config()
296 * Counter must be stopped before modifying mode, prescaler, timer in rzg2l_gpt_config()
301 if (rzg2l_gpt->channel_enable_count[ch] <= 1) { in rzg2l_gpt_config()
304 /* GPT set operating mode (saw-wave up-counting) */ in rzg2l_gpt_config()
322 if (rzg2l_gpt->channel_enable_count[ch] <= 1) { in rzg2l_gpt_config()
337 static int rzg2l_gpt_apply(struct pwm_chip *chip, struct pwm_device *pwm, in rzg2l_gpt_apply() argument
341 bool enabled = pwm->state.enabled; in rzg2l_gpt_apply()
344 if (state->polarity != PWM_POLARITY_NORMAL) in rzg2l_gpt_apply()
345 return -EINVAL; in rzg2l_gpt_apply()
347 guard(mutex)(&rzg2l_gpt->lock); in rzg2l_gpt_apply()
348 if (!state->enabled) { in rzg2l_gpt_apply()
350 rzg2l_gpt_disable(rzg2l_gpt, pwm); in rzg2l_gpt_apply()
355 ret = rzg2l_gpt_config(chip, pwm, state); in rzg2l_gpt_apply()
357 rzg2l_gpt_enable(rzg2l_gpt, pwm); in rzg2l_gpt_apply()
372 struct device *dev = &pdev->dev; in rzg2l_gpt_probe()
384 rzg2l_gpt->mmio = devm_platform_ioremap_resource(pdev, 0); in rzg2l_gpt_probe()
385 if (IS_ERR(rzg2l_gpt->mmio)) in rzg2l_gpt_probe()
386 return PTR_ERR(rzg2l_gpt->mmio); in rzg2l_gpt_probe()
402 return dev_err_probe(dev, -EINVAL, "The gpt clk rate is 0"); in rzg2l_gpt_probe()
409 return dev_err_probe(dev, -EINVAL, "The gpt clk rate is > 1GHz"); in rzg2l_gpt_probe()
416 rzg2l_gpt->rate_khz = rate / KILO; in rzg2l_gpt_probe()
417 if (rzg2l_gpt->rate_khz * KILO != rate) in rzg2l_gpt_probe()
418 return dev_err_probe(dev, -EINVAL, "Rate is not multiple of 1000"); in rzg2l_gpt_probe()
420 mutex_init(&rzg2l_gpt->lock); in rzg2l_gpt_probe()
422 chip->ops = &rzg2l_gpt_ops; in rzg2l_gpt_probe()
425 return dev_err_probe(dev, ret, "Failed to add PWM chip\n"); in rzg2l_gpt_probe()
431 { .compatible = "renesas,rzg2l-gpt", },
438 .name = "pwm-rzg2l-gpt",
446 MODULE_DESCRIPTION("Renesas RZ/G2L General PWM Timer (GPT) Driver");