178e5f5acb40321c4f2cf61257449aee965b932d
[openwrt/openwrt.git] / target / linux / mvebu / patches-4.1 / 202-gpio_mvebu_add_limited_pwm_support.patch
1 Armada 370/XP devices can 'blink' gpio lines with a configurable on
2 and off period. This can be modelled as a PWM.
3
4 However, there are only two sets of PWM configuration registers for
5 all the gpio lines. This driver simply allows a single gpio line per
6 gpio chip of 32 lines to be used as a PWM. Attempts to use more return
7 EBUSY.
8
9 Due to the interleaving of registers it is not simple to separate the
10 PWM driver from the gpio driver. Thus the gpio driver has been
11 extended with a PWM driver.
12
13 Signed-off-by: Andrew Lunn <andrew@lunn.ch>
14 ---
15 drivers/gpio/Kconfig | 5 ++
16 drivers/gpio/Makefile | 1 +
17 drivers/gpio/gpio-mvebu-pwm.c | 202 ++++++++++++++++++++++++++++++++++++++++++
18 drivers/gpio/gpio-mvebu.c | 37 +++-----
19 drivers/gpio/gpio-mvebu.h | 79 +++++++++++++++++
20 5 files changed, 299 insertions(+), 25 deletions(-)
21 create mode 100644 drivers/gpio/gpio-mvebu-pwm.c
22 create mode 100644 drivers/gpio/gpio-mvebu.h
23
24 --- a/drivers/gpio/Kconfig
25 +++ b/drivers/gpio/Kconfig
26 @@ -287,6 +287,11 @@ config GPIO_MVEBU
27 select GPIO_GENERIC
28 select GENERIC_IRQ_CHIP
29
30 +config GPIO_MVEBU_PWM
31 + def_bool y
32 + depends on GPIO_MVEBU
33 + depends on PWM
34 +
35 config GPIO_MXC
36 def_bool y
37 depends on ARCH_MXC
38 --- a/drivers/gpio/Makefile
39 +++ b/drivers/gpio/Makefile
40 @@ -62,6 +62,7 @@ obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8x
41 obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
42 obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
43 obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
44 +obj-$(CONFIG_GPIO_MVEBU_PWM) += gpio-mvebu-pwm.o
45 obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
46 obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
47 obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
48 --- /dev/null
49 +++ b/drivers/gpio/gpio-mvebu-pwm.c
50 @@ -0,0 +1,202 @@
51 +#include <linux/err.h>
52 +#include <linux/module.h>
53 +#include <linux/gpio.h>
54 +#include <linux/pwm.h>
55 +#include <linux/clk.h>
56 +#include <linux/platform_device.h>
57 +#include "gpio-mvebu.h"
58 +#include "gpiolib.h"
59 +
60 +static void __iomem *mvebu_gpioreg_blink_select(struct mvebu_gpio_chip *mvchip)
61 +{
62 + return mvchip->membase + GPIO_BLINK_CNT_SELECT;
63 +}
64 +
65 +static inline struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
66 +{
67 + return container_of(chip, struct mvebu_pwm, chip);
68 +}
69 +
70 +static inline struct mvebu_gpio_chip *to_mvchip(struct mvebu_pwm *pwm)
71 +{
72 + return container_of(pwm, struct mvebu_gpio_chip, pwm);
73 +}
74 +
75 +static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwmd)
76 +{
77 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
78 + struct mvebu_gpio_chip *mvchip = to_mvchip(pwm);
79 + struct gpio_desc *desc = gpio_to_desc(pwmd->pwm);
80 + unsigned long flags;
81 + int ret = 0;
82 +
83 + spin_lock_irqsave(&pwm->lock, flags);
84 + if (pwm->used) {
85 + ret = -EBUSY;
86 + } else {
87 + if (!desc) {
88 + ret = -ENODEV;
89 + goto out;
90 + }
91 + ret = gpiod_request(desc, "mvebu-pwm");
92 + if (ret)
93 + goto out;
94 +
95 + ret = gpiod_direction_output(desc, 0);
96 + if (ret) {
97 + gpiod_free(desc);
98 + goto out;
99 + }
100 +
101 + pwm->pin = pwmd->pwm - mvchip->chip.base;
102 + pwm->used = true;
103 + }
104 +
105 +out:
106 + spin_unlock_irqrestore(&pwm->lock, flags);
107 + return ret;
108 +}
109 +
110 +static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwmd)
111 +{
112 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
113 + struct gpio_desc *desc = gpio_to_desc(pwmd->pwm);
114 + unsigned long flags;
115 +
116 + spin_lock_irqsave(&pwm->lock, flags);
117 + gpiod_free(desc);
118 + pwm->used = false;
119 + spin_unlock_irqrestore(&pwm->lock, flags);
120 +}
121 +
122 +static int mvebu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwmd,
123 + int duty_ns, int period_ns)
124 +{
125 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
126 + struct mvebu_gpio_chip *mvchip = to_mvchip(pwm);
127 + unsigned int on, off;
128 + unsigned long long val;
129 + u32 u;
130 +
131 + val = (unsigned long long) pwm->clk_rate * duty_ns;
132 + do_div(val, NSEC_PER_SEC);
133 + if (val > UINT_MAX)
134 + return -EINVAL;
135 + if (val)
136 + on = val;
137 + else
138 + on = 1;
139 +
140 + val = (unsigned long long) pwm->clk_rate * (period_ns - duty_ns);
141 + do_div(val, NSEC_PER_SEC);
142 + if (val > UINT_MAX)
143 + return -EINVAL;
144 + if (val)
145 + off = val;
146 + else
147 + off = 1;
148 +
149 + u = readl_relaxed(mvebu_gpioreg_blink_select(mvchip));
150 + u &= ~(1 << pwm->pin);
151 + u |= (pwm->id << pwm->pin);
152 + writel_relaxed(u, mvebu_gpioreg_blink_select(mvchip));
153 +
154 + writel_relaxed(on, pwm->membase + BLINK_ON_DURATION);
155 + writel_relaxed(off, pwm->membase + BLINK_OFF_DURATION);
156 +
157 + return 0;
158 +}
159 +
160 +static int mvebu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwmd)
161 +{
162 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
163 + struct mvebu_gpio_chip *mvchip = to_mvchip(pwm);
164 +
165 + mvebu_gpio_blink(&mvchip->chip, pwm->pin, 1);
166 +
167 + return 0;
168 +}
169 +
170 +static void mvebu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwmd)
171 +{
172 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
173 + struct mvebu_gpio_chip *mvchip = to_mvchip(pwm);
174 +
175 + mvebu_gpio_blink(&mvchip->chip, pwm->pin, 0);
176 +}
177 +
178 +static const struct pwm_ops mvebu_pwm_ops = {
179 + .request = mvebu_pwm_request,
180 + .free = mvebu_pwm_free,
181 + .config = mvebu_pwm_config,
182 + .enable = mvebu_pwm_enable,
183 + .disable = mvebu_pwm_disable,
184 + .owner = THIS_MODULE,
185 +};
186 +
187 +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
188 +{
189 + struct mvebu_pwm *pwm = &mvchip->pwm;
190 +
191 + pwm->blink_select = readl_relaxed(mvebu_gpioreg_blink_select(mvchip));
192 + pwm->blink_on_duration =
193 + readl_relaxed(pwm->membase + BLINK_ON_DURATION);
194 + pwm->blink_off_duration =
195 + readl_relaxed(pwm->membase + BLINK_OFF_DURATION);
196 +}
197 +
198 +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
199 +{
200 + struct mvebu_pwm *pwm = &mvchip->pwm;
201 +
202 + writel_relaxed(pwm->blink_select, mvebu_gpioreg_blink_select(mvchip));
203 + writel_relaxed(pwm->blink_on_duration,
204 + pwm->membase + BLINK_ON_DURATION);
205 + writel_relaxed(pwm->blink_off_duration,
206 + pwm->membase + BLINK_OFF_DURATION);
207 +}
208 +
209 +/*
210 + * Armada 370/XP has simple PWM support for gpio lines. Other SoCs
211 + * don't have this hardware. So if we don't have the necessary
212 + * resource, it is not an error.
213 + */
214 +int mvebu_pwm_probe(struct platform_device *pdev,
215 + struct mvebu_gpio_chip *mvchip,
216 + int id)
217 +{
218 + struct device *dev = &pdev->dev;
219 + struct mvebu_pwm *pwm = &mvchip->pwm;
220 + struct resource *res;
221 +
222 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm");
223 + if (!res)
224 + return 0;
225 +
226 + mvchip->pwm.membase = devm_ioremap_resource(&pdev->dev, res);
227 + if (IS_ERR(mvchip->pwm.membase))
228 + return PTR_ERR(mvchip->percpu_membase);
229 +
230 + if (id < 0 || id > 1)
231 + return -EINVAL;
232 + pwm->id = id;
233 +
234 + if (IS_ERR(mvchip->clk))
235 + return PTR_ERR(mvchip->clk);
236 +
237 + pwm->clk_rate = clk_get_rate(mvchip->clk);
238 + if (!pwm->clk_rate) {
239 + dev_err(dev, "failed to get clock rate\n");
240 + return -EINVAL;
241 + }
242 +
243 + pwm->chip.dev = dev;
244 + pwm->chip.ops = &mvebu_pwm_ops;
245 + pwm->chip.base = mvchip->chip.base;
246 + pwm->chip.npwm = mvchip->chip.ngpio;
247 + pwm->chip.can_sleep = false;
248 +
249 + spin_lock_init(&pwm->lock);
250 +
251 + return pwmchip_add(&pwm->chip);
252 +}
253 --- a/drivers/gpio/gpio-mvebu.c
254 +++ b/drivers/gpio/gpio-mvebu.c
255 @@ -42,10 +42,11 @@
256 #include <linux/io.h>
257 #include <linux/of_irq.h>
258 #include <linux/of_device.h>
259 +#include <linux/pwm.h>
260 #include <linux/clk.h>
261 #include <linux/pinctrl/consumer.h>
262 #include <linux/irqchip/chained_irq.h>
263 -
264 +#include "gpio-mvebu.h"
265 /*
266 * GPIO unit register offsets.
267 */
268 @@ -75,24 +76,6 @@
269
270 #define MVEBU_MAX_GPIO_PER_BANK 32
271
272 -struct mvebu_gpio_chip {
273 - struct gpio_chip chip;
274 - spinlock_t lock;
275 - void __iomem *membase;
276 - void __iomem *percpu_membase;
277 - int irqbase;
278 - struct irq_domain *domain;
279 - int soc_variant;
280 -
281 - /* Used to preserve GPIO registers across suspend/resume */
282 - u32 out_reg;
283 - u32 io_conf_reg;
284 - u32 blink_en_reg;
285 - u32 in_pol_reg;
286 - u32 edge_mask_regs[4];
287 - u32 level_mask_regs[4];
288 -};
289 -
290 /*
291 * Functions returning addresses of individual registers for a given
292 * GPIO controller.
293 @@ -228,7 +211,7 @@ static int mvebu_gpio_get(struct gpio_ch
294 return (u >> pin) & 1;
295 }
296
297 -static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
298 +void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
299 {
300 struct mvebu_gpio_chip *mvchip =
301 container_of(chip, struct mvebu_gpio_chip, chip);
302 @@ -617,6 +600,8 @@ static int mvebu_gpio_suspend(struct pla
303 BUG();
304 }
305
306 + mvebu_pwm_suspend(mvchip);
307 +
308 return 0;
309 }
310
311 @@ -660,6 +645,8 @@ static int mvebu_gpio_resume(struct plat
312 BUG();
313 }
314
315 + mvebu_pwm_resume(mvchip);
316 +
317 return 0;
318 }
319
320 @@ -671,7 +658,6 @@ static int mvebu_gpio_probe(struct platf
321 struct resource *res;
322 struct irq_chip_generic *gc;
323 struct irq_chip_type *ct;
324 - struct clk *clk;
325 unsigned int ngpios;
326 int soc_variant;
327 int i, cpu, id;
328 @@ -701,10 +687,10 @@ static int mvebu_gpio_probe(struct platf
329 return id;
330 }
331
332 - clk = devm_clk_get(&pdev->dev, NULL);
333 + mvchip->clk = devm_clk_get(&pdev->dev, NULL);
334 /* Not all SoCs require a clock.*/
335 - if (!IS_ERR(clk))
336 - clk_prepare_enable(clk);
337 + if (!IS_ERR(mvchip->clk))
338 + clk_prepare_enable(mvchip->clk);
339
340 mvchip->soc_variant = soc_variant;
341 mvchip->chip.label = dev_name(&pdev->dev);
342 @@ -838,7 +824,8 @@ static int mvebu_gpio_probe(struct platf
343 goto err_generic_chip;
344 }
345
346 - return 0;
347 + /* Armada 370/XP has simple PWM support for gpio lines */
348 + return mvebu_pwm_probe(pdev, mvchip, id);
349
350 err_generic_chip:
351 irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
352 --- /dev/null
353 +++ b/drivers/gpio/gpio-mvebu.h
354 @@ -0,0 +1,79 @@
355 +/*
356 + * Interface between MVEBU GPIO driver and PWM driver for GPIO pins
357 + *
358 + * Copyright (C) 2015, Andrew Lunn <andrew@lunn.ch>
359 + *
360 + * This program is free software; you can redistribute it and/or modify
361 + * it under the terms of the GNU General Public License version 2 as
362 + * published by the Free Software Foundation.
363 + */
364 +
365 +#ifndef MVEBU_GPIO_PWM_H
366 +#define MVEBU_GPIO_PWM_H
367 +
368 +#define BLINK_ON_DURATION 0x0
369 +#define BLINK_OFF_DURATION 0x4
370 +#define GPIO_BLINK_CNT_SELECT 0x0020
371 +
372 +struct mvebu_pwm {
373 + void __iomem *membase;
374 + unsigned long clk_rate;
375 + bool used;
376 + unsigned pin;
377 + struct pwm_chip chip;
378 + int id;
379 + spinlock_t lock;
380 +
381 + /* Used to preserve GPIO/PWM registers across suspend /
382 + * resume */
383 + u32 blink_select;
384 + u32 blink_on_duration;
385 + u32 blink_off_duration;
386 +};
387 +
388 +struct mvebu_gpio_chip {
389 + struct gpio_chip chip;
390 + spinlock_t lock;
391 + void __iomem *membase;
392 + void __iomem *percpu_membase;
393 + int irqbase;
394 + struct irq_domain *domain;
395 + int soc_variant;
396 + struct clk *clk;
397 +#ifdef CONFIG_PWM
398 + struct mvebu_pwm pwm;
399 +#endif
400 + /* Used to preserve GPIO registers across suspend/resume */
401 + u32 out_reg;
402 + u32 io_conf_reg;
403 + u32 blink_en_reg;
404 + u32 in_pol_reg;
405 + u32 edge_mask_regs[4];
406 + u32 level_mask_regs[4];
407 +};
408 +
409 +void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value);
410 +
411 +#ifdef CONFIG_PWM
412 +int mvebu_pwm_probe(struct platform_device *pdev,
413 + struct mvebu_gpio_chip *mvchip,
414 + int id);
415 +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip);
416 +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip);
417 +#else
418 +int mvebu_pwm_probe(struct platform_device *pdev,
419 + struct mvebu_gpio_chip *mvchip,
420 + int id)
421 +{
422 + return 0;
423 +}
424 +
425 +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
426 +{
427 +}
428 +
429 +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
430 +{
431 +}
432 +#endif
433 +#endif