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 */
94 void __iomem *base = tpd->tpu->base + TPU_CHANNEL_OFFSET in tpu_pwm_write()
95 + tpd->channel * TPU_CHANNEL_SIZE; in tpu_pwm_write()
103 static const char * const states[] = { "inactive", "PWM", "active" }; in tpu_pwm_set_pin()
105 dev_dbg(&tpd->tpu->pdev->dev, "%u: configuring pin as %s\n", in tpu_pwm_set_pin()
106 tpd->channel, states[state]); in tpu_pwm_set_pin()
111 tpd->polarity == PWM_POLARITY_INVERSED ? in tpu_pwm_set_pin()
116 tpd->polarity == PWM_POLARITY_INVERSED ? in tpu_pwm_set_pin()
121 tpd->polarity == PWM_POLARITY_INVERSED ? in tpu_pwm_set_pin()
132 spin_lock_irqsave(&tpd->tpu->lock, flags); in tpu_pwm_start_stop()
133 value = ioread16(tpd->tpu->base + TPU_TSTR); in tpu_pwm_start_stop()
136 value |= 1 << tpd->channel; in tpu_pwm_start_stop()
138 value &= ~(1 << tpd->channel); in tpu_pwm_start_stop()
140 iowrite16(value, tpd->tpu->base + TPU_TSTR); in tpu_pwm_start_stop()
141 spin_unlock_irqrestore(&tpd->tpu->lock, flags); in tpu_pwm_start_stop()
148 if (!tpd->timer_on) { in tpu_pwm_timer_start()
150 pm_runtime_get_sync(&tpd->tpu->pdev->dev); in tpu_pwm_timer_start()
151 ret = clk_prepare_enable(tpd->tpu->clk); in tpu_pwm_timer_start()
153 dev_err(&tpd->tpu->pdev->dev, "cannot enable clock\n"); in tpu_pwm_timer_start()
156 tpd->timer_on = true; in tpu_pwm_timer_start()
168 * - Clear TCNT on TGRB match in tpu_pwm_timer_start()
169 * - Count on rising edge in tpu_pwm_timer_start()
170 * - Set prescaler in tpu_pwm_timer_start()
171 * - Output 0 until TGRA, output 1 until TGRB (active low polarity) in tpu_pwm_timer_start()
172 * - Output 1 until TGRA, output 0 until TGRB (active high polarity in tpu_pwm_timer_start()
173 * - PWM mode in tpu_pwm_timer_start()
176 tpd->prescaler); in tpu_pwm_timer_start()
179 tpu_pwm_write(tpd, TPU_TGRAn, tpd->duty); in tpu_pwm_timer_start()
180 tpu_pwm_write(tpd, TPU_TGRBn, tpd->period); in tpu_pwm_timer_start()
182 dev_dbg(&tpd->tpu->pdev->dev, "%u: TGRA 0x%04x TGRB 0x%04x\n", in tpu_pwm_timer_start()
183 tpd->channel, tpd->duty, tpd->period); in tpu_pwm_timer_start()
193 if (!tpd->timer_on) in tpu_pwm_timer_stop()
200 clk_disable_unprepare(tpd->tpu->clk); in tpu_pwm_timer_stop()
201 pm_runtime_put(&tpd->tpu->pdev->dev); in tpu_pwm_timer_stop()
203 tpd->timer_on = false; in tpu_pwm_timer_stop()
206 /* -----------------------------------------------------------------------------
207 * PWM API
210 static int tpu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_request() argument
215 if (pwm->hwpwm >= TPU_CHANNEL_MAX) in tpu_pwm_request()
216 return -EINVAL; in tpu_pwm_request()
218 tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_request()
220 tpd->tpu = tpu; in tpu_pwm_request()
221 tpd->channel = pwm->hwpwm; in tpu_pwm_request()
222 tpd->polarity = PWM_POLARITY_NORMAL; in tpu_pwm_request()
223 tpd->prescaler = 0; in tpu_pwm_request()
224 tpd->period = 0; in tpu_pwm_request()
225 tpd->duty = 0; in tpu_pwm_request()
227 tpd->timer_on = false; in tpu_pwm_request()
232 static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_free() argument
235 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_free()
240 static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, in tpu_pwm_config() argument
244 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_config()
252 clk_rate = clk_get_rate(tpu->clk); in tpu_pwm_config()
260 return -EINVAL; in tpu_pwm_config()
272 * prescaler = max(ilog2(period) / 2, 7) - 7; in tpu_pwm_config()
295 return -EINVAL; in tpu_pwm_config()
306 dev_dbg(&tpu->pdev->dev, in tpu_pwm_config()
310 if (tpd->prescaler == prescaler && tpd->period == period) in tpu_pwm_config()
313 tpd->prescaler = prescaler; in tpu_pwm_config()
314 tpd->period = period; in tpu_pwm_config()
315 tpd->duty = duty; in tpu_pwm_config()
321 if (duty_only && tpd->timer_on) { in tpu_pwm_config()
323 * If only the duty cycle changed and the timer is already in tpu_pwm_config()
327 tpu_pwm_write(tpd, TPU_TGRAn, tpd->duty); in tpu_pwm_config()
328 dev_dbg(&tpu->pdev->dev, "%u: TGRA 0x%04x\n", tpd->channel, in tpu_pwm_config()
329 tpd->duty); in tpu_pwm_config()
339 * To avoid running the timer when not strictly required, handle in tpu_pwm_config()
340 * 0% and 100% duty cycles as fixed levels and stop the timer. in tpu_pwm_config()
349 static int tpu_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, in tpu_pwm_set_polarity() argument
353 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_set_polarity()
355 tpd->polarity = polarity; in tpu_pwm_set_polarity()
360 static int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_enable() argument
363 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_enable()
371 * To avoid running the timer when not strictly required, handle 0% and in tpu_pwm_enable()
372 * 100% duty cycles as fixed levels and stop the timer. in tpu_pwm_enable()
374 if (tpd->duty == 0 || tpd->duty == tpd->period) { in tpu_pwm_enable()
375 tpu_pwm_set_pin(tpd, tpd->duty ? in tpu_pwm_enable()
383 static void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) in tpu_pwm_disable() argument
386 struct tpu_pwm_device *tpd = &tpu->tpd[pwm->hwpwm]; in tpu_pwm_disable()
388 /* The timer must be running to modify the pin output configuration. */ in tpu_pwm_disable()
394 static int tpu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in tpu_pwm_apply() argument
398 bool enabled = pwm->state.enabled; in tpu_pwm_apply()
400 if (state->polarity != pwm->state.polarity) { in tpu_pwm_apply()
402 tpu_pwm_disable(chip, pwm); in tpu_pwm_apply()
406 err = tpu_pwm_set_polarity(chip, pwm, state->polarity); in tpu_pwm_apply()
411 if (!state->enabled) { in tpu_pwm_apply()
413 tpu_pwm_disable(chip, pwm); in tpu_pwm_apply()
418 err = tpu_pwm_config(chip, pwm, in tpu_pwm_apply()
419 state->duty_cycle, state->period, enabled); in tpu_pwm_apply()
424 err = tpu_pwm_enable(chip, pwm); in tpu_pwm_apply()
435 /* -----------------------------------------------------------------------------
444 tpu = devm_kzalloc(&pdev->dev, sizeof(*tpu), GFP_KERNEL); in tpu_probe()
446 return -ENOMEM; in tpu_probe()
448 spin_lock_init(&tpu->lock); in tpu_probe()
449 tpu->pdev = pdev; in tpu_probe()
452 tpu->base = devm_platform_ioremap_resource(pdev, 0); in tpu_probe()
453 if (IS_ERR(tpu->base)) in tpu_probe()
454 return PTR_ERR(tpu->base); in tpu_probe()
456 tpu->clk = devm_clk_get(&pdev->dev, NULL); in tpu_probe()
457 if (IS_ERR(tpu->clk)) in tpu_probe()
458 return dev_err_probe(&pdev->dev, PTR_ERR(tpu->clk), "Failed to get clock\n"); in tpu_probe()
463 tpu->chip.dev = &pdev->dev; in tpu_probe()
464 tpu->chip.ops = &tpu_pwm_ops; in tpu_probe()
465 tpu->chip.npwm = TPU_CHANNEL_MAX; in tpu_probe()
467 ret = devm_pm_runtime_enable(&pdev->dev); in tpu_probe()
469 return dev_err_probe(&pdev->dev, ret, "Failed to enable runtime PM\n"); in tpu_probe()
471 ret = devm_pwmchip_add(&pdev->dev, &tpu->chip); in tpu_probe()
473 return dev_err_probe(&pdev->dev, ret, "Failed to register PWM chip\n"); in tpu_probe()
480 { .compatible = "renesas,tpu-r8a73a4", },
481 { .compatible = "renesas,tpu-r8a7740", },
482 { .compatible = "renesas,tpu-r8a7790", },
493 .name = "renesas-tpu-pwm",
501 MODULE_DESCRIPTION("Renesas TPU PWM Driver");
503 MODULE_ALIAS("platform:renesas-tpu-pwm");