12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2378fe115SLee Jones /*
37d8a600cSLee Jones * PWM device driver for ST SoCs
4378fe115SLee Jones *
57d8a600cSLee Jones * Copyright (C) 2013-2016 STMicroelectronics (R&D) Limited
67d8a600cSLee Jones *
77d8a600cSLee Jones * Author: Ajit Pal Singh <ajitpal.singh@st.com>
87d8a600cSLee Jones * Lee Jones <lee.jones@linaro.org>
9378fe115SLee Jones */
10378fe115SLee Jones
11378fe115SLee Jones #include <linux/clk.h>
123f0925b5SLee Jones #include <linux/interrupt.h>
13378fe115SLee Jones #include <linux/math64.h>
14378fe115SLee Jones #include <linux/mfd/syscon.h>
15378fe115SLee Jones #include <linux/module.h>
16378fe115SLee Jones #include <linux/of.h>
17378fe115SLee Jones #include <linux/platform_device.h>
18378fe115SLee Jones #include <linux/pwm.h>
19378fe115SLee Jones #include <linux/regmap.h>
203f0925b5SLee Jones #include <linux/sched.h>
21378fe115SLee Jones #include <linux/slab.h>
22378fe115SLee Jones #include <linux/time.h>
233f0925b5SLee Jones #include <linux/wait.h>
24378fe115SLee Jones
25c5f94ae6SLee Jones #define PWM_OUT_VAL(x) (0x00 + (4 * (x))) /* Device's Duty Cycle register */
26f66d78faSLee Jones #define PWM_CPT_VAL(x) (0x10 + (4 * (x))) /* Capture value */
27f66d78faSLee Jones #define PWM_CPT_EDGE(x) (0x30 + (4 * (x))) /* Edge to capture on */
28c5f94ae6SLee Jones
29c5f94ae6SLee Jones #define STI_PWM_CTRL 0x50 /* Control/Config register */
30c5f94ae6SLee Jones #define STI_INT_EN 0x54 /* Interrupt Enable/Disable register */
31f66d78faSLee Jones #define STI_INT_STA 0x58 /* Interrupt Status register */
32f66d78faSLee Jones #define PWM_INT_ACK 0x5c
33bf9cc80bSAjit Pal Singh #define PWM_PRESCALE_LOW_MASK 0x0f
34bf9cc80bSAjit Pal Singh #define PWM_PRESCALE_HIGH_MASK 0xf0
35f66d78faSLee Jones #define PWM_CPT_EDGE_MASK 0x03
36f66d78faSLee Jones #define PWM_INT_ACK_MASK 0x1ff
37f66d78faSLee Jones
38f66d78faSLee Jones #define STI_MAX_CPT_DEVS 4
39f66d78faSLee Jones #define CPT_DC_MAX 0xff
40378fe115SLee Jones
41378fe115SLee Jones /* Regfield IDs */
42378fe115SLee Jones enum {
43c5f94ae6SLee Jones /* Bits in PWM_CTRL*/
44bf9cc80bSAjit Pal Singh PWMCLK_PRESCALE_LOW,
45bf9cc80bSAjit Pal Singh PWMCLK_PRESCALE_HIGH,
46f66d78faSLee Jones CPTCLK_PRESCALE,
47c5f94ae6SLee Jones
48c5f94ae6SLee Jones PWM_OUT_EN,
49f66d78faSLee Jones PWM_CPT_EN,
50c5f94ae6SLee Jones
51c5f94ae6SLee Jones PWM_CPT_INT_EN,
52f66d78faSLee Jones PWM_CPT_INT_STAT,
53378fe115SLee Jones
54378fe115SLee Jones /* Keep last */
55378fe115SLee Jones MAX_REGFIELDS
56378fe115SLee Jones };
57378fe115SLee Jones
587d8a600cSLee Jones /*
597d8a600cSLee Jones * Each capture input can be programmed to detect rising-edge, falling-edge,
607d8a600cSLee Jones * either edge or neither egde.
61f66d78faSLee Jones */
62f66d78faSLee Jones enum sti_cpt_edge {
63f66d78faSLee Jones CPT_EDGE_DISABLED,
64f66d78faSLee Jones CPT_EDGE_RISING,
65f66d78faSLee Jones CPT_EDGE_FALLING,
66f66d78faSLee Jones CPT_EDGE_BOTH,
67f66d78faSLee Jones };
68f66d78faSLee Jones
693f0925b5SLee Jones struct sti_cpt_ddata {
703f0925b5SLee Jones u32 snapshot[3];
713f0925b5SLee Jones unsigned int index;
723f0925b5SLee Jones struct mutex lock;
733f0925b5SLee Jones wait_queue_head_t wait;
743f0925b5SLee Jones };
753f0925b5SLee Jones
76378fe115SLee Jones struct sti_pwm_compat_data {
77378fe115SLee Jones const struct reg_field *reg_fields;
783f0925b5SLee Jones unsigned int pwm_num_devs;
793f0925b5SLee Jones unsigned int cpt_num_devs;
80378fe115SLee Jones unsigned int max_pwm_cnt;
81378fe115SLee Jones unsigned int max_prescale;
827ba9338aSUwe Kleine-König struct sti_cpt_ddata *ddata;
83378fe115SLee Jones };
84378fe115SLee Jones
85378fe115SLee Jones struct sti_pwm_chip {
86378fe115SLee Jones struct device *dev;
87c5f94ae6SLee Jones struct clk *pwm_clk;
88d66a928dSLee Jones struct clk *cpt_clk;
89378fe115SLee Jones struct regmap *regmap;
90378fe115SLee Jones struct sti_pwm_compat_data *cdata;
91bf9cc80bSAjit Pal Singh struct regmap_field *prescale_low;
92bf9cc80bSAjit Pal Singh struct regmap_field *prescale_high;
93c5f94ae6SLee Jones struct regmap_field *pwm_out_en;
9425eb5380SLee Jones struct regmap_field *pwm_cpt_en;
95c5f94ae6SLee Jones struct regmap_field *pwm_cpt_int_en;
9625eb5380SLee Jones struct regmap_field *pwm_cpt_int_stat;
97378fe115SLee Jones struct pwm_chip chip;
985165166eSAjit Pal Singh struct pwm_device *cur;
99cd264b6aSAjit Pal Singh unsigned long configured;
1006ad6b838SAjit Pal Singh unsigned int en_count;
1016ad6b838SAjit Pal Singh struct mutex sti_pwm_lock; /* To sync between enable/disable calls */
102378fe115SLee Jones void __iomem *mmio;
103378fe115SLee Jones };
104378fe115SLee Jones
105378fe115SLee Jones static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
106c5f94ae6SLee Jones [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWM_CTRL, 0, 3),
107c5f94ae6SLee Jones [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWM_CTRL, 11, 14),
108f66d78faSLee Jones [CPTCLK_PRESCALE] = REG_FIELD(STI_PWM_CTRL, 4, 8),
109c5f94ae6SLee Jones [PWM_OUT_EN] = REG_FIELD(STI_PWM_CTRL, 9, 9),
110f66d78faSLee Jones [PWM_CPT_EN] = REG_FIELD(STI_PWM_CTRL, 10, 10),
111c5f94ae6SLee Jones [PWM_CPT_INT_EN] = REG_FIELD(STI_INT_EN, 1, 4),
112f66d78faSLee Jones [PWM_CPT_INT_STAT] = REG_FIELD(STI_INT_STA, 1, 4),
113378fe115SLee Jones };
114378fe115SLee Jones
to_sti_pwmchip(struct pwm_chip * chip)115378fe115SLee Jones static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
116378fe115SLee Jones {
117378fe115SLee Jones return container_of(chip, struct sti_pwm_chip, chip);
118378fe115SLee Jones }
119378fe115SLee Jones
120378fe115SLee Jones /*
1213aacd3e1SAjit Pal Singh * Calculate the prescaler value corresponding to the period.
122378fe115SLee Jones */
sti_pwm_get_prescale(struct sti_pwm_chip * pc,unsigned long period,unsigned int * prescale)1233aacd3e1SAjit Pal Singh static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
1243aacd3e1SAjit Pal Singh unsigned int *prescale)
125378fe115SLee Jones {
126378fe115SLee Jones struct sti_pwm_compat_data *cdata = pc->cdata;
127d81738b7SLee Jones unsigned long clk_rate;
1287d8a600cSLee Jones unsigned long value;
1293aacd3e1SAjit Pal Singh unsigned int ps;
130378fe115SLee Jones
131d81738b7SLee Jones clk_rate = clk_get_rate(pc->pwm_clk);
132d81738b7SLee Jones if (!clk_rate) {
133d81738b7SLee Jones dev_err(pc->dev, "failed to get clock rate\n");
134d81738b7SLee Jones return -EINVAL;
135d81738b7SLee Jones }
136d81738b7SLee Jones
137378fe115SLee Jones /*
1387d8a600cSLee Jones * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_cnt + 1)) - 1
139378fe115SLee Jones */
1407d8a600cSLee Jones value = NSEC_PER_SEC / clk_rate;
1417d8a600cSLee Jones value *= cdata->max_pwm_cnt + 1;
142378fe115SLee Jones
1437d8a600cSLee Jones if (period % value)
1443aacd3e1SAjit Pal Singh return -EINVAL;
1457d8a600cSLee Jones
1467d8a600cSLee Jones ps = period / value - 1;
1473aacd3e1SAjit Pal Singh if (ps > cdata->max_prescale)
1483aacd3e1SAjit Pal Singh return -EINVAL;
1497d8a600cSLee Jones
1503aacd3e1SAjit Pal Singh *prescale = ps;
1513aacd3e1SAjit Pal Singh
1523aacd3e1SAjit Pal Singh return 0;
153378fe115SLee Jones }
154378fe115SLee Jones
155378fe115SLee Jones /*
1567d8a600cSLee Jones * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles. The
1577d8a600cSLee Jones * only way to change the period (apart from changing the PWM input clock) is
1587d8a600cSLee Jones * to change the PWM clock prescaler.
1597d8a600cSLee Jones *
1607d8a600cSLee Jones * The prescaler is of 8 bits, so 256 prescaler values and hence 256 possible
1617d8a600cSLee Jones * period values are supported (for a particular clock rate). The requested
1627d8a600cSLee Jones * period will be applied only if it matches one of these 256 values.
163378fe115SLee Jones */
sti_pwm_config(struct pwm_chip * chip,struct pwm_device * pwm,int duty_ns,int period_ns)164378fe115SLee Jones static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
165378fe115SLee Jones int duty_ns, int period_ns)
166378fe115SLee Jones {
167378fe115SLee Jones struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
168378fe115SLee Jones struct sti_pwm_compat_data *cdata = pc->cdata;
1697d8a600cSLee Jones unsigned int ncfg, value, prescale = 0;
1705165166eSAjit Pal Singh struct pwm_device *cur = pc->cur;
171378fe115SLee Jones struct device *dev = pc->dev;
1725165166eSAjit Pal Singh bool period_same = false;
1737d8a600cSLee Jones int ret;
174378fe115SLee Jones
175cd264b6aSAjit Pal Singh ncfg = hweight_long(pc->configured);
1765165166eSAjit Pal Singh if (ncfg)
1775165166eSAjit Pal Singh period_same = (period_ns == pwm_get_period(cur));
1785165166eSAjit Pal Singh
1797d8a600cSLee Jones /*
1807d8a600cSLee Jones * Allow configuration changes if one of the following conditions
1817d8a600cSLee Jones * satisfy.
18209022e61SLee Jones * 1. No devices have been configured.
1837d8a600cSLee Jones * 2. Only one device has been configured and the new request is for
1847d8a600cSLee Jones * the same device.
1857d8a600cSLee Jones * 3. Only one device has been configured and the new request is for
1867d8a600cSLee Jones * a new device and period of the new device is same as the current
1877d8a600cSLee Jones * configured period.
18809022e61SLee Jones * 4. More than one devices are configured and period of the new
1895165166eSAjit Pal Singh * requestis the same as the current period.
1905165166eSAjit Pal Singh */
1915165166eSAjit Pal Singh if (!ncfg ||
1925165166eSAjit Pal Singh ((ncfg == 1) && (pwm->hwpwm == cur->hwpwm)) ||
1935165166eSAjit Pal Singh ((ncfg == 1) && (pwm->hwpwm != cur->hwpwm) && period_same) ||
1945165166eSAjit Pal Singh ((ncfg > 1) && period_same)) {
1955165166eSAjit Pal Singh /* Enable clock before writing to PWM registers. */
196c5f94ae6SLee Jones ret = clk_enable(pc->pwm_clk);
1975165166eSAjit Pal Singh if (ret)
1985165166eSAjit Pal Singh return ret;
1995165166eSAjit Pal Singh
200d66a928dSLee Jones ret = clk_enable(pc->cpt_clk);
201d66a928dSLee Jones if (ret)
202d66a928dSLee Jones return ret;
203d66a928dSLee Jones
2045165166eSAjit Pal Singh if (!period_same) {
2053aacd3e1SAjit Pal Singh ret = sti_pwm_get_prescale(pc, period_ns, &prescale);
2063aacd3e1SAjit Pal Singh if (ret)
2075165166eSAjit Pal Singh goto clk_dis;
208378fe115SLee Jones
2097d8a600cSLee Jones value = prescale & PWM_PRESCALE_LOW_MASK;
2107d8a600cSLee Jones
2117d8a600cSLee Jones ret = regmap_field_write(pc->prescale_low, value);
2125165166eSAjit Pal Singh if (ret)
2135165166eSAjit Pal Singh goto clk_dis;
2145165166eSAjit Pal Singh
2157d8a600cSLee Jones value = (prescale & PWM_PRESCALE_HIGH_MASK) >> 4;
2167d8a600cSLee Jones
2177d8a600cSLee Jones ret = regmap_field_write(pc->prescale_high, value);
2185165166eSAjit Pal Singh if (ret)
2195165166eSAjit Pal Singh goto clk_dis;
2205165166eSAjit Pal Singh }
2215165166eSAjit Pal Singh
222378fe115SLee Jones /*
223378fe115SLee Jones * When PWMVal == 0, PWM pulse = 1 local clock cycle.
224378fe115SLee Jones * When PWMVal == max_pwm_count,
225378fe115SLee Jones * PWM pulse = (max_pwm_count + 1) local cycles,
226378fe115SLee Jones * that is continuous pulse: signal never goes low.
227378fe115SLee Jones */
2287d8a600cSLee Jones value = cdata->max_pwm_cnt * duty_ns / period_ns;
229378fe115SLee Jones
2307d8a600cSLee Jones ret = regmap_write(pc->regmap, PWM_OUT_VAL(pwm->hwpwm), value);
231378fe115SLee Jones if (ret)
232378fe115SLee Jones goto clk_dis;
233378fe115SLee Jones
234c5f94ae6SLee Jones ret = regmap_field_write(pc->pwm_cpt_int_en, 0);
235378fe115SLee Jones
236cd264b6aSAjit Pal Singh set_bit(pwm->hwpwm, &pc->configured);
2375165166eSAjit Pal Singh pc->cur = pwm;
2385165166eSAjit Pal Singh
2397d8a600cSLee Jones dev_dbg(dev, "prescale:%u, period:%i, duty:%i, value:%u\n",
2407d8a600cSLee Jones prescale, period_ns, duty_ns, value);
2415165166eSAjit Pal Singh } else {
2425165166eSAjit Pal Singh return -EINVAL;
2435165166eSAjit Pal Singh }
2445165166eSAjit Pal Singh
245378fe115SLee Jones clk_dis:
246c5f94ae6SLee Jones clk_disable(pc->pwm_clk);
247d66a928dSLee Jones clk_disable(pc->cpt_clk);
248378fe115SLee Jones return ret;
249378fe115SLee Jones }
250378fe115SLee Jones
sti_pwm_enable(struct pwm_chip * chip,struct pwm_device * pwm)251378fe115SLee Jones static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
252378fe115SLee Jones {
253378fe115SLee Jones struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
254378fe115SLee Jones struct device *dev = pc->dev;
2556ad6b838SAjit Pal Singh int ret = 0;
256378fe115SLee Jones
2576ad6b838SAjit Pal Singh /*
2587d8a600cSLee Jones * Since we have a common enable for all PWM devices, do not enable if
2597d8a600cSLee Jones * already enabled.
2606ad6b838SAjit Pal Singh */
2616ad6b838SAjit Pal Singh mutex_lock(&pc->sti_pwm_lock);
2627d8a600cSLee Jones
2636ad6b838SAjit Pal Singh if (!pc->en_count) {
264c5f94ae6SLee Jones ret = clk_enable(pc->pwm_clk);
265378fe115SLee Jones if (ret)
2666ad6b838SAjit Pal Singh goto out;
267378fe115SLee Jones
268d66a928dSLee Jones ret = clk_enable(pc->cpt_clk);
269d66a928dSLee Jones if (ret)
270d66a928dSLee Jones goto out;
271d66a928dSLee Jones
272c5f94ae6SLee Jones ret = regmap_field_write(pc->pwm_out_en, 1);
2736ad6b838SAjit Pal Singh if (ret) {
2747d8a600cSLee Jones dev_err(dev, "failed to enable PWM device %u: %d\n",
2757d8a600cSLee Jones pwm->hwpwm, ret);
2766ad6b838SAjit Pal Singh goto out;
2776ad6b838SAjit Pal Singh }
2786ad6b838SAjit Pal Singh }
2797d8a600cSLee Jones
2806ad6b838SAjit Pal Singh pc->en_count++;
2817d8a600cSLee Jones
2826ad6b838SAjit Pal Singh out:
2836ad6b838SAjit Pal Singh mutex_unlock(&pc->sti_pwm_lock);
284378fe115SLee Jones return ret;
285378fe115SLee Jones }
286378fe115SLee Jones
sti_pwm_disable(struct pwm_chip * chip,struct pwm_device * pwm)287378fe115SLee Jones static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
288378fe115SLee Jones {
289378fe115SLee Jones struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
290378fe115SLee Jones
2916ad6b838SAjit Pal Singh mutex_lock(&pc->sti_pwm_lock);
2927d8a600cSLee Jones
2936ad6b838SAjit Pal Singh if (--pc->en_count) {
2946ad6b838SAjit Pal Singh mutex_unlock(&pc->sti_pwm_lock);
2956ad6b838SAjit Pal Singh return;
2966ad6b838SAjit Pal Singh }
2977d8a600cSLee Jones
298c5f94ae6SLee Jones regmap_field_write(pc->pwm_out_en, 0);
299378fe115SLee Jones
300c5f94ae6SLee Jones clk_disable(pc->pwm_clk);
301d66a928dSLee Jones clk_disable(pc->cpt_clk);
3027d8a600cSLee Jones
3036ad6b838SAjit Pal Singh mutex_unlock(&pc->sti_pwm_lock);
304378fe115SLee Jones }
305378fe115SLee Jones
sti_pwm_free(struct pwm_chip * chip,struct pwm_device * pwm)306cd264b6aSAjit Pal Singh static void sti_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
307cd264b6aSAjit Pal Singh {
308cd264b6aSAjit Pal Singh struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
309cd264b6aSAjit Pal Singh
310cd264b6aSAjit Pal Singh clear_bit(pwm->hwpwm, &pc->configured);
311cd264b6aSAjit Pal Singh }
312cd264b6aSAjit Pal Singh
sti_pwm_capture(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_capture * result,unsigned long timeout)313c97267aeSLee Jones static int sti_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
314c97267aeSLee Jones struct pwm_capture *result, unsigned long timeout)
315c97267aeSLee Jones {
316c97267aeSLee Jones struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
317c97267aeSLee Jones struct sti_pwm_compat_data *cdata = pc->cdata;
3187ba9338aSUwe Kleine-König struct sti_cpt_ddata *ddata = &cdata->ddata[pwm->hwpwm];
319c97267aeSLee Jones struct device *dev = pc->dev;
320c97267aeSLee Jones unsigned int effective_ticks;
321c97267aeSLee Jones unsigned long long high, low;
322c97267aeSLee Jones int ret;
323c97267aeSLee Jones
324c97267aeSLee Jones if (pwm->hwpwm >= cdata->cpt_num_devs) {
325c97267aeSLee Jones dev_err(dev, "device %u is not valid\n", pwm->hwpwm);
326c97267aeSLee Jones return -EINVAL;
327c97267aeSLee Jones }
328c97267aeSLee Jones
329c97267aeSLee Jones mutex_lock(&ddata->lock);
330c97267aeSLee Jones ddata->index = 0;
331c97267aeSLee Jones
332c97267aeSLee Jones /* Prepare capture measurement */
333c97267aeSLee Jones regmap_write(pc->regmap, PWM_CPT_EDGE(pwm->hwpwm), CPT_EDGE_RISING);
334c97267aeSLee Jones regmap_field_write(pc->pwm_cpt_int_en, BIT(pwm->hwpwm));
335c97267aeSLee Jones
336c97267aeSLee Jones /* Enable capture */
337c97267aeSLee Jones ret = regmap_field_write(pc->pwm_cpt_en, 1);
338c97267aeSLee Jones if (ret) {
339c97267aeSLee Jones dev_err(dev, "failed to enable PWM capture %u: %d\n",
340c97267aeSLee Jones pwm->hwpwm, ret);
341c97267aeSLee Jones goto out;
342c97267aeSLee Jones }
343c97267aeSLee Jones
344c97267aeSLee Jones ret = wait_event_interruptible_timeout(ddata->wait, ddata->index > 1,
345c97267aeSLee Jones msecs_to_jiffies(timeout));
346c97267aeSLee Jones
347c97267aeSLee Jones regmap_write(pc->regmap, PWM_CPT_EDGE(pwm->hwpwm), CPT_EDGE_DISABLED);
348c97267aeSLee Jones
349c97267aeSLee Jones if (ret == -ERESTARTSYS)
350c97267aeSLee Jones goto out;
351c97267aeSLee Jones
352c97267aeSLee Jones switch (ddata->index) {
353c97267aeSLee Jones case 0:
354c97267aeSLee Jones case 1:
355c97267aeSLee Jones /*
356c97267aeSLee Jones * Getting here could mean:
357c97267aeSLee Jones * - input signal is constant of less than 1 Hz
358c97267aeSLee Jones * - there is no input signal at all
359c97267aeSLee Jones *
360c97267aeSLee Jones * In such case the frequency is rounded down to 0
361c97267aeSLee Jones */
362c97267aeSLee Jones result->period = 0;
363c97267aeSLee Jones result->duty_cycle = 0;
364c97267aeSLee Jones
365c97267aeSLee Jones break;
366c97267aeSLee Jones
367c97267aeSLee Jones case 2:
368c97267aeSLee Jones /* We have everying we need */
369c97267aeSLee Jones high = ddata->snapshot[1] - ddata->snapshot[0];
370c97267aeSLee Jones low = ddata->snapshot[2] - ddata->snapshot[1];
371c97267aeSLee Jones
372c97267aeSLee Jones effective_ticks = clk_get_rate(pc->cpt_clk);
373c97267aeSLee Jones
374c97267aeSLee Jones result->period = (high + low) * NSEC_PER_SEC;
375c97267aeSLee Jones result->period /= effective_ticks;
376c97267aeSLee Jones
377c97267aeSLee Jones result->duty_cycle = high * NSEC_PER_SEC;
378c97267aeSLee Jones result->duty_cycle /= effective_ticks;
379c97267aeSLee Jones
380c97267aeSLee Jones break;
381c97267aeSLee Jones
382c97267aeSLee Jones default:
383c97267aeSLee Jones dev_err(dev, "internal error\n");
384c97267aeSLee Jones break;
385c97267aeSLee Jones }
386c97267aeSLee Jones
387c97267aeSLee Jones out:
388c97267aeSLee Jones /* Disable capture */
389c97267aeSLee Jones regmap_field_write(pc->pwm_cpt_en, 0);
390c97267aeSLee Jones
391c97267aeSLee Jones mutex_unlock(&ddata->lock);
392c97267aeSLee Jones return ret;
393c97267aeSLee Jones }
394c97267aeSLee Jones
sti_pwm_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)395b2e60b32SUwe Kleine-König static int sti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
396b2e60b32SUwe Kleine-König const struct pwm_state *state)
397b2e60b32SUwe Kleine-König {
398e326c0d8SUwe Kleine-König struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
399e326c0d8SUwe Kleine-König struct sti_pwm_compat_data *cdata = pc->cdata;
400e326c0d8SUwe Kleine-König struct device *dev = pc->dev;
401b2e60b32SUwe Kleine-König int err;
402b2e60b32SUwe Kleine-König
403e326c0d8SUwe Kleine-König if (pwm->hwpwm >= cdata->pwm_num_devs) {
404e326c0d8SUwe Kleine-König dev_err(dev, "device %u is not valid for pwm mode\n",
405e326c0d8SUwe Kleine-König pwm->hwpwm);
406e326c0d8SUwe Kleine-König return -EINVAL;
407e326c0d8SUwe Kleine-König }
408e326c0d8SUwe Kleine-König
409b2e60b32SUwe Kleine-König if (state->polarity != PWM_POLARITY_NORMAL)
410b2e60b32SUwe Kleine-König return -EINVAL;
411b2e60b32SUwe Kleine-König
412b2e60b32SUwe Kleine-König if (!state->enabled) {
413b2e60b32SUwe Kleine-König if (pwm->state.enabled)
414b2e60b32SUwe Kleine-König sti_pwm_disable(chip, pwm);
415b2e60b32SUwe Kleine-König
416b2e60b32SUwe Kleine-König return 0;
417b2e60b32SUwe Kleine-König }
418b2e60b32SUwe Kleine-König
419b2e60b32SUwe Kleine-König err = sti_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
420b2e60b32SUwe Kleine-König if (err)
421b2e60b32SUwe Kleine-König return err;
422b2e60b32SUwe Kleine-König
423b2e60b32SUwe Kleine-König if (!pwm->state.enabled)
424b2e60b32SUwe Kleine-König err = sti_pwm_enable(chip, pwm);
425b2e60b32SUwe Kleine-König
426b2e60b32SUwe Kleine-König return err;
427b2e60b32SUwe Kleine-König }
428b2e60b32SUwe Kleine-König
429378fe115SLee Jones static const struct pwm_ops sti_pwm_ops = {
430c97267aeSLee Jones .capture = sti_pwm_capture,
431b2e60b32SUwe Kleine-König .apply = sti_pwm_apply,
432cd264b6aSAjit Pal Singh .free = sti_pwm_free,
433378fe115SLee Jones .owner = THIS_MODULE,
434378fe115SLee Jones };
435378fe115SLee Jones
sti_pwm_interrupt(int irq,void * data)43625eb5380SLee Jones static irqreturn_t sti_pwm_interrupt(int irq, void *data)
43725eb5380SLee Jones {
43825eb5380SLee Jones struct sti_pwm_chip *pc = data;
43925eb5380SLee Jones struct device *dev = pc->dev;
44025eb5380SLee Jones struct sti_cpt_ddata *ddata;
44125eb5380SLee Jones int devicenum;
44225eb5380SLee Jones unsigned int cpt_int_stat;
44325eb5380SLee Jones unsigned int reg;
44425eb5380SLee Jones int ret = IRQ_NONE;
44525eb5380SLee Jones
44625eb5380SLee Jones ret = regmap_field_read(pc->pwm_cpt_int_stat, &cpt_int_stat);
44725eb5380SLee Jones if (ret)
44825eb5380SLee Jones return ret;
44925eb5380SLee Jones
45025eb5380SLee Jones while (cpt_int_stat) {
45125eb5380SLee Jones devicenum = ffs(cpt_int_stat) - 1;
45225eb5380SLee Jones
4537ba9338aSUwe Kleine-König ddata = &pc->cdata->ddata[devicenum];
45425eb5380SLee Jones
45525eb5380SLee Jones /*
45625eb5380SLee Jones * Capture input:
45725eb5380SLee Jones * _______ _______
45825eb5380SLee Jones * | | | |
45925eb5380SLee Jones * __| |_________________| |________
46025eb5380SLee Jones * ^0 ^1 ^2
46125eb5380SLee Jones *
4627d8a600cSLee Jones * Capture start by the first available rising edge. When a
4637d8a600cSLee Jones * capture event occurs, capture value (CPT_VALx) is stored,
4647d8a600cSLee Jones * index incremented, capture edge changed.
46525eb5380SLee Jones *
4667d8a600cSLee Jones * After the capture, if the index > 1, we have collected the
4677d8a600cSLee Jones * necessary data so we signal the thread waiting for it and
4687d8a600cSLee Jones * disable the capture by setting capture edge to none
46925eb5380SLee Jones */
47025eb5380SLee Jones
47125eb5380SLee Jones regmap_read(pc->regmap,
47225eb5380SLee Jones PWM_CPT_VAL(devicenum),
47325eb5380SLee Jones &ddata->snapshot[ddata->index]);
47425eb5380SLee Jones
47525eb5380SLee Jones switch (ddata->index) {
47625eb5380SLee Jones case 0:
47725eb5380SLee Jones case 1:
47825eb5380SLee Jones regmap_read(pc->regmap, PWM_CPT_EDGE(devicenum), ®);
47925eb5380SLee Jones reg ^= PWM_CPT_EDGE_MASK;
48025eb5380SLee Jones regmap_write(pc->regmap, PWM_CPT_EDGE(devicenum), reg);
48125eb5380SLee Jones
48225eb5380SLee Jones ddata->index++;
48325eb5380SLee Jones break;
4847d8a600cSLee Jones
48525eb5380SLee Jones case 2:
48625eb5380SLee Jones regmap_write(pc->regmap,
48725eb5380SLee Jones PWM_CPT_EDGE(devicenum),
48825eb5380SLee Jones CPT_EDGE_DISABLED);
48925eb5380SLee Jones wake_up(&ddata->wait);
49025eb5380SLee Jones break;
4917d8a600cSLee Jones
49225eb5380SLee Jones default:
49325eb5380SLee Jones dev_err(dev, "Internal error\n");
49425eb5380SLee Jones }
49525eb5380SLee Jones
49625eb5380SLee Jones cpt_int_stat &= ~BIT_MASK(devicenum);
49725eb5380SLee Jones
49825eb5380SLee Jones ret = IRQ_HANDLED;
49925eb5380SLee Jones }
50025eb5380SLee Jones
50125eb5380SLee Jones /* Just ACK everything */
50225eb5380SLee Jones regmap_write(pc->regmap, PWM_INT_ACK, PWM_INT_ACK_MASK);
50325eb5380SLee Jones
50425eb5380SLee Jones return ret;
50525eb5380SLee Jones }
50625eb5380SLee Jones
sti_pwm_probe_dt(struct sti_pwm_chip * pc)507378fe115SLee Jones static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
508378fe115SLee Jones {
509378fe115SLee Jones struct device *dev = pc->dev;
510378fe115SLee Jones const struct reg_field *reg_fields;
511378fe115SLee Jones struct device_node *np = dev->of_node;
512378fe115SLee Jones struct sti_pwm_compat_data *cdata = pc->cdata;
51309022e61SLee Jones u32 num_devs;
5143f0925b5SLee Jones int ret;
515378fe115SLee Jones
5163f0925b5SLee Jones ret = of_property_read_u32(np, "st,pwm-num-chan", &num_devs);
5173f0925b5SLee Jones if (!ret)
5183f0925b5SLee Jones cdata->pwm_num_devs = num_devs;
5193f0925b5SLee Jones
5203f0925b5SLee Jones ret = of_property_read_u32(np, "st,capture-num-chan", &num_devs);
5213f0925b5SLee Jones if (!ret)
5223f0925b5SLee Jones cdata->cpt_num_devs = num_devs;
523378fe115SLee Jones
52485a834c4SLee Jones if (!cdata->pwm_num_devs && !cdata->cpt_num_devs) {
52585a834c4SLee Jones dev_err(dev, "No channels configured\n");
52685a834c4SLee Jones return -EINVAL;
52785a834c4SLee Jones }
52885a834c4SLee Jones
529378fe115SLee Jones reg_fields = cdata->reg_fields;
530378fe115SLee Jones
531bf9cc80bSAjit Pal Singh pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
532bf9cc80bSAjit Pal Singh reg_fields[PWMCLK_PRESCALE_LOW]);
533bf9cc80bSAjit Pal Singh if (IS_ERR(pc->prescale_low))
534bf9cc80bSAjit Pal Singh return PTR_ERR(pc->prescale_low);
535bf9cc80bSAjit Pal Singh
536bf9cc80bSAjit Pal Singh pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
537bf9cc80bSAjit Pal Singh reg_fields[PWMCLK_PRESCALE_HIGH]);
538bf9cc80bSAjit Pal Singh if (IS_ERR(pc->prescale_high))
539bf9cc80bSAjit Pal Singh return PTR_ERR(pc->prescale_high);
540378fe115SLee Jones
541c5f94ae6SLee Jones pc->pwm_out_en = devm_regmap_field_alloc(dev, pc->regmap,
542c5f94ae6SLee Jones reg_fields[PWM_OUT_EN]);
543c5f94ae6SLee Jones if (IS_ERR(pc->pwm_out_en))
544c5f94ae6SLee Jones return PTR_ERR(pc->pwm_out_en);
545c5f94ae6SLee Jones
546c97267aeSLee Jones pc->pwm_cpt_en = devm_regmap_field_alloc(dev, pc->regmap,
547c97267aeSLee Jones reg_fields[PWM_CPT_EN]);
548c97267aeSLee Jones if (IS_ERR(pc->pwm_cpt_en))
549c97267aeSLee Jones return PTR_ERR(pc->pwm_cpt_en);
550c97267aeSLee Jones
551c5f94ae6SLee Jones pc->pwm_cpt_int_en = devm_regmap_field_alloc(dev, pc->regmap,
552c5f94ae6SLee Jones reg_fields[PWM_CPT_INT_EN]);
553c5f94ae6SLee Jones if (IS_ERR(pc->pwm_cpt_int_en))
554c5f94ae6SLee Jones return PTR_ERR(pc->pwm_cpt_int_en);
555378fe115SLee Jones
55625eb5380SLee Jones pc->pwm_cpt_int_stat = devm_regmap_field_alloc(dev, pc->regmap,
55725eb5380SLee Jones reg_fields[PWM_CPT_INT_STAT]);
55825eb5380SLee Jones if (PTR_ERR_OR_ZERO(pc->pwm_cpt_int_stat))
55925eb5380SLee Jones return PTR_ERR(pc->pwm_cpt_int_stat);
56025eb5380SLee Jones
561378fe115SLee Jones return 0;
562378fe115SLee Jones }
563378fe115SLee Jones
564378fe115SLee Jones static const struct regmap_config sti_pwm_regmap_config = {
565378fe115SLee Jones .reg_bits = 32,
566378fe115SLee Jones .val_bits = 32,
567378fe115SLee Jones .reg_stride = 4,
568378fe115SLee Jones };
569378fe115SLee Jones
sti_pwm_probe(struct platform_device * pdev)570378fe115SLee Jones static int sti_pwm_probe(struct platform_device *pdev)
571378fe115SLee Jones {
572378fe115SLee Jones struct device *dev = &pdev->dev;
573378fe115SLee Jones struct sti_pwm_compat_data *cdata;
574cedd7e53SUwe Kleine-König struct pwm_chip *chip;
575378fe115SLee Jones struct sti_pwm_chip *pc;
5763f0925b5SLee Jones unsigned int i;
57725eb5380SLee Jones int irq, ret;
578378fe115SLee Jones
579378fe115SLee Jones pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
580378fe115SLee Jones if (!pc)
581378fe115SLee Jones return -ENOMEM;
582cedd7e53SUwe Kleine-König chip = &pc->chip;
583378fe115SLee Jones
584378fe115SLee Jones cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
585378fe115SLee Jones if (!cdata)
586378fe115SLee Jones return -ENOMEM;
587378fe115SLee Jones
588728cd3e6SYangtao Li pc->mmio = devm_platform_ioremap_resource(pdev, 0);
589378fe115SLee Jones if (IS_ERR(pc->mmio))
590378fe115SLee Jones return PTR_ERR(pc->mmio);
591378fe115SLee Jones
592378fe115SLee Jones pc->regmap = devm_regmap_init_mmio(dev, pc->mmio,
593378fe115SLee Jones &sti_pwm_regmap_config);
594378fe115SLee Jones if (IS_ERR(pc->regmap))
595378fe115SLee Jones return PTR_ERR(pc->regmap);
596378fe115SLee Jones
59725eb5380SLee Jones irq = platform_get_irq(pdev, 0);
598fb5a35dbSStephen Boyd if (irq < 0)
59925eb5380SLee Jones return irq;
60025eb5380SLee Jones
60125eb5380SLee Jones ret = devm_request_irq(&pdev->dev, irq, sti_pwm_interrupt, 0,
60225eb5380SLee Jones pdev->name, pc);
60325eb5380SLee Jones if (ret < 0) {
60425eb5380SLee Jones dev_err(&pdev->dev, "Failed to request IRQ\n");
60525eb5380SLee Jones return ret;
60625eb5380SLee Jones }
60725eb5380SLee Jones
608378fe115SLee Jones /*
609378fe115SLee Jones * Setup PWM data with default values: some values could be replaced
610378fe115SLee Jones * with specific ones provided from Device Tree.
611378fe115SLee Jones */
6127d8a600cSLee Jones cdata->reg_fields = sti_pwm_regfields;
613378fe115SLee Jones cdata->max_prescale = 0xff;
614378fe115SLee Jones cdata->max_pwm_cnt = 255;
61585a834c4SLee Jones cdata->pwm_num_devs = 0;
6163f0925b5SLee Jones cdata->cpt_num_devs = 0;
617378fe115SLee Jones
618378fe115SLee Jones pc->cdata = cdata;
619378fe115SLee Jones pc->dev = dev;
6206ad6b838SAjit Pal Singh pc->en_count = 0;
6216ad6b838SAjit Pal Singh mutex_init(&pc->sti_pwm_lock);
622378fe115SLee Jones
623378fe115SLee Jones ret = sti_pwm_probe_dt(pc);
624378fe115SLee Jones if (ret)
625378fe115SLee Jones return ret;
626378fe115SLee Jones
627fd3ae02bSThierry Reding if (cdata->pwm_num_devs) {
628*a80814feSUwe Kleine-König pc->pwm_clk = devm_clk_get_prepared(dev, "pwm");
629c5f94ae6SLee Jones if (IS_ERR(pc->pwm_clk)) {
630378fe115SLee Jones dev_err(dev, "failed to get PWM clock\n");
631c5f94ae6SLee Jones return PTR_ERR(pc->pwm_clk);
632378fe115SLee Jones }
633fd3ae02bSThierry Reding }
634378fe115SLee Jones
635fd3ae02bSThierry Reding if (cdata->cpt_num_devs) {
636*a80814feSUwe Kleine-König pc->cpt_clk = devm_clk_get_prepared(dev, "capture");
637d66a928dSLee Jones if (IS_ERR(pc->cpt_clk)) {
638d66a928dSLee Jones dev_err(dev, "failed to get PWM capture clock\n");
639d66a928dSLee Jones return PTR_ERR(pc->cpt_clk);
640d66a928dSLee Jones }
641d66a928dSLee Jones
6427ba9338aSUwe Kleine-König cdata->ddata = devm_kzalloc(dev, cdata->cpt_num_devs * sizeof(*cdata->ddata), GFP_KERNEL);
6437ba9338aSUwe Kleine-König if (!cdata->ddata)
6447ba9338aSUwe Kleine-König return -ENOMEM;
645fd3ae02bSThierry Reding }
646d66a928dSLee Jones
647cedd7e53SUwe Kleine-König chip->dev = dev;
648cedd7e53SUwe Kleine-König chip->ops = &sti_pwm_ops;
649cedd7e53SUwe Kleine-König chip->npwm = max(cdata->pwm_num_devs, cdata->cpt_num_devs);
650378fe115SLee Jones
6517ba9338aSUwe Kleine-König for (i = 0; i < cdata->cpt_num_devs; i++) {
6527ba9338aSUwe Kleine-König struct sti_cpt_ddata *ddata = &cdata->ddata[i];
6537ba9338aSUwe Kleine-König
6547ba9338aSUwe Kleine-König init_waitqueue_head(&ddata->wait);
6557ba9338aSUwe Kleine-König mutex_init(&ddata->lock);
6567ba9338aSUwe Kleine-König }
6577ba9338aSUwe Kleine-König
658*a80814feSUwe Kleine-König return devm_pwmchip_add(dev, chip);
659378fe115SLee Jones }
660378fe115SLee Jones
661378fe115SLee Jones static const struct of_device_id sti_pwm_of_match[] = {
662378fe115SLee Jones { .compatible = "st,sti-pwm", },
663378fe115SLee Jones { /* sentinel */ }
664378fe115SLee Jones };
665378fe115SLee Jones MODULE_DEVICE_TABLE(of, sti_pwm_of_match);
666378fe115SLee Jones
667378fe115SLee Jones static struct platform_driver sti_pwm_driver = {
668378fe115SLee Jones .driver = {
669378fe115SLee Jones .name = "sti-pwm",
670378fe115SLee Jones .of_match_table = sti_pwm_of_match,
671378fe115SLee Jones },
672378fe115SLee Jones .probe = sti_pwm_probe,
673378fe115SLee Jones };
674378fe115SLee Jones module_platform_driver(sti_pwm_driver);
675378fe115SLee Jones
676378fe115SLee Jones MODULE_AUTHOR("Ajit Pal Singh <ajitpal.singh@st.com>");
677378fe115SLee Jones MODULE_DESCRIPTION("STMicroelectronics ST PWM driver");
678378fe115SLee Jones MODULE_LICENSE("GPL");
679