1 Armada 370/XP devices can 'blink' gpio lines with a configurable on
2 and off period. This can be modelled as a PWM.
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
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.
13 Signed-off-by: Andrew Lunn <andrew@lunn.ch>
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
24 --- a/drivers/gpio/Kconfig
25 +++ b/drivers/gpio/Kconfig
26 @@ -287,6 +287,11 @@ config GPIO_MVEBU
28 select GENERIC_IRQ_CHIP
30 +config GPIO_MVEBU_PWM
32 + depends on GPIO_MVEBU
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
49 +++ b/drivers/gpio/gpio-mvebu-pwm.c
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"
60 +static void __iomem *mvebu_gpioreg_blink_select(struct mvebu_gpio_chip *mvchip)
62 + return mvchip->membase + GPIO_BLINK_CNT_SELECT;
65 +static inline struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
67 + return container_of(chip, struct mvebu_pwm, chip);
70 +static inline struct mvebu_gpio_chip *to_mvchip(struct mvebu_pwm *pwm)
72 + return container_of(pwm, struct mvebu_gpio_chip, pwm);
75 +static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwmd)
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;
83 + spin_lock_irqsave(&pwm->lock, flags);
91 + ret = gpiod_request(desc, "mvebu-pwm");
95 + ret = gpiod_direction_output(desc, 0);
101 + pwm->pin = pwmd->pwm - mvchip->chip.base;
106 + spin_unlock_irqrestore(&pwm->lock, flags);
110 +static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwmd)
112 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
113 + struct gpio_desc *desc = gpio_to_desc(pwmd->pwm);
114 + unsigned long flags;
116 + spin_lock_irqsave(&pwm->lock, flags);
119 + spin_unlock_irqrestore(&pwm->lock, flags);
122 +static int mvebu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwmd,
123 + int duty_ns, int period_ns)
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;
131 + val = (unsigned long long) pwm->clk_rate * duty_ns;
132 + do_div(val, NSEC_PER_SEC);
133 + if (val > UINT_MAX)
140 + val = (unsigned long long) pwm->clk_rate * (period_ns - duty_ns);
141 + do_div(val, NSEC_PER_SEC);
142 + if (val > UINT_MAX)
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));
154 + writel_relaxed(on, pwm->membase + BLINK_ON_DURATION);
155 + writel_relaxed(off, pwm->membase + BLINK_OFF_DURATION);
160 +static int mvebu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwmd)
162 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
163 + struct mvebu_gpio_chip *mvchip = to_mvchip(pwm);
165 + mvebu_gpio_blink(&mvchip->chip, pwm->pin, 1);
170 +static void mvebu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwmd)
172 + struct mvebu_pwm *pwm = to_mvebu_pwm(chip);
173 + struct mvebu_gpio_chip *mvchip = to_mvchip(pwm);
175 + mvebu_gpio_blink(&mvchip->chip, pwm->pin, 0);
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,
187 +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
189 + struct mvebu_pwm *pwm = &mvchip->pwm;
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);
198 +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
200 + struct mvebu_pwm *pwm = &mvchip->pwm;
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);
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.
214 +int mvebu_pwm_probe(struct platform_device *pdev,
215 + struct mvebu_gpio_chip *mvchip,
218 + struct device *dev = &pdev->dev;
219 + struct mvebu_pwm *pwm = &mvchip->pwm;
220 + struct resource *res;
222 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm");
226 + mvchip->pwm.membase = devm_ioremap_resource(&pdev->dev, res);
227 + if (IS_ERR(mvchip->pwm.membase))
228 + return PTR_ERR(mvchip->percpu_membase);
230 + if (id < 0 || id > 1)
234 + if (IS_ERR(mvchip->clk))
235 + return PTR_ERR(mvchip->clk);
237 + pwm->clk_rate = clk_get_rate(mvchip->clk);
238 + if (!pwm->clk_rate) {
239 + dev_err(dev, "failed to get clock rate\n");
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;
249 + spin_lock_init(&pwm->lock);
251 + return pwmchip_add(&pwm->chip);
253 --- a/drivers/gpio/gpio-mvebu.c
254 +++ b/drivers/gpio/gpio-mvebu.c
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>
264 +#include "gpio-mvebu.h"
266 * GPIO unit register offsets.
270 #define MVEBU_MAX_GPIO_PER_BANK 32
272 -struct mvebu_gpio_chip {
273 - struct gpio_chip chip;
275 - void __iomem *membase;
276 - void __iomem *percpu_membase;
278 - struct irq_domain *domain;
281 - /* Used to preserve GPIO registers across suspend/resume */
286 - u32 edge_mask_regs[4];
287 - u32 level_mask_regs[4];
291 * Functions returning addresses of individual registers for a given
293 @@ -228,7 +211,7 @@ static int mvebu_gpio_get(struct gpio_ch
294 return (u >> pin) & 1;
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)
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
306 + mvebu_pwm_suspend(mvchip);
311 @@ -660,6 +645,8 @@ static int mvebu_gpio_resume(struct plat
315 + mvebu_pwm_resume(mvchip);
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;
328 @@ -701,10 +687,10 @@ static int mvebu_gpio_probe(struct platf
332 - clk = devm_clk_get(&pdev->dev, NULL);
333 + mvchip->clk = devm_clk_get(&pdev->dev, NULL);
334 /* Not all SoCs require a clock.*/
336 - clk_prepare_enable(clk);
337 + if (!IS_ERR(mvchip->clk))
338 + clk_prepare_enable(mvchip->clk);
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;
347 + /* Armada 370/XP has simple PWM support for gpio lines */
348 + return mvebu_pwm_probe(pdev, mvchip, id);
351 irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
353 +++ b/drivers/gpio/gpio-mvebu.h
356 + * Interface between MVEBU GPIO driver and PWM driver for GPIO pins
358 + * Copyright (C) 2015, Andrew Lunn <andrew@lunn.ch>
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.
365 +#ifndef MVEBU_GPIO_PWM_H
366 +#define MVEBU_GPIO_PWM_H
368 +#define BLINK_ON_DURATION 0x0
369 +#define BLINK_OFF_DURATION 0x4
370 +#define GPIO_BLINK_CNT_SELECT 0x0020
373 + void __iomem *membase;
374 + unsigned long clk_rate;
377 + struct pwm_chip chip;
381 + /* Used to preserve GPIO/PWM registers across suspend /
384 + u32 blink_on_duration;
385 + u32 blink_off_duration;
388 +struct mvebu_gpio_chip {
389 + struct gpio_chip chip;
391 + void __iomem *membase;
392 + void __iomem *percpu_membase;
394 + struct irq_domain *domain;
398 + struct mvebu_pwm pwm;
400 + /* Used to preserve GPIO registers across suspend/resume */
405 + u32 edge_mask_regs[4];
406 + u32 level_mask_regs[4];
409 +void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value);
412 +int mvebu_pwm_probe(struct platform_device *pdev,
413 + struct mvebu_gpio_chip *mvchip,
415 +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip);
416 +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip);
418 +int mvebu_pwm_probe(struct platform_device *pdev,
419 + struct mvebu_gpio_chip *mvchip,
425 +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
429 +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)