From patchwork Fri Sep 28 14:28:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Figa X-Patchwork-Id: 1519831 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id A0B28DF283 for ; Fri, 28 Sep 2012 14:32:06 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1THbZe-0003ay-NI; Fri, 28 Sep 2012 14:29:50 +0000 Received: from mailout2.samsung.com ([203.254.224.25]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1THbZF-0003X2-Ew for linux-arm-kernel@lists.infradead.org; Fri, 28 Sep 2012 14:29:28 +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 <0MB2009Y9DKZWD10@mailout2.samsung.com> for linux-arm-kernel@lists.infradead.org; Fri, 28 Sep 2012 23:29:23 +0900 (KST) X-AuditID: cbfee61a-b7f726d000000ec7-4c-5065b443faf8 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id E6.19.03783.344B5605; Fri, 28 Sep 2012 23:29:23 +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 <0MB200E7BDK3XB70@mmp1.samsung.com> for linux-arm-kernel@lists.infradead.org; Fri, 28 Sep 2012 23:29:22 +0900 (KST) From: Tomasz Figa To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 03/16] pinctrl: samsung: Parse pin banks from DT Date: Fri, 28 Sep 2012 16:28:34 +0200 Message-id: <1348842527-22460-4-git-send-email-t.figa@samsung.com> X-Mailer: git-send-email 1.7.10 In-reply-to: <1348842527-22460-1-git-send-email-t.figa@samsung.com> References: <1348842527-22460-1-git-send-email-t.figa@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrAJMWRmVeSWpSXmKPExsVy+t9jAV3nLakBBu+PcFhsenyN1YHRY/OS +gDGKC6blNSczLLUIn27BK6ML4emsBVscqz4eVi9gfGGaRcjJ4eEgIlEx65vTBC2mMSFe+vZ uhi5OIQEFjFKzNz7gwXC2cwk0XlrKytIFZuAmsTnhkdsILaIgIbElK7H7CA2s8BkJoljC9JB bGEBF4ktCxvBprIIqErM2TwZrIZXwEni9d9jjBDb5CWe3u8DmsPBwSngLLF2ngZIWAiopP9P A8sERt4FjAyrGEVTC5ILipPScw31ihNzi0vz0vWS83M3MYL9/UxqB+PKBotDjAIcjEo8vBYr UwKEWBPLiitzDzFKcDArifBmFKcGCPGmJFZWpRblxxeV5qQWH2KU5mBREudt9gCqFkhPLEnN Tk0tSC2CyTJxcEo1MDawuqSo73uzd8ffZO560fNGh2MP3Tm6snrvxJ3rb+40C35WeZEpm/OG v0+if7iTZQC38lrZLS0q5e2xMR9iJ8iFZPZsS6nt4bnEJvdGvDbZp9fgqNVf0V/dz4OMjNWW 3L/5z+JAn78XU/bN5KJ9n9aV6b7/X77wu+HNpTk97PflZVTYny7WU2Ipzkg01GIuKk4EAC/M a6vzAQAA X-Spam-Note: CRM114 invocation failed X-Spam-Score: -7.7 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.7 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.8 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] Cc: kgene.kim@samsung.com, swarren@wwwdotorg.org, devicetree-discuss@lists.ozlabs.org, tomasz.figa@gmail.com, 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 --- drivers/pinctrl/pinctrl-exynos.c | 5 ++ drivers/pinctrl/pinctrl-samsung.c | 169 +++++++++++++++++++++++++++++++++++++- drivers/pinctrl/pinctrl-samsung.h | 17 +++- 3 files changed, 187 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index b4b58d4..e3fa263 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 c660fa5..e828a0e 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -46,6 +46,8 @@ struct pin_config { { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, }; +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) { @@ -602,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); @@ -778,6 +782,86 @@ 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_type(struct samsung_pin_bank *bank, + struct device_node *np) +{ + struct samsung_pin_bank *type = np->data; + int ret; + u32 val; + + if (type) { + *bank = *type; + return 0; + } + + type = kzalloc(sizeof(*type), GFP_KERNEL); + if (!type) + return -ENOMEM; + + ret = of_property_read_u32(np, "samsung,func-width", &val); + if (ret) + return ret; + type->func_width = val; + + ret = of_property_read_u32(np, "samsung,pud-width", &val); + if (!ret) + type->pud_width = val; + + ret = of_property_read_u32(np, "samsung,drv-width", &val); + if (!ret) + type->drv_width = val; + + ret = of_property_read_u32(np, "samsung,conpdn-width", &val); + if (!ret) + type->conpdn_width = val; + + ret = of_property_read_u32(np, "samsung,pudpdn-width", &val); + if (!ret) + type->pudpdn_width = val; + + *bank = *type; + np->data = type; + + return 0; +} + +static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank, + struct device_node *np) +{ + int ret; + u32 val; + struct device_node *type_np; + + type_np = of_parse_phandle(np, "samsung,bank-type", 0); + if (!type_np) + return -EINVAL; + + ret = samsung_pinctrl_parse_dt_bank_type(bank, type_np); + 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; + + bank->name = np->name; + + 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) @@ -785,6 +869,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) { @@ -792,7 +884,80 @@ 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 (b->eint_type == EINT_TYPE_GPIO) { + 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; + ctrl->base = pin_base; + pin_base += ctrl->nr_pins; + + return ctrl; } static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) @@ -860,7 +1025,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 */