xref: /openbmc/linux/drivers/pwm/pwm-sti.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
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), &reg);
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