Lines Matching +full:timer +full:- +full:pwm
1 // SPDX-License-Identifier: GPL-2.0
3 * R-Mobile TPU PWM driver
17 #include <linux/pwm.h>
23 #define TPU_TSTR 0x00 /* Timer start register (shared) */
25 #define TPU_TCRn 0x00 /* Timer control register */
34 #define TPU_TMDRn 0x04 /* Timer mode register */
40 #define TPU_TIORn 0x08 /* Timer I/O control register */
49 #define TPU_TIERn 0x0c /* Timer interrupt enable register */
50 #define TPU_TSRn 0x10 /* Timer status register */
51 #define TPU_TCNTn 0x14 /* Timer counter */
52 #define TPU_TGRAn 0x18 /* Timer general register A */
53 #define TPU_TGRBn 0x1c /* Timer general register B */
54 #define TPU_TGRCn 0x20 /* Timer general register C */
55 #define TPU_TGRDn 0x24 /* Timer general register D */
62 TPU_PIN_PWM, /* Pin is driven by PWM */
69 bool timer_on; /* Whether the timer is running */
96 void __iomem *base = tpd->tpu->base + TPU_CHANNEL_OFFSET in tpu_pwm_write()
97 + tpd->channel * TPU_CHANNEL_SIZE; in tpu_pwm_write()
105 static const char * const states[] = { "inactive", "PWM", "active" }; in tpu_pwm_set_pin()
107 dev_dbg(&tpd->tpu->pdev->dev, "%u: configuring pin as %s\n", in tpu_pwm_set_pin()
108 tpd->channel, states[state]); in tpu_pwm_set_pin()
113 tpd->polarity == PWM_POLARITY_INVERSED ? in tpu_pwm_set_pin()
118 tpd->polarity == PWM_POLARITY_INVERSED ? in tpu_pwm_set_pin()
123 tpd->polarity == PWM_POLARITY_INVERSED ? in tpu_pwm_set_pin()
134 spin_lock_irqsave(&tpd->tpu->lock, flags); in tpu_pwm_start_stop()
135 value = ioread16(tpd->tpu->base + TPU_TSTR); in tpu_pwm_start_stop()
138 value |= 1 << tpd->channel; in tpu_pwm_start_stop()
140 value &= ~(1 << tpd->channel); in tpu_pwm_start_stop()
142 iowrite16(value, tpd->tpu->base + TPU_TSTR); in tpu_pwm_start_stop()
143 spin_unlock_irqrestore(&tpd->tpu->lock, flags); in tpu_pwm_start_stop()
150 if (!tpd->timer_on) { in tpu_pwm_timer_start()
152 pm_runtime_get_sync(&tpd->tpu->pdev->dev); in tpu_pwm_timer_start()
153 ret = clk_prepare_enable(tpd->tpu->clk); in tpu_pwm_timer_start()
155 dev_err(&tpd->tpu->pdev->dev, "cannot enable clock\n"); in tpu_pwm_timer_start()
158 tpd->timer_on = true; in tpu_pwm_timer_start()
170 * - Clear TCNT on TGRB match in tpu_pwm_timer_start()
171 * - Count on rising edge in tpu_pwm_timer_start()
172 * - Set prescaler in tpu_pwm_timer_start()
173 * - Output 0 until TGRA, output 1 until TGRB (active low polarity) in tpu_pwm_timer_start()
174 * - Output 1 until TGRA, output 0 until TGRB (active high polarity in tpu_pwm_timer_start()
175 * - PWM mode in tpu_pwm_timer_start()
178 tpd->prescaler); in tpu_pwm_timer_start()
181 tpu_pwm_write(tpd, TPU_TGRAn, tpd->duty); in tpu_pwm_timer_start()
182 tpu_pwm_write(tpd, TPU_TGRBn, tpd->period); in tpu_pwm_timer_start()
184 dev_dbg(&tpd->tpu->pdev->dev, "%u: TGRA 0x%04x TGRB 0x%04x\n", in tpu_pwm_timer_start()
185 tpd->channel, tpd->duty, tpd->period); in tpu_pwm_timer_start()
195 if (!tpd->timer_on) in tpu_pwm_timer_stop()
202 clk_disable_unprepare(tpd->tpu->clk); in tpu_pwm_timer_stop()
203 pm_runtime_put(&tpd->tpu->pdev->dev); in tpu_pwm_timer_stop()
205 tpd->timer_on = false; in tpu_pwm_timer_stop()
208 /* -----------------------------------------------------------------------------
209 * PWM API
212 static int tpu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_request() argument
217 if (pwm->hwpwm >= TPU_CHANNEL_MAX) in tpu_pwm_request()
218 return -EINVAL; in tpu_pwm_request()
220 tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_request()
222 tpd->tpu = tpu; in tpu_pwm_request()
223 tpd->channel = pwm->hwpwm; in tpu_pwm_request()
224 tpd->polarity = PWM_POLARITY_NORMAL; in tpu_pwm_request()
225 tpd->prescaler = 0; in tpu_pwm_request()
226 tpd->period = 0; in tpu_pwm_request()
227 tpd->duty = 0; in tpu_pwm_request()
229 tpd->timer_on = false; in tpu_pwm_request()
234 static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_free() argument
237 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_free()
242 static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, in tpu_pwm_config() argument
246 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_config()
254 clk_rate = clk_get_rate(tpu->clk); in tpu_pwm_config()
262 return -EINVAL; in tpu_pwm_config()
274 * prescaler = max(ilog2(period) / 2, 7) - 7; in tpu_pwm_config()
297 return -EINVAL; in tpu_pwm_config()
308 dev_dbg(&tpu->pdev->dev, in tpu_pwm_config()
312 if (tpd->prescaler == prescaler && tpd->period == period) in tpu_pwm_config()
315 tpd->prescaler = prescaler; in tpu_pwm_config()
316 tpd->period = period; in tpu_pwm_config()
317 tpd->duty = duty; in tpu_pwm_config()
323 if (duty_only && tpd->timer_on) { in tpu_pwm_config()
325 * If only the duty cycle changed and the timer is already in tpu_pwm_config()
329 tpu_pwm_write(tpd, TPU_TGRAn, tpd->duty); in tpu_pwm_config()
330 dev_dbg(&tpu->pdev->dev, "%u: TGRA 0x%04x\n", tpd->channel, in tpu_pwm_config()
331 tpd->duty); in tpu_pwm_config()
341 * To avoid running the timer when not strictly required, handle in tpu_pwm_config()
342 * 0% and 100% duty cycles as fixed levels and stop the timer. in tpu_pwm_config()
351 static int tpu_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, in tpu_pwm_set_polarity() argument
355 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_set_polarity()
357 tpd->polarity = polarity; in tpu_pwm_set_polarity()
362 static int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_enable() argument
365 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_enable()
373 * To avoid running the timer when not strictly required, handle 0% and in tpu_pwm_enable()
374 * 100% duty cycles as fixed levels and stop the timer. in tpu_pwm_enable()
376 if (tpd->duty == 0 || tpd->duty == tpd->period) { in tpu_pwm_enable()
377 tpu_pwm_set_pin(tpd, tpd->duty ? in tpu_pwm_enable()
385 static void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_disable() argument
388 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_disable()
390 /* The timer must be running to modify the pin output configuration. */ in tpu_pwm_disable()
396 static int tpu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in tpu_pwm_apply() argument
400 bool enabled = pwm->state.enabled; in tpu_pwm_apply()
402 if (state->polarity != pwm->state.polarity) { in tpu_pwm_apply()
404 tpu_pwm_disable(chip, pwm); in tpu_pwm_apply()
408 err = tpu_pwm_set_polarity(chip, pwm, state->polarity); in tpu_pwm_apply()
413 if (!state->enabled) { in tpu_pwm_apply()
415 tpu_pwm_disable(chip, pwm); in tpu_pwm_apply()
420 err = tpu_pwm_config(chip, pwm, in tpu_pwm_apply()
421 state->duty_cycle, state->period, enabled); in tpu_pwm_apply()
426 err = tpu_pwm_enable(chip, pwm); in tpu_pwm_apply()
437 /* -----------------------------------------------------------------------------
447 chip = devm_pwmchip_alloc(&pdev->dev, TPU_CHANNEL_MAX, sizeof(*tpu)); in tpu_probe()
452 spin_lock_init(&tpu->lock); in tpu_probe()
453 tpu->pdev = pdev; in tpu_probe()
456 tpu->base = devm_platform_ioremap_resource(pdev, 0); in tpu_probe()
457 if (IS_ERR(tpu->base)) in tpu_probe()
458 return PTR_ERR(tpu->base); in tpu_probe()
460 tpu->clk = devm_clk_get(&pdev->dev, NULL); in tpu_probe()
461 if (IS_ERR(tpu->clk)) in tpu_probe()
462 return dev_err_probe(&pdev->dev, PTR_ERR(tpu->clk), "Failed to get clock\n"); in tpu_probe()
467 chip->ops = &tpu_pwm_ops; in tpu_probe()
469 ret = devm_pm_runtime_enable(&pdev->dev); in tpu_probe()
471 return dev_err_probe(&pdev->dev, ret, "Failed to enable runtime PM\n"); in tpu_probe()
473 ret = devm_pwmchip_add(&pdev->dev, chip); in tpu_probe()
475 return dev_err_probe(&pdev->dev, ret, "Failed to register PWM chip\n"); in tpu_probe()
482 { .compatible = "renesas,tpu-r8a73a4", },
483 { .compatible = "renesas,tpu-r8a7740", },
484 { .compatible = "renesas,tpu-r8a7790", },
495 .name = "renesas-tpu-pwm",
503 MODULE_DESCRIPTION("Renesas TPU PWM Driver");
505 MODULE_ALIAS("platform:renesas-tpu-pwm");