Lines Matching +full:output +full:- +full:polarity +full:- +full:invert
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
59 * struct samsung_pwm_channel - private data of PWM channel
71 * struct samsung_pwm_chip - private data of PWM chip
73 * @inverter_mask: inverter status for all channels - one bit per channel
74 * @disabled_mask: disabled status for all channels - one bit per channel
95 * PWM block is shared between pwm-samsung and samsung_pwm_timer drivers
123 unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm); in __pwm_samsung_manual_update()
126 tcon = readl(our_chip->base + REG_TCON); in __pwm_samsung_manual_update()
128 writel(tcon, our_chip->base + REG_TCON); in __pwm_samsung_manual_update()
131 writel(tcon, our_chip->base + REG_TCON); in __pwm_samsung_manual_update()
142 bits = (fls(divisor) - 1) - our_chip->variant.div_base; in pwm_samsung_set_divisor()
146 reg = readl(our_chip->base + REG_TCFG1); in pwm_samsung_set_divisor()
149 writel(reg, our_chip->base + REG_TCFG1); in pwm_samsung_set_divisor()
156 struct samsung_pwm_variant *variant = &our_chip->variant; in pwm_samsung_is_tdiv()
159 reg = readl(our_chip->base + REG_TCFG1); in pwm_samsung_is_tdiv()
163 return (BIT(reg) & variant->tclk_mask) == 0; in pwm_samsung_is_tdiv()
172 rate = clk_get_rate(our_chip->base_clk); in pwm_samsung_get_tin_rate()
174 reg = readl(our_chip->base + REG_TCFG0); in pwm_samsung_get_tin_rate()
186 struct samsung_pwm_variant *variant = &our_chip->variant; in pwm_samsung_calc_tin()
192 clk = (chan < 2) ? our_chip->tclk0 : our_chip->tclk1; in pwm_samsung_calc_tin()
211 if (variant->bits < 32) { in pwm_samsung_calc_tin()
213 for (div = variant->div_base; div < 4; ++div) in pwm_samsung_calc_tin()
214 if ((rate >> (variant->bits + div)) < freq) in pwm_samsung_calc_tin()
221 div = variant->div_base; in pwm_samsung_calc_tin()
233 if (!(our_chip->variant.output_mask & BIT(pwm->hwpwm))) { in pwm_samsung_request()
235 "tried to request PWM channel %d without output\n", in pwm_samsung_request()
236 pwm->hwpwm); in pwm_samsung_request()
237 return -EINVAL; in pwm_samsung_request()
240 memset(&our_chip->channel[pwm->hwpwm], 0, sizeof(our_chip->channel[pwm->hwpwm])); in pwm_samsung_request()
248 unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm); in pwm_samsung_enable()
254 tcon = readl(our_chip->base + REG_TCON); in pwm_samsung_enable()
258 writel(tcon, our_chip->base + REG_TCON); in pwm_samsung_enable()
262 writel(tcon, our_chip->base + REG_TCON); in pwm_samsung_enable()
264 our_chip->disabled_mask &= ~BIT(pwm->hwpwm); in pwm_samsung_enable()
274 unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm); in pwm_samsung_disable()
280 tcon = readl(our_chip->base + REG_TCON); in pwm_samsung_disable()
282 writel(tcon, our_chip->base + REG_TCON); in pwm_samsung_disable()
288 if (readl(our_chip->base + REG_TCMPB(pwm->hwpwm)) == (u32)-1U) in pwm_samsung_disable()
291 our_chip->disabled_mask |= BIT(pwm->hwpwm); in pwm_samsung_disable()
312 struct samsung_pwm_channel *chan = &our_chip->channel[pwm->hwpwm]; in __pwm_samsung_config()
313 u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp; in __pwm_samsung_config()
315 tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm)); in __pwm_samsung_config()
316 oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm)); in __pwm_samsung_config()
322 if (chan->period_ns != period_ns || force_period) { in __pwm_samsung_config()
331 tin_rate = pwm_samsung_calc_tin(chip, pwm->hwpwm, period); in __pwm_samsung_config()
341 return -ERANGE; in __pwm_samsung_config()
350 tcmp = tcnt - tcmp; in __pwm_samsung_config()
353 --tcnt; in __pwm_samsung_config()
354 /* -1UL will give 100% duty. */ in __pwm_samsung_config()
355 --tcmp; in __pwm_samsung_config()
360 writel(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm)); in __pwm_samsung_config()
361 writel(tcmp, our_chip->base + REG_TCMPB(pwm->hwpwm)); in __pwm_samsung_config()
368 if (oldtcmp == (u32) -1) { in __pwm_samsung_config()
373 chan->period_ns = period_ns; in __pwm_samsung_config()
374 chan->tin_ns = tin_ns; in __pwm_samsung_config()
375 chan->duty_ns = duty_ns; in __pwm_samsung_config()
387 unsigned int channel, bool invert) in pwm_samsung_set_invert() argument
395 tcon = readl(our_chip->base + REG_TCON); in pwm_samsung_set_invert()
397 if (invert) { in pwm_samsung_set_invert()
398 our_chip->inverter_mask |= BIT(channel); in pwm_samsung_set_invert()
401 our_chip->inverter_mask &= ~BIT(channel); in pwm_samsung_set_invert()
405 writel(tcon, our_chip->base + REG_TCON); in pwm_samsung_set_invert()
412 enum pwm_polarity polarity) in pwm_samsung_set_polarity() argument
415 bool invert = (polarity == PWM_POLARITY_NORMAL); in pwm_samsung_set_polarity() local
418 pwm_samsung_set_invert(our_chip, pwm->hwpwm, invert); in pwm_samsung_set_polarity()
426 int err, enabled = pwm->state.enabled; in pwm_samsung_apply()
428 if (state->polarity != pwm->state.polarity) { in pwm_samsung_apply()
434 err = pwm_samsung_set_polarity(chip, pwm, state->polarity); in pwm_samsung_apply()
439 if (!state->enabled) { in pwm_samsung_apply()
451 if (state->period > NSEC_PER_SEC) in pwm_samsung_apply()
452 return -ERANGE; in pwm_samsung_apply()
454 err = pwm_samsung_config(chip, pwm, state->duty_cycle, state->period); in pwm_samsung_apply()
458 if (!pwm->state.enabled) in pwm_samsung_apply()
499 { .compatible = "samsung,s3c2410-pwm", .data = &s3c24xx_variant },
500 { .compatible = "samsung,s3c6400-pwm", .data = &s3c64xx_variant },
501 { .compatible = "samsung,s5p6440-pwm", .data = &s5p64x0_variant },
502 { .compatible = "samsung,s5pc100-pwm", .data = &s5pc100_variant },
503 { .compatible = "samsung,exynos4210-pwm", .data = &s5p64x0_variant },
511 struct device_node *np = pwmchip_parent(chip)->of_node; in pwm_samsung_parse_dt()
517 return -ENODEV; in pwm_samsung_parse_dt()
519 memcpy(&our_chip->variant, match->data, sizeof(our_chip->variant)); in pwm_samsung_parse_dt()
521 of_property_for_each_u32(np, "samsung,pwm-outputs", val) { in pwm_samsung_parse_dt()
524 "%s: invalid channel index in samsung,pwm-outputs property\n", in pwm_samsung_parse_dt()
528 our_chip->variant.output_mask |= BIT(val); in pwm_samsung_parse_dt()
536 return -ENODEV; in pwm_samsung_parse_dt()
542 struct device *dev = &pdev->dev; in pwm_samsung_probe()
548 chip = devm_pwmchip_alloc(&pdev->dev, SAMSUNG_PWM_NUM, sizeof(*our_chip)); in pwm_samsung_probe()
553 chip->ops = &pwm_samsung_ops; in pwm_samsung_probe()
554 our_chip->inverter_mask = BIT(SAMSUNG_PWM_NUM) - 1; in pwm_samsung_probe()
556 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { in pwm_samsung_probe()
561 if (!pdev->dev.platform_data) in pwm_samsung_probe()
562 return dev_err_probe(&pdev->dev, -EINVAL, in pwm_samsung_probe()
565 memcpy(&our_chip->variant, pdev->dev.platform_data, in pwm_samsung_probe()
566 sizeof(our_chip->variant)); in pwm_samsung_probe()
569 our_chip->base = devm_platform_ioremap_resource(pdev, 0); in pwm_samsung_probe()
570 if (IS_ERR(our_chip->base)) in pwm_samsung_probe()
571 return PTR_ERR(our_chip->base); in pwm_samsung_probe()
573 our_chip->base_clk = devm_clk_get_enabled(&pdev->dev, "timers"); in pwm_samsung_probe()
574 if (IS_ERR(our_chip->base_clk)) in pwm_samsung_probe()
575 return dev_err_probe(dev, PTR_ERR(our_chip->base_clk), in pwm_samsung_probe()
579 if (our_chip->variant.output_mask & BIT(chan)) in pwm_samsung_probe()
583 our_chip->tclk0 = devm_clk_get(&pdev->dev, "pwm-tclk0"); in pwm_samsung_probe()
584 our_chip->tclk1 = devm_clk_get(&pdev->dev, "pwm-tclk1"); in pwm_samsung_probe()
588 ret = devm_pwmchip_add(&pdev->dev, chip); in pwm_samsung_probe()
593 clk_get_rate(our_chip->base_clk), in pwm_samsung_probe()
594 !IS_ERR(our_chip->tclk0) ? clk_get_rate(our_chip->tclk0) : 0, in pwm_samsung_probe()
595 !IS_ERR(our_chip->tclk1) ? clk_get_rate(our_chip->tclk1) : 0); in pwm_samsung_probe()
607 struct pwm_device *pwm = &chip->pwms[i]; in pwm_samsung_resume()
608 struct samsung_pwm_channel *chan = &our_chip->channel[i]; in pwm_samsung_resume()
610 if (!test_bit(PWMF_REQUESTED, &pwm->flags)) in pwm_samsung_resume()
613 if (our_chip->variant.output_mask & BIT(i)) in pwm_samsung_resume()
615 our_chip->inverter_mask & BIT(i)); in pwm_samsung_resume()
617 if (chan->period_ns) { in pwm_samsung_resume()
618 __pwm_samsung_config(chip, pwm, chan->duty_ns, in pwm_samsung_resume()
619 chan->period_ns, true); in pwm_samsung_resume()
620 /* needed to make PWM disable work on Odroid-XU3 */ in pwm_samsung_resume()
624 if (our_chip->disabled_mask & BIT(i)) in pwm_samsung_resume()
637 .name = "samsung-pwm",
648 MODULE_ALIAS("platform:samsung-pwm");