From patchwork Wed Sep 3 17:05:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grygorii Strashko X-Patchwork-Id: 385591 X-Patchwork-Delegate: linus.walleij@linaro.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 23CFB1401FA for ; Thu, 4 Sep 2014 03:06:41 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932992AbaICRGO (ORCPT ); Wed, 3 Sep 2014 13:06:14 -0400 Received: from devils.ext.ti.com ([198.47.26.153]:40823 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932967AbaICRGN (ORCPT ); Wed, 3 Sep 2014 13:06:13 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id s83H5giJ011698; Wed, 3 Sep 2014 12:05:42 -0500 Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id s83H5gWC023920; Wed, 3 Sep 2014 12:05:42 -0500 Received: from dlep32.itg.ti.com (157.170.170.100) by DFLE73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.3.174.1; Wed, 3 Sep 2014 12:05:42 -0500 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id s83H5fhh013473; Wed, 3 Sep 2014 12:05:42 -0500 From: Grygorii Strashko To: Linus Walleij , , , CC: Rob Herring , Alexandre Courbot , , , Grygorii Strashko Subject: [PATCH v3 2/4] gpio: syscon: retrive syscon node and regs offsets from dt Date: Wed, 3 Sep 2014 20:05:33 +0300 Message-ID: <1409763935-5713-3-git-send-email-grygorii.strashko@ti.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1409763935-5713-1-git-send-email-grygorii.strashko@ti.com> References: <1409763935-5713-1-git-send-email-grygorii.strashko@ti.com> MIME-Version: 1.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org This patch adds handling of new "gpio,syscon-dev" DT property, which allows to specify syscon node and data/direction registers offsets in DT. "gpio,syscon-dev" has following format: gpio,syscon-dev = <&syscon_dev data_reg_offset [direction_reg_offset]>; where - syscon_dev - phandle on syscon node - data_reg_offset - offset of data register (in bytes) - direction_reg_offset - offset of dirrection register (optional, in bytes) for example: gpio,syscon-dev = <&devctrl 0x254>; In such way, the support of multiple Syscon GPIO devices is added. Signed-off-by: Grygorii Strashko --- drivers/gpio/gpio-syscon.c | 51 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index d50ff93..049391b 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c @@ -55,6 +55,8 @@ struct syscon_gpio_priv { struct gpio_chip chip; struct regmap *syscon; const struct syscon_gpio_data *data; + u32 dreg_offset; + u32 dir_reg_offset; }; static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) @@ -65,9 +67,11 @@ static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) { struct syscon_gpio_priv *priv = to_syscon_gpio(chip); - unsigned int val, offs = priv->data->dat_bit_offset + offset; + unsigned int val, offs; int ret; + offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; + ret = regmap_read(priv->syscon, (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, &val); if (ret) @@ -79,7 +83,9 @@ static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { struct syscon_gpio_priv *priv = to_syscon_gpio(chip); - unsigned int offs = priv->data->dat_bit_offset + offset; + unsigned int offs; + + offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; regmap_update_bits(priv->syscon, (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, @@ -92,7 +98,10 @@ static int syscon_gpio_dir_in(struct gpio_chip *chip, unsigned offset) struct syscon_gpio_priv *priv = to_syscon_gpio(chip); if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { - unsigned int offs = priv->data->dir_bit_offset + offset; + unsigned int offs; + + offs = priv->dir_reg_offset + + priv->data->dir_bit_offset + offset; regmap_update_bits(priv->syscon, (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, @@ -107,7 +116,10 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) struct syscon_gpio_priv *priv = to_syscon_gpio(chip); if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { - unsigned int offs = priv->data->dir_bit_offset + offset; + unsigned int offs; + + offs = priv->dir_reg_offset + + priv->data->dir_bit_offset + offset; regmap_update_bits(priv->syscon, (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, @@ -142,6 +154,8 @@ static int syscon_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; const struct of_device_id *of_id = of_match_device(syscon_gpio_ids, dev); struct syscon_gpio_priv *priv; + struct device_node *np = dev->of_node; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -149,10 +163,31 @@ static int syscon_gpio_probe(struct platform_device *pdev) priv->data = of_id->data; - priv->syscon = - syscon_regmap_lookup_by_compatible(priv->data->compatible); - if (IS_ERR(priv->syscon)) - return PTR_ERR(priv->syscon); + if (priv->data->compatible) { + priv->syscon = syscon_regmap_lookup_by_compatible( + priv->data->compatible); + if (IS_ERR(priv->syscon)) + return PTR_ERR(priv->syscon); + } else { + priv->syscon = + syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev"); + if (IS_ERR(priv->syscon)) + return PTR_ERR(priv->syscon); + + ret = of_property_read_u32_index(np, "gpio,syscon-dev", 1, + &priv->dreg_offset); + if (ret) + dev_err(dev, "can't read the data register offset!\n"); + + priv->dreg_offset <<= 3; + + ret = of_property_read_u32_index(np, "gpio,syscon-dev", 2, + &priv->dir_reg_offset); + if (ret) + dev_err(dev, "can't read the dir register offset!\n"); + + priv->dir_reg_offset <<= 3; + } priv->chip.dev = dev; priv->chip.owner = THIS_MODULE;