From patchwork Fri Jul 20 19:23:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aditya Prayoga X-Patchwork-Id: 947179 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kobol.io Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41XMfZ3R3Yz9sBW for ; Sat, 21 Jul 2018 06:19:02 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728263AbeGTVIl (ORCPT ); Fri, 20 Jul 2018 17:08:41 -0400 Received: from mslow2.mail.gandi.net ([217.70.178.242]:49052 "EHLO slow1-d.mail.gandi.net" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727383AbeGTVIl (ORCPT ); Fri, 20 Jul 2018 17:08:41 -0400 Received: from relay6-d.mail.gandi.net (unknown [217.70.183.198]) by slow1-d.mail.gandi.net (Postfix) with ESMTP id CE5AB3A5A76; Fri, 20 Jul 2018 21:24:11 +0200 (CEST) X-Originating-IP: 140.213.19.3 Received: from ubuntuVM.localdomain (unknown [140.213.19.3]) (Authenticated sender: aditya@kobol.io) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 5CB0BC000A; Fri, 20 Jul 2018 19:24:05 +0000 (UTC) From: Aditya Prayoga To: linux-gpio@vger.kernel.org Cc: Gauthier Provost , Alban Browaeys , Thierry Reding , Linus Walleij , linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org, Aditya Prayoga Subject: [PATCH 1/2] gpio: mvebu: Add support for multiple PWM lines per GPIO chip Date: Sat, 21 Jul 2018 03:23:42 +0800 Message-Id: <1532114623-81911-2-git-send-email-aditya@kobol.io> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1532114623-81911-1-git-send-email-aditya@kobol.io> References: <1532114623-81911-1-git-send-email-aditya@kobol.io> X-Spam-Level: Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org 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 --- 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))