1 // SPDX-License-Identifier: GPL-2.0
3 * simple driver for PWM (Pulse Width Modulator) controller
5 * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
8 #include <linux/bitfield.h>
9 #include <linux/bitops.h>
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/err.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
17 #include <linux/of_device.h>
18 #include <linux/platform_device.h>
19 #include <linux/pwm.h>
20 #include <linux/slab.h>
22 #define MX3_PWMCR 0x00 /* PWM Control Register */
23 #define MX3_PWMSR 0x04 /* PWM Status Register */
24 #define MX3_PWMSAR 0x0C /* PWM Sample Register */
25 #define MX3_PWMPR 0x10 /* PWM Period Register */
27 #define MX3_PWMCR_FWM GENMASK(27, 26)
28 #define MX3_PWMCR_STOPEN BIT(25)
29 #define MX3_PWMCR_DOZEN BIT(24)
30 #define MX3_PWMCR_WAITEN BIT(23)
31 #define MX3_PWMCR_DBGEN BIT(22)
32 #define MX3_PWMCR_BCTR BIT(21)
33 #define MX3_PWMCR_HCTR BIT(20)
35 #define MX3_PWMCR_POUTC GENMASK(19, 18)
36 #define MX3_PWMCR_POUTC_NORMAL 0
37 #define MX3_PWMCR_POUTC_INVERTED 1
38 #define MX3_PWMCR_POUTC_OFF 2
40 #define MX3_PWMCR_CLKSRC GENMASK(17, 16)
41 #define MX3_PWMCR_CLKSRC_OFF 0
42 #define MX3_PWMCR_CLKSRC_IPG 1
43 #define MX3_PWMCR_CLKSRC_IPG_HIGH 2
44 #define MX3_PWMCR_CLKSRC_IPG_32K 3
46 #define MX3_PWMCR_PRESCALER GENMASK(15, 4)
48 #define MX3_PWMCR_SWR BIT(3)
50 #define MX3_PWMCR_REPEAT GENMASK(2, 1)
51 #define MX3_PWMCR_REPEAT_1X 0
52 #define MX3_PWMCR_REPEAT_2X 1
53 #define MX3_PWMCR_REPEAT_4X 2
54 #define MX3_PWMCR_REPEAT_8X 3
56 #define MX3_PWMCR_EN BIT(0)
58 #define MX3_PWMSR_FWE BIT(6)
59 #define MX3_PWMSR_CMP BIT(5)
60 #define MX3_PWMSR_ROV BIT(4)
61 #define MX3_PWMSR_FE BIT(3)
63 #define MX3_PWMSR_FIFOAV GENMASK(2, 0)
64 #define MX3_PWMSR_FIFOAV_EMPTY 0
65 #define MX3_PWMSR_FIFOAV_1WORD 1
66 #define MX3_PWMSR_FIFOAV_2WORDS 2
67 #define MX3_PWMSR_FIFOAV_3WORDS 3
68 #define MX3_PWMSR_FIFOAV_4WORDS 4
70 #define MX3_PWMCR_PRESCALER_SET(x) FIELD_PREP(MX3_PWMCR_PRESCALER, (x) - 1)
71 #define MX3_PWMCR_PRESCALER_GET(x) (FIELD_GET(MX3_PWMCR_PRESCALER, \
74 #define MX3_PWM_SWR_LOOP 5
76 /* PWMPR register value of 0xffff has the same effect as 0xfffe */
77 #define MX3_PWMPR_MAX 0xfffe
79 struct pwm_imx27_chip
{
82 void __iomem
*mmio_base
;
86 #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip)
88 static int pwm_imx27_clk_prepare_enable(struct pwm_chip
*chip
)
90 struct pwm_imx27_chip
*imx
= to_pwm_imx27_chip(chip
);
93 ret
= clk_prepare_enable(imx
->clk_ipg
);
97 ret
= clk_prepare_enable(imx
->clk_per
);
99 clk_disable_unprepare(imx
->clk_ipg
);
106 static void pwm_imx27_clk_disable_unprepare(struct pwm_chip
*chip
)
108 struct pwm_imx27_chip
*imx
= to_pwm_imx27_chip(chip
);
110 clk_disable_unprepare(imx
->clk_per
);
111 clk_disable_unprepare(imx
->clk_ipg
);
114 static void pwm_imx27_get_state(struct pwm_chip
*chip
,
115 struct pwm_device
*pwm
, struct pwm_state
*state
)
117 struct pwm_imx27_chip
*imx
= to_pwm_imx27_chip(chip
);
118 u32 period
, prescaler
, pwm_clk
, val
;
122 ret
= pwm_imx27_clk_prepare_enable(chip
);
126 val
= readl(imx
->mmio_base
+ MX3_PWMCR
);
128 if (val
& MX3_PWMCR_EN
)
129 state
->enabled
= true;
131 state
->enabled
= false;
133 switch (FIELD_GET(MX3_PWMCR_POUTC
, val
)) {
134 case MX3_PWMCR_POUTC_NORMAL
:
135 state
->polarity
= PWM_POLARITY_NORMAL
;
137 case MX3_PWMCR_POUTC_INVERTED
:
138 state
->polarity
= PWM_POLARITY_INVERSED
;
141 dev_warn(chip
->dev
, "can't set polarity, output disconnected");
144 prescaler
= MX3_PWMCR_PRESCALER_GET(val
);
145 pwm_clk
= clk_get_rate(imx
->clk_per
);
146 pwm_clk
= DIV_ROUND_CLOSEST_ULL(pwm_clk
, prescaler
);
147 val
= readl(imx
->mmio_base
+ MX3_PWMPR
);
148 period
= val
>= MX3_PWMPR_MAX
? MX3_PWMPR_MAX
: val
;
150 /* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */
151 tmp
= NSEC_PER_SEC
* (u64
)(period
+ 2);
152 state
->period
= DIV_ROUND_CLOSEST_ULL(tmp
, pwm_clk
);
154 /* PWMSAR can be read only if PWM is enabled */
155 if (state
->enabled
) {
156 val
= readl(imx
->mmio_base
+ MX3_PWMSAR
);
157 tmp
= NSEC_PER_SEC
* (u64
)(val
);
158 state
->duty_cycle
= DIV_ROUND_CLOSEST_ULL(tmp
, pwm_clk
);
160 state
->duty_cycle
= 0;
164 pwm_imx27_clk_disable_unprepare(chip
);
167 static void pwm_imx27_sw_reset(struct pwm_chip
*chip
)
169 struct pwm_imx27_chip
*imx
= to_pwm_imx27_chip(chip
);
170 struct device
*dev
= chip
->dev
;
174 writel(MX3_PWMCR_SWR
, imx
->mmio_base
+ MX3_PWMCR
);
176 usleep_range(200, 1000);
177 cr
= readl(imx
->mmio_base
+ MX3_PWMCR
);
178 } while ((cr
& MX3_PWMCR_SWR
) &&
179 (wait_count
++ < MX3_PWM_SWR_LOOP
));
181 if (cr
& MX3_PWMCR_SWR
)
182 dev_warn(dev
, "software reset timeout\n");
185 static void pwm_imx27_wait_fifo_slot(struct pwm_chip
*chip
,
186 struct pwm_device
*pwm
)
188 struct pwm_imx27_chip
*imx
= to_pwm_imx27_chip(chip
);
189 struct device
*dev
= chip
->dev
;
190 unsigned int period_ms
;
194 sr
= readl(imx
->mmio_base
+ MX3_PWMSR
);
195 fifoav
= FIELD_GET(MX3_PWMSR_FIFOAV
, sr
);
196 if (fifoav
== MX3_PWMSR_FIFOAV_4WORDS
) {
197 period_ms
= DIV_ROUND_UP(pwm_get_period(pwm
),
201 sr
= readl(imx
->mmio_base
+ MX3_PWMSR
);
202 if (fifoav
== FIELD_GET(MX3_PWMSR_FIFOAV
, sr
))
203 dev_warn(dev
, "there is no free FIFO slot\n");
207 static int pwm_imx27_apply(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
208 struct pwm_state
*state
)
210 unsigned long period_cycles
, duty_cycles
, prescale
;
211 struct pwm_imx27_chip
*imx
= to_pwm_imx27_chip(chip
);
212 struct pwm_state cstate
;
213 unsigned long long c
;
217 pwm_get_state(pwm
, &cstate
);
219 if (state
->enabled
) {
220 c
= clk_get_rate(imx
->clk_per
);
223 do_div(c
, 1000000000);
226 prescale
= period_cycles
/ 0x10000 + 1;
228 period_cycles
/= prescale
;
229 c
= (unsigned long long)period_cycles
* state
->duty_cycle
;
230 do_div(c
, state
->period
);
234 * according to imx pwm RM, the real period value should be
235 * PERIOD value in PWMPR plus 2.
237 if (period_cycles
> 2)
243 * Wait for a free FIFO slot if the PWM is already enabled, and
244 * flush the FIFO if the PWM was disabled and is about to be
247 if (cstate
.enabled
) {
248 pwm_imx27_wait_fifo_slot(chip
, pwm
);
250 ret
= pwm_imx27_clk_prepare_enable(chip
);
254 pwm_imx27_sw_reset(chip
);
257 writel(duty_cycles
, imx
->mmio_base
+ MX3_PWMSAR
);
258 writel(period_cycles
, imx
->mmio_base
+ MX3_PWMPR
);
260 cr
= MX3_PWMCR_PRESCALER_SET(prescale
) |
261 MX3_PWMCR_STOPEN
| MX3_PWMCR_DOZEN
| MX3_PWMCR_WAITEN
|
262 FIELD_PREP(MX3_PWMCR_CLKSRC
, MX3_PWMCR_CLKSRC_IPG_HIGH
) |
263 MX3_PWMCR_DBGEN
| MX3_PWMCR_EN
;
265 if (state
->polarity
== PWM_POLARITY_INVERSED
)
266 cr
|= FIELD_PREP(MX3_PWMCR_POUTC
,
267 MX3_PWMCR_POUTC_INVERTED
);
269 writel(cr
, imx
->mmio_base
+ MX3_PWMCR
);
270 } else if (cstate
.enabled
) {
271 writel(0, imx
->mmio_base
+ MX3_PWMCR
);
273 pwm_imx27_clk_disable_unprepare(chip
);
279 static const struct pwm_ops pwm_imx27_ops
= {
280 .apply
= pwm_imx27_apply
,
281 .get_state
= pwm_imx27_get_state
,
282 .owner
= THIS_MODULE
,
285 static const struct of_device_id pwm_imx27_dt_ids
[] = {
286 { .compatible
= "fsl,imx27-pwm", },
289 MODULE_DEVICE_TABLE(of
, pwm_imx27_dt_ids
);
291 static int pwm_imx27_probe(struct platform_device
*pdev
)
293 struct pwm_imx27_chip
*imx
;
295 imx
= devm_kzalloc(&pdev
->dev
, sizeof(*imx
), GFP_KERNEL
);
299 platform_set_drvdata(pdev
, imx
);
301 imx
->clk_ipg
= devm_clk_get(&pdev
->dev
, "ipg");
302 if (IS_ERR(imx
->clk_ipg
)) {
303 dev_err(&pdev
->dev
, "getting ipg clock failed with %ld\n",
304 PTR_ERR(imx
->clk_ipg
));
305 return PTR_ERR(imx
->clk_ipg
);
308 imx
->clk_per
= devm_clk_get(&pdev
->dev
, "per");
309 if (IS_ERR(imx
->clk_per
)) {
310 int ret
= PTR_ERR(imx
->clk_per
);
312 if (ret
!= -EPROBE_DEFER
)
314 "failed to get peripheral clock: %d\n",
320 imx
->chip
.ops
= &pwm_imx27_ops
;
321 imx
->chip
.dev
= &pdev
->dev
;
325 imx
->chip
.of_xlate
= of_pwm_xlate_with_flags
;
326 imx
->chip
.of_pwm_n_cells
= 3;
328 imx
->mmio_base
= devm_platform_ioremap_resource(pdev
, 0);
329 if (IS_ERR(imx
->mmio_base
))
330 return PTR_ERR(imx
->mmio_base
);
332 return pwmchip_add(&imx
->chip
);
335 static int pwm_imx27_remove(struct platform_device
*pdev
)
337 struct pwm_imx27_chip
*imx
;
339 imx
= platform_get_drvdata(pdev
);
341 pwm_imx27_clk_disable_unprepare(&imx
->chip
);
343 return pwmchip_remove(&imx
->chip
);
346 static struct platform_driver imx_pwm_driver
= {
349 .of_match_table
= pwm_imx27_dt_ids
,
351 .probe
= pwm_imx27_probe
,
352 .remove
= pwm_imx27_remove
,
354 module_platform_driver(imx_pwm_driver
);
356 MODULE_LICENSE("GPL v2");
357 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");