From patchwork Fri Jun 18 06:24:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330253 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7406C48BDF for ; Fri, 18 Jun 2021 06:25:12 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7EDCE611CE for ; Fri, 18 Jun 2021 06:25:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7EDCE611CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=aJlNHZum5QL4zvB6ULevdyP8mT7QhunF2E88Lehxj/8=; b=fvhUKg5u30prHA 9E3uUfZ0NnwUWrbt4iZb8OjDXlY/P3TmW3d8xKoBLklNS4Cx6w6x2cuYc+qJz1BffYOv7JMYqZrBw cUH+qBACfH1r6Ai2swJSv4Xaf74O431cjsIoTUQms7MWwJUpc1SA/COm/4WIRXt1V+E6SIp57VkDy LjtqsX0TjB4pFRixzlWp5DluatO2k1dQxtwL5cJkmn3AOlJ1bKpTT3hnFFjkQV9fUnSJtmAq4De4n NDpHwXxXsKHz5p88WTNg5V6M7OTPQWQ65WBxE6WOZAzlr8bVo0m9+uhChFSvc5er/hsQpl78F+WLf MLVwjPZmJ12u8DTyfK/A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wC-00CpkU-Nv; Fri, 18 Jun 2021 06:25:08 +0000 Received: from lucky1.263xmail.com ([211.157.147.134]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wA-00Cpj5-2t for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:25:08 +0000 Received: from localhost (unknown [192.168.167.16]) by lucky1.263xmail.com (Postfix) with ESMTP id 14DDDC81A5; Fri, 18 Jun 2021 14:24:58 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P16485T139919018157824S1623997492865409_; Fri, 18 Jun 2021 14:24:56 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <5aaa7dd8ec3975f83d224d8297a772fa> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 1/9] pinctrl/rockchip: always enable clock for gpio controller Date: Fri, 18 Jun 2021 14:24:41 +0800 Message-Id: <20210618062449.1067106-2-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232506_501258_4E260F2E X-CRM114-Status: GOOD ( 12.58 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org Since gate and ungate pclk of gpio has very litte benifit for system power consumption, just keep it always ungate. Signed-off-by: Jianqun Xu --- drivers/pinctrl/pinctrl-rockchip.c | 40 +----------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 067fc4208de4..650c71c740f0 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -2299,17 +2299,8 @@ static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct rockchip_pin_bank *bank = gpiochip_get_data(chip); u32 data; - int ret; - ret = clk_enable(bank->clk); - if (ret < 0) { - dev_err(bank->drvdata->dev, - "failed to enable clock for bank %s\n", bank->name); - return ret; - } data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); - clk_disable(bank->clk); - if (data & BIT(offset)) return GPIO_LINE_DIRECTION_OUT; @@ -2335,7 +2326,6 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, if (ret < 0) return ret; - clk_enable(bank->clk); raw_spin_lock_irqsave(&bank->slock, flags); data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); @@ -2347,7 +2337,6 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); raw_spin_unlock_irqrestore(&bank->slock, flags); - clk_disable(bank->clk); return 0; } @@ -2798,7 +2787,6 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value) unsigned long flags; u32 data; - clk_enable(bank->clk); raw_spin_lock_irqsave(&bank->slock, flags); data = readl(reg); @@ -2808,7 +2796,6 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value) writel(data, reg); raw_spin_unlock_irqrestore(&bank->slock, flags); - clk_disable(bank->clk); } /* @@ -2820,9 +2807,7 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset) struct rockchip_pin_bank *bank = gpiochip_get_data(gc); u32 data; - clk_enable(bank->clk); data = readl(bank->reg_base + GPIO_EXT_PORT); - clk_disable(bank->clk); data >>= offset; data &= 1; return data; @@ -2858,7 +2843,6 @@ static void rockchip_gpio_set_debounce(struct gpio_chip *gc, unsigned long flags; u32 data; - clk_enable(bank->clk); raw_spin_lock_irqsave(&bank->slock, flags); data = readl(reg); @@ -2869,7 +2853,6 @@ static void rockchip_gpio_set_debounce(struct gpio_chip *gc, writel(data, reg); raw_spin_unlock_irqrestore(&bank->slock, flags); - clk_disable(bank->clk); } /* @@ -2914,9 +2897,7 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset) if (!bank->domain) return -ENXIO; - clk_enable(bank->clk); virq = irq_create_mapping(bank->domain, offset); - clk_disable(bank->clk); return (virq) ? : -ENXIO; } @@ -3015,7 +2996,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) if (ret < 0) return ret; - clk_enable(bank->clk); raw_spin_lock_irqsave(&bank->slock, flags); data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); @@ -3073,7 +3053,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) default: irq_gc_unlock(gc); raw_spin_unlock_irqrestore(&bank->slock, flags); - clk_disable(bank->clk); return -EINVAL; } @@ -3082,7 +3061,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) irq_gc_unlock(gc); raw_spin_unlock_irqrestore(&bank->slock, flags); - clk_disable(bank->clk); return 0; } @@ -3092,10 +3070,8 @@ static void rockchip_irq_suspend(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct rockchip_pin_bank *bank = gc->private; - clk_enable(bank->clk); bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK); irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK); - clk_disable(bank->clk); } static void rockchip_irq_resume(struct irq_data *d) @@ -3103,9 +3079,7 @@ static void rockchip_irq_resume(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct rockchip_pin_bank *bank = gc->private; - clk_enable(bank->clk); irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK); - clk_disable(bank->clk); } static void rockchip_irq_enable(struct irq_data *d) @@ -3113,7 +3087,6 @@ static void rockchip_irq_enable(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct rockchip_pin_bank *bank = gc->private; - clk_enable(bank->clk); irq_gc_mask_clr_bit(d); } @@ -3123,7 +3096,6 @@ static void rockchip_irq_disable(struct irq_data *d) struct rockchip_pin_bank *bank = gc->private; irq_gc_mask_set_bit(d); - clk_disable(bank->clk); } static int rockchip_interrupts_register(struct platform_device *pdev, @@ -3143,19 +3115,11 @@ static int rockchip_interrupts_register(struct platform_device *pdev, continue; } - ret = clk_enable(bank->clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable clock for bank %s\n", - bank->name); - continue; - } - bank->domain = irq_domain_add_linear(bank->of_node, 32, &irq_generic_chip_ops, NULL); if (!bank->domain) { dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n", bank->name); - clk_disable(bank->clk); continue; } @@ -3166,7 +3130,6 @@ static int rockchip_interrupts_register(struct platform_device *pdev, dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n", bank->name); irq_domain_remove(bank->domain); - clk_disable(bank->clk); continue; } @@ -3198,7 +3161,6 @@ static int rockchip_interrupts_register(struct platform_device *pdev, irq_set_chained_handler_and_data(bank->irq, rockchip_irq_demux, bank); - clk_disable(bank->clk); } return 0; @@ -3317,7 +3279,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, if (IS_ERR(bank->clk)) return PTR_ERR(bank->clk); - return clk_prepare(bank->clk); + return clk_prepare_enable(bank->clk); } static const struct of_device_id rockchip_pinctrl_dt_match[]; From patchwork Fri Jun 18 06:24:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330257 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A6A69C48BE8 for ; Fri, 18 Jun 2021 06:25:18 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6A570611CD for ; Fri, 18 Jun 2021 06:25:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6A570611CD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=1c+dwQEWEPgjKLwBHbVmTzMGrP6dvVH3aqsqvvKCjeE=; b=oYWMWegdu04iie ksxVWPe8nPuRjkq4UU5+yIyWQxF2iTiprEPHKVCsrNZa9XLfrXajlH5DDyyff3Dhrpy+V5J9j8/1V jni9HSNhJYDrb7umdKLqhpbPa6+3HgAMcpZUj5t2Gf1p8kR92q8FJoLcBDD2ufJZT4uxVkAl/o+4V PltTBVjHbS/aKIqkCVkkDcEuzqSOyIwo8pfCG1veHWRK9lAQ5j/oqWwWg8fAD4752WSCWfs3LgUAU ZQINs4cteH2AYPUyrouXreCHSC6dzSAR9z9NhnbOki2HbrC6teWnaUbM3Nno/Zdc43jyESoc8c4hS uPXWMJl35CbSAiUcnNAw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wI-00CpmY-Id; Fri, 18 Jun 2021 06:25:14 +0000 Received: from lucky1.263xmail.com ([211.157.147.130]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wA-00CpjJ-Ms for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:25:12 +0000 Received: from localhost (unknown [192.168.167.16]) by lucky1.263xmail.com (Postfix) with ESMTP id A2235D1C53; Fri, 18 Jun 2021 14:25:03 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P16485T139919018157824S1623997492865409_; Fri, 18 Jun 2021 14:25:03 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <332e0c723185a29c42039667af31d3f0> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 2/9] pinctrl/rockchip: separate struct rockchip_pin_bank to a head file Date: Fri, 18 Jun 2021 14:24:42 +0800 Message-Id: <20210618062449.1067106-3-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232507_114595_9A1A43C0 X-CRM114-Status: GOOD ( 23.68 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org Separate struct rockchip_pin_bank to pinctrl-rockchip.h file, which will be used by gpio-rockchip driver in the future. Signed-off-by: Jianqun Xu --- drivers/pinctrl/pinctrl-rockchip.c | 226 +------------------------- drivers/pinctrl/pinctrl-rockchip.h | 245 +++++++++++++++++++++++++++++ 2 files changed, 246 insertions(+), 225 deletions(-) create mode 100644 drivers/pinctrl/pinctrl-rockchip.h diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 650c71c740f0..b99813379918 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -37,6 +37,7 @@ #include "core.h" #include "pinconf.h" +#include "pinctrl-rockchip.h" /* GPIO control registers */ #define GPIO_SWPORT_DR 0x00 @@ -52,21 +53,6 @@ #define GPIO_EXT_PORT 0x50 #define GPIO_LS_SYNC 0x60 -enum rockchip_pinctrl_type { - PX30, - RV1108, - RK2928, - RK3066B, - RK3128, - RK3188, - RK3288, - RK3308, - RK3368, - RK3399, - RK3568, -}; - - /** * Generate a bitmask for setting a value (v) with a write mask bit in hiword * register 31:16 area. @@ -84,103 +70,6 @@ enum rockchip_pinctrl_type { #define IOMUX_WIDTH_3BIT BIT(4) #define IOMUX_WIDTH_2BIT BIT(5) -/** - * struct rockchip_iomux - * @type: iomux variant using IOMUX_* constants - * @offset: if initialized to -1 it will be autocalculated, by specifying - * an initial offset value the relevant source offset can be reset - * to a new value for autocalculating the following iomux registers. - */ -struct rockchip_iomux { - int type; - int offset; -}; - -/* - * enum type index corresponding to rockchip_perpin_drv_list arrays index. - */ -enum rockchip_pin_drv_type { - DRV_TYPE_IO_DEFAULT = 0, - DRV_TYPE_IO_1V8_OR_3V0, - DRV_TYPE_IO_1V8_ONLY, - DRV_TYPE_IO_1V8_3V0_AUTO, - DRV_TYPE_IO_3V3_ONLY, - DRV_TYPE_MAX -}; - -/* - * enum type index corresponding to rockchip_pull_list arrays index. - */ -enum rockchip_pin_pull_type { - PULL_TYPE_IO_DEFAULT = 0, - PULL_TYPE_IO_1V8_ONLY, - PULL_TYPE_MAX -}; - -/** - * struct rockchip_drv - * @drv_type: drive strength variant using rockchip_perpin_drv_type - * @offset: if initialized to -1 it will be autocalculated, by specifying - * an initial offset value the relevant source offset can be reset - * to a new value for autocalculating the following drive strength - * registers. if used chips own cal_drv func instead to calculate - * registers offset, the variant could be ignored. - */ -struct rockchip_drv { - enum rockchip_pin_drv_type drv_type; - int offset; -}; - -/** - * struct rockchip_pin_bank - * @reg_base: register base of the gpio bank - * @regmap_pull: optional separate register for additional pull settings - * @clk: clock of the gpio bank - * @irq: interrupt of the gpio bank - * @saved_masks: Saved content of GPIO_INTEN at suspend time. - * @pin_base: first pin number - * @nr_pins: number of pins in this bank - * @name: name of the bank - * @bank_num: number of the bank, to account for holes - * @iomux: array describing the 4 iomux sources of the bank - * @drv: array describing the 4 drive strength sources of the bank - * @pull_type: array describing the 4 pull type sources of the bank - * @valid: is all necessary information present - * @of_node: dt node of this bank - * @drvdata: common pinctrl basedata - * @domain: irqdomain of the gpio bank - * @gpio_chip: gpiolib chip - * @grange: gpio range - * @slock: spinlock for the gpio bank - * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode - * @recalced_mask: bit mask to indicate a need to recalulate the mask - * @route_mask: bits describing the routing pins of per bank - */ -struct rockchip_pin_bank { - void __iomem *reg_base; - struct regmap *regmap_pull; - struct clk *clk; - int irq; - u32 saved_masks; - u32 pin_base; - u8 nr_pins; - char *name; - u8 bank_num; - struct rockchip_iomux iomux[4]; - struct rockchip_drv drv[4]; - enum rockchip_pin_pull_type pull_type[4]; - bool valid; - struct device_node *of_node; - struct rockchip_pinctrl *drvdata; - struct irq_domain *domain; - struct gpio_chip gpio_chip; - struct pinctrl_gpio_range grange; - raw_spinlock_t slock; - u32 toggle_edge_mode; - u32 recalced_mask; - u32 route_mask; -}; - #define PIN_BANK(id, pins, label) \ { \ .bank_num = id, \ @@ -320,119 +209,6 @@ struct rockchip_pin_bank { #define RK_MUXROUTE_PMU(ID, PIN, FUNC, REG, VAL) \ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_PMU) -/** - * struct rockchip_mux_recalced_data: represent a pin iomux data. - * @num: bank number. - * @pin: pin number. - * @bit: index at register. - * @reg: register offset. - * @mask: mask bit - */ -struct rockchip_mux_recalced_data { - u8 num; - u8 pin; - u32 reg; - u8 bit; - u8 mask; -}; - -enum rockchip_mux_route_location { - ROCKCHIP_ROUTE_SAME = 0, - ROCKCHIP_ROUTE_PMU, - ROCKCHIP_ROUTE_GRF, -}; - -/** - * struct rockchip_mux_recalced_data: represent a pin iomux data. - * @bank_num: bank number. - * @pin: index at register or used to calc index. - * @func: the min pin. - * @route_location: the mux route location (same, pmu, grf). - * @route_offset: the max pin. - * @route_val: the register offset. - */ -struct rockchip_mux_route_data { - u8 bank_num; - u8 pin; - u8 func; - enum rockchip_mux_route_location route_location; - u32 route_offset; - u32 route_val; -}; - -struct rockchip_pin_ctrl { - struct rockchip_pin_bank *pin_banks; - u32 nr_banks; - u32 nr_pins; - char *label; - enum rockchip_pinctrl_type type; - int grf_mux_offset; - int pmu_mux_offset; - int grf_drv_offset; - int pmu_drv_offset; - struct rockchip_mux_recalced_data *iomux_recalced; - u32 niomux_recalced; - struct rockchip_mux_route_data *iomux_routes; - u32 niomux_routes; - - void (*pull_calc_reg)(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit); - void (*drv_calc_reg)(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit); - int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit); -}; - -struct rockchip_pin_config { - unsigned int func; - unsigned long *configs; - unsigned int nconfigs; -}; - -/** - * struct rockchip_pin_group: represent group of pins of a pinmux function. - * @name: name of the pin group, used to lookup the group. - * @pins: the pins included in this group. - * @npins: number of pins included in this group. - * @data: local pin configuration - */ -struct rockchip_pin_group { - const char *name; - unsigned int npins; - unsigned int *pins; - struct rockchip_pin_config *data; -}; - -/** - * struct rockchip_pmx_func: represent a pin function. - * @name: name of the pin function, used to lookup the function. - * @groups: one or more names of pin groups that provide this function. - * @ngroups: number of groups included in @groups. - */ -struct rockchip_pmx_func { - const char *name; - const char **groups; - u8 ngroups; -}; - -struct rockchip_pinctrl { - struct regmap *regmap_base; - int reg_size; - struct regmap *regmap_pull; - struct regmap *regmap_pmu; - struct device *dev; - struct rockchip_pin_ctrl *ctrl; - struct pinctrl_desc pctl; - struct pinctrl_dev *pctl_dev; - struct rockchip_pin_group *groups; - unsigned int ngroups; - struct rockchip_pmx_func *functions; - unsigned int nfunctions; -}; - static struct regmap_config rockchip_regmap_config = { .reg_bits = 32, .val_bits = 32, diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h new file mode 100644 index 000000000000..dba9e9540633 --- /dev/null +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020-2021 Rockchip Electronics Co. Ltd. + * + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * With some ideas taken from pinctrl-samsung: + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2012 Linaro Ltd + * https://www.linaro.org + * + * and pinctrl-at91: + * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD + */ + +#ifndef _PINCTRL_ROCKCHIP_H +#define _PINCTRL_ROCKCHIP_H + +enum rockchip_pinctrl_type { + PX30, + RV1108, + RK2928, + RK3066B, + RK3128, + RK3188, + RK3288, + RK3308, + RK3368, + RK3399, + RK3568, +}; + +/** + * struct rockchip_iomux + * @type: iomux variant using IOMUX_* constants + * @offset: if initialized to -1 it will be autocalculated, by specifying + * an initial offset value the relevant source offset can be reset + * to a new value for autocalculating the following iomux registers. + */ +struct rockchip_iomux { + int type; + int offset; +}; + +/* + * enum type index corresponding to rockchip_perpin_drv_list arrays index. + */ +enum rockchip_pin_drv_type { + DRV_TYPE_IO_DEFAULT = 0, + DRV_TYPE_IO_1V8_OR_3V0, + DRV_TYPE_IO_1V8_ONLY, + DRV_TYPE_IO_1V8_3V0_AUTO, + DRV_TYPE_IO_3V3_ONLY, + DRV_TYPE_MAX +}; + +/* + * enum type index corresponding to rockchip_pull_list arrays index. + */ +enum rockchip_pin_pull_type { + PULL_TYPE_IO_DEFAULT = 0, + PULL_TYPE_IO_1V8_ONLY, + PULL_TYPE_MAX +}; + +/** + * struct rockchip_drv + * @drv_type: drive strength variant using rockchip_perpin_drv_type + * @offset: if initialized to -1 it will be autocalculated, by specifying + * an initial offset value the relevant source offset can be reset + * to a new value for autocalculating the following drive strength + * registers. if used chips own cal_drv func instead to calculate + * registers offset, the variant could be ignored. + */ +struct rockchip_drv { + enum rockchip_pin_drv_type drv_type; + int offset; +}; + +/** + * struct rockchip_pin_bank + * @reg_base: register base of the gpio bank + * @regmap_pull: optional separate register for additional pull settings + * @clk: clock of the gpio bank + * @irq: interrupt of the gpio bank + * @saved_masks: Saved content of GPIO_INTEN at suspend time. + * @pin_base: first pin number + * @nr_pins: number of pins in this bank + * @name: name of the bank + * @bank_num: number of the bank, to account for holes + * @iomux: array describing the 4 iomux sources of the bank + * @drv: array describing the 4 drive strength sources of the bank + * @pull_type: array describing the 4 pull type sources of the bank + * @valid: is all necessary information present + * @of_node: dt node of this bank + * @drvdata: common pinctrl basedata + * @domain: irqdomain of the gpio bank + * @gpio_chip: gpiolib chip + * @grange: gpio range + * @slock: spinlock for the gpio bank + * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode + * @recalced_mask: bit mask to indicate a need to recalulate the mask + * @route_mask: bits describing the routing pins of per bank + */ +struct rockchip_pin_bank { + void __iomem *reg_base; + struct regmap *regmap_pull; + struct clk *clk; + int irq; + u32 saved_masks; + u32 pin_base; + u8 nr_pins; + char *name; + u8 bank_num; + struct rockchip_iomux iomux[4]; + struct rockchip_drv drv[4]; + enum rockchip_pin_pull_type pull_type[4]; + bool valid; + struct device_node *of_node; + struct rockchip_pinctrl *drvdata; + struct irq_domain *domain; + struct gpio_chip gpio_chip; + struct pinctrl_gpio_range grange; + raw_spinlock_t slock; + u32 toggle_edge_mode; + u32 recalced_mask; + u32 route_mask; +}; + +/** + * struct rockchip_mux_recalced_data: represent a pin iomux data. + * @num: bank number. + * @pin: pin number. + * @bit: index at register. + * @reg: register offset. + * @mask: mask bit + */ +struct rockchip_mux_recalced_data { + u8 num; + u8 pin; + u32 reg; + u8 bit; + u8 mask; +}; + +enum rockchip_mux_route_location { + ROCKCHIP_ROUTE_SAME = 0, + ROCKCHIP_ROUTE_PMU, + ROCKCHIP_ROUTE_GRF, +}; + +/** + * struct rockchip_mux_recalced_data: represent a pin iomux data. + * @bank_num: bank number. + * @pin: index at register or used to calc index. + * @func: the min pin. + * @route_location: the mux route location (same, pmu, grf). + * @route_offset: the max pin. + * @route_val: the register offset. + */ +struct rockchip_mux_route_data { + u8 bank_num; + u8 pin; + u8 func; + enum rockchip_mux_route_location route_location; + u32 route_offset; + u32 route_val; +}; + +struct rockchip_pin_ctrl { + struct rockchip_pin_bank *pin_banks; + u32 nr_banks; + u32 nr_pins; + char *label; + enum rockchip_pinctrl_type type; + int grf_mux_offset; + int pmu_mux_offset; + int grf_drv_offset; + int pmu_drv_offset; + struct rockchip_mux_recalced_data *iomux_recalced; + u32 niomux_recalced; + struct rockchip_mux_route_data *iomux_routes; + u32 niomux_routes; + + void (*pull_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit); + void (*drv_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit); + int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit); +}; + +struct rockchip_pin_config { + unsigned int func; + unsigned long *configs; + unsigned int nconfigs; +}; + +/** + * struct rockchip_pin_group: represent group of pins of a pinmux function. + * @name: name of the pin group, used to lookup the group. + * @pins: the pins included in this group. + * @npins: number of pins included in this group. + * @data: local pin configuration + */ +struct rockchip_pin_group { + const char *name; + unsigned int npins; + unsigned int *pins; + struct rockchip_pin_config *data; +}; + +/** + * struct rockchip_pmx_func: represent a pin function. + * @name: name of the pin function, used to lookup the function. + * @groups: one or more names of pin groups that provide this function. + * @ngroups: number of groups included in @groups. + */ +struct rockchip_pmx_func { + const char *name; + const char **groups; + u8 ngroups; +}; + +struct rockchip_pinctrl { + struct regmap *regmap_base; + int reg_size; + struct regmap *regmap_pull; + struct regmap *regmap_pmu; + struct device *dev; + struct rockchip_pin_ctrl *ctrl; + struct pinctrl_desc pctl; + struct pinctrl_dev *pctl_dev; + struct rockchip_pin_group *groups; + unsigned int ngroups; + struct rockchip_pmx_func *functions; + unsigned int nfunctions; +}; + +#endif From patchwork Fri Jun 18 06:24:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D802C49EA2 for ; Fri, 18 Jun 2021 06:25:20 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CFFD2611CE for ; Fri, 18 Jun 2021 06:25:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CFFD2611CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=GjdQ2GjlJOQ+AKyx2Xe7b65L1PpEAcG/V2aeGRRjBxk=; b=AG7y+EuHjT/YQO Cu+FkRRrFTaTJ1xWKh0cVMFqzfMcjnDwiPZx2+OyYUcHo8mwZqp225rYVj30uoYx+b2o3G3KEyHVk sPBW2x2+GAikvU0xDe/C1vhdnr5n0C+24oY9UvfSDC9/vrj4BPgASr1xePySuxFu/XgR8xUSj7M3U xSXznhwEorPuTKV5otIiNStHi7YAltHiMEUra0TNnpcJ7c6HMV0cNUKIkb6tNzBqZp2TeBLM696oO +NXHEMxsr99iL1/yP46BtoIaaLAFrsDnIdD9Ad5CDEcex6h3f1IUxsufvxu9j+ESnjWzOae4XnuMa UJNARCplYVfuFKJHcPuQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wJ-00Cpmq-8S; Fri, 18 Jun 2021 06:25:15 +0000 Received: from lucky1.263xmail.com ([211.157.147.132]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wG-00Cpku-8k for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:25:13 +0000 Received: from localhost (unknown [192.168.167.16]) by lucky1.263xmail.com (Postfix) with ESMTP id 63525F52C3; Fri, 18 Jun 2021 14:25:09 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P16485T139919018157824S1623997492865409_; Fri, 18 Jun 2021 14:25:05 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <082f98ea10dc16b0b92da5203b844e3a> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 3/9] pinctrl/rockchip: add pinctrl device to gpio bank struct Date: Fri, 18 Jun 2021 14:24:43 +0800 Message-Id: <20210618062449.1067106-4-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232512_506798_FB98419C X-CRM114-Status: GOOD ( 11.75 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org Store a pointer from the pinctrl device for the gpio bank. Signed-off-by: Jianqun Xu --- drivers/pinctrl/pinctrl-rockchip.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index dba9e9540633..4aa3d2f1fa67 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -81,6 +81,7 @@ struct rockchip_drv { /** * struct rockchip_pin_bank + * @dev: the pinctrl device bind to the bank * @reg_base: register base of the gpio bank * @regmap_pull: optional separate register for additional pull settings * @clk: clock of the gpio bank @@ -105,6 +106,7 @@ struct rockchip_drv { * @route_mask: bits describing the routing pins of per bank */ struct rockchip_pin_bank { + struct device *dev; void __iomem *reg_base; struct regmap *regmap_pull; struct clk *clk; From patchwork Fri Jun 18 06:24:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330255 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90858C48BDF for ; Fri, 18 Jun 2021 06:25:18 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 60163611CE for ; Fri, 18 Jun 2021 06:25:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 60163611CE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=KiuQaj5vw1CttaOaVaY/bUpOBSVkF/DUT6zLS4IQyI4=; b=cdUlHf45Dl9zP4 xpCwlFQDubT2m1M+ULtm3goWMJ7N6uhssG9raJgCQXwocPhPJk3wjLZHFlMm34xvzZUkUdyiMksaF YBt1Qb9hHA3DPFfRU3QwLKkPnad+PKA2SFdDHsPPh346gAAs1/HY1KXgYhZzttNtR+dSZicGvdzjP 5BUGqHN+JaHw4OJXYolfwzaPBkkBvtNZEj8XBi+0uKqB0UZ2o5XBhroNYOWz7tHLWlv9kOBrkqrXv mng660fZ7g5cq5huHWLmiR/ZKFocduJSCuItEQNL11TOpNQSIbHotsDeVgw3z5xTNhsUCwNRtn7jp 1RWg9yOKeoUEmZ+c4Kcg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wK-00Cpn8-18; Fri, 18 Jun 2021 06:25:16 +0000 Received: from lucky1.263xmail.com ([211.157.147.130]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7wG-00CplN-UA for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:25:14 +0000 Received: from localhost (unknown [192.168.167.16]) by lucky1.263xmail.com (Postfix) with ESMTP id 43398D1C48; Fri, 18 Jun 2021 14:25:10 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P16485T139919018157824S1623997492865409_; Fri, 18 Jun 2021 14:25:08 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Liang Chen Subject: [PATCH 4/9] dt-bindings: gpio: change items restriction of clock for rockchip, gpio-bank Date: Fri, 18 Jun 2021 14:24:44 +0800 Message-Id: <20210618062449.1067106-5-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232513_167288_0278AD65 X-CRM114-Status: UNSURE ( 9.91 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org From: Liang Chen The clock property need 2 items on some rockchip chips. Signed-off-by: Liang Chen --- .../devicetree/bindings/gpio/rockchip,gpio-bank.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/rockchip,gpio-bank.yaml b/Documentation/devicetree/bindings/gpio/rockchip,gpio-bank.yaml index d993e002cebe..0d62c28fb58d 100644 --- a/Documentation/devicetree/bindings/gpio/rockchip,gpio-bank.yaml +++ b/Documentation/devicetree/bindings/gpio/rockchip,gpio-bank.yaml @@ -22,7 +22,10 @@ properties: maxItems: 1 clocks: - maxItems: 1 + minItems: 1 + items: + - description: APB interface clock source + - description: GPIO debounce reference clock source gpio-controller: true From patchwork Fri Jun 18 06:27:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330263 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DD17C48BE8 for ; Fri, 18 Jun 2021 06:27:50 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2D88860C41 for ; Fri, 18 Jun 2021 06:27:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2D88860C41 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8qntEBwqSN5MyjpD7eseSsy82EQbskncbHKoIwrSJIY=; b=L/AurMMoeiVkBo 7fQVliiQHTaZ4/IIjZrvVyHvjSWz1X+hVyovDcYEdObt0M3wJAd+99/fkkGDbfKWNIL+h0KxHU+Dj A9bUi4p85XP1WRi7BX+h1GU0wD1P4+c/XWWjh+WuastCHimjydaWJnEKoSMrnyJsxG0i8fEsh3LeX o7AbFuSqvhwMGBBpaJRaLYgv6mdbw+hdresiIfQH9pgDIuh8frN7xLw3h4SLTPQ3py4tM26gOGwXQ bvB4VHiCo8g088LxuXVoelYhVVybau6BQalfdlHNFIbYp8jFSMPb0sukUXP1/KiO7W0dXmKHCFavp gd9tobss4VrXrIXWXn4Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7yk-00CqCX-Av; Fri, 18 Jun 2021 06:27:46 +0000 Received: from lucky1.263xmail.com ([211.157.147.132]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7yg-00CqBP-N8 for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:27:45 +0000 Received: from localhost (unknown [192.168.167.172]) by lucky1.263xmail.com (Postfix) with ESMTP id 1B741F534B; Fri, 18 Jun 2021 14:27:41 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P3914T140193786996480S1623997658378526_; Fri, 18 Jun 2021 14:27:39 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <55e746d352cbb0254ec1763e86655f87> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 5/9] gpio/rockchip: add driver for rockchip gpio Date: Fri, 18 Jun 2021 14:27:36 +0800 Message-Id: <20210618062736.1067313-1-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232743_148313_E035CA5F X-CRM114-Status: GOOD ( 26.65 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org This patch add support for rockchip gpio controller, which is supported in pinctrl driver in the past. With this patch, the pinctrl-rockchip driver will drop gpio related codes and populate platform driver to gpio-rockchip. Signed-off-by: Jianqun Xu --- drivers/gpio/Kconfig | 8 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rockchip.c | 621 +++++++++++++++++++++++++++++++++++ 3 files changed, 630 insertions(+) create mode 100644 drivers/gpio/gpio-rockchip.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1dd0ec6727fd..764ef6b14678 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -520,6 +520,14 @@ config GPIO_REG A 32-bit single register GPIO fixed in/out implementation. This can be used to represent any register as a set of GPIO signals. +config GPIO_ROCKCHIP + tristate "Rockchip GPIO support" + depends on ARCH_ROCKCHIP || COMPILE_TEST + select GPIOLIB_IRQCHIP + default ARCH_ROCKCHIP + help + Say yes here to support GPIO on Rockchip SoCs. + config GPIO_SAMA5D2_PIOBU tristate "SAMA5D2 PIOBU GPIO support" depends on MFD_SYSCON diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d7c81e1611a4..81e95a0db25b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -127,6 +127,7 @@ obj-$(CONFIG_GPIO_RDA) += gpio-rda.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o obj-$(CONFIG_GPIO_REG) += gpio-reg.o +obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c new file mode 100644 index 000000000000..cbf1f24f9eaa --- /dev/null +++ b/drivers/gpio/gpio-rockchip.c @@ -0,0 +1,621 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pinctrl/core.h" +#include "../pinctrl/pinctrl-rockchip.h" + +/* GPIO control registers */ +#define GPIO_SWPORT_DR 0x00 +#define GPIO_SWPORT_DDR 0x04 +#define GPIO_INTEN 0x30 +#define GPIO_INTMASK 0x34 +#define GPIO_INTTYPE_LEVEL 0x38 +#define GPIO_INT_POLARITY 0x3c +#define GPIO_INT_STATUS 0x40 +#define GPIO_INT_RAWSTATUS 0x44 +#define GPIO_DEBOUNCE 0x48 +#define GPIO_PORTS_EOI 0x4c +#define GPIO_EXT_PORT 0x50 +#define GPIO_LS_SYNC 0x60 + +static int rockchip_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(chip); + u32 data; + + data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + if (data & BIT(offset)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int rockchip_gpio_set_direction(struct gpio_chip *chip, + unsigned int offset, bool input) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(chip); + unsigned long flags; + u32 data; + + raw_spin_lock_irqsave(&bank->slock, flags); + + data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + /* set bit to 1 for output, 0 for input */ + if (!input) + data |= BIT(offset); + else + data &= ~BIT(offset); + writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); + + raw_spin_unlock_irqrestore(&bank->slock, flags); + + return 0; +} + +static void rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(gc); + void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR; + unsigned long flags; + u32 data; + + raw_spin_lock_irqsave(&bank->slock, flags); + + data = readl(reg); + data &= ~BIT(offset); + if (value) + data |= BIT(offset); + writel(data, reg); + + raw_spin_unlock_irqrestore(&bank->slock, flags); +} + +static int rockchip_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(gc); + u32 data; + + data = readl(bank->reg_base + GPIO_EXT_PORT); + data >>= offset; + data &= 1; + return data; +} + +static void rockchip_gpio_set_debounce(struct gpio_chip *gc, + unsigned int offset, bool enable) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(gc); + void __iomem *reg = bank->reg_base + GPIO_DEBOUNCE; + unsigned long flags; + u32 data; + + raw_spin_lock_irqsave(&bank->slock, flags); + + data = readl(reg); + if (enable) + data |= BIT(offset); + else + data &= ~BIT(offset); + writel(data, reg); + + raw_spin_unlock_irqrestore(&bank->slock, flags); +} + +static int rockchip_gpio_direction_input(struct gpio_chip *gc, + unsigned int offset) +{ + return rockchip_gpio_set_direction(gc, offset, true); +} + +static int rockchip_gpio_direction_output(struct gpio_chip *gc, + unsigned int offset, int value) +{ + rockchip_gpio_set(gc, offset, value); + + return rockchip_gpio_set_direction(gc, offset, false); +} + +/* + * gpiolib set_config callback function. The setting of the pin + * mux function as 'gpio output' will be handled by the pinctrl subsystem + * interface. + */ +static int rockchip_gpio_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) +{ + enum pin_config_param param = pinconf_to_config_param(config); + + switch (param) { + case PIN_CONFIG_INPUT_DEBOUNCE: + rockchip_gpio_set_debounce(gc, offset, true); + /* + * Rockchip's gpio could only support up to one period + * of the debounce clock(pclk), which is far away from + * satisftying the requirement, as pclk is usually near + * 100MHz shared by all peripherals. So the fact is it + * has crippled debounce capability could only be useful + * to prevent any spurious glitches from waking up the system + * if the gpio is conguired as wakeup interrupt source. Let's + * still return -ENOTSUPP as before, to make sure the caller + * of gpiod_set_debounce won't change its behaviour. + */ + return -ENOTSUPP; + default: + return -ENOTSUPP; + } +} + +/* + * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin + * and a virtual IRQ, if not already present. + */ +static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(gc); + unsigned int virq; + + if (!bank->domain) + return -ENXIO; + + virq = irq_create_mapping(bank->domain, offset); + + return (virq) ? : -ENXIO; +} + +static const struct gpio_chip rockchip_gpiolib_chip = { + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .set = rockchip_gpio_set, + .get = rockchip_gpio_get, + .get_direction = rockchip_gpio_get_direction, + .direction_input = rockchip_gpio_direction_input, + .direction_output = rockchip_gpio_direction_output, + .set_config = rockchip_gpio_set_config, + .to_irq = rockchip_gpio_to_irq, + .owner = THIS_MODULE, +}; + +static void rockchip_irq_demux(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc); + u32 pend; + + dev_dbg(bank->dev, "got irq for bank %s\n", bank->name); + + chained_irq_enter(chip, desc); + + pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); + + while (pend) { + unsigned int irq, virq; + + irq = __ffs(pend); + pend &= ~BIT(irq); + virq = irq_find_mapping(bank->domain, irq); + + if (!virq) { + dev_err(bank->dev, "unmapped irq %d\n", irq); + continue; + } + + dev_dbg(bank->dev, "handling irq %d\n", irq); + + /* + * Triggering IRQ on both rising and falling edge + * needs manual intervention. + */ + if (bank->toggle_edge_mode & BIT(irq)) { + u32 data, data_old, polarity; + unsigned long flags; + + data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); + do { + raw_spin_lock_irqsave(&bank->slock, flags); + + polarity = readl_relaxed(bank->reg_base + + GPIO_INT_POLARITY); + if (data & BIT(irq)) + polarity &= ~BIT(irq); + else + polarity |= BIT(irq); + writel(polarity, + bank->reg_base + GPIO_INT_POLARITY); + + raw_spin_unlock_irqrestore(&bank->slock, flags); + + data_old = data; + data = readl_relaxed(bank->reg_base + + GPIO_EXT_PORT); + } while ((data & BIT(irq)) != (data_old & BIT(irq))); + } + + generic_handle_irq(virq); + } + + chained_irq_exit(chip, desc); +} + +static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct rockchip_pin_bank *bank = gc->private; + u32 mask = BIT(d->hwirq); + u32 polarity; + u32 level; + u32 data; + unsigned long flags; + + raw_spin_lock_irqsave(&bank->slock, flags); + + data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + data &= ~mask; + writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); + + raw_spin_unlock_irqrestore(&bank->slock, flags); + + if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(d, handle_edge_irq); + else + irq_set_handler_locked(d, handle_level_irq); + + raw_spin_lock_irqsave(&bank->slock, flags); + irq_gc_lock(gc); + + level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); + polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + bank->toggle_edge_mode |= mask; + level |= mask; + + /* + * Determine gpio state. If 1 next interrupt should be falling + * otherwise rising. + */ + data = readl(bank->reg_base + GPIO_EXT_PORT); + if (data & mask) + polarity &= ~mask; + else + polarity |= mask; + break; + case IRQ_TYPE_EDGE_RISING: + bank->toggle_edge_mode &= ~mask; + level |= mask; + polarity |= mask; + break; + case IRQ_TYPE_EDGE_FALLING: + bank->toggle_edge_mode &= ~mask; + level |= mask; + polarity &= ~mask; + break; + case IRQ_TYPE_LEVEL_HIGH: + bank->toggle_edge_mode &= ~mask; + level &= ~mask; + polarity |= mask; + break; + case IRQ_TYPE_LEVEL_LOW: + bank->toggle_edge_mode &= ~mask; + level &= ~mask; + polarity &= ~mask; + break; + default: + irq_gc_unlock(gc); + raw_spin_unlock_irqrestore(&bank->slock, flags); + clk_disable(bank->clk); + return -EINVAL; + } + + writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL); + writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); + + irq_gc_unlock(gc); + raw_spin_unlock_irqrestore(&bank->slock, flags); + + return 0; +} + +static void rockchip_irq_suspend(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct rockchip_pin_bank *bank = gc->private; + + bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK); + irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK); +} + +static void rockchip_irq_resume(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct rockchip_pin_bank *bank = gc->private; + + irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK); +} + +static void rockchip_irq_enable(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct rockchip_pin_bank *bank = gc->private; + + irq_gc_mask_clr_bit(d); +} + +static void rockchip_irq_disable(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct rockchip_pin_bank *bank = gc->private; + + irq_gc_mask_set_bit(d); + clk_disable(bank->clk); +} + +static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) +{ + unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; + struct irq_chip_generic *gc; + int ret; + + bank->domain = irq_domain_add_linear(bank->of_node, 32, + &irq_generic_chip_ops, NULL); + if (!bank->domain) { + dev_warn(bank->dev, "could not init irq domain for bank %s\n", + bank->name); + return -EINVAL; + } + + ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1, + "rockchip_gpio_irq", + handle_level_irq, + clr, 0, 0); + if (ret) { + dev_err(bank->dev, "could not alloc generic chips for bank %s\n", + bank->name); + irq_domain_remove(bank->domain); + return -EINVAL; + } + + gc = irq_get_domain_generic_chip(bank->domain, 0); + gc->reg_base = bank->reg_base; + gc->private = bank; + gc->chip_types[0].regs.mask = GPIO_INTMASK; + gc->chip_types[0].regs.ack = GPIO_PORTS_EOI; + gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; + gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; + gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; + gc->chip_types[0].chip.irq_enable = rockchip_irq_enable; + gc->chip_types[0].chip.irq_disable = rockchip_irq_disable; + gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake; + gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend; + gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; + gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; + gc->wake_enabled = IRQ_MSK(bank->nr_pins); + + /* + * Linux assumes that all interrupts start out disabled/masked. + * Our driver only uses the concept of masked and always keeps + * things enabled, so for us that's all masked and all enabled. + */ + writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK); + writel_relaxed(0xffffffff, bank->reg_base + GPIO_PORTS_EOI); + writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN); + gc->mask_cache = 0xffffffff; + + irq_set_chained_handler_and_data(bank->irq, + rockchip_irq_demux, bank); + + return 0; +} + +static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank) +{ + struct gpio_chip *gc; + int ret; + + bank->gpio_chip = rockchip_gpiolib_chip; + + gc = &bank->gpio_chip; + gc->base = bank->pin_base; + gc->ngpio = bank->nr_pins; + gc->label = bank->name; + gc->parent = bank->dev; +#ifdef CONFIG_OF_GPIO + gc->of_node = of_node_get(bank->of_node); +#endif + + ret = gpiochip_add_data(gc, bank); + if (ret) { + dev_err(bank->dev, "failed to add gpiochip %s, %d\n", + gc->label, ret); + return ret; + } + + /* + * For DeviceTree-supported systems, the gpio core checks the + * pinctrl's device node for the "gpio-ranges" property. + * If it is present, it takes care of adding the pin ranges + * for the driver. In this case the driver can skip ahead. + * + * In order to remain compatible with older, existing DeviceTree + * files which don't set the "gpio-ranges" property or systems that + * utilize ACPI the driver has to call gpiochip_add_pin_range(). + */ + if (!of_property_read_bool(bank->of_node, "gpio-ranges")) { + struct device_node *pctlnp = of_get_parent(bank->of_node); + struct pinctrl_dev *pctldev = NULL; + + if (!pctlnp) + return -ENODATA; + + pctldev = of_pinctrl_get(pctlnp); + if (!pctldev) + return -ENODEV; + + ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0, + gc->base, gc->ngpio); + if (ret) { + dev_err(bank->dev, "Failed to add pin range\n"); + goto fail; + } + } + + ret = rockchip_interrupts_register(bank); + if (ret) { + dev_err(bank->dev, "failed to register interrupt, %d\n", ret); + goto fail; + } + + return 0; + +fail: + gpiochip_remove(&bank->gpio_chip); + + return ret; +} + +static int rockchip_get_bank_data(struct rockchip_pin_bank *bank) +{ + struct resource res; + + if (of_address_to_resource(bank->of_node, 0, &res)) { + dev_err(bank->dev, "cannot find IO resource for bank\n"); + return -ENOENT; + } + + bank->reg_base = devm_ioremap_resource(bank->dev, &res); + if (IS_ERR(bank->reg_base)) + return PTR_ERR(bank->reg_base); + + bank->irq = irq_of_parse_and_map(bank->of_node, 0); + + bank->clk = of_clk_get(bank->of_node, 0); + if (!IS_ERR(bank->clk)) + return clk_prepare_enable(bank->clk); + + bank->clk = NULL; + return 0; +} + +static struct rockchip_pin_bank * +rockchip_gpio_find_bank(struct pinctrl_dev *pctldev, const char *name) +{ + struct rockchip_pinctrl *info; + struct rockchip_pin_bank *bank; + int i, found = 0; + + info = pinctrl_dev_get_drvdata(pctldev); + bank = info->ctrl->pin_banks; + for (i = 0; i < info->ctrl->nr_banks; i++, bank++) { + if (!strcmp(bank->name, name)) { + found = 1; + break; + } + } + + return found ? bank : NULL; +} + +static int rockchip_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *pctlnp = of_get_parent(np); + struct pinctrl_dev *pctldev = NULL; + struct rockchip_pin_bank *bank = NULL; + int ret; + + if (!np || !pctlnp) + return -ENODEV; + + pctldev = of_pinctrl_get(pctlnp); + if (!pctldev) + return -EPROBE_DEFER; + + bank = rockchip_gpio_find_bank(pctldev, np->name); + if (!bank) + return -EINVAL; + + bank->dev = dev; + bank->of_node = np; + + raw_spin_lock_init(&bank->slock); + + ret = rockchip_get_bank_data(bank); + if (ret) + return ret; + + ret = rockchip_gpiolib_register(bank); + if (ret) { + clk_disable_unprepare(bank->clk); + return ret; + } + + platform_set_drvdata(pdev, bank); + dev_info(dev, "probed %pOF\n", np); + + return 0; +} + +static int rockchip_gpio_remove(struct platform_device *pdev) +{ + struct rockchip_pin_bank *bank = platform_get_drvdata(pdev); + + clk_disable_unprepare(bank->clk); + gpiochip_remove(&bank->gpio_chip); + + return 0; +} + +static const struct of_device_id rockchip_gpio_match[] = { + { .compatible = "rockchip,gpio-bank", }, + { .compatible = "rockchip,rk3188-gpio-bank0" }, + { }, +}; + +static struct platform_driver rockchip_gpio_driver = { + .probe = rockchip_gpio_probe, + .remove = rockchip_gpio_remove, + .driver = { + .name = "rockchip-gpio", + .of_match_table = rockchip_gpio_match, + }, +}; + +static int __init rockchip_gpio_init(void) +{ + return platform_driver_register(&rockchip_gpio_driver); +} +postcore_initcall(rockchip_gpio_init); + +static void __exit rockchip_gpio_exit(void) +{ + platform_driver_unregister(&rockchip_gpio_driver); +} +module_exit(rockchip_gpio_exit); + +MODULE_DESCRIPTION("Rockchip gpio driver"); +MODULE_ALIAS("platform:rockchip-gpio"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, rockchip_gpio_match); From patchwork Fri Jun 18 06:28:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330265 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17A06C48BDF for ; Fri, 18 Jun 2021 06:28:27 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C0B3F61209 for ; Fri, 18 Jun 2021 06:28:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C0B3F61209 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=rLhqCGVAJgM0ljnLLjvTu8EU9B5TdwIHaUb4nPbXI9c=; b=HzvM1Hz56555wn rFsK+L7kAgxkJ0UH9meu1dfz5P+0HnJ39v7pXJUiryWeQ+WtxT+110nYerDNKDC2A3Jbup2mGtfsg Zg8QbXGszfCRE/ldANYwXo5ehY/HxykWyrXgngvwASl5psTljkHy+8O0cY3iNWUbMGsIUlKnDIZK9 +caJIcOR7057WPFibzC4hKO+nJ0lDwP6hA+slDCxF0c97a5viV2tGTAlIbdJF8hGGeUHIQsZW6JPp y5CCrq6k5egmU9Cdx4WdviCjKbg6EjwG7DxYkw7XwZYehfLhFng1gNoDQFY5y6msDPu7lqvaeFJvD Bq2lUF/Law5GRN/0rJZA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7zJ-00CqIS-Oy; Fri, 18 Jun 2021 06:28:21 +0000 Received: from lucky1.263xmail.com ([211.157.147.132]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7zG-00CqHX-H8 for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:28:20 +0000 Received: from localhost (unknown [192.168.167.70]) by lucky1.263xmail.com (Postfix) with ESMTP id EA3E0F504B; Fri, 18 Jun 2021 14:28:16 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P4790T140158428321536S1623997693052153_; Fri, 18 Jun 2021 14:28:14 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <4387bcd58a6ce98e95b615bc0aaa6b5b> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 6/9] gpio/rockchip: use struct rockchip_gpio_regs for gpio controller Date: Fri, 18 Jun 2021 14:28:11 +0800 Message-Id: <20210618062811.1067370-1-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232818_934603_1CF753AF X-CRM114-Status: GOOD ( 19.11 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org Store register offsets in the struct rockchip_gpio_regs, this patch prepare for the driver update for new gpio controller. Reviewed-by: Heiko Stuebner Signed-off-by: Jianqun Xu --- drivers/gpio/gpio-rockchip.c | 86 ++++++++++++++++-------------- drivers/pinctrl/pinctrl-rockchip.h | 38 +++++++++++++ 2 files changed, 85 insertions(+), 39 deletions(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index cbf1f24f9eaa..eb134731b9ae 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -24,19 +24,21 @@ #include "../pinctrl/core.h" #include "../pinctrl/pinctrl-rockchip.h" -/* GPIO control registers */ -#define GPIO_SWPORT_DR 0x00 -#define GPIO_SWPORT_DDR 0x04 -#define GPIO_INTEN 0x30 -#define GPIO_INTMASK 0x34 -#define GPIO_INTTYPE_LEVEL 0x38 -#define GPIO_INT_POLARITY 0x3c -#define GPIO_INT_STATUS 0x40 -#define GPIO_INT_RAWSTATUS 0x44 -#define GPIO_DEBOUNCE 0x48 -#define GPIO_PORTS_EOI 0x4c -#define GPIO_EXT_PORT 0x50 -#define GPIO_LS_SYNC 0x60 +#define GPIO_TYPE_V1 (0) /* GPIO Version ID reserved */ + +static const struct rockchip_gpio_regs gpio_regs_v1 = { + .port_dr = 0x00, + .port_ddr = 0x04, + .int_en = 0x30, + .int_mask = 0x34, + .int_type = 0x38, + .int_polarity = 0x3c, + .int_status = 0x40, + .int_rawstatus = 0x44, + .debounce = 0x48, + .port_eoi = 0x4c, + .ext_port = 0x50, +}; static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) @@ -44,7 +46,7 @@ static int rockchip_gpio_get_direction(struct gpio_chip *chip, struct rockchip_pin_bank *bank = gpiochip_get_data(chip); u32 data; - data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + data = readl_relaxed(bank->reg_base + bank->gpio_regs->port_ddr); if (data & BIT(offset)) return GPIO_LINE_DIRECTION_OUT; @@ -60,13 +62,13 @@ static int rockchip_gpio_set_direction(struct gpio_chip *chip, raw_spin_lock_irqsave(&bank->slock, flags); - data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + data = readl_relaxed(bank->reg_base + bank->gpio_regs->port_ddr); /* set bit to 1 for output, 0 for input */ if (!input) data |= BIT(offset); else data &= ~BIT(offset); - writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); + writel_relaxed(data, bank->reg_base + bank->gpio_regs->port_ddr); raw_spin_unlock_irqrestore(&bank->slock, flags); @@ -77,7 +79,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) { struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR; + void __iomem *reg = bank->reg_base + bank->gpio_regs->port_dr; unsigned long flags; u32 data; @@ -97,9 +99,10 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned int offset) struct rockchip_pin_bank *bank = gpiochip_get_data(gc); u32 data; - data = readl(bank->reg_base + GPIO_EXT_PORT); + data = readl(bank->reg_base + bank->gpio_regs->ext_port); data >>= offset; data &= 1; + return data; } @@ -107,7 +110,7 @@ static void rockchip_gpio_set_debounce(struct gpio_chip *gc, unsigned int offset, bool enable) { struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - void __iomem *reg = bank->reg_base + GPIO_DEBOUNCE; + void __iomem *reg = bank->reg_base + bank->gpio_regs->debounce; unsigned long flags; u32 data; @@ -207,7 +210,7 @@ static void rockchip_irq_demux(struct irq_desc *desc) chained_irq_enter(chip, desc); - pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); + pend = readl_relaxed(bank->reg_base + bank->gpio_regs->int_status); while (pend) { unsigned int irq, virq; @@ -231,24 +234,26 @@ static void rockchip_irq_demux(struct irq_desc *desc) u32 data, data_old, polarity; unsigned long flags; - data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); + data = readl_relaxed(bank->reg_base + + bank->gpio_regs->ext_port); do { raw_spin_lock_irqsave(&bank->slock, flags); polarity = readl_relaxed(bank->reg_base + - GPIO_INT_POLARITY); + bank->gpio_regs->int_polarity); if (data & BIT(irq)) polarity &= ~BIT(irq); else polarity |= BIT(irq); writel(polarity, - bank->reg_base + GPIO_INT_POLARITY); + bank->reg_base + + bank->gpio_regs->int_polarity); raw_spin_unlock_irqrestore(&bank->slock, flags); data_old = data; data = readl_relaxed(bank->reg_base + - GPIO_EXT_PORT); + bank->gpio_regs->ext_port); } while ((data & BIT(irq)) != (data_old & BIT(irq))); } @@ -270,9 +275,9 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) raw_spin_lock_irqsave(&bank->slock, flags); - data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); + data = readl_relaxed(bank->reg_base + bank->gpio_regs->port_ddr); data &= ~mask; - writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); + writel_relaxed(data, bank->reg_base + bank->gpio_regs->port_ddr); raw_spin_unlock_irqrestore(&bank->slock, flags); @@ -284,8 +289,8 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) raw_spin_lock_irqsave(&bank->slock, flags); irq_gc_lock(gc); - level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); - polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); + level = readl_relaxed(gc->reg_base + bank->gpio_regs->int_type); + polarity = readl_relaxed(gc->reg_base + bank->gpio_regs->int_polarity); switch (type) { case IRQ_TYPE_EDGE_BOTH: @@ -296,7 +301,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) * Determine gpio state. If 1 next interrupt should be falling * otherwise rising. */ - data = readl(bank->reg_base + GPIO_EXT_PORT); + data = readl(bank->reg_base + bank->gpio_regs->ext_port); if (data & mask) polarity &= ~mask; else @@ -329,8 +334,8 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) return -EINVAL; } - writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL); - writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); + writel_relaxed(level, gc->reg_base + bank->gpio_regs->int_type); + writel_relaxed(polarity, gc->reg_base + bank->gpio_regs->int_polarity); irq_gc_unlock(gc); raw_spin_unlock_irqrestore(&bank->slock, flags); @@ -343,8 +348,8 @@ static void rockchip_irq_suspend(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct rockchip_pin_bank *bank = gc->private; - bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK); - irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK); + bank->saved_masks = irq_reg_readl(gc, bank->gpio_regs->int_mask); + irq_reg_writel(gc, ~gc->wake_active, bank->gpio_regs->int_mask); } static void rockchip_irq_resume(struct irq_data *d) @@ -352,7 +357,7 @@ static void rockchip_irq_resume(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct rockchip_pin_bank *bank = gc->private; - irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK); + irq_reg_writel(gc, bank->saved_masks, bank->gpio_regs->int_mask); } static void rockchip_irq_enable(struct irq_data *d) @@ -400,8 +405,8 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) gc = irq_get_domain_generic_chip(bank->domain, 0); gc->reg_base = bank->reg_base; gc->private = bank; - gc->chip_types[0].regs.mask = GPIO_INTMASK; - gc->chip_types[0].regs.ack = GPIO_PORTS_EOI; + gc->chip_types[0].regs.mask = bank->gpio_regs->int_mask; + gc->chip_types[0].regs.ack = bank->gpio_regs->port_eoi; gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; @@ -418,9 +423,9 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) * Our driver only uses the concept of masked and always keeps * things enabled, so for us that's all masked and all enabled. */ - writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK); - writel_relaxed(0xffffffff, bank->reg_base + GPIO_PORTS_EOI); - writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN); + writel_relaxed(0xffffffff, bank->reg_base + bank->gpio_regs->int_mask); + writel_relaxed(0xffffffff, bank->reg_base + bank->gpio_regs->port_eoi); + writel_relaxed(0xffffffff, bank->reg_base + bank->gpio_regs->int_en); gc->mask_cache = 0xffffffff; irq_set_chained_handler_and_data(bank->irq, @@ -510,6 +515,9 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank) bank->irq = irq_of_parse_and_map(bank->of_node, 0); + bank->gpio_regs = &gpio_regs_v1; + bank->gpio_type = GPIO_TYPE_V1; + bank->clk = of_clk_get(bank->of_node, 0); if (!IS_ERR(bank->clk)) return clk_prepare_enable(bank->clk); diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index 4aa3d2f1fa67..1b774b6bbc3e 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -32,6 +32,42 @@ enum rockchip_pinctrl_type { RK3568, }; +/** + * struct rockchip_gpio_regs + * @port_dr: data register + * @port_ddr: data direction register + * @int_en: interrupt enable + * @int_mask: interrupt mask + * @int_type: interrupt trigger type, such as high, low, edge trriger type. + * @int_polarity: interrupt polarity enable register + * @int_bothedge: interrupt bothedge enable register + * @int_status: interrupt status register + * @int_rawstatus: int_status = int_rawstatus & int_mask + * @debounce: enable debounce for interrupt signal + * @dbclk_div_en: enable divider for debounce clock + * @dbclk_div_con: setting for divider of debounce clock + * @port_eoi: end of interrupt of the port + * @ext_port: port data from external + * @version_id: controller version register + */ +struct rockchip_gpio_regs { + u32 port_dr; + u32 port_ddr; + u32 int_en; + u32 int_mask; + u32 int_type; + u32 int_polarity; + u32 int_bothedge; + u32 int_status; + u32 int_rawstatus; + u32 debounce; + u32 dbclk_div_en; + u32 dbclk_div_con; + u32 port_eoi; + u32 ext_port; + u32 version_id; +}; + /** * struct rockchip_iomux * @type: iomux variant using IOMUX_* constants @@ -126,6 +162,8 @@ struct rockchip_pin_bank { struct gpio_chip gpio_chip; struct pinctrl_gpio_range grange; raw_spinlock_t slock; + const struct rockchip_gpio_regs *gpio_regs; + u32 gpio_type; u32 toggle_edge_mode; u32 recalced_mask; u32 route_mask; From patchwork Fri Jun 18 06:28:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330267 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8DFA2C48BDF for ; Fri, 18 Jun 2021 06:28:45 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 50AFF60C41 for ; Fri, 18 Jun 2021 06:28:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 50AFF60C41 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=w+icLNGlCdh0ITWcZsFSjNEs+VFVOPR6HszvBS6z3GM=; b=W7zpcZ11CIc09V k10g1sYZ2ncu//H5yHatBmbqvJnU/eSaX+ZpEDYfkqBi/x3m6I1/8p4pOWSx4u/rddvL6SHUge7v+ pGt2WIp1eaW18dimzpnIe49goOu5To+OaE9KNqGHLXW/4SLEXBKIQoE/G2fCPGE1HPBMomIkSW1hG xorEC+/CVj+g1s4Oe0h3oXz6FpWH1BGcq19ScrS+O/AEe7oEla6j3LCgioIEVFOfuWm8LxHfCw1Dx RltPmkNeNvP218sdKIfqs1l9BZbppLPUcGyRQBVPvzA3qlQv+/um/yM29+dG1BhBEyxguriOhOlfA kZN6HifAvHiFJtWQ9tDQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7zb-00CqM7-TY; Fri, 18 Jun 2021 06:28:39 +0000 Received: from lucky1.263xmail.com ([211.157.147.132]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu7zY-00CqLM-01 for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:28:38 +0000 Received: from localhost (unknown [192.168.167.13]) by lucky1.263xmail.com (Postfix) with ESMTP id 66CA1F5188; Fri, 18 Jun 2021 14:28:34 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P5457T140566159423232S1623997713569343_; Fri, 18 Jun 2021 14:28:34 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 7/9] gpio/rockchip: support next version gpio controller Date: Fri, 18 Jun 2021 14:28:31 +0800 Message-Id: <20210618062831.1067435-1-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232836_409151_89ACF786 X-CRM114-Status: GOOD ( 26.32 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org The next version gpio controller on SoCs like rk3568 have more write mask bits for registers. Signed-off-by: Jianqun Xu --- drivers/gpio/gpio-rockchip.c | 283 +++++++++++++++++++++-------- drivers/pinctrl/pinctrl-rockchip.h | 2 + 2 files changed, 213 insertions(+), 72 deletions(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index eb134731b9ae..db1ce402e7dc 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -25,6 +25,7 @@ #include "../pinctrl/pinctrl-rockchip.h" #define GPIO_TYPE_V1 (0) /* GPIO Version ID reserved */ +#define GPIO_TYPE_V2 (0x01000C2B) /* GPIO Version ID 0x01000C2B */ static const struct rockchip_gpio_regs gpio_regs_v1 = { .port_dr = 0x00, @@ -40,13 +41,106 @@ static const struct rockchip_gpio_regs gpio_regs_v1 = { .ext_port = 0x50, }; +static const struct rockchip_gpio_regs gpio_regs_v2 = { + .port_dr = 0x00, + .port_ddr = 0x08, + .int_en = 0x10, + .int_mask = 0x18, + .int_type = 0x20, + .int_polarity = 0x28, + .int_bothedge = 0x30, + .int_status = 0x50, + .int_rawstatus = 0x58, + .debounce = 0x38, + .dbclk_div_en = 0x40, + .dbclk_div_con = 0x48, + .port_eoi = 0x60, + .ext_port = 0x70, + .version_id = 0x78, +}; + +static inline void gpio_writel_v2(u32 val, void __iomem *reg) +{ + writel((val & 0xffff) | 0xffff0000, reg); + writel((val >> 16) | 0xffff0000, reg + 0x4); +} + +static inline u32 gpio_readl_v2(void __iomem *reg) +{ + return readl(reg + 0x4) << 16 | readl(reg); +} + +static inline void rockchip_gpio_writel(struct rockchip_pin_bank *bank, + u32 value, unsigned int offset) +{ + void __iomem *reg = bank->reg_base + offset; + + if (bank->gpio_type == GPIO_TYPE_V2) + gpio_writel_v2(value, reg); + else + writel(value, reg); +} + +static inline u32 rockchip_gpio_readl(struct rockchip_pin_bank *bank, + unsigned int offset) +{ + void __iomem *reg = bank->reg_base + offset; + u32 value; + + if (bank->gpio_type == GPIO_TYPE_V2) + value = gpio_readl_v2(reg); + else + value = readl(reg); + + return value; +} + +static inline void rockchip_gpio_writel_bit(struct rockchip_pin_bank *bank, + u32 bit, u32 value, + unsigned int offset) +{ + void __iomem *reg = bank->reg_base + offset; + u32 data; + + if (bank->gpio_type == GPIO_TYPE_V2) { + if (value) + data = BIT(bit % 16) | BIT(bit % 16 + 16); + else + data = BIT(bit % 16 + 16); + writel(data, bit >= 16 ? reg + 0x4 : reg); + } else { + data = readl(reg); + data &= ~BIT(bit); + if (value) + data |= BIT(bit); + writel(data, reg); + } +} + +static inline u32 rockchip_gpio_readl_bit(struct rockchip_pin_bank *bank, + u32 bit, unsigned int offset) +{ + void __iomem *reg = bank->reg_base + offset; + u32 data; + + if (bank->gpio_type == GPIO_TYPE_V2) { + data = readl(bit >= 16 ? reg + 0x4 : reg); + data >>= bit % 16; + } else { + data = readl(reg); + data >>= bit; + } + + return data & (0x1); +} + static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { struct rockchip_pin_bank *bank = gpiochip_get_data(chip); u32 data; - data = readl_relaxed(bank->reg_base + bank->gpio_regs->port_ddr); + data = rockchip_gpio_readl_bit(bank, offset, bank->gpio_regs->port_ddr); if (data & BIT(offset)) return GPIO_LINE_DIRECTION_OUT; @@ -58,18 +152,10 @@ static int rockchip_gpio_set_direction(struct gpio_chip *chip, { struct rockchip_pin_bank *bank = gpiochip_get_data(chip); unsigned long flags; - u32 data; + u32 data = input ? 0 : 1; raw_spin_lock_irqsave(&bank->slock, flags); - - data = readl_relaxed(bank->reg_base + bank->gpio_regs->port_ddr); - /* set bit to 1 for output, 0 for input */ - if (!input) - data |= BIT(offset); - else - data &= ~BIT(offset); - writel_relaxed(data, bank->reg_base + bank->gpio_regs->port_ddr); - + rockchip_gpio_writel_bit(bank, offset, data, bank->gpio_regs->port_ddr); raw_spin_unlock_irqrestore(&bank->slock, flags); return 0; @@ -79,18 +165,10 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) { struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - void __iomem *reg = bank->reg_base + bank->gpio_regs->port_dr; unsigned long flags; - u32 data; raw_spin_lock_irqsave(&bank->slock, flags); - - data = readl(reg); - data &= ~BIT(offset); - if (value) - data |= BIT(offset); - writel(data, reg); - + rockchip_gpio_writel_bit(bank, offset, value, bank->gpio_regs->port_dr); raw_spin_unlock_irqrestore(&bank->slock, flags); } @@ -106,24 +184,65 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned int offset) return data; } -static void rockchip_gpio_set_debounce(struct gpio_chip *gc, - unsigned int offset, bool enable) +static int rockchip_gpio_set_debounce(struct gpio_chip *gc, + unsigned int offset, + unsigned int debounce) { struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - void __iomem *reg = bank->reg_base + bank->gpio_regs->debounce; - unsigned long flags; - u32 data; + const struct rockchip_gpio_regs *reg = bank->gpio_regs; + unsigned long flags, div_reg, freq, max_debounce; + bool div_debounce_support; + unsigned int cur_div_reg; + u64 div; + + if (!IS_ERR(bank->db_clk)) { + div_debounce_support = true; + freq = clk_get_rate(bank->db_clk); + max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq; + if (debounce > max_debounce) + return -EINVAL; + + div = debounce * freq; + div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC) - 1; + } else { + div_debounce_support = false; + } raw_spin_lock_irqsave(&bank->slock, flags); - data = readl(reg); - if (enable) - data |= BIT(offset); - else - data &= ~BIT(offset); - writel(data, reg); + /* Only the v1 needs to configure div_en and div_con for dbclk */ + if (debounce) { + if (div_debounce_support) { + /* Configure the max debounce from consumers */ + cur_div_reg = readl(bank->reg_base + + reg->dbclk_div_con); + if (cur_div_reg < div_reg) + writel(div_reg, bank->reg_base + + reg->dbclk_div_con); + rockchip_gpio_writel_bit(bank, offset, 1, + reg->dbclk_div_en); + } + + rockchip_gpio_writel_bit(bank, offset, 1, reg->debounce); + } else { + if (div_debounce_support) + rockchip_gpio_writel_bit(bank, offset, 0, + reg->dbclk_div_en); + + rockchip_gpio_writel_bit(bank, offset, 0, reg->debounce); + } raw_spin_unlock_irqrestore(&bank->slock, flags); + + /* Enable or disable dbclk at last */ + if (div_debounce_support) { + if (debounce) + clk_prepare_enable(bank->db_clk); + else + clk_disable_unprepare(bank->db_clk); + } + + return 0; } static int rockchip_gpio_direction_input(struct gpio_chip *gc, @@ -272,12 +391,12 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) u32 level; u32 data; unsigned long flags; + int ret = 0; raw_spin_lock_irqsave(&bank->slock, flags); - data = readl_relaxed(bank->reg_base + bank->gpio_regs->port_ddr); - data &= ~mask; - writel_relaxed(data, bank->reg_base + bank->gpio_regs->port_ddr); + rockchip_gpio_writel_bit(bank, d->hwirq, 0, + bank->gpio_regs->port_ddr); raw_spin_unlock_irqrestore(&bank->slock, flags); @@ -289,23 +408,30 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) raw_spin_lock_irqsave(&bank->slock, flags); irq_gc_lock(gc); - level = readl_relaxed(gc->reg_base + bank->gpio_regs->int_type); - polarity = readl_relaxed(gc->reg_base + bank->gpio_regs->int_polarity); + level = rockchip_gpio_readl(bank, bank->gpio_regs->int_type); + polarity = rockchip_gpio_readl(bank, bank->gpio_regs->int_polarity); switch (type) { case IRQ_TYPE_EDGE_BOTH: - bank->toggle_edge_mode |= mask; - level |= mask; - - /* - * Determine gpio state. If 1 next interrupt should be falling - * otherwise rising. - */ - data = readl(bank->reg_base + bank->gpio_regs->ext_port); - if (data & mask) - polarity &= ~mask; - else - polarity |= mask; + if (bank->gpio_type == GPIO_TYPE_V2) { + bank->toggle_edge_mode &= ~mask; + rockchip_gpio_writel_bit(bank, d->hwirq, 1, + bank->gpio_regs->int_bothedge); + goto out; + } else { + bank->toggle_edge_mode |= mask; + level |= mask; + + /* + * Determine gpio state. If 1 next interrupt should be + * falling otherwise rising. + */ + data = readl(bank->reg_base + bank->gpio_regs->ext_port); + if (data & mask) + polarity &= ~mask; + else + polarity |= mask; + } break; case IRQ_TYPE_EDGE_RISING: bank->toggle_edge_mode &= ~mask; @@ -328,19 +454,17 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) polarity &= ~mask; break; default: - irq_gc_unlock(gc); - raw_spin_unlock_irqrestore(&bank->slock, flags); - clk_disable(bank->clk); - return -EINVAL; + ret = -EINVAL; + goto out; } - writel_relaxed(level, gc->reg_base + bank->gpio_regs->int_type); - writel_relaxed(polarity, gc->reg_base + bank->gpio_regs->int_polarity); - + rockchip_gpio_writel(bank, level, bank->gpio_regs->int_type); + rockchip_gpio_writel(bank, polarity, bank->gpio_regs->int_polarity); +out: irq_gc_unlock(gc); raw_spin_unlock_irqrestore(&bank->slock, flags); - return 0; + return ret; } static void rockchip_irq_suspend(struct irq_data *d) @@ -362,19 +486,12 @@ static void rockchip_irq_resume(struct irq_data *d) static void rockchip_irq_enable(struct irq_data *d) { - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - irq_gc_mask_clr_bit(d); } static void rockchip_irq_disable(struct irq_data *d) { - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - irq_gc_mask_set_bit(d); - clk_disable(bank->clk); } static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) @@ -403,6 +520,11 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) } gc = irq_get_domain_generic_chip(bank->domain, 0); + if (bank->gpio_type == GPIO_TYPE_V2) { + gc->reg_writel = gpio_writel_v2; + gc->reg_readl = gpio_readl_v2; + } + gc->reg_base = bank->reg_base; gc->private = bank; gc->chip_types[0].regs.mask = bank->gpio_regs->int_mask; @@ -423,9 +545,9 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) * Our driver only uses the concept of masked and always keeps * things enabled, so for us that's all masked and all enabled. */ - writel_relaxed(0xffffffff, bank->reg_base + bank->gpio_regs->int_mask); - writel_relaxed(0xffffffff, bank->reg_base + bank->gpio_regs->port_eoi); - writel_relaxed(0xffffffff, bank->reg_base + bank->gpio_regs->int_en); + rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->int_mask); + rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->port_eoi); + rockchip_gpio_writel(bank, 0xffffffff, bank->gpio_regs->int_en); gc->mask_cache = 0xffffffff; irq_set_chained_handler_and_data(bank->irq, @@ -503,6 +625,7 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank) static int rockchip_get_bank_data(struct rockchip_pin_bank *bank) { struct resource res; + int id = 0; if (of_address_to_resource(bank->of_node, 0, &res)) { dev_err(bank->dev, "cannot find IO resource for bank\n"); @@ -514,15 +637,31 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank) return PTR_ERR(bank->reg_base); bank->irq = irq_of_parse_and_map(bank->of_node, 0); - - bank->gpio_regs = &gpio_regs_v1; - bank->gpio_type = GPIO_TYPE_V1; + if (!bank->irq) + return -EINVAL; bank->clk = of_clk_get(bank->of_node, 0); - if (!IS_ERR(bank->clk)) - return clk_prepare_enable(bank->clk); + if (IS_ERR(bank->clk)) + return PTR_ERR(bank->clk); + + clk_prepare_enable(bank->clk); + id = readl(bank->reg_base + gpio_regs_v2.version_id); + + /* If not gpio v2, that is default to v1. */ + if (id == GPIO_TYPE_V2) { + bank->gpio_regs = &gpio_regs_v2; + bank->gpio_type = GPIO_TYPE_V2; + bank->db_clk = of_clk_get(bank->of_node, 1); + if (IS_ERR(bank->db_clk)) { + dev_err(bank->dev, "cannot find debounce clk\n"); + clk_disable_unprepare(bank->clk); + return -EINVAL; + } + } else { + bank->gpio_regs = &gpio_regs_v1; + bank->gpio_type = GPIO_TYPE_V1; + } - bank->clk = NULL; return 0; } diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index 1b774b6bbc3e..589d4d2a98c9 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -121,6 +121,7 @@ struct rockchip_drv { * @reg_base: register base of the gpio bank * @regmap_pull: optional separate register for additional pull settings * @clk: clock of the gpio bank + * @db_clk: clock of the gpio debounce * @irq: interrupt of the gpio bank * @saved_masks: Saved content of GPIO_INTEN at suspend time. * @pin_base: first pin number @@ -146,6 +147,7 @@ struct rockchip_pin_bank { void __iomem *reg_base; struct regmap *regmap_pull; struct clk *clk; + struct clk *db_clk; int irq; u32 saved_masks; u32 pin_base; From patchwork Fri Jun 18 06:29:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330269 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DFFBC48BE8 for ; Fri, 18 Jun 2021 06:29:16 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2AC9160C41 for ; Fri, 18 Jun 2021 06:29:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2AC9160C41 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=aWJpycMlWL8NAodpnUhDsLdWVzP3JkKkPQ1ZfevqNXM=; b=r1LeH6yCJOct/M xH1v1UdYOqywuetPRj46k+wbtbzd6/gbdgFTicmj5tXiHJ/rNbr3EfnDgcC02Rcw2XzOoDgE8Jo/o whbl2j44M+gc1vPwGSOqhleWaizMOBveCUYKvhXs/T/DaGE0CMyTmcWcmDuhxoWNr6YrfDXFxUOZh r2JxZwrERbGDvM44ve1xq+XU1gre2GCYda1QgYc7lskjwBvXWg7nKsPkfZ8saKBcFQwPFjnCqTLgP mF9A3PYS7HuS1/ObFb1v1x0EJzuugxGfXlQmDCXINcVDOsjBiqo6WwIvKXwU25PUmsKTR/6IPkUMY zg/CU8tcZrP2irZtm/1g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu806-00CqRT-EI; Fri, 18 Jun 2021 06:29:10 +0000 Received: from lucky1.263xmail.com ([211.157.147.131]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu804-00CqQy-05 for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:29:09 +0000 Received: from localhost (unknown [192.168.167.16]) by lucky1.263xmail.com (Postfix) with ESMTP id 9FBD9BA6BC; Fri, 18 Jun 2021 14:29:06 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P16485T139919007667968S1623997744947849_; Fri, 18 Jun 2021 14:29:06 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <3367e283884d649e3e2fccbc997d39a6> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 8/9] gpio/rockchip: drop irq_gc_lock/irq_gc_unlock for irq set type Date: Fri, 18 Jun 2021 14:29:03 +0800 Message-Id: <20210618062903.1067494-1-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232908_233750_2895048F X-CRM114-Status: UNSURE ( 9.17 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org There has spin lock for irq set type already, so drop irq_gc_lock and irq_gc_unlock. Reviewed-by: Heiko Stuebner Signed-off-by: Jianqun Xu --- drivers/gpio/gpio-rockchip.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index db1ce402e7dc..5ace197a0448 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -406,7 +406,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) irq_set_handler_locked(d, handle_level_irq); raw_spin_lock_irqsave(&bank->slock, flags); - irq_gc_lock(gc); level = rockchip_gpio_readl(bank, bank->gpio_regs->int_type); polarity = rockchip_gpio_readl(bank, bank->gpio_regs->int_polarity); @@ -461,7 +460,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) rockchip_gpio_writel(bank, level, bank->gpio_regs->int_type); rockchip_gpio_writel(bank, polarity, bank->gpio_regs->int_polarity); out: - irq_gc_unlock(gc); raw_spin_unlock_irqrestore(&bank->slock, flags); return ret; From patchwork Fri Jun 18 06:29:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jianqun Xu X-Patchwork-Id: 12330271 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B1F1C49361 for ; Fri, 18 Jun 2021 06:29:36 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1346360C41 for ; Fri, 18 Jun 2021 06:29:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1346360C41 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=rock-chips.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=IUpfSjDsw2AzwZV6+djrRNnj3GViYfTQGAWR1QbG/6A=; b=A3PR49cULpBUQJ LDDnNaGLWln496Bx1hnzgTbsNlyj/A9ktsc0GlJdoKZu3WPPkx5/EW7Jm9vz2FJTGOHbLRKrRpQSV hXhBZOmiFAb3amDut0JoBmyHkPptyuHOCQMIL5yzwPfGNsBmGyh4abxeMCBgShislDLFDhJ3Qf/5r /rqiInvxBDf8JXlXUUBTagSR40VU4ckV6amvcypQkHiT4X29pzJzPpxXBfUr2Vf2Yl95Ga83/AtuV fMegkArRGt0aMepTVX/F2Ayji0A/0eBSzJjBHTNrcANv0ExaEnRbOLesASmxkfrIV5/FNLTIk+Qx+ UwWjUeWlKWyFNrtJrv4Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu80R-00CqVX-Lh; Fri, 18 Jun 2021 06:29:31 +0000 Received: from lucky1.263xmail.com ([211.157.147.135]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lu80M-00CqTs-JR for linux-rockchip@lists.infradead.org; Fri, 18 Jun 2021 06:29:30 +0000 Received: from localhost (unknown [192.168.167.235]) by lucky1.263xmail.com (Postfix) with ESMTP id 346A8AD1E7; Fri, 18 Jun 2021 14:29:24 +0800 (CST) X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-ADDR-CHECKED4: 1 X-SKE-CHECKED: 1 X-ANTISPAM-LEVEL: 2 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (postfix) whith ESMTP id P15326T140654724400896S1623997759134365_; Fri, 18 Jun 2021 14:29:20 +0800 (CST) X-IP-DOMAINF: 1 X-UNIQUE-TAG: <0dea5f3be60ae80b611013648602a3a5> X-RL-SENDER: jay.xu@rock-chips.com X-SENDER: xjq@rock-chips.com X-LOGIN-NAME: jay.xu@rock-chips.com X-FST-TO: heiko@sntech.de X-RCPT-COUNT: 7 X-SENDER-IP: 58.22.7.114 X-ATTACHMENT-NUM: 0 X-System-Flag: 0 From: Jianqun Xu To: heiko@sntech.de, linus.walleij@linaro.org Cc: linux-gpio@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, kever.yang@rock-chips.com, Jianqun Xu Subject: [PATCH 9/9] pinctrl/rockchip: drop the gpio related codes Date: Fri, 18 Jun 2021 14:29:18 +0800 Message-Id: <20210618062918.1067557-1-jay.xu@rock-chips.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210618062449.1067106-1-jay.xu@rock-chips.com> References: <20210618062449.1067106-1-jay.xu@rock-chips.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210617_232927_171721_A631288B X-CRM114-Status: GOOD ( 24.43 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=archiver.kernel.org@lists.infradead.org With the patch to separate the gpio driver from the pinctrl driver, now the pinctrl-rockchip can drop the gpio related codes now. Signed-off-by: Jianqun Xu --- drivers/pinctrl/pinctrl-rockchip.c | 647 +---------------------------- 1 file changed, 18 insertions(+), 629 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index b99813379918..f30f2265aa63 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -20,9 +20,9 @@ #include #include #include -#include -#include +#include #include +#include #include #include #include @@ -39,20 +39,6 @@ #include "pinconf.h" #include "pinctrl-rockchip.h" -/* GPIO control registers */ -#define GPIO_SWPORT_DR 0x00 -#define GPIO_SWPORT_DDR 0x04 -#define GPIO_INTEN 0x30 -#define GPIO_INTMASK 0x34 -#define GPIO_INTTYPE_LEVEL 0x38 -#define GPIO_INT_POLARITY 0x3c -#define GPIO_INT_STATUS 0x40 -#define GPIO_INT_RAWSTATUS 0x44 -#define GPIO_DEBOUNCE 0x48 -#define GPIO_PORTS_EOI 0x4c -#define GPIO_EXT_PORT 0x50 -#define GPIO_LS_SYNC 0x60 - /** * Generate a bitmask for setting a value (v) with a write mask bit in hiword * register 31:16 area. @@ -2071,75 +2057,11 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, return 0; } -static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset) -{ - struct rockchip_pin_bank *bank = gpiochip_get_data(chip); - u32 data; - - data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); - if (data & BIT(offset)) - return GPIO_LINE_DIRECTION_OUT; - - return GPIO_LINE_DIRECTION_IN; -} - -/* - * The calls to gpio_direction_output() and gpio_direction_input() - * leads to this function call (via the pinctrl_gpio_direction_{input|output}() - * function called from the gpiolib interface). - */ -static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, - int pin, bool input) -{ - struct rockchip_pin_bank *bank; - int ret; - unsigned long flags; - u32 data; - - bank = gpiochip_get_data(chip); - - ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO); - if (ret < 0) - return ret; - - raw_spin_lock_irqsave(&bank->slock, flags); - - data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); - /* set bit to 1 for output, 0 for input */ - if (!input) - data |= BIT(pin); - else - data &= ~BIT(pin); - writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); - - raw_spin_unlock_irqrestore(&bank->slock, flags); - - return 0; -} - -static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned offset, bool input) -{ - struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); - struct gpio_chip *chip; - int pin; - - chip = range->gc; - pin = offset - chip->base; - dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n", - offset, range->name, pin, input ? "input" : "output"); - - return _rockchip_pmx_gpio_set_direction(chip, offset - chip->base, - input); -} - static const struct pinmux_ops rockchip_pmx_ops = { .get_functions_count = rockchip_pmx_get_funcs_count, .get_function_name = rockchip_pmx_get_func_name, .get_function_groups = rockchip_pmx_get_groups, .set_mux = rockchip_pmx_set, - .gpio_set_direction = rockchip_pmx_gpio_set_direction, }; /* @@ -2170,15 +2092,13 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, return false; } -static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value); -static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset); - /* set the pin config settings for a specified pin */ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs, unsigned num_configs) { struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); struct rockchip_pin_bank *bank = pin_to_bank(info, pin); + struct gpio_chip *gpio = &bank->gpio_chip; enum pin_config_param param; u32 arg; int i; @@ -2211,10 +2131,13 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, return rc; break; case PIN_CONFIG_OUTPUT: - rockchip_gpio_set(&bank->gpio_chip, - pin - bank->pin_base, arg); - rc = _rockchip_pmx_gpio_set_direction(&bank->gpio_chip, - pin - bank->pin_base, false); + rc = rockchip_set_mux(bank, pin - bank->pin_base, + RK_FUNC_GPIO); + if (rc != RK_FUNC_GPIO) + return -EINVAL; + + rc = gpio->direction_output(gpio, pin - bank->pin_base, + arg); if (rc) return rc; break; @@ -2252,6 +2175,7 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, { struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); struct rockchip_pin_bank *bank = pin_to_bank(info, pin); + struct gpio_chip *gpio = &bank->gpio_chip; enum pin_config_param param = pinconf_to_config_param(*config); u16 arg; int rc; @@ -2280,7 +2204,7 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, if (rc != RK_FUNC_GPIO) return -EINVAL; - rc = rockchip_gpio_get(&bank->gpio_chip, pin - bank->pin_base); + rc = gpio->get(gpio, pin - bank->pin_base); if (rc < 0) return rc; @@ -2518,7 +2442,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, ctrldesc->npins = info->ctrl->nr_pins; pdesc = pindesc; - for (bank = 0 , k = 0; bank < info->ctrl->nr_banks; bank++) { + for (bank = 0, k = 0; bank < info->ctrl->nr_banks; bank++) { pin_bank = &info->ctrl->pin_banks[bank]; for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) { pdesc->number = k; @@ -2538,526 +2462,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, return PTR_ERR(info->pctl_dev); } - for (bank = 0; bank < info->ctrl->nr_banks; ++bank) { - pin_bank = &info->ctrl->pin_banks[bank]; - pin_bank->grange.name = pin_bank->name; - pin_bank->grange.id = bank; - pin_bank->grange.pin_base = pin_bank->pin_base; - pin_bank->grange.base = pin_bank->gpio_chip.base; - pin_bank->grange.npins = pin_bank->gpio_chip.ngpio; - pin_bank->grange.gc = &pin_bank->gpio_chip; - pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange); - } - return 0; } -/* - * GPIO handling - */ - -static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value) -{ - struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR; - unsigned long flags; - u32 data; - - raw_spin_lock_irqsave(&bank->slock, flags); - - data = readl(reg); - data &= ~BIT(offset); - if (value) - data |= BIT(offset); - writel(data, reg); - - raw_spin_unlock_irqrestore(&bank->slock, flags); -} - -/* - * Returns the level of the pin for input direction and setting of the DR - * register for output gpios. - */ -static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - u32 data; - - data = readl(bank->reg_base + GPIO_EXT_PORT); - data >>= offset; - data &= 1; - return data; -} - -/* - * gpiolib gpio_direction_input callback function. The setting of the pin - * mux function as 'gpio input' will be handled by the pinctrl subsystem - * interface. - */ -static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - return pinctrl_gpio_direction_input(gc->base + offset); -} - -/* - * gpiolib gpio_direction_output callback function. The setting of the pin - * mux function as 'gpio output' will be handled by the pinctrl subsystem - * interface. - */ -static int rockchip_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, int value) -{ - rockchip_gpio_set(gc, offset, value); - return pinctrl_gpio_direction_output(gc->base + offset); -} - -static void rockchip_gpio_set_debounce(struct gpio_chip *gc, - unsigned int offset, bool enable) -{ - struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - void __iomem *reg = bank->reg_base + GPIO_DEBOUNCE; - unsigned long flags; - u32 data; - - raw_spin_lock_irqsave(&bank->slock, flags); - - data = readl(reg); - if (enable) - data |= BIT(offset); - else - data &= ~BIT(offset); - writel(data, reg); - - raw_spin_unlock_irqrestore(&bank->slock, flags); -} - -/* - * gpiolib set_config callback function. The setting of the pin - * mux function as 'gpio output' will be handled by the pinctrl subsystem - * interface. - */ -static int rockchip_gpio_set_config(struct gpio_chip *gc, unsigned int offset, - unsigned long config) -{ - enum pin_config_param param = pinconf_to_config_param(config); - - switch (param) { - case PIN_CONFIG_INPUT_DEBOUNCE: - rockchip_gpio_set_debounce(gc, offset, true); - /* - * Rockchip's gpio could only support up to one period - * of the debounce clock(pclk), which is far away from - * satisftying the requirement, as pclk is usually near - * 100MHz shared by all peripherals. So the fact is it - * has crippled debounce capability could only be useful - * to prevent any spurious glitches from waking up the system - * if the gpio is conguired as wakeup interrupt source. Let's - * still return -ENOTSUPP as before, to make sure the caller - * of gpiod_set_debounce won't change its behaviour. - */ - return -ENOTSUPP; - default: - return -ENOTSUPP; - } -} - -/* - * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin - * and a virtual IRQ, if not already present. - */ -static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct rockchip_pin_bank *bank = gpiochip_get_data(gc); - unsigned int virq; - - if (!bank->domain) - return -ENXIO; - - virq = irq_create_mapping(bank->domain, offset); - - return (virq) ? : -ENXIO; -} - -static const struct gpio_chip rockchip_gpiolib_chip = { - .request = gpiochip_generic_request, - .free = gpiochip_generic_free, - .set = rockchip_gpio_set, - .get = rockchip_gpio_get, - .get_direction = rockchip_gpio_get_direction, - .direction_input = rockchip_gpio_direction_input, - .direction_output = rockchip_gpio_direction_output, - .set_config = rockchip_gpio_set_config, - .to_irq = rockchip_gpio_to_irq, - .owner = THIS_MODULE, -}; - -/* - * Interrupt handling - */ - -static void rockchip_irq_demux(struct irq_desc *desc) -{ - struct irq_chip *chip = irq_desc_get_chip(desc); - struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc); - u32 pend; - - dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); - - chained_irq_enter(chip, desc); - - pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); - - while (pend) { - unsigned int irq, virq; - - irq = __ffs(pend); - pend &= ~BIT(irq); - virq = irq_find_mapping(bank->domain, irq); - - if (!virq) { - dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq); - continue; - } - - dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq); - - /* - * Triggering IRQ on both rising and falling edge - * needs manual intervention. - */ - if (bank->toggle_edge_mode & BIT(irq)) { - u32 data, data_old, polarity; - unsigned long flags; - - data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); - do { - raw_spin_lock_irqsave(&bank->slock, flags); - - polarity = readl_relaxed(bank->reg_base + - GPIO_INT_POLARITY); - if (data & BIT(irq)) - polarity &= ~BIT(irq); - else - polarity |= BIT(irq); - writel(polarity, - bank->reg_base + GPIO_INT_POLARITY); - - raw_spin_unlock_irqrestore(&bank->slock, flags); - - data_old = data; - data = readl_relaxed(bank->reg_base + - GPIO_EXT_PORT); - } while ((data & BIT(irq)) != (data_old & BIT(irq))); - } - - generic_handle_irq(virq); - } - - chained_irq_exit(chip, desc); -} - -static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - u32 mask = BIT(d->hwirq); - u32 polarity; - u32 level; - u32 data; - unsigned long flags; - int ret; - - /* make sure the pin is configured as gpio input */ - ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO); - if (ret < 0) - return ret; - - raw_spin_lock_irqsave(&bank->slock, flags); - - data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); - data &= ~mask; - writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); - - raw_spin_unlock_irqrestore(&bank->slock, flags); - - if (type & IRQ_TYPE_EDGE_BOTH) - irq_set_handler_locked(d, handle_edge_irq); - else - irq_set_handler_locked(d, handle_level_irq); - - raw_spin_lock_irqsave(&bank->slock, flags); - irq_gc_lock(gc); - - level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); - polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); - - switch (type) { - case IRQ_TYPE_EDGE_BOTH: - bank->toggle_edge_mode |= mask; - level |= mask; - - /* - * Determine gpio state. If 1 next interrupt should be falling - * otherwise rising. - */ - data = readl(bank->reg_base + GPIO_EXT_PORT); - if (data & mask) - polarity &= ~mask; - else - polarity |= mask; - break; - case IRQ_TYPE_EDGE_RISING: - bank->toggle_edge_mode &= ~mask; - level |= mask; - polarity |= mask; - break; - case IRQ_TYPE_EDGE_FALLING: - bank->toggle_edge_mode &= ~mask; - level |= mask; - polarity &= ~mask; - break; - case IRQ_TYPE_LEVEL_HIGH: - bank->toggle_edge_mode &= ~mask; - level &= ~mask; - polarity |= mask; - break; - case IRQ_TYPE_LEVEL_LOW: - bank->toggle_edge_mode &= ~mask; - level &= ~mask; - polarity &= ~mask; - break; - default: - irq_gc_unlock(gc); - raw_spin_unlock_irqrestore(&bank->slock, flags); - return -EINVAL; - } - - writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL); - writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); - - irq_gc_unlock(gc); - raw_spin_unlock_irqrestore(&bank->slock, flags); - - return 0; -} - -static void rockchip_irq_suspend(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - - bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK); - irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK); -} - -static void rockchip_irq_resume(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - - irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK); -} - -static void rockchip_irq_enable(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - - irq_gc_mask_clr_bit(d); -} - -static void rockchip_irq_disable(struct irq_data *d) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct rockchip_pin_bank *bank = gc->private; - - irq_gc_mask_set_bit(d); -} - -static int rockchip_interrupts_register(struct platform_device *pdev, - struct rockchip_pinctrl *info) -{ - struct rockchip_pin_ctrl *ctrl = info->ctrl; - struct rockchip_pin_bank *bank = ctrl->pin_banks; - unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; - struct irq_chip_generic *gc; - int ret; - int i; - - for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { - if (!bank->valid) { - dev_warn(&pdev->dev, "bank %s is not valid\n", - bank->name); - continue; - } - - bank->domain = irq_domain_add_linear(bank->of_node, 32, - &irq_generic_chip_ops, NULL); - if (!bank->domain) { - dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n", - bank->name); - continue; - } - - ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1, - "rockchip_gpio_irq", handle_level_irq, - clr, 0, 0); - if (ret) { - dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n", - bank->name); - irq_domain_remove(bank->domain); - continue; - } - - gc = irq_get_domain_generic_chip(bank->domain, 0); - gc->reg_base = bank->reg_base; - gc->private = bank; - gc->chip_types[0].regs.mask = GPIO_INTMASK; - gc->chip_types[0].regs.ack = GPIO_PORTS_EOI; - gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; - gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; - gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; - gc->chip_types[0].chip.irq_enable = rockchip_irq_enable; - gc->chip_types[0].chip.irq_disable = rockchip_irq_disable; - gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake; - gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend; - gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; - gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; - gc->wake_enabled = IRQ_MSK(bank->nr_pins); - - /* - * Linux assumes that all interrupts start out disabled/masked. - * Our driver only uses the concept of masked and always keeps - * things enabled, so for us that's all masked and all enabled. - */ - writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK); - writel_relaxed(0xffffffff, bank->reg_base + GPIO_PORTS_EOI); - writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN); - gc->mask_cache = 0xffffffff; - - irq_set_chained_handler_and_data(bank->irq, - rockchip_irq_demux, bank); - } - - return 0; -} - -static int rockchip_gpiolib_register(struct platform_device *pdev, - struct rockchip_pinctrl *info) -{ - struct rockchip_pin_ctrl *ctrl = info->ctrl; - struct rockchip_pin_bank *bank = ctrl->pin_banks; - struct gpio_chip *gc; - int ret; - int i; - - for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { - if (!bank->valid) { - dev_warn(&pdev->dev, "bank %s is not valid\n", - bank->name); - continue; - } - - bank->gpio_chip = rockchip_gpiolib_chip; - - gc = &bank->gpio_chip; - gc->base = bank->pin_base; - gc->ngpio = bank->nr_pins; - gc->parent = &pdev->dev; - gc->of_node = bank->of_node; - gc->label = bank->name; - - ret = gpiochip_add_data(gc, bank); - if (ret) { - dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n", - gc->label, ret); - goto fail; - } - } - - rockchip_interrupts_register(pdev, info); - - return 0; - -fail: - for (--i, --bank; i >= 0; --i, --bank) { - if (!bank->valid) - continue; - gpiochip_remove(&bank->gpio_chip); - } - return ret; -} - -static int rockchip_gpiolib_unregister(struct platform_device *pdev, - struct rockchip_pinctrl *info) -{ - struct rockchip_pin_ctrl *ctrl = info->ctrl; - struct rockchip_pin_bank *bank = ctrl->pin_banks; - int i; - - for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { - if (!bank->valid) - continue; - gpiochip_remove(&bank->gpio_chip); - } - - return 0; -} - -static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, - struct rockchip_pinctrl *info) -{ - struct resource res; - void __iomem *base; - - if (of_address_to_resource(bank->of_node, 0, &res)) { - dev_err(info->dev, "cannot find IO resource for bank\n"); - return -ENOENT; - } - - bank->reg_base = devm_ioremap_resource(info->dev, &res); - if (IS_ERR(bank->reg_base)) - return PTR_ERR(bank->reg_base); - - /* - * special case, where parts of the pull setting-registers are - * part of the PMU register space - */ - if (of_device_is_compatible(bank->of_node, - "rockchip,rk3188-gpio-bank0")) { - struct device_node *node; - - node = of_parse_phandle(bank->of_node->parent, - "rockchip,pmu", 0); - if (!node) { - if (of_address_to_resource(bank->of_node, 1, &res)) { - dev_err(info->dev, "cannot find IO resource for bank\n"); - return -ENOENT; - } - - base = devm_ioremap_resource(info->dev, &res); - if (IS_ERR(base)) - return PTR_ERR(base); - rockchip_regmap_config.max_register = - resource_size(&res) - 4; - rockchip_regmap_config.name = - "rockchip,rk3188-gpio-bank0-pull"; - bank->regmap_pull = devm_regmap_init_mmio(info->dev, - base, - &rockchip_regmap_config); - } - of_node_put(node); - } - - bank->irq = irq_of_parse_and_map(bank->of_node, 0); - - bank->clk = of_clk_get(bank->of_node, 0); - if (IS_ERR(bank->clk)) - return PTR_ERR(bank->clk); - - return clk_prepare_enable(bank->clk); -} - static const struct of_device_id rockchip_pinctrl_dt_match[]; /* retrieve the soc specific data */ @@ -3067,7 +2474,6 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( { const struct of_device_id *match; struct device_node *node = pdev->dev.of_node; - struct device_node *np; struct rockchip_pin_ctrl *ctrl; struct rockchip_pin_bank *bank; int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j; @@ -3075,23 +2481,6 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( match = of_match_node(rockchip_pinctrl_dt_match, node); ctrl = (struct rockchip_pin_ctrl *)match->data; - for_each_child_of_node(node, np) { - if (!of_find_property(np, "gpio-controller", NULL)) - continue; - - bank = ctrl->pin_banks; - for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { - if (!strcmp(bank->name, np->name)) { - bank->of_node = np; - - if (!rockchip_get_bank_data(bank, d)) - bank->valid = true; - - break; - } - } - } - grf_offs = ctrl->grf_mux_offset; pmu_offs = ctrl->pmu_mux_offset; drv_pmu_offs = ctrl->pmu_drv_offset; @@ -3312,18 +2701,18 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) return PTR_ERR(info->regmap_pmu); } - ret = rockchip_gpiolib_register(pdev, info); + ret = rockchip_pinctrl_register(pdev, info); if (ret) return ret; - ret = rockchip_pinctrl_register(pdev, info); + platform_set_drvdata(pdev, info); + + ret = of_platform_populate(np, rockchip_bank_match, NULL, NULL); if (ret) { - rockchip_gpiolib_unregister(pdev, info); + dev_err(&pdev->dev, "failed to register gpio device\n"); return ret; } - platform_set_drvdata(pdev, info); - return 0; }