184a14ae8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2841e6f90SAriel D'Alessandro /*
3841e6f90SAriel D'Alessandro * NXP LPC18xx State Configurable Timer - Pulse Width Modulator driver
4841e6f90SAriel D'Alessandro *
5841e6f90SAriel D'Alessandro * Copyright (c) 2015 Ariel D'Alessandro <ariel@vanguardiasur.com>
6841e6f90SAriel D'Alessandro *
7841e6f90SAriel D'Alessandro * Notes
8841e6f90SAriel D'Alessandro * =====
9841e6f90SAriel D'Alessandro * NXP LPC18xx provides a State Configurable Timer (SCT) which can be configured
10841e6f90SAriel D'Alessandro * as a Pulse Width Modulator.
11841e6f90SAriel D'Alessandro *
12841e6f90SAriel D'Alessandro * SCT supports 16 outputs, 16 events and 16 registers. Each event will be
13841e6f90SAriel D'Alessandro * triggered when its related register matches the SCT counter value, and it
14841e6f90SAriel D'Alessandro * will set or clear a selected output.
15841e6f90SAriel D'Alessandro *
16841e6f90SAriel D'Alessandro * One of the events is preselected to generate the period, thus the maximum
17841e6f90SAriel D'Alessandro * number of simultaneous channels is limited to 15. Notice that period is
18841e6f90SAriel D'Alessandro * global to all the channels, thus PWM driver will refuse setting different
19841e6f90SAriel D'Alessandro * values to it, unless there's only one channel requested.
20841e6f90SAriel D'Alessandro */
21841e6f90SAriel D'Alessandro
22841e6f90SAriel D'Alessandro #include <linux/clk.h>
23841e6f90SAriel D'Alessandro #include <linux/err.h>
24841e6f90SAriel D'Alessandro #include <linux/io.h>
250a41b0c5SRob Herring #include <linux/mod_devicetable.h>
26841e6f90SAriel D'Alessandro #include <linux/module.h>
27841e6f90SAriel D'Alessandro #include <linux/platform_device.h>
28841e6f90SAriel D'Alessandro #include <linux/pwm.h>
29841e6f90SAriel D'Alessandro
30841e6f90SAriel D'Alessandro /* LPC18xx SCT registers */
31841e6f90SAriel D'Alessandro #define LPC18XX_PWM_CONFIG 0x000
32841e6f90SAriel D'Alessandro #define LPC18XX_PWM_CONFIG_UNIFY BIT(0)
33841e6f90SAriel D'Alessandro #define LPC18XX_PWM_CONFIG_NORELOAD BIT(7)
34841e6f90SAriel D'Alessandro
35841e6f90SAriel D'Alessandro #define LPC18XX_PWM_CTRL 0x004
36841e6f90SAriel D'Alessandro #define LPC18XX_PWM_CTRL_HALT BIT(2)
37841e6f90SAriel D'Alessandro #define LPC18XX_PWM_BIDIR BIT(4)
38841e6f90SAriel D'Alessandro #define LPC18XX_PWM_PRE_SHIFT 5
39841e6f90SAriel D'Alessandro #define LPC18XX_PWM_PRE_MASK (0xff << LPC18XX_PWM_PRE_SHIFT)
40841e6f90SAriel D'Alessandro #define LPC18XX_PWM_PRE(x) (x << LPC18XX_PWM_PRE_SHIFT)
41841e6f90SAriel D'Alessandro
42841e6f90SAriel D'Alessandro #define LPC18XX_PWM_LIMIT 0x008
43841e6f90SAriel D'Alessandro
44841e6f90SAriel D'Alessandro #define LPC18XX_PWM_RES_BASE 0x058
45841e6f90SAriel D'Alessandro #define LPC18XX_PWM_RES_SHIFT(_ch) (_ch * 2)
46841e6f90SAriel D'Alessandro #define LPC18XX_PWM_RES(_ch, _action) (_action << LPC18XX_PWM_RES_SHIFT(_ch))
47841e6f90SAriel D'Alessandro #define LPC18XX_PWM_RES_MASK(_ch) (0x3 << LPC18XX_PWM_RES_SHIFT(_ch))
48841e6f90SAriel D'Alessandro
49841e6f90SAriel D'Alessandro #define LPC18XX_PWM_MATCH_BASE 0x100
50841e6f90SAriel D'Alessandro #define LPC18XX_PWM_MATCH(_ch) (LPC18XX_PWM_MATCH_BASE + _ch * 4)
51841e6f90SAriel D'Alessandro
52841e6f90SAriel D'Alessandro #define LPC18XX_PWM_MATCHREL_BASE 0x200
53841e6f90SAriel D'Alessandro #define LPC18XX_PWM_MATCHREL(_ch) (LPC18XX_PWM_MATCHREL_BASE + _ch * 4)
54841e6f90SAriel D'Alessandro
55841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVSTATEMSK_BASE 0x300
56841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVSTATEMSK(_ch) (LPC18XX_PWM_EVSTATEMSK_BASE + _ch * 8)
57841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVSTATEMSK_ALL 0xffffffff
58841e6f90SAriel D'Alessandro
59841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVCTRL_BASE 0x304
60841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVCTRL(_ev) (LPC18XX_PWM_EVCTRL_BASE + _ev * 8)
61841e6f90SAriel D'Alessandro
62841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVCTRL_MATCH(_ch) _ch
63841e6f90SAriel D'Alessandro
64841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVCTRL_COMB_SHIFT 12
65841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVCTRL_COMB_MATCH (0x1 << LPC18XX_PWM_EVCTRL_COMB_SHIFT)
66841e6f90SAriel D'Alessandro
67841e6f90SAriel D'Alessandro #define LPC18XX_PWM_OUTPUTSET_BASE 0x500
68841e6f90SAriel D'Alessandro #define LPC18XX_PWM_OUTPUTSET(_ch) (LPC18XX_PWM_OUTPUTSET_BASE + _ch * 8)
69841e6f90SAriel D'Alessandro
70841e6f90SAriel D'Alessandro #define LPC18XX_PWM_OUTPUTCL_BASE 0x504
71841e6f90SAriel D'Alessandro #define LPC18XX_PWM_OUTPUTCL(_ch) (LPC18XX_PWM_OUTPUTCL_BASE + _ch * 8)
72841e6f90SAriel D'Alessandro
73841e6f90SAriel D'Alessandro /* LPC18xx SCT unified counter */
74841e6f90SAriel D'Alessandro #define LPC18XX_PWM_TIMER_MAX 0xffffffff
75841e6f90SAriel D'Alessandro
76841e6f90SAriel D'Alessandro /* LPC18xx SCT events */
77841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVENT_PERIOD 0
78841e6f90SAriel D'Alessandro #define LPC18XX_PWM_EVENT_MAX 16
79841e6f90SAriel D'Alessandro
8020d9de9cSUwe Kleine-König #define LPC18XX_NUM_PWMS 16
8120d9de9cSUwe Kleine-König
82841e6f90SAriel D'Alessandro /* SCT conflict resolution */
83841e6f90SAriel D'Alessandro enum lpc18xx_pwm_res_action {
84841e6f90SAriel D'Alessandro LPC18XX_PWM_RES_NONE,
85841e6f90SAriel D'Alessandro LPC18XX_PWM_RES_SET,
86841e6f90SAriel D'Alessandro LPC18XX_PWM_RES_CLEAR,
87841e6f90SAriel D'Alessandro LPC18XX_PWM_RES_TOGGLE,
88841e6f90SAriel D'Alessandro };
89841e6f90SAriel D'Alessandro
90841e6f90SAriel D'Alessandro struct lpc18xx_pwm_data {
91841e6f90SAriel D'Alessandro unsigned int duty_event;
92841e6f90SAriel D'Alessandro };
93841e6f90SAriel D'Alessandro
94841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip {
95841e6f90SAriel D'Alessandro struct device *dev;
96841e6f90SAriel D'Alessandro struct pwm_chip chip;
97841e6f90SAriel D'Alessandro void __iomem *base;
98841e6f90SAriel D'Alessandro struct clk *pwm_clk;
99841e6f90SAriel D'Alessandro unsigned long clk_rate;
100841e6f90SAriel D'Alessandro unsigned int period_ns;
101841e6f90SAriel D'Alessandro unsigned int min_period_ns;
1028933d30cSUwe Kleine-König u64 max_period_ns;
103841e6f90SAriel D'Alessandro unsigned int period_event;
104841e6f90SAriel D'Alessandro unsigned long event_map;
105841e6f90SAriel D'Alessandro struct mutex res_lock;
106841e6f90SAriel D'Alessandro struct mutex period_lock;
10720d9de9cSUwe Kleine-König struct lpc18xx_pwm_data channeldata[LPC18XX_NUM_PWMS];
108841e6f90SAriel D'Alessandro };
109841e6f90SAriel D'Alessandro
110841e6f90SAriel D'Alessandro static inline struct lpc18xx_pwm_chip *
to_lpc18xx_pwm_chip(struct pwm_chip * chip)111841e6f90SAriel D'Alessandro to_lpc18xx_pwm_chip(struct pwm_chip *chip)
112841e6f90SAriel D'Alessandro {
113841e6f90SAriel D'Alessandro return container_of(chip, struct lpc18xx_pwm_chip, chip);
114841e6f90SAriel D'Alessandro }
115841e6f90SAriel D'Alessandro
lpc18xx_pwm_writel(struct lpc18xx_pwm_chip * lpc18xx_pwm,u32 reg,u32 val)116841e6f90SAriel D'Alessandro static inline void lpc18xx_pwm_writel(struct lpc18xx_pwm_chip *lpc18xx_pwm,
117841e6f90SAriel D'Alessandro u32 reg, u32 val)
118841e6f90SAriel D'Alessandro {
119841e6f90SAriel D'Alessandro writel(val, lpc18xx_pwm->base + reg);
120841e6f90SAriel D'Alessandro }
121841e6f90SAriel D'Alessandro
lpc18xx_pwm_readl(struct lpc18xx_pwm_chip * lpc18xx_pwm,u32 reg)122841e6f90SAriel D'Alessandro static inline u32 lpc18xx_pwm_readl(struct lpc18xx_pwm_chip *lpc18xx_pwm,
123841e6f90SAriel D'Alessandro u32 reg)
124841e6f90SAriel D'Alessandro {
125841e6f90SAriel D'Alessandro return readl(lpc18xx_pwm->base + reg);
126841e6f90SAriel D'Alessandro }
127841e6f90SAriel D'Alessandro
lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip * lpc18xx_pwm,struct pwm_device * pwm,enum lpc18xx_pwm_res_action action)128841e6f90SAriel D'Alessandro static void lpc18xx_pwm_set_conflict_res(struct lpc18xx_pwm_chip *lpc18xx_pwm,
129841e6f90SAriel D'Alessandro struct pwm_device *pwm,
130841e6f90SAriel D'Alessandro enum lpc18xx_pwm_res_action action)
131841e6f90SAriel D'Alessandro {
132841e6f90SAriel D'Alessandro u32 val;
133841e6f90SAriel D'Alessandro
134841e6f90SAriel D'Alessandro mutex_lock(&lpc18xx_pwm->res_lock);
135841e6f90SAriel D'Alessandro
136841e6f90SAriel D'Alessandro /*
137841e6f90SAriel D'Alessandro * Simultaneous set and clear may happen on an output, that is the case
138841e6f90SAriel D'Alessandro * when duty_ns == period_ns. LPC18xx SCT allows to set a conflict
139841e6f90SAriel D'Alessandro * resolution action to be taken in such a case.
140841e6f90SAriel D'Alessandro */
141841e6f90SAriel D'Alessandro val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_RES_BASE);
142841e6f90SAriel D'Alessandro val &= ~LPC18XX_PWM_RES_MASK(pwm->hwpwm);
143841e6f90SAriel D'Alessandro val |= LPC18XX_PWM_RES(pwm->hwpwm, action);
144841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_RES_BASE, val);
145841e6f90SAriel D'Alessandro
146841e6f90SAriel D'Alessandro mutex_unlock(&lpc18xx_pwm->res_lock);
147841e6f90SAriel D'Alessandro }
148841e6f90SAriel D'Alessandro
lpc18xx_pwm_config_period(struct pwm_chip * chip,u64 period_ns)1498933d30cSUwe Kleine-König static void lpc18xx_pwm_config_period(struct pwm_chip *chip, u64 period_ns)
150841e6f90SAriel D'Alessandro {
151841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
1528933d30cSUwe Kleine-König u32 val;
153841e6f90SAriel D'Alessandro
1548933d30cSUwe Kleine-König /*
1558933d30cSUwe Kleine-König * With clk_rate < NSEC_PER_SEC this cannot overflow.
1568933d30cSUwe Kleine-König * With period_ns < max_period_ns this also fits into an u32.
1578933d30cSUwe Kleine-König * As period_ns >= min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, lpc18xx_pwm->clk_rate);
1588933d30cSUwe Kleine-König * we have val >= 1.
1598933d30cSUwe Kleine-König */
1608933d30cSUwe Kleine-König val = mul_u64_u64_div_u64(period_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC);
161841e6f90SAriel D'Alessandro
162841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
163841e6f90SAriel D'Alessandro LPC18XX_PWM_MATCH(lpc18xx_pwm->period_event),
1648933d30cSUwe Kleine-König val - 1);
165841e6f90SAriel D'Alessandro
166841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
167841e6f90SAriel D'Alessandro LPC18XX_PWM_MATCHREL(lpc18xx_pwm->period_event),
1688933d30cSUwe Kleine-König val - 1);
169841e6f90SAriel D'Alessandro }
170841e6f90SAriel D'Alessandro
lpc18xx_pwm_config_duty(struct pwm_chip * chip,struct pwm_device * pwm,u64 duty_ns)171841e6f90SAriel D'Alessandro static void lpc18xx_pwm_config_duty(struct pwm_chip *chip,
1728933d30cSUwe Kleine-König struct pwm_device *pwm, u64 duty_ns)
173841e6f90SAriel D'Alessandro {
174841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
1759136a39eSUwe Kleine-König struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
1768933d30cSUwe Kleine-König u32 val;
177841e6f90SAriel D'Alessandro
1788933d30cSUwe Kleine-König /*
17907d8d8d2SUwe Kleine-König * With clk_rate <= NSEC_PER_SEC this cannot overflow.
1808933d30cSUwe Kleine-König * With duty_ns <= period_ns < max_period_ns this also fits into an u32.
1818933d30cSUwe Kleine-König */
1828933d30cSUwe Kleine-König val = mul_u64_u64_div_u64(duty_ns, lpc18xx_pwm->clk_rate, NSEC_PER_SEC);
183841e6f90SAriel D'Alessandro
184841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
185841e6f90SAriel D'Alessandro LPC18XX_PWM_MATCH(lpc18xx_data->duty_event),
1868933d30cSUwe Kleine-König val);
187841e6f90SAriel D'Alessandro
188841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
189841e6f90SAriel D'Alessandro LPC18XX_PWM_MATCHREL(lpc18xx_data->duty_event),
1908933d30cSUwe Kleine-König val);
191841e6f90SAriel D'Alessandro }
192841e6f90SAriel D'Alessandro
lpc18xx_pwm_config(struct pwm_chip * chip,struct pwm_device * pwm,int duty_ns,int period_ns)193841e6f90SAriel D'Alessandro static int lpc18xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
194841e6f90SAriel D'Alessandro int duty_ns, int period_ns)
195841e6f90SAriel D'Alessandro {
196841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
197841e6f90SAriel D'Alessandro int requested_events, i;
198841e6f90SAriel D'Alessandro
199841e6f90SAriel D'Alessandro if (period_ns < lpc18xx_pwm->min_period_ns ||
200841e6f90SAriel D'Alessandro period_ns > lpc18xx_pwm->max_period_ns) {
201841e6f90SAriel D'Alessandro dev_err(chip->dev, "period %d not in range\n", period_ns);
202841e6f90SAriel D'Alessandro return -ERANGE;
203841e6f90SAriel D'Alessandro }
204841e6f90SAriel D'Alessandro
205841e6f90SAriel D'Alessandro mutex_lock(&lpc18xx_pwm->period_lock);
206841e6f90SAriel D'Alessandro
207841e6f90SAriel D'Alessandro requested_events = bitmap_weight(&lpc18xx_pwm->event_map,
208841e6f90SAriel D'Alessandro LPC18XX_PWM_EVENT_MAX);
209841e6f90SAriel D'Alessandro
210841e6f90SAriel D'Alessandro /*
211841e6f90SAriel D'Alessandro * The PWM supports only a single period for all PWM channels.
212841e6f90SAriel D'Alessandro * Once the period is set, it can only be changed if no more than one
213841e6f90SAriel D'Alessandro * channel is requested at that moment.
214841e6f90SAriel D'Alessandro */
215841e6f90SAriel D'Alessandro if (requested_events > 2 && lpc18xx_pwm->period_ns != period_ns &&
216841e6f90SAriel D'Alessandro lpc18xx_pwm->period_ns) {
217841e6f90SAriel D'Alessandro dev_err(chip->dev, "conflicting period requested for PWM %u\n",
218841e6f90SAriel D'Alessandro pwm->hwpwm);
219841e6f90SAriel D'Alessandro mutex_unlock(&lpc18xx_pwm->period_lock);
220841e6f90SAriel D'Alessandro return -EBUSY;
221841e6f90SAriel D'Alessandro }
222841e6f90SAriel D'Alessandro
223841e6f90SAriel D'Alessandro if ((requested_events <= 2 && lpc18xx_pwm->period_ns != period_ns) ||
224841e6f90SAriel D'Alessandro !lpc18xx_pwm->period_ns) {
225841e6f90SAriel D'Alessandro lpc18xx_pwm->period_ns = period_ns;
226841e6f90SAriel D'Alessandro for (i = 0; i < chip->npwm; i++)
227841e6f90SAriel D'Alessandro pwm_set_period(&chip->pwms[i], period_ns);
228841e6f90SAriel D'Alessandro lpc18xx_pwm_config_period(chip, period_ns);
229841e6f90SAriel D'Alessandro }
230841e6f90SAriel D'Alessandro
231841e6f90SAriel D'Alessandro mutex_unlock(&lpc18xx_pwm->period_lock);
232841e6f90SAriel D'Alessandro
233841e6f90SAriel D'Alessandro lpc18xx_pwm_config_duty(chip, pwm, duty_ns);
234841e6f90SAriel D'Alessandro
235841e6f90SAriel D'Alessandro return 0;
236841e6f90SAriel D'Alessandro }
237841e6f90SAriel D'Alessandro
lpc18xx_pwm_enable(struct pwm_chip * chip,struct pwm_device * pwm,enum pwm_polarity polarity)238c449a8caSUwe Kleine-König static int lpc18xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, enum pwm_polarity polarity)
239841e6f90SAriel D'Alessandro {
240841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
2419136a39eSUwe Kleine-König struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
242841e6f90SAriel D'Alessandro enum lpc18xx_pwm_res_action res_action;
243841e6f90SAriel D'Alessandro unsigned int set_event, clear_event;
244841e6f90SAriel D'Alessandro
245841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
246841e6f90SAriel D'Alessandro LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event),
247841e6f90SAriel D'Alessandro LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_data->duty_event) |
248841e6f90SAriel D'Alessandro LPC18XX_PWM_EVCTRL_COMB_MATCH);
249841e6f90SAriel D'Alessandro
250841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
251841e6f90SAriel D'Alessandro LPC18XX_PWM_EVSTATEMSK(lpc18xx_data->duty_event),
252841e6f90SAriel D'Alessandro LPC18XX_PWM_EVSTATEMSK_ALL);
253841e6f90SAriel D'Alessandro
254c449a8caSUwe Kleine-König if (polarity == PWM_POLARITY_NORMAL) {
255841e6f90SAriel D'Alessandro set_event = lpc18xx_pwm->period_event;
256841e6f90SAriel D'Alessandro clear_event = lpc18xx_data->duty_event;
257841e6f90SAriel D'Alessandro res_action = LPC18XX_PWM_RES_SET;
258841e6f90SAriel D'Alessandro } else {
259841e6f90SAriel D'Alessandro set_event = lpc18xx_data->duty_event;
260841e6f90SAriel D'Alessandro clear_event = lpc18xx_pwm->period_event;
261841e6f90SAriel D'Alessandro res_action = LPC18XX_PWM_RES_CLEAR;
262841e6f90SAriel D'Alessandro }
263841e6f90SAriel D'Alessandro
264841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm),
265841e6f90SAriel D'Alessandro BIT(set_event));
266841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm),
267841e6f90SAriel D'Alessandro BIT(clear_event));
268841e6f90SAriel D'Alessandro lpc18xx_pwm_set_conflict_res(lpc18xx_pwm, pwm, res_action);
269841e6f90SAriel D'Alessandro
270841e6f90SAriel D'Alessandro return 0;
271841e6f90SAriel D'Alessandro }
272841e6f90SAriel D'Alessandro
lpc18xx_pwm_disable(struct pwm_chip * chip,struct pwm_device * pwm)273841e6f90SAriel D'Alessandro static void lpc18xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
274841e6f90SAriel D'Alessandro {
275841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
2769136a39eSUwe Kleine-König struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
277841e6f90SAriel D'Alessandro
278841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
279841e6f90SAriel D'Alessandro LPC18XX_PWM_EVCTRL(lpc18xx_data->duty_event), 0);
280841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTSET(pwm->hwpwm), 0);
281841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_OUTPUTCL(pwm->hwpwm), 0);
282841e6f90SAriel D'Alessandro }
283841e6f90SAriel D'Alessandro
lpc18xx_pwm_request(struct pwm_chip * chip,struct pwm_device * pwm)284841e6f90SAriel D'Alessandro static int lpc18xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
285841e6f90SAriel D'Alessandro {
286841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
2879136a39eSUwe Kleine-König struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
288841e6f90SAriel D'Alessandro unsigned long event;
289841e6f90SAriel D'Alessandro
290841e6f90SAriel D'Alessandro event = find_first_zero_bit(&lpc18xx_pwm->event_map,
291841e6f90SAriel D'Alessandro LPC18XX_PWM_EVENT_MAX);
292841e6f90SAriel D'Alessandro
293841e6f90SAriel D'Alessandro if (event >= LPC18XX_PWM_EVENT_MAX) {
294841e6f90SAriel D'Alessandro dev_err(lpc18xx_pwm->dev,
295841e6f90SAriel D'Alessandro "maximum number of simultaneous channels reached\n");
296841e6f90SAriel D'Alessandro return -EBUSY;
2979a9dd7e4SYang Li }
298841e6f90SAriel D'Alessandro
299841e6f90SAriel D'Alessandro set_bit(event, &lpc18xx_pwm->event_map);
300841e6f90SAriel D'Alessandro lpc18xx_data->duty_event = event;
301841e6f90SAriel D'Alessandro
302841e6f90SAriel D'Alessandro return 0;
303841e6f90SAriel D'Alessandro }
304841e6f90SAriel D'Alessandro
lpc18xx_pwm_free(struct pwm_chip * chip,struct pwm_device * pwm)305841e6f90SAriel D'Alessandro static void lpc18xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
306841e6f90SAriel D'Alessandro {
307841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = to_lpc18xx_pwm_chip(chip);
3089136a39eSUwe Kleine-König struct lpc18xx_pwm_data *lpc18xx_data = &lpc18xx_pwm->channeldata[pwm->hwpwm];
309841e6f90SAriel D'Alessandro
310841e6f90SAriel D'Alessandro clear_bit(lpc18xx_data->duty_event, &lpc18xx_pwm->event_map);
311841e6f90SAriel D'Alessandro }
312841e6f90SAriel D'Alessandro
lpc18xx_pwm_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)313c449a8caSUwe Kleine-König static int lpc18xx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
314c449a8caSUwe Kleine-König const struct pwm_state *state)
315c449a8caSUwe Kleine-König {
316c449a8caSUwe Kleine-König int err;
317c449a8caSUwe Kleine-König bool enabled = pwm->state.enabled;
318c449a8caSUwe Kleine-König
319c449a8caSUwe Kleine-König if (state->polarity != pwm->state.polarity && pwm->state.enabled) {
320c449a8caSUwe Kleine-König lpc18xx_pwm_disable(chip, pwm);
321c449a8caSUwe Kleine-König enabled = false;
322c449a8caSUwe Kleine-König }
323c449a8caSUwe Kleine-König
324c449a8caSUwe Kleine-König if (!state->enabled) {
325c449a8caSUwe Kleine-König if (enabled)
326c449a8caSUwe Kleine-König lpc18xx_pwm_disable(chip, pwm);
327c449a8caSUwe Kleine-König
328c449a8caSUwe Kleine-König return 0;
329c449a8caSUwe Kleine-König }
330c449a8caSUwe Kleine-König
331c449a8caSUwe Kleine-König err = lpc18xx_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period);
332c449a8caSUwe Kleine-König if (err)
333c449a8caSUwe Kleine-König return err;
334c449a8caSUwe Kleine-König
335c449a8caSUwe Kleine-König if (!enabled)
336c449a8caSUwe Kleine-König err = lpc18xx_pwm_enable(chip, pwm, state->polarity);
337c449a8caSUwe Kleine-König
338c449a8caSUwe Kleine-König return err;
339c449a8caSUwe Kleine-König }
340841e6f90SAriel D'Alessandro static const struct pwm_ops lpc18xx_pwm_ops = {
341c449a8caSUwe Kleine-König .apply = lpc18xx_pwm_apply,
342841e6f90SAriel D'Alessandro .request = lpc18xx_pwm_request,
343841e6f90SAriel D'Alessandro .free = lpc18xx_pwm_free,
344841e6f90SAriel D'Alessandro .owner = THIS_MODULE,
345841e6f90SAriel D'Alessandro };
346841e6f90SAriel D'Alessandro
347841e6f90SAriel D'Alessandro static const struct of_device_id lpc18xx_pwm_of_match[] = {
348841e6f90SAriel D'Alessandro { .compatible = "nxp,lpc1850-sct-pwm" },
349841e6f90SAriel D'Alessandro {}
350841e6f90SAriel D'Alessandro };
351841e6f90SAriel D'Alessandro MODULE_DEVICE_TABLE(of, lpc18xx_pwm_of_match);
352841e6f90SAriel D'Alessandro
lpc18xx_pwm_probe(struct platform_device * pdev)353841e6f90SAriel D'Alessandro static int lpc18xx_pwm_probe(struct platform_device *pdev)
354841e6f90SAriel D'Alessandro {
355841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm;
3569136a39eSUwe Kleine-König int ret;
357841e6f90SAriel D'Alessandro u64 val;
358841e6f90SAriel D'Alessandro
359841e6f90SAriel D'Alessandro lpc18xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*lpc18xx_pwm),
360841e6f90SAriel D'Alessandro GFP_KERNEL);
361841e6f90SAriel D'Alessandro if (!lpc18xx_pwm)
362841e6f90SAriel D'Alessandro return -ENOMEM;
363841e6f90SAriel D'Alessandro
364841e6f90SAriel D'Alessandro lpc18xx_pwm->dev = &pdev->dev;
365841e6f90SAriel D'Alessandro
36674ec20a4SYangtao Li lpc18xx_pwm->base = devm_platform_ioremap_resource(pdev, 0);
367841e6f90SAriel D'Alessandro if (IS_ERR(lpc18xx_pwm->base))
368841e6f90SAriel D'Alessandro return PTR_ERR(lpc18xx_pwm->base);
369841e6f90SAriel D'Alessandro
370*4aed0ccdSUwe Kleine-König lpc18xx_pwm->pwm_clk = devm_clk_get_enabled(&pdev->dev, "pwm");
3712ba1aedeSUwe Kleine-König if (IS_ERR(lpc18xx_pwm->pwm_clk))
3722ba1aedeSUwe Kleine-König return dev_err_probe(&pdev->dev, PTR_ERR(lpc18xx_pwm->pwm_clk),
3732ba1aedeSUwe Kleine-König "failed to get pwm clock\n");
374841e6f90SAriel D'Alessandro
375841e6f90SAriel D'Alessandro lpc18xx_pwm->clk_rate = clk_get_rate(lpc18xx_pwm->pwm_clk);
376*4aed0ccdSUwe Kleine-König if (!lpc18xx_pwm->clk_rate)
377*4aed0ccdSUwe Kleine-König return dev_err_probe(&pdev->dev,
3782ba1aedeSUwe Kleine-König -EINVAL, "pwm clock has no frequency\n");
379841e6f90SAriel D'Alessandro
3808933d30cSUwe Kleine-König /*
3818933d30cSUwe Kleine-König * If clkrate is too fast, the calculations in .apply() might overflow.
3828933d30cSUwe Kleine-König */
383*4aed0ccdSUwe Kleine-König if (lpc18xx_pwm->clk_rate > NSEC_PER_SEC)
384*4aed0ccdSUwe Kleine-König return dev_err_probe(&pdev->dev, -EINVAL, "pwm clock to fast\n");
3858933d30cSUwe Kleine-König
386841e6f90SAriel D'Alessandro mutex_init(&lpc18xx_pwm->res_lock);
387841e6f90SAriel D'Alessandro mutex_init(&lpc18xx_pwm->period_lock);
388841e6f90SAriel D'Alessandro
3898933d30cSUwe Kleine-König lpc18xx_pwm->max_period_ns =
3908933d30cSUwe Kleine-König mul_u64_u64_div_u64(NSEC_PER_SEC, LPC18XX_PWM_TIMER_MAX, lpc18xx_pwm->clk_rate);
391841e6f90SAriel D'Alessandro
392841e6f90SAriel D'Alessandro lpc18xx_pwm->min_period_ns = DIV_ROUND_UP(NSEC_PER_SEC,
393841e6f90SAriel D'Alessandro lpc18xx_pwm->clk_rate);
394841e6f90SAriel D'Alessandro
395841e6f90SAriel D'Alessandro lpc18xx_pwm->chip.dev = &pdev->dev;
396841e6f90SAriel D'Alessandro lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops;
39720d9de9cSUwe Kleine-König lpc18xx_pwm->chip.npwm = LPC18XX_NUM_PWMS;
398841e6f90SAriel D'Alessandro
399841e6f90SAriel D'Alessandro /* SCT counter must be in unify (32 bit) mode */
400841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG,
401841e6f90SAriel D'Alessandro LPC18XX_PWM_CONFIG_UNIFY);
402841e6f90SAriel D'Alessandro
403841e6f90SAriel D'Alessandro /*
404841e6f90SAriel D'Alessandro * Everytime the timer counter reaches the period value, the related
405841e6f90SAriel D'Alessandro * event will be triggered and the counter reset to 0.
406841e6f90SAriel D'Alessandro */
407841e6f90SAriel D'Alessandro set_bit(LPC18XX_PWM_EVENT_PERIOD, &lpc18xx_pwm->event_map);
408841e6f90SAriel D'Alessandro lpc18xx_pwm->period_event = LPC18XX_PWM_EVENT_PERIOD;
409841e6f90SAriel D'Alessandro
410841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
411841e6f90SAriel D'Alessandro LPC18XX_PWM_EVSTATEMSK(lpc18xx_pwm->period_event),
412841e6f90SAriel D'Alessandro LPC18XX_PWM_EVSTATEMSK_ALL);
413841e6f90SAriel D'Alessandro
414841e6f90SAriel D'Alessandro val = LPC18XX_PWM_EVCTRL_MATCH(lpc18xx_pwm->period_event) |
415841e6f90SAriel D'Alessandro LPC18XX_PWM_EVCTRL_COMB_MATCH;
416841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm,
417841e6f90SAriel D'Alessandro LPC18XX_PWM_EVCTRL(lpc18xx_pwm->period_event), val);
418841e6f90SAriel D'Alessandro
419841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT,
420841e6f90SAriel D'Alessandro BIT(lpc18xx_pwm->period_event));
421841e6f90SAriel D'Alessandro
422841e6f90SAriel D'Alessandro val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
423841e6f90SAriel D'Alessandro val &= ~LPC18XX_PWM_BIDIR;
424841e6f90SAriel D'Alessandro val &= ~LPC18XX_PWM_CTRL_HALT;
425841e6f90SAriel D'Alessandro val &= ~LPC18XX_PWM_PRE_MASK;
426841e6f90SAriel D'Alessandro val |= LPC18XX_PWM_PRE(0);
427841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val);
428841e6f90SAriel D'Alessandro
4290401f24cSUwe Kleine-König ret = pwmchip_add(&lpc18xx_pwm->chip);
430*4aed0ccdSUwe Kleine-König if (ret < 0)
431*4aed0ccdSUwe Kleine-König return dev_err_probe(&pdev->dev, ret, "pwmchip_add failed\n");
4320401f24cSUwe Kleine-König
4330401f24cSUwe Kleine-König platform_set_drvdata(pdev, lpc18xx_pwm);
4340401f24cSUwe Kleine-König
435841e6f90SAriel D'Alessandro return 0;
436841e6f90SAriel D'Alessandro }
437841e6f90SAriel D'Alessandro
lpc18xx_pwm_remove(struct platform_device * pdev)438fbd2d733SUwe Kleine-König static void lpc18xx_pwm_remove(struct platform_device *pdev)
439841e6f90SAriel D'Alessandro {
440841e6f90SAriel D'Alessandro struct lpc18xx_pwm_chip *lpc18xx_pwm = platform_get_drvdata(pdev);
441841e6f90SAriel D'Alessandro u32 val;
442841e6f90SAriel D'Alessandro
443d58a484eSUwe Kleine-König pwmchip_remove(&lpc18xx_pwm->chip);
444d58a484eSUwe Kleine-König
445841e6f90SAriel D'Alessandro val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
446841e6f90SAriel D'Alessandro lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL,
447841e6f90SAriel D'Alessandro val | LPC18XX_PWM_CTRL_HALT);
448841e6f90SAriel D'Alessandro }
449841e6f90SAriel D'Alessandro
450841e6f90SAriel D'Alessandro static struct platform_driver lpc18xx_pwm_driver = {
451841e6f90SAriel D'Alessandro .driver = {
452841e6f90SAriel D'Alessandro .name = "lpc18xx-sct-pwm",
453841e6f90SAriel D'Alessandro .of_match_table = lpc18xx_pwm_of_match,
454841e6f90SAriel D'Alessandro },
455841e6f90SAriel D'Alessandro .probe = lpc18xx_pwm_probe,
456fbd2d733SUwe Kleine-König .remove_new = lpc18xx_pwm_remove,
457841e6f90SAriel D'Alessandro };
458841e6f90SAriel D'Alessandro module_platform_driver(lpc18xx_pwm_driver);
459841e6f90SAriel D'Alessandro
460841e6f90SAriel D'Alessandro MODULE_AUTHOR("Ariel D'Alessandro <ariel@vanguardiasur.com.ar>");
461841e6f90SAriel D'Alessandro MODULE_DESCRIPTION("NXP LPC18xx PWM driver");
462841e6f90SAriel D'Alessandro MODULE_LICENSE("GPL v2");
463