1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PWM framework driver for Cirrus Logic EP93xx
5 * Copyright (c) 2009 Matthieu Crapet <mcrapet@gmail.com>
6 * Copyright (c) 2009, 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
8 * EP9301/02 have only one channel:
9 * platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
11 * EP9307 has only one channel:
12 * platform device ep93xx-pwm.0 - PWMOUT
14 * EP9312/15 have two channels:
15 * platform device ep93xx-pwm.0 - PWMOUT
16 * platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <linux/clk.h>
23 #include <linux/err.h>
25 #include <linux/pwm.h>
27 #include <asm/div64.h>
29 #include <linux/soc/cirrus/ep93xx.h> /* for ep93xx_pwm_{acquire,release}_gpio() */
31 #define EP93XX_PWMx_TERM_COUNT 0x00
32 #define EP93XX_PWMx_DUTY_CYCLE 0x04
33 #define EP93XX_PWMx_ENABLE 0x08
34 #define EP93XX_PWMx_INVERT 0x0c
42 static inline struct ep93xx_pwm
*to_ep93xx_pwm(struct pwm_chip
*chip
)
44 return container_of(chip
, struct ep93xx_pwm
, chip
);
47 static int ep93xx_pwm_request(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
49 struct platform_device
*pdev
= to_platform_device(chip
->dev
);
51 return ep93xx_pwm_acquire_gpio(pdev
);
54 static void ep93xx_pwm_free(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
56 struct platform_device
*pdev
= to_platform_device(chip
->dev
);
58 ep93xx_pwm_release_gpio(pdev
);
61 static int ep93xx_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
62 int duty_ns
, int period_ns
)
64 struct ep93xx_pwm
*ep93xx_pwm
= to_ep93xx_pwm(chip
);
65 void __iomem
*base
= ep93xx_pwm
->base
;
67 unsigned long period_cycles
;
68 unsigned long duty_cycles
;
73 * The clock needs to be enabled to access the PWM registers.
74 * Configuration can be changed at any time.
76 if (!pwm_is_enabled(pwm
)) {
77 ret
= clk_enable(ep93xx_pwm
->clk
);
82 c
= clk_get_rate(ep93xx_pwm
->clk
);
84 do_div(c
, 1000000000);
92 if (period_cycles
< 0x10000 && duty_cycles
< 0x10000) {
93 term
= readw(base
+ EP93XX_PWMx_TERM_COUNT
);
95 /* Order is important if PWM is running */
96 if (period_cycles
> term
) {
97 writew(period_cycles
, base
+ EP93XX_PWMx_TERM_COUNT
);
98 writew(duty_cycles
, base
+ EP93XX_PWMx_DUTY_CYCLE
);
100 writew(duty_cycles
, base
+ EP93XX_PWMx_DUTY_CYCLE
);
101 writew(period_cycles
, base
+ EP93XX_PWMx_TERM_COUNT
);
107 if (!pwm_is_enabled(pwm
))
108 clk_disable(ep93xx_pwm
->clk
);
113 static int ep93xx_pwm_polarity(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
114 enum pwm_polarity polarity
)
116 struct ep93xx_pwm
*ep93xx_pwm
= to_ep93xx_pwm(chip
);
120 * The clock needs to be enabled to access the PWM registers.
121 * Polarity can only be changed when the PWM is disabled.
123 ret
= clk_enable(ep93xx_pwm
->clk
);
127 if (polarity
== PWM_POLARITY_INVERSED
)
128 writew(0x1, ep93xx_pwm
->base
+ EP93XX_PWMx_INVERT
);
130 writew(0x0, ep93xx_pwm
->base
+ EP93XX_PWMx_INVERT
);
132 clk_disable(ep93xx_pwm
->clk
);
137 static int ep93xx_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
139 struct ep93xx_pwm
*ep93xx_pwm
= to_ep93xx_pwm(chip
);
142 ret
= clk_enable(ep93xx_pwm
->clk
);
146 writew(0x1, ep93xx_pwm
->base
+ EP93XX_PWMx_ENABLE
);
151 static void ep93xx_pwm_disable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
153 struct ep93xx_pwm
*ep93xx_pwm
= to_ep93xx_pwm(chip
);
155 writew(0x0, ep93xx_pwm
->base
+ EP93XX_PWMx_ENABLE
);
156 clk_disable(ep93xx_pwm
->clk
);
159 static const struct pwm_ops ep93xx_pwm_ops
= {
160 .request
= ep93xx_pwm_request
,
161 .free
= ep93xx_pwm_free
,
162 .config
= ep93xx_pwm_config
,
163 .set_polarity
= ep93xx_pwm_polarity
,
164 .enable
= ep93xx_pwm_enable
,
165 .disable
= ep93xx_pwm_disable
,
166 .owner
= THIS_MODULE
,
169 static int ep93xx_pwm_probe(struct platform_device
*pdev
)
171 struct ep93xx_pwm
*ep93xx_pwm
;
172 struct resource
*res
;
175 ep93xx_pwm
= devm_kzalloc(&pdev
->dev
, sizeof(*ep93xx_pwm
), GFP_KERNEL
);
179 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
180 ep93xx_pwm
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
181 if (IS_ERR(ep93xx_pwm
->base
))
182 return PTR_ERR(ep93xx_pwm
->base
);
184 ep93xx_pwm
->clk
= devm_clk_get(&pdev
->dev
, "pwm_clk");
185 if (IS_ERR(ep93xx_pwm
->clk
))
186 return PTR_ERR(ep93xx_pwm
->clk
);
188 ep93xx_pwm
->chip
.dev
= &pdev
->dev
;
189 ep93xx_pwm
->chip
.ops
= &ep93xx_pwm_ops
;
190 ep93xx_pwm
->chip
.base
= -1;
191 ep93xx_pwm
->chip
.npwm
= 1;
193 ret
= pwmchip_add(&ep93xx_pwm
->chip
);
197 platform_set_drvdata(pdev
, ep93xx_pwm
);
201 static int ep93xx_pwm_remove(struct platform_device
*pdev
)
203 struct ep93xx_pwm
*ep93xx_pwm
= platform_get_drvdata(pdev
);
205 return pwmchip_remove(&ep93xx_pwm
->chip
);
208 static struct platform_driver ep93xx_pwm_driver
= {
210 .name
= "ep93xx-pwm",
212 .probe
= ep93xx_pwm_probe
,
213 .remove
= ep93xx_pwm_remove
,
215 module_platform_driver(ep93xx_pwm_driver
);
217 MODULE_DESCRIPTION("Cirrus Logic EP93xx PWM driver");
218 MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
219 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
220 MODULE_ALIAS("platform:ep93xx-pwm");
221 MODULE_LICENSE("GPL");