Lines Matching +full:clk +full:- +full:pwm
1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/clk.h>
12 #include <linux/pwm.h>
29 #define IPROC_PWM_PRESCALE_SHIFT(ch) ((3 - (ch)) * \
39 struct clk *clk; member
51 value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_enable()
53 writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_enable()
63 value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_disable()
65 writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_disable()
71 static int iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, in iproc_pwmc_get_state() argument
78 value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_get_state()
80 if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm))) in iproc_pwmc_get_state()
81 state->enabled = true; in iproc_pwmc_get_state()
83 state->enabled = false; in iproc_pwmc_get_state()
85 if (value & BIT(IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm))) in iproc_pwmc_get_state()
86 state->polarity = PWM_POLARITY_NORMAL; in iproc_pwmc_get_state()
88 state->polarity = PWM_POLARITY_INVERSED; in iproc_pwmc_get_state()
90 rate = clk_get_rate(ip->clk); in iproc_pwmc_get_state()
92 state->period = 0; in iproc_pwmc_get_state()
93 state->duty_cycle = 0; in iproc_pwmc_get_state()
97 value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); in iproc_pwmc_get_state()
98 prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm); in iproc_pwmc_get_state()
103 value = readl(ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm)); in iproc_pwmc_get_state()
105 state->period = div64_u64(tmp, rate); in iproc_pwmc_get_state()
107 value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm)); in iproc_pwmc_get_state()
109 state->duty_cycle = div64_u64(tmp, rate); in iproc_pwmc_get_state()
114 static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, in iproc_pwmc_apply() argument
122 rate = clk_get_rate(ip->clk); in iproc_pwmc_apply()
138 value = rate * state->period; in iproc_pwmc_apply()
140 value = rate * state->duty_cycle; in iproc_pwmc_apply()
144 return -EINVAL; in iproc_pwmc_apply()
152 return -EINVAL; in iproc_pwmc_apply()
155 iproc_pwmc_disable(ip, pwm->hwpwm); in iproc_pwmc_apply()
158 value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); in iproc_pwmc_apply()
159 value &= ~IPROC_PWM_PRESCALE_MASK(pwm->hwpwm); in iproc_pwmc_apply()
160 value |= prescale << IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm); in iproc_pwmc_apply()
161 writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET); in iproc_pwmc_apply()
164 writel(period, ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm)); in iproc_pwmc_apply()
165 writel(duty, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm)); in iproc_pwmc_apply()
168 value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_apply()
170 if (state->polarity == PWM_POLARITY_NORMAL) in iproc_pwmc_apply()
171 value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm); in iproc_pwmc_apply()
173 value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm)); in iproc_pwmc_apply()
175 writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_apply()
177 if (state->enabled) in iproc_pwmc_apply()
178 iproc_pwmc_enable(ip, pwm->hwpwm); in iproc_pwmc_apply()
196 ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL); in iproc_pwmc_probe()
198 return -ENOMEM; in iproc_pwmc_probe()
202 ip->chip.dev = &pdev->dev; in iproc_pwmc_probe()
203 ip->chip.ops = &iproc_pwm_ops; in iproc_pwmc_probe()
204 ip->chip.npwm = 4; in iproc_pwmc_probe()
206 ip->base = devm_platform_ioremap_resource(pdev, 0); in iproc_pwmc_probe()
207 if (IS_ERR(ip->base)) in iproc_pwmc_probe()
208 return PTR_ERR(ip->base); in iproc_pwmc_probe()
210 ip->clk = devm_clk_get(&pdev->dev, NULL); in iproc_pwmc_probe()
211 if (IS_ERR(ip->clk)) { in iproc_pwmc_probe()
212 dev_err(&pdev->dev, "failed to get clock: %ld\n", in iproc_pwmc_probe()
213 PTR_ERR(ip->clk)); in iproc_pwmc_probe()
214 return PTR_ERR(ip->clk); in iproc_pwmc_probe()
217 ret = clk_prepare_enable(ip->clk); in iproc_pwmc_probe()
219 dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); in iproc_pwmc_probe()
224 value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_probe()
226 for (i = 0; i < ip->chip.npwm; i++) { in iproc_pwmc_probe()
231 writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); in iproc_pwmc_probe()
233 ret = pwmchip_add(&ip->chip); in iproc_pwmc_probe()
235 dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); in iproc_pwmc_probe()
236 clk_disable_unprepare(ip->clk); in iproc_pwmc_probe()
246 pwmchip_remove(&ip->chip); in iproc_pwmc_remove()
248 clk_disable_unprepare(ip->clk); in iproc_pwmc_remove()
252 { .compatible = "brcm,iproc-pwm" },
259 .name = "bcm-iproc-pwm",
268 MODULE_DESCRIPTION("Broadcom iProc PWM driver");