Lines Matching +full:pwm +full:- +full:channels +full:- +full:mask
59 #include <linux/clk-provider.h>
67 #include <linux/pwm.h>
126 static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) in meson_pwm_request() argument
128 struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); in meson_pwm_request()
129 struct device *dev = chip->dev; in meson_pwm_request()
133 return -ENODEV; in meson_pwm_request()
135 if (channel->clk_parent) { in meson_pwm_request()
136 err = clk_set_parent(channel->clk, channel->clk_parent); in meson_pwm_request()
139 __clk_get_name(channel->clk_parent), in meson_pwm_request()
140 __clk_get_name(channel->clk), err); in meson_pwm_request()
145 err = clk_prepare_enable(channel->clk); in meson_pwm_request()
148 __clk_get_name(channel->clk), err); in meson_pwm_request()
152 chip->ops->get_state(chip, pwm, &channel->state); in meson_pwm_request()
157 static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) in meson_pwm_free() argument
159 struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); in meson_pwm_free()
162 clk_disable_unprepare(channel->clk); in meson_pwm_free()
170 unsigned long fin_freq = -1; in meson_pwm_calc()
173 if (~(meson->inverter_mask >> id) & 0x1) in meson_pwm_calc()
174 duty = period - duty; in meson_pwm_calc()
176 if (period == channel->state.period && in meson_pwm_calc()
177 duty == channel->state.duty_cycle) in meson_pwm_calc()
180 fin_freq = clk_get_rate(channel->clk); in meson_pwm_calc()
182 dev_err(meson->chip.dev, "invalid source clock frequency\n"); in meson_pwm_calc()
183 return -EINVAL; in meson_pwm_calc()
186 dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq); in meson_pwm_calc()
194 dev_dbg(meson->chip.dev, "fin_ps=%llu pre_div=%u cnt=%u\n", in meson_pwm_calc()
201 dev_err(meson->chip.dev, "unable to get period pre_div\n"); in meson_pwm_calc()
202 return -EINVAL; in meson_pwm_calc()
205 dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period, in meson_pwm_calc()
209 channel->pre_div = pre_div; in meson_pwm_calc()
210 channel->hi = cnt; in meson_pwm_calc()
211 channel->lo = 0; in meson_pwm_calc()
213 channel->pre_div = pre_div; in meson_pwm_calc()
214 channel->hi = 0; in meson_pwm_calc()
215 channel->lo = cnt; in meson_pwm_calc()
221 dev_err(meson->chip.dev, "unable to get duty cycle\n"); in meson_pwm_calc()
222 return -EINVAL; in meson_pwm_calc()
225 dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n", in meson_pwm_calc()
228 channel->pre_div = pre_div; in meson_pwm_calc()
229 channel->hi = duty_cnt; in meson_pwm_calc()
230 channel->lo = cnt - duty_cnt; in meson_pwm_calc()
263 spin_lock_irqsave(&meson->lock, flags); in meson_pwm_enable()
265 value = readl(meson->base + REG_MISC_AB); in meson_pwm_enable()
267 value |= channel->pre_div << clk_shift; in meson_pwm_enable()
269 writel(value, meson->base + REG_MISC_AB); in meson_pwm_enable()
271 value = (channel->hi << PWM_HIGH_SHIFT) | channel->lo; in meson_pwm_enable()
272 writel(value, meson->base + offset); in meson_pwm_enable()
274 value = readl(meson->base + REG_MISC_AB); in meson_pwm_enable()
276 writel(value, meson->base + REG_MISC_AB); in meson_pwm_enable()
278 spin_unlock_irqrestore(&meson->lock, flags); in meson_pwm_enable()
299 spin_lock_irqsave(&meson->lock, flags); in meson_pwm_disable()
301 value = readl(meson->base + REG_MISC_AB); in meson_pwm_disable()
303 writel(value, meson->base + REG_MISC_AB); in meson_pwm_disable()
305 spin_unlock_irqrestore(&meson->lock, flags); in meson_pwm_disable()
308 static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in meson_pwm_apply() argument
311 struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); in meson_pwm_apply()
316 return -EINVAL; in meson_pwm_apply()
318 if (!state->enabled) { in meson_pwm_apply()
319 meson_pwm_disable(meson, pwm->hwpwm); in meson_pwm_apply()
320 channel->state.enabled = false; in meson_pwm_apply()
325 if (state->period != channel->state.period || in meson_pwm_apply()
326 state->duty_cycle != channel->state.duty_cycle || in meson_pwm_apply()
327 state->polarity != channel->state.polarity) { in meson_pwm_apply()
328 if (state->polarity != channel->state.polarity) { in meson_pwm_apply()
329 if (state->polarity == PWM_POLARITY_NORMAL) in meson_pwm_apply()
330 meson->inverter_mask |= BIT(pwm->hwpwm); in meson_pwm_apply()
332 meson->inverter_mask &= ~BIT(pwm->hwpwm); in meson_pwm_apply()
335 err = meson_pwm_calc(meson, channel, pwm->hwpwm, in meson_pwm_apply()
336 state->duty_cycle, state->period); in meson_pwm_apply()
340 channel->state.polarity = state->polarity; in meson_pwm_apply()
341 channel->state.period = state->period; in meson_pwm_apply()
342 channel->state.duty_cycle = state->duty_cycle; in meson_pwm_apply()
345 if (state->enabled && !channel->state.enabled) { in meson_pwm_apply()
346 meson_pwm_enable(meson, channel, pwm->hwpwm); in meson_pwm_apply()
347 channel->state.enabled = true; in meson_pwm_apply()
353 static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, in meson_pwm_get_state() argument
357 u32 value, mask; in meson_pwm_get_state() local
362 switch (pwm->hwpwm) { in meson_pwm_get_state()
364 mask = MISC_A_EN; in meson_pwm_get_state()
368 mask = MISC_B_EN; in meson_pwm_get_state()
375 value = readl(meson->base + REG_MISC_AB); in meson_pwm_get_state()
376 state->enabled = (value & mask) != 0; in meson_pwm_get_state()
438 .compatible = "amlogic,meson8b-pwm",
442 .compatible = "amlogic,meson-gxbb-pwm",
446 .compatible = "amlogic,meson-gxbb-ao-pwm",
450 .compatible = "amlogic,meson-axg-ee-pwm",
454 .compatible = "amlogic,meson-axg-ao-pwm",
462 struct meson_pwm_channel *channels) in meson_pwm_init_channels() argument
464 struct device *dev = meson->chip.dev; in meson_pwm_init_channels()
470 for (i = 0; i < meson->chip.npwm; i++) { in meson_pwm_init_channels()
471 struct meson_pwm_channel *channel = &channels[i]; in meson_pwm_init_channels()
478 init.parent_names = meson->data->parent_names; in meson_pwm_init_channels()
479 init.num_parents = meson->data->num_parents; in meson_pwm_init_channels()
481 channel->mux.reg = meson->base + REG_MISC_AB; in meson_pwm_init_channels()
482 channel->mux.shift = mux_reg_shifts[i]; in meson_pwm_init_channels()
483 channel->mux.mask = BIT(MISC_CLK_SEL_WIDTH) - 1; in meson_pwm_init_channels()
484 channel->mux.flags = 0; in meson_pwm_init_channels()
485 channel->mux.lock = &meson->lock; in meson_pwm_init_channels()
486 channel->mux.table = NULL; in meson_pwm_init_channels()
487 channel->mux.hw.init = &init; in meson_pwm_init_channels()
489 channel->clk = devm_clk_register(dev, &channel->mux.hw); in meson_pwm_init_channels()
490 if (IS_ERR(channel->clk)) { in meson_pwm_init_channels()
491 err = PTR_ERR(channel->clk); in meson_pwm_init_channels()
498 channel->clk_parent = devm_clk_get(dev, name); in meson_pwm_init_channels()
499 if (IS_ERR(channel->clk_parent)) { in meson_pwm_init_channels()
500 err = PTR_ERR(channel->clk_parent); in meson_pwm_init_channels()
501 if (err == -EPROBE_DEFER) in meson_pwm_init_channels()
504 channel->clk_parent = NULL; in meson_pwm_init_channels()
512 struct meson_pwm_channel *channels) in meson_pwm_add_channels() argument
516 for (i = 0; i < meson->chip.npwm; i++) in meson_pwm_add_channels()
517 pwm_set_chip_data(&meson->chip.pwms[i], &channels[i]); in meson_pwm_add_channels()
522 struct meson_pwm_channel *channels; in meson_pwm_probe() local
527 meson = devm_kzalloc(&pdev->dev, sizeof(*meson), GFP_KERNEL); in meson_pwm_probe()
529 return -ENOMEM; in meson_pwm_probe()
532 meson->base = devm_ioremap_resource(&pdev->dev, regs); in meson_pwm_probe()
533 if (IS_ERR(meson->base)) in meson_pwm_probe()
534 return PTR_ERR(meson->base); in meson_pwm_probe()
536 spin_lock_init(&meson->lock); in meson_pwm_probe()
537 meson->chip.dev = &pdev->dev; in meson_pwm_probe()
538 meson->chip.ops = &meson_pwm_ops; in meson_pwm_probe()
539 meson->chip.base = -1; in meson_pwm_probe()
540 meson->chip.npwm = 2; in meson_pwm_probe()
541 meson->chip.of_xlate = of_pwm_xlate_with_flags; in meson_pwm_probe()
542 meson->chip.of_pwm_n_cells = 3; in meson_pwm_probe()
544 meson->data = of_device_get_match_data(&pdev->dev); in meson_pwm_probe()
545 meson->inverter_mask = BIT(meson->chip.npwm) - 1; in meson_pwm_probe()
547 channels = devm_kcalloc(&pdev->dev, meson->chip.npwm, in meson_pwm_probe()
548 sizeof(*channels), GFP_KERNEL); in meson_pwm_probe()
549 if (!channels) in meson_pwm_probe()
550 return -ENOMEM; in meson_pwm_probe()
552 err = meson_pwm_init_channels(meson, channels); in meson_pwm_probe()
556 err = pwmchip_add(&meson->chip); in meson_pwm_probe()
558 dev_err(&pdev->dev, "failed to register PWM chip: %d\n", err); in meson_pwm_probe()
562 meson_pwm_add_channels(meson, channels); in meson_pwm_probe()
573 return pwmchip_remove(&meson->chip); in meson_pwm_remove()
578 .name = "meson-pwm",
586 MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver");