[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1532114623-81911-2-git-send-email-aditya@kobol.io>
Date: Sat, 21 Jul 2018 03:23:42 +0800
From: Aditya Prayoga <aditya@...ol.io>
To: linux-gpio@...r.kernel.org
Cc: Gauthier Provost <gauthier@...ol.io>,
Alban Browaeys <alban.browaeys@...il.com>,
Thierry Reding <thierry.reding@...il.com>,
Linus Walleij <linus.walleij@...aro.org>,
linux-pwm@...r.kernel.org, linux-kernel@...r.kernel.org,
Aditya Prayoga <aditya@...ol.io>
Subject: [PATCH 1/2] gpio: mvebu: Add support for multiple PWM lines per GPIO chip
Allow more than 1 PWM request (eg. PWM fan) on the same GPIO chip.
based on initial work on LK4.4 by Alban Browaeys.
URL: https://github.com/helios-4/linux-marvell/commit/743ae97
[Aditya Prayoga: forward port, cleanup]
Signed-off-by: Aditya Prayoga <aditya@...ol.io>
---
drivers/gpio/gpio-mvebu.c | 63 ++++++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 22 deletions(-)
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 6e02148..0617e66 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -92,10 +92,17 @@
#define MVEBU_MAX_GPIO_PER_BANK 32
+struct mvebu_pwm_item {
+ struct gpio_desc *gpiod;
+ struct pwm_device *device;
+ struct list_head node;
+};
+
struct mvebu_pwm {
void __iomem *membase;
unsigned long clk_rate;
- struct gpio_desc *gpiod;
+ int id;
+ struct list_head pwms;
struct pwm_chip chip;
spinlock_t lock;
struct mvebu_gpio_chip *mvchip;
@@ -599,29 +606,31 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
struct gpio_desc *desc;
+ struct mvebu_pwm_item *item;
unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&mvpwm->lock, flags);
-
- if (mvpwm->gpiod) {
- ret = -EBUSY;
- } else {
- desc = gpiochip_request_own_desc(&mvchip->chip,
- pwm->hwpwm, "mvebu-pwm");
- if (IS_ERR(desc)) {
- ret = PTR_ERR(desc);
- goto out;
- }
+ item = kzalloc(sizeof(*item), GFP_KERNEL);
+ if (!item)
+ return -ENODEV;
- ret = gpiod_direction_output(desc, 0);
- if (ret) {
- gpiochip_free_own_desc(desc);
- goto out;
- }
+ spin_lock_irqsave(&mvpwm->lock, flags);
+ desc = gpiochip_request_own_desc(&mvchip->chip,
+ pwm->hwpwm, "mvebu-pwm");
+ if (IS_ERR(desc)) {
+ ret = PTR_ERR(desc);
+ goto out;
+ }
- mvpwm->gpiod = desc;
+ ret = gpiod_direction_output(desc, 0);
+ if (ret) {
+ gpiochip_free_own_desc(desc);
+ goto out;
}
+ item->gpiod = desc;
+ item->device = pwm;
+ INIT_LIST_HEAD(&item->node);
+ list_add_tail(&item->node, &mvpwm->pwms);
out:
spin_unlock_irqrestore(&mvpwm->lock, flags);
return ret;
@@ -630,12 +639,20 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
+ struct mvebu_pwm_item *item, *tmp;
unsigned long flags;
- spin_lock_irqsave(&mvpwm->lock, flags);
- gpiochip_free_own_desc(mvpwm->gpiod);
- mvpwm->gpiod = NULL;
- spin_unlock_irqrestore(&mvpwm->lock, flags);
+ list_for_each_entry_safe(item, tmp, &mvpwm->pwms, node) {
+ if (item->device == pwm) {
+ spin_lock_irqsave(&mvpwm->lock, flags);
+ gpiochip_free_own_desc(item->gpiod);
+ item->gpiod = NULL;
+ item->device = NULL;
+ list_del(&item->node);
+ spin_unlock_irqrestore(&mvpwm->lock, flags);
+ kfree(item);
+ }
+ }
}
static void mvebu_pwm_get_state(struct pwm_chip *chip,
@@ -804,6 +821,8 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
return -ENOMEM;
mvchip->mvpwm = mvpwm;
mvpwm->mvchip = mvchip;
+ mvpwm->id = id;
+ INIT_LIST_HEAD(&mvpwm->pwms);
mvpwm->membase = devm_ioremap_resource(dev, res);
if (IS_ERR(mvpwm->membase))
--
2.7.4
Powered by blists - more mailing lists