From patchwork Mon May 5 11:58:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heiko Stuebner X-Patchwork-Id: 4114171 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id F22E29F1E1 for ; Mon, 5 May 2014 12:00:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E09482024C for ; Mon, 5 May 2014 12:00:05 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8A8C6201F7 for ; Mon, 5 May 2014 12:00:04 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WhHX7-0004yQ-34; Mon, 05 May 2014 11:58:09 +0000 Received: from gloria.sntech.de ([95.129.55.99]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WhHX4-0004gI-9O for linux-arm-kernel@lists.infradead.org; Mon, 05 May 2014 11:58:07 +0000 Received: from 146-52-69-41-dynip.superkabel.de ([146.52.69.41] helo=diego.localnet) by gloria.sntech.de with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.80) (envelope-from ) id 1WhHWh-0001vx-OK; Mon, 05 May 2014 13:57:44 +0200 From: Heiko =?ISO-8859-1?Q?St=FCbner?= To: linus.walleij@linaro.org Subject: [PATCH v2 2/8] pinctrl: rockchip: use regmaps instead of raw mappings Date: Mon, 05 May 2014 13:58:20 +0200 Message-ID: <1445574.d5GfQcodaO@diego> User-Agent: KMail/4.11.5 (Linux/3.13-1-amd64; KDE/4.11.3; x86_64; ; ) In-Reply-To: <11862890.WUjscWaP3U@diego> References: <11862890.WUjscWaP3U@diego> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140505_045806_509651_10CD0CFF X-CRM114-Status: GOOD ( 19.27 ) X-Spam-Score: -0.7 (/) Cc: Mark Rutland , devicetree@vger.kernel.org, Pawel Moll , Ian Campbell , max.schwarz@online.de, Rob Herring , Kumar Gala , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This allows us to use syscons in the future. Signed-off-by: Heiko Stuebner Tested-by: Max Schwarz --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/pinctrl-rockchip.c | 116 +++++++++++++++++++++++++------------ 2 files changed, 81 insertions(+), 36 deletions(-) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 934fd89..96ca6c1 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -275,6 +275,7 @@ config PINCTRL_ROCKCHIP select PINMUX select GENERIC_PINCONF select GENERIC_IRQ_CHIP + select MFD_SYSCON config PINCTRL_SINGLE tristate "One-register-per-pin type device tree based pinctrl driver" diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index ab71de8..71d9c99 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "core.h" @@ -86,7 +87,7 @@ enum rockchip_pin_bank_type { */ struct rockchip_pin_bank { void __iomem *reg_base; - void __iomem *reg_pull; + struct regmap *regmap_pull; struct clk *clk; int irq; u32 pin_base; @@ -120,8 +121,9 @@ struct rockchip_pin_ctrl { char *label; enum rockchip_pinctrl_type type; int mux_offset; - void (*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, - void __iomem **reg, u8 *bit); + void (*pull_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit); }; struct rockchip_pin_config { @@ -159,9 +161,9 @@ struct rockchip_pmx_func { }; struct rockchip_pinctrl { - void __iomem *reg_base; + struct regmap *regmap_base; int reg_size; - void __iomem *reg_pull; + struct regmap *regmap_pull; struct device *dev; struct rockchip_pin_ctrl *ctrl; struct pinctrl_desc pctl; @@ -172,6 +174,12 @@ struct rockchip_pinctrl { unsigned int nfunctions; }; +static struct regmap_config rockchip_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + static inline struct rockchip_pin_bank *gc_to_pin_bank(struct gpio_chip *gc) { return container_of(gc, struct rockchip_pin_bank, gpio_chip); @@ -333,18 +341,24 @@ static const struct pinctrl_ops rockchip_pctrl_ops = { static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) { struct rockchip_pinctrl *info = bank->drvdata; - void __iomem *reg = info->reg_base + info->ctrl->mux_offset; + unsigned int val; + int reg, ret; u8 bit; if (bank->bank_type == RK3188_BANK0 && pin < 16) return RK_FUNC_GPIO; /* get basic quadrupel of mux registers and the correct reg inside */ + reg = info->ctrl->mux_offset; reg += bank->bank_num * 0x10; reg += (pin / 8) * 4; bit = (pin % 8) * 2; - return ((readl(reg) >> bit) & 3); + ret = regmap_read(info->regmap_base, reg, &val); + if (ret) + return ret; + + return ((val >> bit) & 3); } /* @@ -363,7 +377,7 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl *info = bank->drvdata; - void __iomem *reg = info->reg_base + info->ctrl->mux_offset; + int reg, ret; unsigned long flags; u8 bit; u32 data; @@ -386,6 +400,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) bank->bank_num, pin, mux); /* get basic quadrupel of mux registers and the correct reg inside */ + reg = info->ctrl->mux_offset; reg += bank->bank_num * 0x10; reg += (pin / 8) * 4; bit = (pin % 8) * 2; @@ -394,11 +409,11 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) data = (3 << (bit + 16)); data |= (mux & 3) << bit; - writel(data, reg); + ret = regmap_write(info->regmap_base, reg, data); spin_unlock_irqrestore(&bank->slock, flags); - return 0; + return ret; } #define RK2928_PULL_OFFSET 0x118 @@ -406,11 +421,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) #define RK2928_PULL_BANK_STRIDE 8 static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, void __iomem **reg, u8 *bit) + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; - *reg = info->reg_base + RK2928_PULL_OFFSET; + *regmap = info->regmap_base; + *reg = RK2928_PULL_OFFSET; *reg += bank->bank_num * RK2928_PULL_BANK_STRIDE; *reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4; @@ -423,19 +440,23 @@ static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3188_PULL_BANK_STRIDE 16 static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, void __iomem **reg, u8 *bit) + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; /* The first 12 pins of the first bank are located elsewhere */ if (bank->bank_type == RK3188_BANK0 && pin_num < 12) { - *reg = bank->reg_pull + - ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); + *regmap = bank->regmap_pull; + *reg = 0; + *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); *bit = pin_num % RK3188_PULL_PINS_PER_REG; *bit *= RK3188_PULL_BITS_PER_PIN; } else { - *reg = info->reg_pull ? info->reg_pull - : info->reg_base + RK3188_PULL_OFFSET; + *regmap = info->regmap_pull ? info->regmap_pull + : info->regmap_base; + *reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET; + /* correct the offset, as it is the 2nd pull register */ *reg -= 4; *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; @@ -455,7 +476,8 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; - void __iomem *reg; + struct regmap *regmap; + int reg, ret; u8 bit; u32 data; @@ -463,15 +485,19 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) if (ctrl->type == RK3066B) return PIN_CONFIG_BIAS_DISABLE; - ctrl->pull_calc_reg(bank, pin_num, ®, &bit); + ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + + ret = regmap_read(regmap, reg, &data); + if (ret) + return ret; switch (ctrl->type) { case RK2928: - return !(readl_relaxed(reg) & BIT(bit)) + return !(data & BIT(bit)) ? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT : PIN_CONFIG_BIAS_DISABLE; case RK3188: - data = readl_relaxed(reg) >> bit; + data >>= bit; data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; switch (data) { @@ -498,7 +524,8 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; - void __iomem *reg; + struct regmap *regmap; + int reg, ret; unsigned long flags; u8 bit; u32 data; @@ -510,7 +537,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, if (ctrl->type == RK3066B) return pull ? -EINVAL : 0; - ctrl->pull_calc_reg(bank, pin_num, ®, &bit); + ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); switch (ctrl->type) { case RK2928: @@ -519,7 +546,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, data = BIT(bit + 16); if (pull == PIN_CONFIG_BIAS_DISABLE) data |= BIT(bit); - writel(data, reg); + ret = regmap_write(regmap, reg, data); spin_unlock_irqrestore(&bank->slock, flags); break; @@ -548,7 +575,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, return -EINVAL; } - writel(data, reg); + ret = regmap_write(regmap, reg, data); spin_unlock_irqrestore(&bank->slock, flags); break; @@ -557,7 +584,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, return -EINVAL; } - return 0; + return ret; } /* @@ -1416,6 +1443,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, struct device *dev) { struct resource res; + void __iomem *base; if (of_address_to_resource(bank->of_node, 0, &res)) { dev_err(dev, "cannot find IO resource for bank\n"); @@ -1440,9 +1468,14 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, return -ENOENT; } - bank->reg_pull = devm_ioremap_resource(dev, &res); - if (IS_ERR(bank->reg_pull)) - return PTR_ERR(bank->reg_pull); + base = devm_ioremap_resource(dev, &res); + if (IS_ERR(base)) + return PTR_ERR(base); + rockchip_regmap_config.max_register = resource_size(&res) - 4; + rockchip_regmap_config.name = "rockchip,rk3188-gpio-bank0-pull"; + bank->regmap_pull = devm_regmap_init_mmio(dev, base, + &rockchip_regmap_config); + } else { bank->bank_type = COMMON_BANK; } @@ -1507,6 +1540,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rockchip_pin_ctrl *ctrl; struct resource *res; + void __iomem *base; int ret; if (!dev->of_node) { @@ -1527,19 +1561,29 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) info->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(info->reg_base)) - return PTR_ERR(info->reg_base); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + rockchip_regmap_config.max_register = resource_size(res) - 4; + rockchip_regmap_config.name = "rockchip,pinctrl"; + info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base, + &rockchip_regmap_config); /* to check for the old dt-bindings */ info->reg_size = resource_size(res); /* Honor the old binding, with pull registers as 2nd resource */ - if (ctrl->type == RK3188 && info->reg_size < 0x200) { + if (ctrl->type == RK3188 && info->reg_size < 0x200) { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - info->reg_pull = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(info->reg_pull)) - return PTR_ERR(info->reg_pull); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + rockchip_regmap_config.max_register = resource_size(res) - 4; + rockchip_regmap_config.name = "rockchip,pinctrl-pull"; + info->regmap_pull = devm_regmap_init_mmio(&pdev->dev, base, + &rockchip_regmap_config); } ret = rockchip_gpiolib_register(pdev, info);