From patchwork Thu Sep 20 08:53:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Figa X-Patchwork-Id: 1483411 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 84939400EC for ; Thu, 20 Sep 2012 09:03:17 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TEcdE-0008TU-PH; Thu, 20 Sep 2012 09:01:12 +0000 Received: from mailout2.samsung.com ([203.254.224.25]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TEcVu-00052B-SR for linux-arm-kernel@lists.infradead.org; Thu, 20 Sep 2012 08:53:41 +0000 Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MAN009MV4P23OA0@mailout2.samsung.com> for linux-arm-kernel@lists.infradead.org; Thu, 20 Sep 2012 17:53:37 +0900 (KST) X-AuditID: cbfee61a-b7f726d000000ec7-9d-505ad991cd7d Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id A3.0F.03783.199DA505; Thu, 20 Sep 2012 17:53:37 +0900 (KST) Received: from mcdsrvbld02.digital.local ([106.116.37.23]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MAN00DG64OWJ930@mmp1.samsung.com> for linux-arm-kernel@lists.infradead.org; Thu, 20 Sep 2012 17:53:37 +0900 (KST) From: Tomasz Figa To: linux-arm-kernel@lists.infradead.org Subject: [RFC 2/6] pinctrl: samsung: Parse pin banks from DT Date: Thu, 20 Sep 2012 10:53:13 +0200 Message-id: <1348131197-25506-3-git-send-email-t.figa@samsung.com> X-Mailer: git-send-email 1.7.10 In-reply-to: <1348131197-25506-1-git-send-email-t.figa@samsung.com> References: <1348131197-25506-1-git-send-email-t.figa@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrEJMWRmVeSWpSXmKPExsVy+t9jAd2JN6MCDC4v1rDY9PgaqwOjx+Yl 9QGMUVw2Kak5mWWpRfp2CVwZS75cYSqY4VDx48BX1gbGRtMuRk4OCQETie2H3jNB2GISF+6t Z+ti5OIQEljEKLH28BwmCGczk8SnrcvZQarYBNQkPjc8YgOxRQQ0JKZ0PWYHKWIWeMwoMXv+ HrAiYQEbiRUz77OC2CwCqhK9M3vA4rwCThKfHkxghlgnL/H0fh/YIE4BZ4m3fw8DxTmAtjlJ TDmgNoGRdwEjwypG0dSC5ILipPRcQ73ixNzi0rx0veT83E2MYJ8/k9rBuLLB4hCjAAejEg9v 4/KoACHWxLLiytxDjBIczEoivBsnAoV4UxIrq1KL8uOLSnNSiw8xSnOwKInzCn8KDBASSE8s Sc1OTS1ILYLJMnFwSjUwnvj/5l360ow1e09NCJkrdPnetgzWi4+P3ryvU6KhU5kQUuZUtyD0 jPtt25RAm2P9Kr7hB5KvXZHgNtxzzubPBNteZqV/E9Y+cXr00e3A1ngbo+mfFgvtaIld6pIk sSue18DV+9Cr8rmsDpOPGnOYfdz/fNN0b4PnD7e1BeyVcOwIuSLFwxNTpMRSnJFoqMVcVJwI AHzj4W/1AQAA X-Bad-Reply: References and In-Reply-To but no 'Re:' in Subject. X-Spam-Note: CRM114 invocation failed X-Spam-Score: -7.4 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [203.254.224.25 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.5 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Mailman-Approved-At: Thu, 20 Sep 2012 05:00:03 -0400 Cc: kgene.kim@samsung.com, devicetree-discuss@lists.ozlabs.org, t.figa@samsung.com, kyungmin.park@samsung.com, linux-samsung-soc@vger.kernel.org, thomas.abraham@linaro.org, linus.walleij@linaro.org, m.szyprowski@samsung.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Currently platform-specific properties such as list of pin banks, register offsets and bitfield sizes is being taken from static data structure residing in pinctrl-exynos.c. This patch modifies the pinctrl-samsung driver to parse all platform-specific data from device tree, which will allow to remove the static data structures and facilitate adding of further SoC variants to the pinctrl-samsung driver. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park --- drivers/pinctrl/pinctrl-exynos.c | 5 ++ drivers/pinctrl/pinctrl-samsung.c | 148 +++++++++++++++++++++++++++++++++++++- drivers/pinctrl/pinctrl-samsung.h | 17 ++++- 3 files changed, 166 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 575378a..827b744 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -599,3 +599,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .label = "exynos4210-gpio-ctrl2", }, }; + +struct samsung_pin_ctrl_variant exynos4_pin_ctrl = { + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, +}; diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index dd108a9..ff1d001 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "core.h" #include "pinctrl-samsung.h" @@ -46,6 +47,10 @@ struct pin_config { { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, }; +DEFINE_SPINLOCK(init_lock); + +static unsigned int pin_base = 0; + /* check if the selector is a valid pin group selector */ static int samsung_get_group_count(struct pinctrl_dev *pctldev) { @@ -599,6 +604,8 @@ static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev, u32 function; if (of_find_property(cfg_np, "interrupt-controller", NULL)) continue; + if (of_find_property(cfg_np, "gpio-controller", NULL)) + continue; ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np, &drvdata->pctl, &pin_list, &npins); @@ -775,6 +782,59 @@ static int __init samsung_gpiolib_unregister(struct platform_device *pdev, static const struct of_device_id samsung_pinctrl_dt_match[]; +static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank, + struct device_node *np) +{ + int ret; + u32 val; + + ret = of_property_read_string(np, "samsung,pin-bank", &bank->name); + if (ret) + return ret; + + ret = of_property_read_u32(np, "samsung,pctl-offset", &val); + if (ret) + return ret; + bank->pctl_offset = val; + + ret = of_property_read_u32(np, "samsung,pin-count", &val); + if (ret) + return ret; + bank->nr_pins = val; + + ret = of_property_read_u32(np, "samsung,func-width", &val); + if (ret) + return ret; + bank->func_width = val; + + ret = of_property_read_u32(np, "samsung,pud-width", &val); + if (ret) + return ret; + bank->pud_width = val; + + ret = of_property_read_u32(np, "samsung,drv-width", &val); + if (ret) + return ret; + bank->drv_width = val; + + ret = of_property_read_u32(np, "samsung,conpdn-width", &val); + if (!ret) + bank->conpdn_width = val; + + ret = of_property_read_u32(np, "samsung,pudpdn-width", &val); + if (!ret) + bank->pudpdn_width = val; + + if (!of_find_property(np, "interrupt-controller", NULL)) { + bank->eint_type = EINT_TYPE_NONE; + return 0; + } + + bank->eint_type = EINT_TYPE_GPIO; + + return 0; +} + /* retrieve the soc specific data */ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( struct platform_device *pdev) @@ -782,6 +842,14 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( int id; const struct of_device_id *match; const struct device_node *node = pdev->dev.of_node; + struct device_node *bank_np; + struct samsung_pin_ctrl *ctrl; + struct samsung_pin_bank *banks, *b; + struct samsung_pin_ctrl_variant *variant; + unsigned int bank_cnt = 0; + unsigned int eint_cnt = 0; + u32 val; + int ret; id = of_alias_get_id(pdev->dev.of_node, "pinctrl"); if (id < 0) { @@ -789,7 +857,83 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( return NULL; } match = of_match_node(samsung_pinctrl_dt_match, node); - return (struct samsung_pin_ctrl *)match->data + id; + variant = match->data; + + for_each_child_of_node(node, bank_np) { + if (!of_find_property(bank_np, "gpio-controller", NULL)) + continue; + ++bank_cnt; + } + + if (!bank_cnt) { + dev_err(&pdev->dev, "no pin banks specified\n"); + return NULL; + } + + ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) { + dev_err(&pdev->dev, "failed to allocate soc data\n"); + return NULL; + } + + banks = devm_kzalloc(&pdev->dev, + bank_cnt * sizeof(*ctrl->pin_banks), GFP_KERNEL); + if (!banks) { + dev_err(&pdev->dev, "failed to allocate pin banks\n"); + return NULL; + } + + b = banks; + for_each_child_of_node(node, bank_np) { + if (!of_find_property(bank_np, "gpio-controller", NULL)) + continue; + if (samsung_pinctrl_parse_dt_bank(b, bank_np)) + return NULL; + b->pin_base = ctrl->nr_pins; + ctrl->nr_pins += b->nr_pins; + if (of_find_property(bank_np, "interrupt-controller", NULL)) { + b->irq_base = eint_cnt; + eint_cnt += b->nr_pins; + } + ++b; + } + + if (eint_cnt) { + ret = of_property_read_u32(node, "samsung,geint-con", &val); + if (ret) + return NULL; + ctrl->geint_con = val; + + ret = of_property_read_u32(node, "samsung,geint-mask", &val); + if (ret) + return NULL; + ctrl->geint_mask = val; + + ret = of_property_read_u32(node, "samsung,geint-pend", &val); + if (ret) + return NULL; + ctrl->geint_pend = val; + + ret = of_property_read_u32(node, "samsung,svc", &val); + if (ret) + return NULL; + ctrl->svc = val; + + ctrl->eint_gpio_init = variant->eint_gpio_init; + } + + ctrl->pin_banks = banks; + ctrl->nr_banks = bank_cnt; + ctrl->nr_gint = eint_cnt; + ctrl->label = node->name; + ctrl->eint_wkup_init = variant->eint_wkup_init; + + spin_lock(&init_lock); + ctrl->base = pin_base; + pin_base += ctrl->nr_pins; + spin_unlock(&init_lock); + + return ctrl; } static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) @@ -857,7 +1001,7 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) static const struct of_device_id samsung_pinctrl_dt_match[] = { { .compatible = "samsung,pinctrl-exynos4210", - .data = (void *)exynos4210_pin_ctrl }, + .data = &exynos4_pin_ctrl }, {}, }; MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index b895693..5d59ce6 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -123,7 +123,19 @@ struct samsung_pin_bank { u8 pudpdn_width; enum eint_type eint_type; u32 irq_base; - char *name; + const char *name; +}; + +/** + * struct samsung_pin_ctrl_variant: represents a pin controller variant. + * @eint_gpio_init: platform specific callback to setup the external gpio + * interrupts for the controller. + * @eint_wkup_init: platform specific callback to setup the external wakeup + * interrupts for the controller. + */ +struct samsung_pin_ctrl_variant { + int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); + int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); }; /** @@ -168,7 +180,7 @@ struct samsung_pin_ctrl { int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); - char *label; + const char *label; }; /** @@ -235,5 +247,6 @@ struct samsung_pmx_func { /* list of all exported SoC specific data */ extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; +extern struct samsung_pin_ctrl_variant exynos4_pin_ctrl; #endif /* __PINCTRL_SAMSUNG_H */