From patchwork Wed Aug 24 13:49:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chanwoo Choi X-Patchwork-Id: 9297909 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5D70A607F0 for ; Wed, 24 Aug 2016 13:52:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4C50128FED for ; Wed, 24 Aug 2016 13:52:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F86528FE3; Wed, 24 Aug 2016 13:52:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4275528FE3 for ; Wed, 24 Aug 2016 13:52:31 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bcYZu-0000Yv-Gw; Wed, 24 Aug 2016 13:50:50 +0000 Received: from mailout3.samsung.com ([203.254.224.33]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bcYYt-0007MH-Dv for linux-arm-kernel@lists.infradead.org; Wed, 24 Aug 2016 13:49:54 +0000 Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OCF00D5F2EDL540@mailout3.samsung.com> for linux-arm-kernel@lists.infradead.org; Wed, 24 Aug 2016 22:49:25 +0900 (KST) Received: from epcpsbgm2new.samsung.com ( [172.20.52.113]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id 2B.D4.31386.5E5ADB75; Wed, 24 Aug 2016 22:49:25 +0900 (KST) X-AuditID: cbfee68d-f79286d000007a9a-f0-57bda5e5ea87 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2new.samsung.com (EPCPMTA) with SMTP id CE.9B.07740.4E5ADB75; Wed, 24 Aug 2016 06:49:25 -0700 (MST) Received: from chan.10.32.193.11 ([10.113.62.212]) by mmp1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OCF00GWI2EBKL20@mmp1.samsung.com>; Wed, 24 Aug 2016 22:49:24 +0900 (KST) From: Chanwoo Choi To: k.kozlowski@samsung.com, kgene@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/7] pinctrl: samsung: Add the support the multiple IORESOURCE_MEM for one pin-bank Date: Wed, 24 Aug 2016 22:49:07 +0900 Message-id: <1472046551-703-4-git-send-email-cw00.choi@samsung.com> X-Mailer: git-send-email 1.8.0 In-reply-to: <1472046551-703-1-git-send-email-cw00.choi@samsung.com> References: <1472046551-703-1-git-send-email-cw00.choi@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAAzWSW0iTcRjG++87bK6kr6n1d6TRwBsrcx7/WkhgF1/gRRQhFKHTPuZK59ym KBGuizRHLY+oJZrpVKapbCIqHufIyHSTydzMQ2XqxMA8EJombWp3v5fneZ/n4n05GM+K8zkS qZKRS0WpApKLt3iHZVxa1PbFBz+dPYmmW8cJNLrRyUZrDS8AKrJP4mhqa5lANSaXoK3QEKjn 7zxAXY4tEhXPF+KoS2UikP1PHoEKxn5gyDk3gaNVpxC9WljFkNnczkale40spF+wEchQsweQ taeKRBXmfhZ6b5plI+3UBAs96zOx0fDPfAJVlKyQSNfj8q2sf8Sv+dEt1S2A7n49y6b1ugKS nrH1krShPpfWdOgAvan3v8m+y736gEmVZDHyyzGJ3JR69TYha9eAbEdZP6ECA0o18OBAKgyu 2hvAIZ+Glrk2Ug24HB7VBGBdoxH7b7LsF4BDQQugvraVcAs8agvAb2UZbiapQDjgtB9se1Ma Fmz4NMZyDxi1hsFZ3XOW2+VFpUCDevGAcSoA7lptB+xJxUJbaflRnT/81fud7WYP6jqs3da4 Ujmutlg4WX7KnQkpCwd+NlSCwxwK/i4x4m4PpPygfvAoxhcONdnxQuD1FhzTAR9GlixTJInl wiCFKE2RKRUHJaen6YHr1qP7Sy+7wJfBK0ZAcYDghKdlrjeeR4iyFDlpRhDuaijC+D7J6a73 kCoThKERISg8LDw0JDIqQnDG8zx/5zaPEouUzCOGkTHyBHlmKqMwAhbHg68CqtremXEmU3L8 Ht087OD7OwKaueadulZrWYzlw/04VfudMEdy3dLoULTNrGwomqDzhzZyyotzk2LPygq/amtI 08YN4RtxR9yUPnIseDcbe9fdlljwJC5BMn3L0h09sjD3cN3i+ziv4qIanauMjl+OGtkctjRW 8as7FU7PC2IBrkgRCQMxuUL0D8+xaHbmAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrAKsWRmVeSWpSXmKPExsVy+t9jAd2nS/eGGzS+ZbG4te4cq8XpT9vY Ld4v62G0mHjjCovF9S/PWS3mHwFKLJ3Rx2qx6+99RosdN7+wWUy6P4HFYkfDEVaLG7/aWC06 zz5htnhx7yKLxesXhhb9j18zW5w/v4HdYsqf5UwWmx5fY7XYPP8Po8XlXXPYLGac38dksfbI XXaLpdcvMlm07j3CbnH4TTurxYzJL9ksVu0Cqnv58QSLg6zHmnlrGD12zrrL7rFpVSebx51r e9g8Ni+p9+jbsorR4/MmuQD2qAZGm4zUxJTUIoXUvOT8lMy8dFsl7+B453hTMwNDXUNLC3Ml hbzE3FRbJRefAF23zByg75UUyhJzSoFCAYnFxUr6dpgmhIa46VrANEbo+oYEwfUYGaCBhDWM GUu6frAWbOhjrLg5dR9rA+P+ki5GTg4JAROJC/86GSFsMYkL99azdTFycQgJLGWU2LRwHStI QkjgC6PEw6mFIDabgJbE/hc3wIpEBPqYJJadOssE4jALvGeWuLuqgwmkSlggQ2Jz11Mwm0VA VeL35WtgNq+As8S1KdOZIdbJSXzY84gdxOYUcJFY+KMPaCoH0DZniSvTBScw8i5gZFjFKJFa kFxQnJSea5SXWq5XnJhbXJqXrpecn7uJEZw6nknvYDy8y/0QowAHoxIP7w/GveFCrIllxZW5 hxglOJiVRHhFgIlHiDclsbIqtSg/vqg0J7X4EKMp0F0TmaVEk/OBaS2vJN7Q2MTMyNLI3NDC yNhcSZz38f91YUIC6YklqdmpqQWpRTB9TBycUg2MsvILYg4tEOc8w/LFzFv65uQbS++VvljU 3+FzSnfTxIKKRTN3WHXZuBqeblSecfCydoJRSvECzyWnRIRmBd538b6xdtW/zVOES+e9rPf8 VBgRoLh2sUqdkZDAEda669Vzl/POmdVcnznNp+PNo07J2917Z28wdnv1ZdpJN0GzqYo+8yvc T6zKVmIpzkg01GIuKk4EAEYfAaMzAwAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160824_064947_879954_EF749111 X-CRM114-Status: GOOD ( 17.66 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: inki.dae@samsung.com, jonghwa3.lee@samsung.com, s.nawrocki@samsung.com, jy0922.shim@samsung.com, a.hajda@samsung.com, jaewon02.kim@samsung.com, Linus Walleij , sw0312.kim@samsung.com, Tomasz Figa , krzk@kernel.org, jh80.chung@samsung.com, cw00.choi@samsung.com, human.hwang@samsung.com, linux-gpio@vger.kernel.org, chanwoo@kernel.org, ingi2.kim@samsung.com, m.szyprowski@samsung.com, beomho.seo@samsung.com, ideal.song@samsung.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch supports the multiple IORESOURCE_MEM resources for one pin-bank. In the pre-existing Exynos series, the registers of the gpio bank are included in the one memory map. But, some gpio bank need to support the one more memory map (IORESOURCE_MEM) because the registers of gpio bank are located in the different memory map. For example, The both ALIVE and IMEM domain have the different memory base address. The GFP[1-5] of exynos5433 are composed as following: - ALIVE domain : WEINT_* registers - IMEM domain : CON/DAT/PUD/DRV/CONPDN/PUDPDN register Cc: Linus Walleij Cc: Rob Herring Cc: Mark Rutland Cc: Tomasz Figa Cc: Krzysztof Kozlowski Cc: Sylwester Nawrocki Cc: Kukjin Kim Cc: linux-gpio@vger.kernel.org Suggested-by: Tomasz Figa Signed-off-by: Chanwoo Choi --- .../bindings/pinctrl/samsung-pinctrl.txt | 17 +++++++ drivers/pinctrl/samsung/pinctrl-exynos.c | 46 +++++++++++------- drivers/pinctrl/samsung/pinctrl-exynos.h | 47 ++++++++++++++++-- drivers/pinctrl/samsung/pinctrl-samsung.c | 55 ++++++++++++++-------- drivers/pinctrl/samsung/pinctrl-samsung.h | 7 ++- 5 files changed, 131 insertions(+), 41 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt index 6db16b90873a..37bc692445d4 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt @@ -94,6 +94,11 @@ Required Properties: pin configuration should use the bindings listed in the "pinctrl-bindings.txt" file. +Optional Properties: +- reg: Second base address of the pin controller hardware module and length of + the address space it occupies if the specific register of the pin controller + are located in the different base address. + External GPIO and Wakeup Interrupts: The controller supports two types of external interrupts over gpio. The first @@ -305,6 +310,18 @@ Example 2: A pin-controller node with external wakeup interrupt controller node. }; }; + - A pin-controller node with multiple base address. + + pinctrl_0: pinctrl@10580000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x10580000 0x1a20>, <0x11090000 0x100>; + + wakeup-interrupt-controller { + compatible = "samsung,exynos7-wakeup-eint"; + interrupts = <0 16 0>; + }; + }; + Example 3: A uart client node that supports 'default' and 'flow-control' states. uart@13800000 { diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index 051b5bf701a8..12fa9d3f1113 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -65,12 +65,13 @@ static void exynos_irq_mask(struct irq_data *irqd) unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; unsigned long mask; unsigned long flags; + unsigned int eint_res_idx = bank->eint_res_idx; spin_lock_irqsave(&bank->slock, flags); - mask = readl(d->virt_base + reg_mask); + mask = readl(d->virt_base[eint_res_idx] + reg_mask); mask |= 1 << irqd->hwirq; - writel(mask, d->virt_base + reg_mask); + writel(mask, d->virt_base[eint_res_idx] + reg_mask); spin_unlock_irqrestore(&bank->slock, flags); } @@ -82,8 +83,9 @@ static void exynos_irq_ack(struct irq_data *irqd) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset; + unsigned int eint_res_idx = bank->eint_res_idx; - writel(1 << irqd->hwirq, d->virt_base + reg_pend); + writel(1 << irqd->hwirq, d->virt_base[eint_res_idx] + reg_pend); } static void exynos_irq_unmask(struct irq_data *irqd) @@ -95,6 +97,7 @@ static void exynos_irq_unmask(struct irq_data *irqd) unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; unsigned long mask; unsigned long flags; + unsigned int eint_res_idx = bank->eint_res_idx; /* * Ack level interrupts right before unmask @@ -109,9 +112,9 @@ static void exynos_irq_unmask(struct irq_data *irqd) spin_lock_irqsave(&bank->slock, flags); - mask = readl(d->virt_base + reg_mask); + mask = readl(d->virt_base[eint_res_idx] + reg_mask); mask &= ~(1 << irqd->hwirq); - writel(mask, d->virt_base + reg_mask); + writel(mask, d->virt_base[eint_res_idx] + reg_mask); spin_unlock_irqrestore(&bank->slock, flags); } @@ -125,6 +128,7 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type) unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq; unsigned int con, trig_type; unsigned long reg_con = our_chip->eint_con + bank->eint_offset; + unsigned int eint_res_idx = bank->eint_res_idx; switch (type) { case IRQ_TYPE_EDGE_RISING: @@ -152,10 +156,10 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type) else irq_set_handler_locked(irqd, handle_level_irq); - con = readl(d->virt_base + reg_con); + con = readl(d->virt_base[eint_res_idx] + reg_con); con &= ~(EXYNOS_EINT_CON_MASK << shift); con |= trig_type << shift; - writel(con, d->virt_base + reg_con); + writel(con, d->virt_base[eint_res_idx] + reg_con); return 0; } @@ -169,6 +173,7 @@ static int exynos_irq_request_resources(struct irq_data *irqd) struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq; unsigned long reg_con = our_chip->eint_con + bank->eint_offset; + unsigned int eint_res_idx = bank->eint_res_idx; unsigned long flags; unsigned int mask; unsigned int con; @@ -188,10 +193,10 @@ static int exynos_irq_request_resources(struct irq_data *irqd) spin_lock_irqsave(&bank->slock, flags); - con = readl(d->virt_base + reg_con); + con = readl(d->virt_base[eint_res_idx] + reg_con); con &= ~(mask << shift); con |= EXYNOS_EINT_FUNC << shift; - writel(con, d->virt_base + reg_con); + writel(con, d->virt_base[eint_res_idx] + reg_con); spin_unlock_irqrestore(&bank->slock, flags); @@ -209,6 +214,7 @@ static void exynos_irq_release_resources(struct irq_data *irqd) struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq; unsigned long reg_con = our_chip->eint_con + bank->eint_offset; + unsigned int eint_res_idx = bank->eint_res_idx; unsigned long flags; unsigned int mask; unsigned int con; @@ -221,10 +227,10 @@ static void exynos_irq_release_resources(struct irq_data *irqd) spin_lock_irqsave(&bank->slock, flags); - con = readl(d->virt_base + reg_con); + con = readl(d->virt_base[eint_res_idx] + reg_con); con &= ~(mask << shift); con |= FUNC_INPUT << shift; - writel(con, d->virt_base + reg_con); + writel(con, d->virt_base[eint_res_idx] + reg_con); spin_unlock_irqrestore(&bank->slock, flags); @@ -272,9 +278,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data) { struct samsung_pinctrl_drv_data *d = data; struct samsung_pin_bank *bank = d->pin_banks; + unsigned int eint_res_idx = bank->eint_res_idx; unsigned int svc, group, pin, virq; - svc = readl(d->virt_base + EXYNOS_SVC_OFFSET); + svc = readl(d->virt_base[eint_res_idx] + EXYNOS_SVC_OFFSET); group = EXYNOS_SVC_GROUP(svc); pin = svc & EXYNOS_SVC_NUM_MASK; @@ -465,10 +472,11 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc) for (i = 0; i < eintd->nr_banks; ++i) { struct samsung_pin_bank *b = eintd->banks[i]; - pend = readl(d->virt_base + b->irq_chip->eint_pend - + b->eint_offset); - mask = readl(d->virt_base + b->irq_chip->eint_mask - + b->eint_offset); + unsigned int eint_res_idx = b->eint_res_idx; + pend = readl(d->virt_base[eint_res_idx] + + b->irq_chip->eint_pend + b->eint_offset); + mask = readl(d->virt_base[eint_res_idx] + + b->irq_chip->eint_mask + b->eint_offset); exynos_irq_demux_eint(pend & ~mask, b->irq_domain); } @@ -585,7 +593,8 @@ static void exynos_pinctrl_suspend_bank( struct samsung_pin_bank *bank) { struct exynos_eint_gpio_save *save = bank->soc_priv; - void __iomem *regs = drvdata->virt_base; + unsigned int eint_res_idx = bank->eint_res_idx; + void __iomem *regs = drvdata->virt_base[eint_res_idx]; save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET + bank->eint_offset); @@ -614,7 +623,8 @@ static void exynos_pinctrl_resume_bank( struct samsung_pin_bank *bank) { struct exynos_eint_gpio_save *save = bank->soc_priv; - void __iomem *regs = drvdata->virt_base; + unsigned int eint_res_idx = bank->eint_res_idx; + void __iomem *regs = drvdata->virt_base[eint_res_idx]; pr_debug("%s: con %#010x => %#010x\n", bank->name, readl(regs + EXYNOS_GPIO_ECON_OFFSET diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h index 0f0f7cedb2dc..865a84c32fdc 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.h +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h @@ -56,7 +56,9 @@ .pctl_offset = reg, \ .nr_pins = pins, \ .eint_type = EINT_TYPE_NONE, \ - .name = id \ + .name = id, \ + .pctl_res_idx = 0, \ + .eint_res_idx = 0 \ } #define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \ @@ -66,7 +68,9 @@ .nr_pins = pins, \ .eint_type = EINT_TYPE_GPIO, \ .eint_offset = offs, \ - .name = id \ + .name = id, \ + .pctl_res_idx = 0, \ + .eint_res_idx = 0 \ } #define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \ @@ -76,7 +80,44 @@ .nr_pins = pins, \ .eint_type = EINT_TYPE_WKUP, \ .eint_offset = offs, \ - .name = id \ + .name = id, \ + .pctl_res_idx = 0, \ + .eint_res_idx = 0 \ + } + +#define EXYNOS_PIN_BANK_EINTN_EXT(pins, reg, id, pctl_idx, eint_idx) \ + { \ + .type = &bank_type_off, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_NONE, \ + .name = id, \ + .pctl_res_idx = pctl_idx, \ + .eint_res_idx = eint_dix \ + } + +#define EXYNOS_PIN_BANK_EINTG_EXT(pins, reg, id, offs, pctl_idx, eint_idx) \ + { \ + .type = &bank_type_off, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_GPIO, \ + .eint_offset = offs, \ + .name = id, \ + .pctl_res_idx = pctl_idx, \ + .eint_res_idx = eint_idx \ + } + +#define EXYNOS_PIN_BANK_EINTW_EXT(pins, reg, id, offs, pctl_idx, eint_idx) \ + { \ + .type = &bank_type_alive, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_WKUP, \ + .eint_offset = offs, \ + .name = id, \ + .pctl_res_idx = pctl_idx, \ + .eint_res_idx = eint_idx \ } /** diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 513fe6b23248..f63f7608aef6 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -338,6 +338,7 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, struct samsung_pin_bank **bank) { struct samsung_pin_bank *b; + unsigned int pctl_res_idx; b = drvdata->pin_banks; @@ -345,7 +346,8 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, ((b->pin_base + b->nr_pins - 1) < pin)) b++; - *reg = drvdata->virt_base + b->pctl_offset; + pctl_res_idx = b->pctl_res_idx; + *reg = drvdata->virt_base[pctl_res_idx] + b->pctl_offset; *offset = pin - b->pin_base; if (bank) *bank = b; @@ -524,9 +526,10 @@ static void samsung_gpio_set_value(struct gpio_chip *gc, struct samsung_pin_bank *bank = gpiochip_get_data(gc); const struct samsung_pin_bank_type *type = bank->type; void __iomem *reg; + unsigned int pctl_res_idx = bank->pctl_res_idx; u32 data; - reg = bank->drvdata->virt_base + bank->pctl_offset; + reg = bank->drvdata->virt_base[pctl_res_idx] + bank->pctl_offset; data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); data &= ~(1 << offset); @@ -553,8 +556,9 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) u32 data; struct samsung_pin_bank *bank = gpiochip_get_data(gc); const struct samsung_pin_bank_type *type = bank->type; + unsigned int pctl_res_idx = bank->pctl_res_idx; - reg = bank->drvdata->virt_base + bank->pctl_offset; + reg = bank->drvdata->virt_base[pctl_res_idx] + bank->pctl_offset; data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); data >>= offset; @@ -575,13 +579,15 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, struct samsung_pin_bank *bank; struct samsung_pinctrl_drv_data *drvdata; void __iomem *reg; + unsigned int pctl_res_idx; u32 data, mask, shift; bank = gpiochip_get_data(gc); type = bank->type; drvdata = bank->drvdata; + pctl_res_idx = bank->pctl_res_idx; - reg = drvdata->virt_base + bank->pctl_offset + + reg = drvdata->virt_base[pctl_res_idx] + bank->pctl_offset + type->reg_offset[PINCFG_TYPE_FUNC]; mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1; @@ -979,7 +985,8 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, const struct samsung_pin_bank_data *bdata; const struct samsung_pin_ctrl *ctrl; struct samsung_pin_bank *bank; - int i; + struct resource *res; + int i, j; id = of_alias_get_id(node, "pinctrl"); if (id < 0) { @@ -1008,6 +1015,8 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, bank->eint_mask = bdata->eint_mask; bank->eint_offset = bdata->eint_offset; bank->name = bdata->name; + bank->pctl_res_idx = bdata->pctl_res_idx; + bank->eint_res_idx = bdata->eint_res_idx; spin_lock_init(&bank->slock); bank->drvdata = d; @@ -1015,6 +1024,22 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, d->nr_pins += bank->nr_pins; } + d->virt_base = devm_kzalloc(&pdev->dev, sizeof(void __iomem) * + (ctrl->nr_ext_resources + 1), GFP_KERNEL); + if (!d->virt_base) + return NULL; + + for (j = 0 ; j < ctrl->nr_ext_resources + 1; j++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, j); + d->virt_base[j] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(d->virt_base[j])) + return NULL; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) + d->irq = res->start; + for_each_child_of_node(node, np) { if (!of_find_property(np, "gpio-controller", NULL)) continue; @@ -1038,7 +1063,6 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) struct samsung_pinctrl_drv_data *drvdata; const struct samsung_pin_ctrl *ctrl; struct device *dev = &pdev->dev; - struct resource *res; int ret; if (!dev->of_node) { @@ -1060,15 +1084,6 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) } drvdata->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->virt_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(drvdata->virt_base)) - return PTR_ERR(drvdata->virt_base); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res) - drvdata->irq = res->start; - ret = samsung_gpiolib_register(pdev, drvdata); if (ret) return ret; @@ -1102,12 +1117,13 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) static void samsung_pinctrl_suspend_dev( struct samsung_pinctrl_drv_data *drvdata) { - void __iomem *virt_base = drvdata->virt_base; int i; for (i = 0; i < drvdata->nr_banks; i++) { struct samsung_pin_bank *bank = &drvdata->pin_banks[i]; - void __iomem *reg = virt_base + bank->pctl_offset; + unsigned int pctl_res_idx = bank->pctl_res_idx; + void __iomem *reg = + drvdata->virt_base[pctl_res_idx] + bank->pctl_offset; const u8 *offs = bank->type->reg_offset; const u8 *widths = bank->type->fld_width; enum pincfg_type type; @@ -1148,7 +1164,6 @@ static void samsung_pinctrl_suspend_dev( */ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) { - void __iomem *virt_base = drvdata->virt_base; int i; if (drvdata->resume) @@ -1156,7 +1171,9 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) for (i = 0; i < drvdata->nr_banks; i++) { struct samsung_pin_bank *bank = &drvdata->pin_banks[i]; - void __iomem *reg = virt_base + bank->pctl_offset; + unsigned int pctl_res_idx = bank->pctl_res_idx; + void __iomem *reg = + drvdata->virt_base[pctl_res_idx] + bank->pctl_offset; const u8 *offs = bank->type->reg_offset; const u8 *widths = bank->type->fld_width; enum pincfg_type type; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index cd31bfaf62cb..d2e4921cc2e5 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -132,6 +132,8 @@ struct samsung_pin_bank_data { u32 eint_mask; u32 eint_offset; const char *name; + unsigned int pctl_res_idx; + unsigned int eint_res_idx; }; /** @@ -164,6 +166,8 @@ struct samsung_pin_bank { u32 eint_mask; u32 eint_offset; const char *name; + unsigned int pctl_res_idx; + unsigned int eint_res_idx; u32 pin_base; void *soc_priv; @@ -190,6 +194,7 @@ struct samsung_pin_bank { struct samsung_pin_ctrl { const struct samsung_pin_bank_data *pin_banks; u32 nr_banks; + u32 nr_ext_resources; int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); @@ -215,7 +220,7 @@ struct samsung_pin_ctrl { */ struct samsung_pinctrl_drv_data { struct list_head node; - void __iomem *virt_base; + void __iomem **virt_base; struct device *dev; int irq;