From patchwork Fri Sep 28 14:28:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Figa X-Patchwork-Id: 1519941 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 088253FE80 for ; Fri, 28 Sep 2012 14:38:45 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1THbfX-0006s7-KK; Fri, 28 Sep 2012 14:35:56 +0000 Received: from mailout1.samsung.com ([203.254.224.24]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1THbZw-0003gW-Ui for linux-arm-kernel@lists.infradead.org; Fri, 28 Sep 2012 14:30:14 +0000 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MB20016SDM3TH00@mailout1.samsung.com> for linux-arm-kernel@lists.infradead.org; Fri, 28 Sep 2012 23:30:07 +0900 (KST) X-AuditID: cbfee61b-b7f2b6d000000f14-e7-5065b46fee57 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 68.9D.03860.F64B5605; Fri, 28 Sep 2012 23:30:07 +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:30:07 +0900 (KST) From: Tomasz Figa To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 13/16] pinctrl: samsung: Parse offsets of particular registers from DT Date: Fri, 28 Sep 2012 16:28:44 +0200 Message-id: <1348842527-22460-14-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+NgFnrIJMWRmVeSWpSXmKPExsVy+t9jAd38LakBBn8v6llsenyN1YHRY/OS +gDGKC6blNSczLLUIn27BK6MdxumsRdcdavou3mIvYGxw7KLkZNDQsBE4s+mFkYIW0ziwr31 bF2MXBxCAosYJb5f+ccI4WxmknjQ+gqsik1ATeJzwyM2EFtEQENiStdjdhCbWWAyk8SxBekg trBAjETHzmlgNSwCqhKLji4Bq+EVcJZovrOEBWKbvMTT+31ANRwcnEDxtfM0QMJCAk4S/X8a WCYw8i5gZFjFKJpakFxQnJSea6RXnJhbXJqXrpecn7uJEezxZ9I7GFc1WBxiFOBgVOLhvTE/ JUCINbGsuDL3EKMEB7OSCG9GcWqAEG9KYmVValF+fFFpTmrxIUZpDhYlcd5mD6BqgfTEktTs 1NSC1CKYLBMHp1QDo0puQfmioF8ZUb1vIs/+c0uJNpyreHm364XyLT8+Jv7bLnya4y/bic5J 27duObZ3u9GXVSazb7+M/HgiSXEKb9/G1i0/DjoEll88Z1H076X0vu5Z/0zuTVt5IXqu5LYS g3d+WauksubZTn1noNXxf1shf+WJ8/qKFevfHHsyy2etiqb83fcvVDcrsRRnJBpqMRcVJwIA 5hF6dvQBAAA= 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.24 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 The order and availability of pin control registers vary with SoC. This patch modifies the driver to parse register offsets from device tree as a part of bank type definition. Signed-off-by: Tomasz Figa --- drivers/pinctrl/pinctrl-exynos.c | 12 ++--- drivers/pinctrl/pinctrl-samsung.c | 93 +++++++++++++++++++++------------------ drivers/pinctrl/pinctrl-samsung.h | 38 +++++++++------- 3 files changed, 78 insertions(+), 65 deletions(-) diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 001d2ec..7ad2884 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -113,9 +113,9 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) con |= trig_type << shift; writel(con, d->virt_base + reg_con); - reg_con = bank->pctl_offset; - shift = pin * bank->func_width; - mask = (1 << bank->func_width) - 1; + reg_con = bank->pctl_offset + bank->regs[REG_FUNC].offset; + shift = pin * bank->regs[REG_FUNC].width; + mask = (1 << bank->regs[REG_FUNC].width) - 1; con = readl(d->virt_base + reg_con); con &= ~(mask << shift); @@ -290,9 +290,9 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) con |= trig_type << shift; writel(con, d->virt_base + reg_con); - reg_con = bank->pctl_offset; - shift = pin * bank->func_width; - mask = (1 << bank->func_width) - 1; + reg_con = bank->pctl_offset + bank->regs[REG_FUNC].offset; + shift = pin * bank->regs[REG_FUNC].width; + mask = (1 << bank->regs[REG_FUNC].width) - 1; con = readl(d->virt_base + reg_con); con &= ~(mask << shift); diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 9b38609..b02cd46 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -273,10 +273,6 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, *offset = pin - b->pin_base; if (bank) *bank = b; - - /* some banks have two config registers in a single bank */ - if (*offset * b->func_width > BITS_PER_LONG) - *reg += 4; } /* enable or disable a pinmux function */ @@ -299,8 +295,9 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) { pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base, ®, &pin_offset, &bank); - mask = (1 << bank->func_width) - 1; - shift = pin_offset * bank->func_width; + mask = (1 << bank->regs[REG_FUNC].width) - 1; + shift = pin_offset * bank->regs[REG_FUNC].width; + reg += bank->regs[REG_FUNC].offset; data = readl(reg); data &= ~(mask << shift); @@ -342,10 +339,11 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, drvdata = pinctrl_dev_get_drvdata(pctldev); pin_offset = offset - bank->pin_base; - reg = drvdata->virt_base + bank->pctl_offset; + reg = drvdata->virt_base + bank->pctl_offset + + bank->regs[REG_FUNC].offset; - mask = (1 << bank->func_width) - 1; - shift = pin_offset * bank->func_width; + mask = (1 << bank->regs[REG_FUNC].width) - 1; + shift = pin_offset * bank->regs[REG_FUNC].width; data = readl(reg); data &= ~(mask << shift); @@ -382,20 +380,20 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin, switch (cfg_type) { case PINCFG_TYPE_PUD: - width = bank->pud_width; - cfg_reg = PUD_REG; + width = bank->regs[REG_PUD].width; + cfg_reg = bank->regs[REG_PUD].offset; break; case PINCFG_TYPE_DRV: - width = bank->drv_width; - cfg_reg = DRV_REG; + width = bank->regs[REG_DRV].width; + cfg_reg = bank->regs[REG_DRV].offset; break; case PINCFG_TYPE_CON_PDN: - width = bank->conpdn_width; - cfg_reg = CONPDN_REG; + width = bank->regs[REG_CONPDN].width; + cfg_reg = bank->regs[REG_CONPDN].offset; break; case PINCFG_TYPE_PUD_PDN: - width = bank->pudpdn_width; - cfg_reg = PUDPDN_REG; + width = bank->regs[REG_PUDPDN].width; + cfg_reg = bank->regs[REG_PUDPDN].offset; break; default: WARN_ON(1); @@ -481,13 +479,14 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) void __iomem *reg; u32 data; - reg = bank->drvdata->virt_base + bank->pctl_offset; + reg = bank->drvdata->virt_base + bank->pctl_offset + + bank->regs[REG_DAT].offset; - data = readl(reg + DAT_REG); + data = readl(reg); data &= ~(1 << offset); if (value) data |= 1 << offset; - writel(data, reg + DAT_REG); + writel(data, reg); } /* gpiolib gpio_get callback function */ @@ -497,9 +496,10 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) u32 data; struct samsung_pin_bank *bank = gc_to_pin_bank(gc); - reg = bank->drvdata->virt_base + bank->pctl_offset; + reg = bank->drvdata->virt_base + bank->pctl_offset + + bank->regs[REG_DAT].offset; - data = readl(reg + DAT_REG); + data = readl(reg); data >>= offset; data &= 1; return data; @@ -817,12 +817,24 @@ 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) { + static const char *reg_names[REG_NUM] = { + [REG_FUNC] = "func", + [REG_DAT] = "dat", + [REG_PUD] = "pud", + [REG_DRV] = "drv", + [REG_CONPDN] = "conpdn", + [REG_PUDPDN] = "pudpdn", + }; struct samsung_pin_bank *type = np->data; - int ret; - u32 val; + const __be32 *data; + int len = 0; + int index; + int i; if (type) { *bank = *type; @@ -833,26 +845,21 @@ static int samsung_pinctrl_parse_dt_bank_type(struct samsung_pin_bank *bank, 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; + data = of_get_property(np, "samsung,reg-params", &len); + if (!data) + return -EINVAL; + len /= sizeof(*data); - ret = of_property_read_u32(np, "samsung,pudpdn-width", &val); - if (!ret) - type->pudpdn_width = val; + for (i = 0; i < ARRAY_SIZE(reg_names); ++i) { + index = of_property_match_string(np, "samsung,reg-names", + reg_names[i]); + if (index < 0) + continue; + if (index >= len / 2) + return -EINVAL; + type->regs[i].offset = be32_to_cpu(data[2 * index]); + type->regs[i].width = be32_to_cpu(data[2 * index + 1]); + } *bank = *type; np->data = type; diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 355f4e2..684f042 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -25,12 +25,16 @@ #include -/* register offsets within a pin bank */ -#define DAT_REG 0x4 -#define PUD_REG 0x8 -#define DRV_REG 0xC -#define CONPDN_REG 0x10 -#define PUDPDN_REG 0x14 +enum pincfg_reg { + REG_FUNC = 0, + REG_DAT, + REG_PUD, + REG_DRV, + REG_CONPDN, + REG_PUDPDN, + + REG_NUM +}; /* pinmux function number for pin as gpio output line */ #define FUNC_OUTPUT 0x1 @@ -103,15 +107,21 @@ enum eint_type { struct samsung_pinctrl_drv_data; /** + * struct samsung_pin_reg: defines a configuration register. + * @offset: offset from bank base. + * @width: with of a bit field used for single pin. + */ +struct samsung_pin_reg { + u8 offset; + u8 width; +}; + +/** * struct samsung_pin_bank: represent a controller pin-bank. * @reg_offset: starting offset of the pin-bank registers. * @pin_base: starting pin number of the bank. * @nr_pins: number of pins included in this bank. - * @func_width: width of the function selector bit field. - * @pud_width: width of the pin pull up/down selector bit field. - * @drv_width: width of the pin driver strength selector bit field. - * @conpdn_width: width of the sleep mode function selector bin field. - * @pudpdn_width: width of the sleep mode pull up/down selector bit field. + * @regs: low level parameters of available configuration registers. * @eint_type: type of the external interrupt supported by the bank. * @name: name to be prefixed for each pin in this pin bank. * @of_node: node of pin bank in device tree @@ -124,11 +134,7 @@ struct samsung_pin_bank { u32 pctl_offset; u32 pin_base; u8 nr_pins; - u8 func_width; - u8 pud_width; - u8 drv_width; - u8 conpdn_width; - u8 pudpdn_width; + struct samsung_pin_reg regs[REG_NUM]; enum eint_type eint_type; u32 eint_offset; const char *name;