Lines Matching +full:- +full:pwm
1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/pwm/pwm-vt8500.c
16 #include <linux/pwm.h>
28 #define REG_CTRL(pwm) (((pwm) << 4) + 0x00) argument
29 #define REG_SCALAR(pwm) (((pwm) << 4) + 0x04) argument
30 #define REG_PERIOD(pwm) (((pwm) << 4) + 0x08) argument
31 #define REG_DUTY(pwm) (((pwm) << 4) + 0x0C) argument
64 while ((readl(vt8500->base + REG_STATUS) & mask) && --loops) in vt8500_pwm_busy_wait()
72 static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, in vt8500_pwm_config() argument
81 err = clk_enable(vt8500->clk); in vt8500_pwm_config()
87 c = clk_get_rate(vt8500->clk); in vt8500_pwm_config()
94 prescale = (period_cycles - 1) / 4096; in vt8500_pwm_config()
95 pv = period_cycles / (prescale + 1) - 1; in vt8500_pwm_config()
100 clk_disable(vt8500->clk); in vt8500_pwm_config()
101 return -EINVAL; in vt8500_pwm_config()
108 writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm)); in vt8500_pwm_config()
109 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_SCALAR_UPDATE); in vt8500_pwm_config()
111 writel(pv, vt8500->base + REG_PERIOD(pwm->hwpwm)); in vt8500_pwm_config()
112 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_PERIOD_UPDATE); in vt8500_pwm_config()
114 writel(dc, vt8500->base + REG_DUTY(pwm->hwpwm)); in vt8500_pwm_config()
115 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_DUTY_UPDATE); in vt8500_pwm_config()
117 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_config()
119 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_config()
120 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); in vt8500_pwm_config()
122 clk_disable(vt8500->clk); in vt8500_pwm_config()
126 static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) in vt8500_pwm_enable() argument
132 err = clk_enable(vt8500->clk); in vt8500_pwm_enable()
138 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_enable()
140 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_enable()
141 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); in vt8500_pwm_enable()
146 static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) in vt8500_pwm_disable() argument
151 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_disable()
153 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_disable()
154 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); in vt8500_pwm_disable()
156 clk_disable(vt8500->clk); in vt8500_pwm_disable()
160 struct pwm_device *pwm, in vt8500_pwm_set_polarity() argument
166 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_set_polarity()
173 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); in vt8500_pwm_set_polarity()
174 vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); in vt8500_pwm_set_polarity()
179 static int vt8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in vt8500_pwm_apply() argument
183 bool enabled = pwm->state.enabled; in vt8500_pwm_apply()
185 if (state->polarity != pwm->state.polarity) { in vt8500_pwm_apply()
187 * Changing the polarity of a running PWM is only allowed when in vt8500_pwm_apply()
188 * the PWM driver implements ->apply(). in vt8500_pwm_apply()
191 vt8500_pwm_disable(chip, pwm); in vt8500_pwm_apply()
196 err = vt8500_pwm_set_polarity(chip, pwm, state->polarity); in vt8500_pwm_apply()
201 if (!state->enabled) { in vt8500_pwm_apply()
203 vt8500_pwm_disable(chip, pwm); in vt8500_pwm_apply()
209 * We cannot skip calling ->config even if state->period == in vt8500_pwm_apply()
210 * pwm->state.period && state->duty_cycle == pwm->state.duty_cycle in vt8500_pwm_apply()
212 * pwm_apply_might_sleep because of !state->enabled and so the two values in in vt8500_pwm_apply()
213 * pwm->state might not be configured in hardware. in vt8500_pwm_apply()
215 err = vt8500_pwm_config(chip, pwm, state->duty_cycle, state->period); in vt8500_pwm_apply()
220 err = vt8500_pwm_enable(chip, pwm); in vt8500_pwm_apply()
230 { .compatible = "via,vt8500-pwm", },
239 struct device_node *np = pdev->dev.of_node; in vt8500_pwm_probe()
243 return dev_err_probe(&pdev->dev, -EINVAL, "invalid devicetree node\n"); in vt8500_pwm_probe()
245 chip = devm_pwmchip_alloc(&pdev->dev, VT8500_NR_PWMS, sizeof(*vt8500)); in vt8500_pwm_probe()
250 chip->ops = &vt8500_pwm_ops; in vt8500_pwm_probe()
252 vt8500->clk = devm_clk_get_prepared(&pdev->dev, NULL); in vt8500_pwm_probe()
253 if (IS_ERR(vt8500->clk)) in vt8500_pwm_probe()
254 return dev_err_probe(&pdev->dev, PTR_ERR(vt8500->clk), "clock source not specified\n"); in vt8500_pwm_probe()
256 vt8500->base = devm_platform_ioremap_resource(pdev, 0); in vt8500_pwm_probe()
257 if (IS_ERR(vt8500->base)) in vt8500_pwm_probe()
258 return PTR_ERR(vt8500->base); in vt8500_pwm_probe()
260 ret = devm_pwmchip_add(&pdev->dev, chip); in vt8500_pwm_probe()
262 return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n"); in vt8500_pwm_probe()
270 .name = "vt8500-pwm",
276 MODULE_DESCRIPTION("VT8500 PWM Driver");