1f50a7f3dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
209853ce7SAlexandre Belloni /*
309853ce7SAlexandre Belloni * Driver for Allwinner sun4i Pulse Width Modulation Controller
409853ce7SAlexandre Belloni *
509853ce7SAlexandre Belloni * Copyright (C) 2014 Alexandre Belloni <alexandre.belloni@free-electrons.com>
69f28e95bSJernej Skrabec *
79f28e95bSJernej Skrabec * Limitations:
89f28e95bSJernej Skrabec * - When outputing the source clock directly, the PWM logic will be bypassed
99f28e95bSJernej Skrabec * and the currently running period is not guaranteed to be completed
1009853ce7SAlexandre Belloni */
1109853ce7SAlexandre Belloni
1209853ce7SAlexandre Belloni #include <linux/bitops.h>
1309853ce7SAlexandre Belloni #include <linux/clk.h>
14c32c5c50SAlexandre Belloni #include <linux/delay.h>
1509853ce7SAlexandre Belloni #include <linux/err.h>
1609853ce7SAlexandre Belloni #include <linux/io.h>
17c32c5c50SAlexandre Belloni #include <linux/jiffies.h>
1809853ce7SAlexandre Belloni #include <linux/module.h>
1909853ce7SAlexandre Belloni #include <linux/of.h>
2009853ce7SAlexandre Belloni #include <linux/platform_device.h>
2109853ce7SAlexandre Belloni #include <linux/pwm.h>
22a7fe9856SJernej Skrabec #include <linux/reset.h>
2309853ce7SAlexandre Belloni #include <linux/slab.h>
2409853ce7SAlexandre Belloni #include <linux/spinlock.h>
2509853ce7SAlexandre Belloni #include <linux/time.h>
2609853ce7SAlexandre Belloni
2709853ce7SAlexandre Belloni #define PWM_CTRL_REG 0x0
2809853ce7SAlexandre Belloni
2909853ce7SAlexandre Belloni #define PWM_CH_PRD_BASE 0x4
3009853ce7SAlexandre Belloni #define PWM_CH_PRD_OFFSET 0x4
3109853ce7SAlexandre Belloni #define PWM_CH_PRD(ch) (PWM_CH_PRD_BASE + PWM_CH_PRD_OFFSET * (ch))
3209853ce7SAlexandre Belloni
3309853ce7SAlexandre Belloni #define PWMCH_OFFSET 15
3409853ce7SAlexandre Belloni #define PWM_PRESCAL_MASK GENMASK(3, 0)
3509853ce7SAlexandre Belloni #define PWM_PRESCAL_OFF 0
3609853ce7SAlexandre Belloni #define PWM_EN BIT(4)
3709853ce7SAlexandre Belloni #define PWM_ACT_STATE BIT(5)
3809853ce7SAlexandre Belloni #define PWM_CLK_GATING BIT(6)
3909853ce7SAlexandre Belloni #define PWM_MODE BIT(7)
4009853ce7SAlexandre Belloni #define PWM_PULSE BIT(8)
4109853ce7SAlexandre Belloni #define PWM_BYPASS BIT(9)
4209853ce7SAlexandre Belloni
4309853ce7SAlexandre Belloni #define PWM_RDY_BASE 28
4409853ce7SAlexandre Belloni #define PWM_RDY_OFFSET 1
4509853ce7SAlexandre Belloni #define PWM_RDY(ch) BIT(PWM_RDY_BASE + PWM_RDY_OFFSET * (ch))
4609853ce7SAlexandre Belloni
4709853ce7SAlexandre Belloni #define PWM_PRD(prd) (((prd) - 1) << 16)
4809853ce7SAlexandre Belloni #define PWM_PRD_MASK GENMASK(15, 0)
4909853ce7SAlexandre Belloni
5009853ce7SAlexandre Belloni #define PWM_DTY_MASK GENMASK(15, 0)
5109853ce7SAlexandre Belloni
5293e0dfb2SAlexandre Belloni #define PWM_REG_PRD(reg) ((((reg) >> 16) & PWM_PRD_MASK) + 1)
5393e0dfb2SAlexandre Belloni #define PWM_REG_DTY(reg) ((reg) & PWM_DTY_MASK)
5493e0dfb2SAlexandre Belloni #define PWM_REG_PRESCAL(reg, chan) (((reg) >> ((chan) * PWMCH_OFFSET)) & PWM_PRESCAL_MASK)
5593e0dfb2SAlexandre Belloni
5609853ce7SAlexandre Belloni #define BIT_CH(bit, chan) ((bit) << ((chan) * PWMCH_OFFSET))
5709853ce7SAlexandre Belloni
5809853ce7SAlexandre Belloni static const u32 prescaler_table[] = {
5909853ce7SAlexandre Belloni 120,
6009853ce7SAlexandre Belloni 180,
6109853ce7SAlexandre Belloni 240,
6209853ce7SAlexandre Belloni 360,
6309853ce7SAlexandre Belloni 480,
6409853ce7SAlexandre Belloni 0,
6509853ce7SAlexandre Belloni 0,
6609853ce7SAlexandre Belloni 0,
6709853ce7SAlexandre Belloni 12000,
6809853ce7SAlexandre Belloni 24000,
6909853ce7SAlexandre Belloni 36000,
7009853ce7SAlexandre Belloni 48000,
7109853ce7SAlexandre Belloni 72000,
7209853ce7SAlexandre Belloni 0,
7309853ce7SAlexandre Belloni 0,
7409853ce7SAlexandre Belloni 0, /* Actually 1 but tested separately */
7509853ce7SAlexandre Belloni };
7609853ce7SAlexandre Belloni
7709853ce7SAlexandre Belloni struct sun4i_pwm_data {
7809853ce7SAlexandre Belloni bool has_prescaler_bypass;
799f28e95bSJernej Skrabec bool has_direct_mod_clk_output;
80f6649f7aSHans de Goede unsigned int npwm;
8109853ce7SAlexandre Belloni };
8209853ce7SAlexandre Belloni
8309853ce7SAlexandre Belloni struct sun4i_pwm_chip {
8409853ce7SAlexandre Belloni struct pwm_chip chip;
855b090b43SJernej Skrabec struct clk *bus_clk;
8609853ce7SAlexandre Belloni struct clk *clk;
87a7fe9856SJernej Skrabec struct reset_control *rst;
8809853ce7SAlexandre Belloni void __iomem *base;
8909853ce7SAlexandre Belloni spinlock_t ctrl_lock;
9009853ce7SAlexandre Belloni const struct sun4i_pwm_data *data;
9109853ce7SAlexandre Belloni };
9209853ce7SAlexandre Belloni
to_sun4i_pwm_chip(struct pwm_chip * chip)9309853ce7SAlexandre Belloni static inline struct sun4i_pwm_chip *to_sun4i_pwm_chip(struct pwm_chip *chip)
9409853ce7SAlexandre Belloni {
9509853ce7SAlexandre Belloni return container_of(chip, struct sun4i_pwm_chip, chip);
9609853ce7SAlexandre Belloni }
9709853ce7SAlexandre Belloni
sun4i_pwm_readl(struct sun4i_pwm_chip * chip,unsigned long offset)9809853ce7SAlexandre Belloni static inline u32 sun4i_pwm_readl(struct sun4i_pwm_chip *chip,
9909853ce7SAlexandre Belloni unsigned long offset)
10009853ce7SAlexandre Belloni {
10109853ce7SAlexandre Belloni return readl(chip->base + offset);
10209853ce7SAlexandre Belloni }
10309853ce7SAlexandre Belloni
sun4i_pwm_writel(struct sun4i_pwm_chip * chip,u32 val,unsigned long offset)10409853ce7SAlexandre Belloni static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *chip,
10509853ce7SAlexandre Belloni u32 val, unsigned long offset)
10609853ce7SAlexandre Belloni {
10709853ce7SAlexandre Belloni writel(val, chip->base + offset);
10809853ce7SAlexandre Belloni }
10909853ce7SAlexandre Belloni
sun4i_pwm_get_state(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_state * state)1106c452cffSUwe Kleine-König static int sun4i_pwm_get_state(struct pwm_chip *chip,
11193e0dfb2SAlexandre Belloni struct pwm_device *pwm,
11293e0dfb2SAlexandre Belloni struct pwm_state *state)
11393e0dfb2SAlexandre Belloni {
11493e0dfb2SAlexandre Belloni struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
11593e0dfb2SAlexandre Belloni u64 clk_rate, tmp;
11693e0dfb2SAlexandre Belloni u32 val;
11793e0dfb2SAlexandre Belloni unsigned int prescaler;
11893e0dfb2SAlexandre Belloni
11993e0dfb2SAlexandre Belloni clk_rate = clk_get_rate(sun4i_pwm->clk);
120a08b318aSAndre Przywara if (!clk_rate)
121a08b318aSAndre Przywara return -EINVAL;
12293e0dfb2SAlexandre Belloni
12393e0dfb2SAlexandre Belloni val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
12493e0dfb2SAlexandre Belloni
1259f28e95bSJernej Skrabec /*
1269f28e95bSJernej Skrabec * PWM chapter in H6 manual has a diagram which explains that if bypass
1279f28e95bSJernej Skrabec * bit is set, no other setting has any meaning. Even more, experiment
1289f28e95bSJernej Skrabec * proved that also enable bit is ignored in this case.
1299f28e95bSJernej Skrabec */
1309f28e95bSJernej Skrabec if ((val & BIT_CH(PWM_BYPASS, pwm->hwpwm)) &&
1319f28e95bSJernej Skrabec sun4i_pwm->data->has_direct_mod_clk_output) {
1329f28e95bSJernej Skrabec state->period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, clk_rate);
1339f28e95bSJernej Skrabec state->duty_cycle = DIV_ROUND_UP_ULL(state->period, 2);
1349f28e95bSJernej Skrabec state->polarity = PWM_POLARITY_NORMAL;
1359f28e95bSJernej Skrabec state->enabled = true;
1366c452cffSUwe Kleine-König return 0;
1379f28e95bSJernej Skrabec }
1389f28e95bSJernej Skrabec
139989ae7a5SAlexandre Belloni if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) &&
140989ae7a5SAlexandre Belloni sun4i_pwm->data->has_prescaler_bypass)
14193e0dfb2SAlexandre Belloni prescaler = 1;
14293e0dfb2SAlexandre Belloni else
14393e0dfb2SAlexandre Belloni prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)];
14493e0dfb2SAlexandre Belloni
14593e0dfb2SAlexandre Belloni if (prescaler == 0)
146a08b318aSAndre Przywara return -EINVAL;
14793e0dfb2SAlexandre Belloni
14893e0dfb2SAlexandre Belloni if (val & BIT_CH(PWM_ACT_STATE, pwm->hwpwm))
14993e0dfb2SAlexandre Belloni state->polarity = PWM_POLARITY_NORMAL;
15093e0dfb2SAlexandre Belloni else
15193e0dfb2SAlexandre Belloni state->polarity = PWM_POLARITY_INVERSED;
15293e0dfb2SAlexandre Belloni
153989ae7a5SAlexandre Belloni if ((val & BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm)) ==
154989ae7a5SAlexandre Belloni BIT_CH(PWM_CLK_GATING | PWM_EN, pwm->hwpwm))
15593e0dfb2SAlexandre Belloni state->enabled = true;
15693e0dfb2SAlexandre Belloni else
15793e0dfb2SAlexandre Belloni state->enabled = false;
15893e0dfb2SAlexandre Belloni
15993e0dfb2SAlexandre Belloni val = sun4i_pwm_readl(sun4i_pwm, PWM_CH_PRD(pwm->hwpwm));
16093e0dfb2SAlexandre Belloni
16150cc7e3eSOndrej Jirman tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_DTY(val);
16293e0dfb2SAlexandre Belloni state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
16393e0dfb2SAlexandre Belloni
16450cc7e3eSOndrej Jirman tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_PRD(val);
16593e0dfb2SAlexandre Belloni state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
1666c452cffSUwe Kleine-König
1676c452cffSUwe Kleine-König return 0;
16893e0dfb2SAlexandre Belloni }
16993e0dfb2SAlexandre Belloni
sun4i_pwm_calculate(struct sun4i_pwm_chip * sun4i_pwm,const struct pwm_state * state,u32 * dty,u32 * prd,unsigned int * prsclr,bool * bypass)170c32c5c50SAlexandre Belloni static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
17171523d18SUwe Kleine-König const struct pwm_state *state,
1729f28e95bSJernej Skrabec u32 *dty, u32 *prd, unsigned int *prsclr,
1739f28e95bSJernej Skrabec bool *bypass)
174c32c5c50SAlexandre Belloni {
175c32c5c50SAlexandre Belloni u64 clk_rate, div = 0;
176f6003f94SUwe Kleine-König unsigned int prescaler = 0;
177c32c5c50SAlexandre Belloni
178c32c5c50SAlexandre Belloni clk_rate = clk_get_rate(sun4i_pwm->clk);
179c32c5c50SAlexandre Belloni
1809f28e95bSJernej Skrabec *bypass = sun4i_pwm->data->has_direct_mod_clk_output &&
1819f28e95bSJernej Skrabec state->enabled &&
1829f28e95bSJernej Skrabec (state->period * clk_rate >= NSEC_PER_SEC) &&
1839f28e95bSJernej Skrabec (state->period * clk_rate < 2 * NSEC_PER_SEC) &&
1849f28e95bSJernej Skrabec (state->duty_cycle * clk_rate * 2 >= NSEC_PER_SEC);
1859f28e95bSJernej Skrabec
1869f28e95bSJernej Skrabec /* Skip calculation of other parameters if we bypass them */
1879f28e95bSJernej Skrabec if (*bypass)
1889f28e95bSJernej Skrabec return 0;
1899f28e95bSJernej Skrabec
190c32c5c50SAlexandre Belloni if (sun4i_pwm->data->has_prescaler_bypass) {
191c32c5c50SAlexandre Belloni /* First, test without any prescaler when available */
192c32c5c50SAlexandre Belloni prescaler = PWM_PRESCAL_MASK;
193c32c5c50SAlexandre Belloni /*
194c32c5c50SAlexandre Belloni * When not using any prescaler, the clock period in nanoseconds
195c32c5c50SAlexandre Belloni * is not an integer so round it half up instead of
196c32c5c50SAlexandre Belloni * truncating to get less surprising values.
197c32c5c50SAlexandre Belloni */
198c32c5c50SAlexandre Belloni div = clk_rate * state->period + NSEC_PER_SEC / 2;
199c32c5c50SAlexandre Belloni do_div(div, NSEC_PER_SEC);
200c32c5c50SAlexandre Belloni if (div - 1 > PWM_PRD_MASK)
201c32c5c50SAlexandre Belloni prescaler = 0;
202c32c5c50SAlexandre Belloni }
203c32c5c50SAlexandre Belloni
204c32c5c50SAlexandre Belloni if (prescaler == 0) {
205c32c5c50SAlexandre Belloni /* Go up from the first divider */
206c32c5c50SAlexandre Belloni for (prescaler = 0; prescaler < PWM_PRESCAL_MASK; prescaler++) {
207f6003f94SUwe Kleine-König unsigned int pval = prescaler_table[prescaler];
208f6003f94SUwe Kleine-König
209f6003f94SUwe Kleine-König if (!pval)
210c32c5c50SAlexandre Belloni continue;
211f6003f94SUwe Kleine-König
212c32c5c50SAlexandre Belloni div = clk_rate;
213c32c5c50SAlexandre Belloni do_div(div, pval);
214c32c5c50SAlexandre Belloni div = div * state->period;
215c32c5c50SAlexandre Belloni do_div(div, NSEC_PER_SEC);
216c32c5c50SAlexandre Belloni if (div - 1 <= PWM_PRD_MASK)
217c32c5c50SAlexandre Belloni break;
218c32c5c50SAlexandre Belloni }
219c32c5c50SAlexandre Belloni
220c32c5c50SAlexandre Belloni if (div - 1 > PWM_PRD_MASK)
221c32c5c50SAlexandre Belloni return -EINVAL;
222c32c5c50SAlexandre Belloni }
223c32c5c50SAlexandre Belloni
224c32c5c50SAlexandre Belloni *prd = div;
225c32c5c50SAlexandre Belloni div *= state->duty_cycle;
226c32c5c50SAlexandre Belloni do_div(div, state->period);
227c32c5c50SAlexandre Belloni *dty = div;
228c32c5c50SAlexandre Belloni *prsclr = prescaler;
229c32c5c50SAlexandre Belloni
230c32c5c50SAlexandre Belloni return 0;
231c32c5c50SAlexandre Belloni }
232c32c5c50SAlexandre Belloni
sun4i_pwm_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)233c32c5c50SAlexandre Belloni static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
23471523d18SUwe Kleine-König const struct pwm_state *state)
235c32c5c50SAlexandre Belloni {
236c32c5c50SAlexandre Belloni struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
237c32c5c50SAlexandre Belloni struct pwm_state cstate;
238413c2a11SThierry Reding u32 ctrl, duty = 0, period = 0, val;
239c32c5c50SAlexandre Belloni int ret;
240413c2a11SThierry Reding unsigned int delay_us, prescaler = 0;
2419f28e95bSJernej Skrabec bool bypass;
242c32c5c50SAlexandre Belloni
243c32c5c50SAlexandre Belloni pwm_get_state(pwm, &cstate);
244c32c5c50SAlexandre Belloni
245c32c5c50SAlexandre Belloni if (!cstate.enabled) {
246c32c5c50SAlexandre Belloni ret = clk_prepare_enable(sun4i_pwm->clk);
247c32c5c50SAlexandre Belloni if (ret) {
248c32c5c50SAlexandre Belloni dev_err(chip->dev, "failed to enable PWM clock\n");
249c32c5c50SAlexandre Belloni return ret;
250c32c5c50SAlexandre Belloni }
251c32c5c50SAlexandre Belloni }
252c32c5c50SAlexandre Belloni
2539f28e95bSJernej Skrabec ret = sun4i_pwm_calculate(sun4i_pwm, state, &duty, &period, &prescaler,
2549f28e95bSJernej Skrabec &bypass);
255c32c5c50SAlexandre Belloni if (ret) {
256c32c5c50SAlexandre Belloni dev_err(chip->dev, "period exceeds the maximum value\n");
257c32c5c50SAlexandre Belloni if (!cstate.enabled)
258c32c5c50SAlexandre Belloni clk_disable_unprepare(sun4i_pwm->clk);
259c32c5c50SAlexandre Belloni return ret;
260c32c5c50SAlexandre Belloni }
261c32c5c50SAlexandre Belloni
2623e954d96SClément Péron spin_lock(&sun4i_pwm->ctrl_lock);
2633e954d96SClément Péron ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
2643e954d96SClément Péron
2659f28e95bSJernej Skrabec if (sun4i_pwm->data->has_direct_mod_clk_output) {
2669f28e95bSJernej Skrabec if (bypass) {
2679f28e95bSJernej Skrabec ctrl |= BIT_CH(PWM_BYPASS, pwm->hwpwm);
2689f28e95bSJernej Skrabec /* We can skip other parameter */
2699f28e95bSJernej Skrabec sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
2709f28e95bSJernej Skrabec spin_unlock(&sun4i_pwm->ctrl_lock);
2719f28e95bSJernej Skrabec return 0;
2729f28e95bSJernej Skrabec }
2739f28e95bSJernej Skrabec
2749f28e95bSJernej Skrabec ctrl &= ~BIT_CH(PWM_BYPASS, pwm->hwpwm);
2759f28e95bSJernej Skrabec }
2769f28e95bSJernej Skrabec
277c32c5c50SAlexandre Belloni if (PWM_REG_PRESCAL(ctrl, pwm->hwpwm) != prescaler) {
278c32c5c50SAlexandre Belloni /* Prescaler changed, the clock has to be gated */
279c32c5c50SAlexandre Belloni ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
280c32c5c50SAlexandre Belloni sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
281c32c5c50SAlexandre Belloni
282c32c5c50SAlexandre Belloni ctrl &= ~BIT_CH(PWM_PRESCAL_MASK, pwm->hwpwm);
283c32c5c50SAlexandre Belloni ctrl |= BIT_CH(prescaler, pwm->hwpwm);
284c32c5c50SAlexandre Belloni }
285c32c5c50SAlexandre Belloni
286c32c5c50SAlexandre Belloni val = (duty & PWM_DTY_MASK) | PWM_PRD(period);
287c32c5c50SAlexandre Belloni sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm));
288c32c5c50SAlexandre Belloni
289c32c5c50SAlexandre Belloni if (state->polarity != PWM_POLARITY_NORMAL)
290c32c5c50SAlexandre Belloni ctrl &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm);
291c32c5c50SAlexandre Belloni else
292c32c5c50SAlexandre Belloni ctrl |= BIT_CH(PWM_ACT_STATE, pwm->hwpwm);
293c32c5c50SAlexandre Belloni
294c32c5c50SAlexandre Belloni ctrl |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
295fa4d8178SClément Péron
2966eefb79dSThierry Reding if (state->enabled)
297c32c5c50SAlexandre Belloni ctrl |= BIT_CH(PWM_EN, pwm->hwpwm);
298c32c5c50SAlexandre Belloni
299c32c5c50SAlexandre Belloni sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
300c32c5c50SAlexandre Belloni
301c32c5c50SAlexandre Belloni spin_unlock(&sun4i_pwm->ctrl_lock);
302c32c5c50SAlexandre Belloni
303c32c5c50SAlexandre Belloni if (state->enabled)
304c32c5c50SAlexandre Belloni return 0;
305c32c5c50SAlexandre Belloni
306c32c5c50SAlexandre Belloni /* We need a full period to elapse before disabling the channel. */
3078246b478SMax Kellermann delay_us = DIV_ROUND_UP_ULL(cstate.period, NSEC_PER_USEC);
308c32c5c50SAlexandre Belloni if ((delay_us / 500) > MAX_UDELAY_MS)
309c32c5c50SAlexandre Belloni msleep(delay_us / 1000 + 1);
310c32c5c50SAlexandre Belloni else
311c32c5c50SAlexandre Belloni usleep_range(delay_us, delay_us * 2);
312c32c5c50SAlexandre Belloni
313c32c5c50SAlexandre Belloni spin_lock(&sun4i_pwm->ctrl_lock);
314c32c5c50SAlexandre Belloni ctrl = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG);
315c32c5c50SAlexandre Belloni ctrl &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm);
316c32c5c50SAlexandre Belloni ctrl &= ~BIT_CH(PWM_EN, pwm->hwpwm);
317c32c5c50SAlexandre Belloni sun4i_pwm_writel(sun4i_pwm, ctrl, PWM_CTRL_REG);
318c32c5c50SAlexandre Belloni spin_unlock(&sun4i_pwm->ctrl_lock);
319c32c5c50SAlexandre Belloni
320c32c5c50SAlexandre Belloni clk_disable_unprepare(sun4i_pwm->clk);
321c32c5c50SAlexandre Belloni
322c32c5c50SAlexandre Belloni return 0;
323c32c5c50SAlexandre Belloni }
324c32c5c50SAlexandre Belloni
32509853ce7SAlexandre Belloni static const struct pwm_ops sun4i_pwm_ops = {
326c32c5c50SAlexandre Belloni .apply = sun4i_pwm_apply,
32793e0dfb2SAlexandre Belloni .get_state = sun4i_pwm_get_state,
32809853ce7SAlexandre Belloni .owner = THIS_MODULE,
32909853ce7SAlexandre Belloni };
33009853ce7SAlexandre Belloni
3317b4c7c56SAndre Przywara static const struct sun4i_pwm_data sun4i_pwm_dual_nobypass = {
33209853ce7SAlexandre Belloni .has_prescaler_bypass = false,
333f6649f7aSHans de Goede .npwm = 2,
334f6649f7aSHans de Goede };
335f6649f7aSHans de Goede
3367b4c7c56SAndre Przywara static const struct sun4i_pwm_data sun4i_pwm_dual_bypass = {
337f6649f7aSHans de Goede .has_prescaler_bypass = true,
338f6649f7aSHans de Goede .npwm = 2,
339f6649f7aSHans de Goede };
340f6649f7aSHans de Goede
3417b4c7c56SAndre Przywara static const struct sun4i_pwm_data sun4i_pwm_single_bypass = {
34242ddcf4fSMilo Kim .has_prescaler_bypass = true,
34342ddcf4fSMilo Kim .npwm = 1,
34442ddcf4fSMilo Kim };
34542ddcf4fSMilo Kim
346856c45d8SPeter Vasil static const struct sun4i_pwm_data sun50i_a64_pwm_data = {
347856c45d8SPeter Vasil .has_prescaler_bypass = true,
348856c45d8SPeter Vasil .has_direct_mod_clk_output = true,
349856c45d8SPeter Vasil .npwm = 1,
350856c45d8SPeter Vasil };
351856c45d8SPeter Vasil
352fdd2c12eSJernej Skrabec static const struct sun4i_pwm_data sun50i_h6_pwm_data = {
353fdd2c12eSJernej Skrabec .has_prescaler_bypass = true,
354fdd2c12eSJernej Skrabec .has_direct_mod_clk_output = true,
355fdd2c12eSJernej Skrabec .npwm = 2,
356fdd2c12eSJernej Skrabec };
357fdd2c12eSJernej Skrabec
35809853ce7SAlexandre Belloni static const struct of_device_id sun4i_pwm_dt_ids[] = {
35909853ce7SAlexandre Belloni {
36009853ce7SAlexandre Belloni .compatible = "allwinner,sun4i-a10-pwm",
3617b4c7c56SAndre Przywara .data = &sun4i_pwm_dual_nobypass,
36209853ce7SAlexandre Belloni }, {
363f6649f7aSHans de Goede .compatible = "allwinner,sun5i-a10s-pwm",
3647b4c7c56SAndre Przywara .data = &sun4i_pwm_dual_bypass,
365f6649f7aSHans de Goede }, {
366f6649f7aSHans de Goede .compatible = "allwinner,sun5i-a13-pwm",
3677b4c7c56SAndre Przywara .data = &sun4i_pwm_single_bypass,
368f6649f7aSHans de Goede }, {
36909853ce7SAlexandre Belloni .compatible = "allwinner,sun7i-a20-pwm",
3707b4c7c56SAndre Przywara .data = &sun4i_pwm_dual_bypass,
37109853ce7SAlexandre Belloni }, {
37242ddcf4fSMilo Kim .compatible = "allwinner,sun8i-h3-pwm",
3737b4c7c56SAndre Przywara .data = &sun4i_pwm_single_bypass,
37442ddcf4fSMilo Kim }, {
375856c45d8SPeter Vasil .compatible = "allwinner,sun50i-a64-pwm",
376856c45d8SPeter Vasil .data = &sun50i_a64_pwm_data,
377856c45d8SPeter Vasil }, {
378fdd2c12eSJernej Skrabec .compatible = "allwinner,sun50i-h6-pwm",
379fdd2c12eSJernej Skrabec .data = &sun50i_h6_pwm_data,
380fdd2c12eSJernej Skrabec }, {
38109853ce7SAlexandre Belloni /* sentinel */
38209853ce7SAlexandre Belloni },
38309853ce7SAlexandre Belloni };
38409853ce7SAlexandre Belloni MODULE_DEVICE_TABLE(of, sun4i_pwm_dt_ids);
38509853ce7SAlexandre Belloni
sun4i_pwm_probe(struct platform_device * pdev)38609853ce7SAlexandre Belloni static int sun4i_pwm_probe(struct platform_device *pdev)
38709853ce7SAlexandre Belloni {
388c4fab452SUwe Kleine-König struct sun4i_pwm_chip *sun4ichip;
38993e0dfb2SAlexandre Belloni int ret;
39009853ce7SAlexandre Belloni
391c4fab452SUwe Kleine-König sun4ichip = devm_kzalloc(&pdev->dev, sizeof(*sun4ichip), GFP_KERNEL);
392c4fab452SUwe Kleine-König if (!sun4ichip)
39309853ce7SAlexandre Belloni return -ENOMEM;
39409853ce7SAlexandre Belloni
395c4fab452SUwe Kleine-König sun4ichip->data = of_device_get_match_data(&pdev->dev);
396c4fab452SUwe Kleine-König if (!sun4ichip->data)
397df4f6e8cSCorentin Labbe return -ENODEV;
398df4f6e8cSCorentin Labbe
399c4fab452SUwe Kleine-König sun4ichip->base = devm_platform_ioremap_resource(pdev, 0);
400c4fab452SUwe Kleine-König if (IS_ERR(sun4ichip->base))
401c4fab452SUwe Kleine-König return PTR_ERR(sun4ichip->base);
40209853ce7SAlexandre Belloni
403b8d74644SClément Péron /*
404b8d74644SClément Péron * All hardware variants need a source clock that is divided and
405b8d74644SClément Péron * then feeds the counter that defines the output wave form. In the
406b8d74644SClément Péron * device tree this clock is either unnamed or called "mod".
407b8d74644SClément Péron * Some variants (e.g. H6) need another clock to access the
408b8d74644SClément Péron * hardware registers; this is called "bus".
409b8d74644SClément Péron * So we request "mod" first (and ignore the corner case that a
410b8d74644SClément Péron * parent provides a "mod" clock while the right one would be the
411b8d74644SClément Péron * unnamed one of the PWM device) and if this is not found we fall
412b8d74644SClément Péron * back to the first clock of the PWM.
413b8d74644SClément Péron */
414c4fab452SUwe Kleine-König sun4ichip->clk = devm_clk_get_optional(&pdev->dev, "mod");
415c4fab452SUwe Kleine-König if (IS_ERR(sun4ichip->clk))
416c4fab452SUwe Kleine-König return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->clk),
4175327f34bSKrzysztof Kozlowski "get mod clock failed\n");
418b8d74644SClément Péron
419c4fab452SUwe Kleine-König if (!sun4ichip->clk) {
420c4fab452SUwe Kleine-König sun4ichip->clk = devm_clk_get(&pdev->dev, NULL);
421c4fab452SUwe Kleine-König if (IS_ERR(sun4ichip->clk))
422c4fab452SUwe Kleine-König return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->clk),
4235327f34bSKrzysztof Kozlowski "get unnamed clock failed\n");
424b8d74644SClément Péron }
42509853ce7SAlexandre Belloni
426c4fab452SUwe Kleine-König sun4ichip->bus_clk = devm_clk_get_optional(&pdev->dev, "bus");
427c4fab452SUwe Kleine-König if (IS_ERR(sun4ichip->bus_clk))
428c4fab452SUwe Kleine-König return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->bus_clk),
4295327f34bSKrzysztof Kozlowski "get bus clock failed\n");
4305b090b43SJernej Skrabec
431c4fab452SUwe Kleine-König sun4ichip->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
432c4fab452SUwe Kleine-König if (IS_ERR(sun4ichip->rst))
433c4fab452SUwe Kleine-König return dev_err_probe(&pdev->dev, PTR_ERR(sun4ichip->rst),
4345327f34bSKrzysztof Kozlowski "get reset failed\n");
435a7fe9856SJernej Skrabec
436a7fe9856SJernej Skrabec /* Deassert reset */
437c4fab452SUwe Kleine-König ret = reset_control_deassert(sun4ichip->rst);
438a7fe9856SJernej Skrabec if (ret) {
439a7fe9856SJernej Skrabec dev_err(&pdev->dev, "cannot deassert reset control: %pe\n",
440a7fe9856SJernej Skrabec ERR_PTR(ret));
441a7fe9856SJernej Skrabec return ret;
442a7fe9856SJernej Skrabec }
443a7fe9856SJernej Skrabec
4445b090b43SJernej Skrabec /*
4455b090b43SJernej Skrabec * We're keeping the bus clock on for the sake of simplicity.
4465b090b43SJernej Skrabec * Actually it only needs to be on for hardware register accesses.
4475b090b43SJernej Skrabec */
448c4fab452SUwe Kleine-König ret = clk_prepare_enable(sun4ichip->bus_clk);
4495b090b43SJernej Skrabec if (ret) {
4505b090b43SJernej Skrabec dev_err(&pdev->dev, "cannot prepare and enable bus_clk %pe\n",
4515b090b43SJernej Skrabec ERR_PTR(ret));
4525b090b43SJernej Skrabec goto err_bus;
4535b090b43SJernej Skrabec }
4545b090b43SJernej Skrabec
455c4fab452SUwe Kleine-König sun4ichip->chip.dev = &pdev->dev;
456c4fab452SUwe Kleine-König sun4ichip->chip.ops = &sun4i_pwm_ops;
457c4fab452SUwe Kleine-König sun4ichip->chip.npwm = sun4ichip->data->npwm;
45809853ce7SAlexandre Belloni
459c4fab452SUwe Kleine-König spin_lock_init(&sun4ichip->ctrl_lock);
46009853ce7SAlexandre Belloni
461c4fab452SUwe Kleine-König ret = pwmchip_add(&sun4ichip->chip);
46209853ce7SAlexandre Belloni if (ret < 0) {
46309853ce7SAlexandre Belloni dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
464a7fe9856SJernej Skrabec goto err_pwm_add;
46509853ce7SAlexandre Belloni }
46609853ce7SAlexandre Belloni
467c4fab452SUwe Kleine-König platform_set_drvdata(pdev, sun4ichip);
46809853ce7SAlexandre Belloni
46909853ce7SAlexandre Belloni return 0;
470a7fe9856SJernej Skrabec
471a7fe9856SJernej Skrabec err_pwm_add:
472c4fab452SUwe Kleine-König clk_disable_unprepare(sun4ichip->bus_clk);
4735b090b43SJernej Skrabec err_bus:
474c4fab452SUwe Kleine-König reset_control_assert(sun4ichip->rst);
475a7fe9856SJernej Skrabec
476a7fe9856SJernej Skrabec return ret;
47709853ce7SAlexandre Belloni }
47809853ce7SAlexandre Belloni
sun4i_pwm_remove(struct platform_device * pdev)479*0bda6b01SUwe Kleine-König static void sun4i_pwm_remove(struct platform_device *pdev)
48009853ce7SAlexandre Belloni {
481c4fab452SUwe Kleine-König struct sun4i_pwm_chip *sun4ichip = platform_get_drvdata(pdev);
48209853ce7SAlexandre Belloni
483c4fab452SUwe Kleine-König pwmchip_remove(&sun4ichip->chip);
484a7fe9856SJernej Skrabec
485c4fab452SUwe Kleine-König clk_disable_unprepare(sun4ichip->bus_clk);
486c4fab452SUwe Kleine-König reset_control_assert(sun4ichip->rst);
48709853ce7SAlexandre Belloni }
48809853ce7SAlexandre Belloni
48909853ce7SAlexandre Belloni static struct platform_driver sun4i_pwm_driver = {
49009853ce7SAlexandre Belloni .driver = {
49109853ce7SAlexandre Belloni .name = "sun4i-pwm",
49209853ce7SAlexandre Belloni .of_match_table = sun4i_pwm_dt_ids,
49309853ce7SAlexandre Belloni },
49409853ce7SAlexandre Belloni .probe = sun4i_pwm_probe,
495*0bda6b01SUwe Kleine-König .remove_new = sun4i_pwm_remove,
49609853ce7SAlexandre Belloni };
49709853ce7SAlexandre Belloni module_platform_driver(sun4i_pwm_driver);
49809853ce7SAlexandre Belloni
49909853ce7SAlexandre Belloni MODULE_ALIAS("platform:sun4i-pwm");
50009853ce7SAlexandre Belloni MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
50109853ce7SAlexandre Belloni MODULE_DESCRIPTION("Allwinner sun4i PWM driver");
50209853ce7SAlexandre Belloni MODULE_LICENSE("GPL v2");
503