2 * Marvell Berlin PWM driver
4 * Copyright (C) 2015 Marvell Technology Group Ltd.
6 * Author: Antoine Tenart <antoine.tenart@free-electrons.com>
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
13 #include <linux/clk.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/pwm.h>
20 #define BERLIN_PWM_EN 0x0
21 #define BERLIN_PWM_ENABLE BIT(0)
22 #define BERLIN_PWM_CONTROL 0x4
23 #define BERLIN_PWM_PRESCALE_MASK 0x7
24 #define BERLIN_PWM_PRESCALE_MAX 4096
25 #define BERLIN_PWM_INVERT_POLARITY BIT(3)
26 #define BERLIN_PWM_DUTY 0x8
27 #define BERLIN_PWM_TCNT 0xc
28 #define BERLIN_PWM_MAX_TCNT 65535
30 struct berlin_pwm_chip
{
36 static inline struct berlin_pwm_chip
*to_berlin_pwm_chip(struct pwm_chip
*chip
)
38 return container_of(chip
, struct berlin_pwm_chip
, chip
);
41 static const u32 prescaler_table
[] = {
42 1, 4, 8, 16, 64, 256, 1024, 4096
45 static inline u32
berlin_pwm_readl(struct berlin_pwm_chip
*chip
,
46 unsigned int channel
, unsigned long offset
)
48 return readl_relaxed(chip
->base
+ channel
* 0x10 + offset
);
51 static inline void berlin_pwm_writel(struct berlin_pwm_chip
*chip
,
52 unsigned int channel
, u32 value
,
55 writel_relaxed(value
, chip
->base
+ channel
* 0x10 + offset
);
58 static int berlin_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm_dev
,
59 int duty_ns
, int period_ns
)
61 struct berlin_pwm_chip
*pwm
= to_berlin_pwm_chip(chip
);
62 unsigned int prescale
;
63 u32 value
, duty
, period
;
66 cycles
= clk_get_rate(pwm
->clk
);
68 do_div(cycles
, NSEC_PER_SEC
);
70 for (prescale
= 0; prescale
< ARRAY_SIZE(prescaler_table
); prescale
++) {
72 do_div(tmp
, prescaler_table
[prescale
]);
74 if (tmp
<= BERLIN_PWM_MAX_TCNT
)
78 if (tmp
> BERLIN_PWM_MAX_TCNT
)
82 cycles
= tmp
* duty_ns
;
83 do_div(cycles
, period_ns
);
86 value
= berlin_pwm_readl(pwm
, pwm_dev
->hwpwm
, BERLIN_PWM_CONTROL
);
87 value
&= ~BERLIN_PWM_PRESCALE_MASK
;
89 berlin_pwm_writel(pwm
, pwm_dev
->hwpwm
, value
, BERLIN_PWM_CONTROL
);
91 berlin_pwm_writel(pwm
, pwm_dev
->hwpwm
, duty
, BERLIN_PWM_DUTY
);
92 berlin_pwm_writel(pwm
, pwm_dev
->hwpwm
, period
, BERLIN_PWM_TCNT
);
97 static int berlin_pwm_set_polarity(struct pwm_chip
*chip
,
98 struct pwm_device
*pwm_dev
,
99 enum pwm_polarity polarity
)
101 struct berlin_pwm_chip
*pwm
= to_berlin_pwm_chip(chip
);
104 value
= berlin_pwm_readl(pwm
, pwm_dev
->hwpwm
, BERLIN_PWM_CONTROL
);
106 if (polarity
== PWM_POLARITY_NORMAL
)
107 value
&= ~BERLIN_PWM_INVERT_POLARITY
;
109 value
|= BERLIN_PWM_INVERT_POLARITY
;
111 berlin_pwm_writel(pwm
, pwm_dev
->hwpwm
, value
, BERLIN_PWM_CONTROL
);
116 static int berlin_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm_dev
)
118 struct berlin_pwm_chip
*pwm
= to_berlin_pwm_chip(chip
);
121 value
= berlin_pwm_readl(pwm
, pwm_dev
->hwpwm
, BERLIN_PWM_EN
);
122 value
|= BERLIN_PWM_ENABLE
;
123 berlin_pwm_writel(pwm
, pwm_dev
->hwpwm
, value
, BERLIN_PWM_EN
);
128 static void berlin_pwm_disable(struct pwm_chip
*chip
,
129 struct pwm_device
*pwm_dev
)
131 struct berlin_pwm_chip
*pwm
= to_berlin_pwm_chip(chip
);
134 value
= berlin_pwm_readl(pwm
, pwm_dev
->hwpwm
, BERLIN_PWM_EN
);
135 value
&= ~BERLIN_PWM_ENABLE
;
136 berlin_pwm_writel(pwm
, pwm_dev
->hwpwm
, value
, BERLIN_PWM_EN
);
139 static const struct pwm_ops berlin_pwm_ops
= {
140 .config
= berlin_pwm_config
,
141 .set_polarity
= berlin_pwm_set_polarity
,
142 .enable
= berlin_pwm_enable
,
143 .disable
= berlin_pwm_disable
,
144 .owner
= THIS_MODULE
,
147 static const struct of_device_id berlin_pwm_match
[] = {
148 { .compatible
= "marvell,berlin-pwm" },
151 MODULE_DEVICE_TABLE(of
, berlin_pwm_match
);
153 static int berlin_pwm_probe(struct platform_device
*pdev
)
155 struct berlin_pwm_chip
*pwm
;
156 struct resource
*res
;
159 pwm
= devm_kzalloc(&pdev
->dev
, sizeof(*pwm
), GFP_KERNEL
);
163 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
164 pwm
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
165 if (IS_ERR(pwm
->base
))
166 return PTR_ERR(pwm
->base
);
168 pwm
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
169 if (IS_ERR(pwm
->clk
))
170 return PTR_ERR(pwm
->clk
);
172 ret
= clk_prepare_enable(pwm
->clk
);
176 pwm
->chip
.dev
= &pdev
->dev
;
177 pwm
->chip
.ops
= &berlin_pwm_ops
;
180 pwm
->chip
.can_sleep
= true;
181 pwm
->chip
.of_xlate
= of_pwm_xlate_with_flags
;
182 pwm
->chip
.of_pwm_n_cells
= 3;
184 ret
= pwmchip_add(&pwm
->chip
);
186 dev_err(&pdev
->dev
, "failed to add PWM chip: %d\n", ret
);
187 clk_disable_unprepare(pwm
->clk
);
191 platform_set_drvdata(pdev
, pwm
);
196 static int berlin_pwm_remove(struct platform_device
*pdev
)
198 struct berlin_pwm_chip
*pwm
= platform_get_drvdata(pdev
);
201 ret
= pwmchip_remove(&pwm
->chip
);
202 clk_disable_unprepare(pwm
->clk
);
207 static struct platform_driver berlin_pwm_driver
= {
208 .probe
= berlin_pwm_probe
,
209 .remove
= berlin_pwm_remove
,
211 .name
= "berlin-pwm",
212 .of_match_table
= berlin_pwm_match
,
215 module_platform_driver(berlin_pwm_driver
);
217 MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
218 MODULE_DESCRIPTION("Marvell Berlin PWM driver");
219 MODULE_LICENSE("GPL v2");