Commit 751a99ab authored by Heiko Stübner's avatar Heiko Stübner Committed by Linus Walleij

pinctrl: rockchip: use regmaps instead of raw mappings

This allows us to use syscons in the future.
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
Tested-by: default avatarMax Schwarz <max.schwarz@online.de>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent bfc7a42a
...@@ -275,6 +275,7 @@ config PINCTRL_ROCKCHIP ...@@ -275,6 +275,7 @@ config PINCTRL_ROCKCHIP
select PINMUX select PINMUX
select GENERIC_PINCONF select GENERIC_PINCONF
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
select MFD_SYSCON
config PINCTRL_SINGLE config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver" tristate "One-register-per-pin type device tree based pinctrl driver"
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf-generic.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/regmap.h>
#include <dt-bindings/pinctrl/rockchip.h> #include <dt-bindings/pinctrl/rockchip.h>
#include "core.h" #include "core.h"
...@@ -86,7 +87,7 @@ enum rockchip_pin_bank_type { ...@@ -86,7 +87,7 @@ enum rockchip_pin_bank_type {
*/ */
struct rockchip_pin_bank { struct rockchip_pin_bank {
void __iomem *reg_base; void __iomem *reg_base;
void __iomem *reg_pull; struct regmap *regmap_pull;
struct clk *clk; struct clk *clk;
int irq; int irq;
u32 pin_base; u32 pin_base;
...@@ -120,8 +121,9 @@ struct rockchip_pin_ctrl { ...@@ -120,8 +121,9 @@ struct rockchip_pin_ctrl {
char *label; char *label;
enum rockchip_pinctrl_type type; enum rockchip_pinctrl_type type;
int mux_offset; int mux_offset;
void (*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, void (*pull_calc_reg)(struct rockchip_pin_bank *bank,
void __iomem **reg, u8 *bit); int pin_num, struct regmap **regmap,
int *reg, u8 *bit);
}; };
struct rockchip_pin_config { struct rockchip_pin_config {
...@@ -159,9 +161,9 @@ struct rockchip_pmx_func { ...@@ -159,9 +161,9 @@ struct rockchip_pmx_func {
}; };
struct rockchip_pinctrl { struct rockchip_pinctrl {
void __iomem *reg_base; struct regmap *regmap_base;
int reg_size; int reg_size;
void __iomem *reg_pull; struct regmap *regmap_pull;
struct device *dev; struct device *dev;
struct rockchip_pin_ctrl *ctrl; struct rockchip_pin_ctrl *ctrl;
struct pinctrl_desc pctl; struct pinctrl_desc pctl;
...@@ -172,6 +174,12 @@ struct rockchip_pinctrl { ...@@ -172,6 +174,12 @@ struct rockchip_pinctrl {
unsigned int nfunctions; 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) static inline struct rockchip_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
{ {
return container_of(gc, struct rockchip_pin_bank, gpio_chip); return container_of(gc, struct rockchip_pin_bank, gpio_chip);
...@@ -333,18 +341,24 @@ static const struct pinctrl_ops rockchip_pctrl_ops = { ...@@ -333,18 +341,24 @@ static const struct pinctrl_ops rockchip_pctrl_ops = {
static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
{ {
struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pinctrl *info = bank->drvdata;
void __iomem *reg = info->reg_base + info->ctrl->mux_offset; unsigned int val;
int reg, ret;
u8 bit; u8 bit;
if (bank->bank_type == RK3188_BANK0 && pin < 16) if (bank->bank_type == RK3188_BANK0 && pin < 16)
return RK_FUNC_GPIO; return RK_FUNC_GPIO;
/* get basic quadrupel of mux registers and the correct reg inside */ /* get basic quadrupel of mux registers and the correct reg inside */
reg = info->ctrl->mux_offset;
reg += bank->bank_num * 0x10; reg += bank->bank_num * 0x10;
reg += (pin / 8) * 4; reg += (pin / 8) * 4;
bit = (pin % 8) * 2; 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) ...@@ -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) static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
{ {
struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pinctrl *info = bank->drvdata;
void __iomem *reg = info->reg_base + info->ctrl->mux_offset; int reg, ret;
unsigned long flags; unsigned long flags;
u8 bit; u8 bit;
u32 data; u32 data;
...@@ -386,6 +400,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) ...@@ -386,6 +400,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
bank->bank_num, pin, mux); bank->bank_num, pin, mux);
/* get basic quadrupel of mux registers and the correct reg inside */ /* get basic quadrupel of mux registers and the correct reg inside */
reg = info->ctrl->mux_offset;
reg += bank->bank_num * 0x10; reg += bank->bank_num * 0x10;
reg += (pin / 8) * 4; reg += (pin / 8) * 4;
bit = (pin % 8) * 2; bit = (pin % 8) * 2;
...@@ -394,11 +409,11 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) ...@@ -394,11 +409,11 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
data = (3 << (bit + 16)); data = (3 << (bit + 16));
data |= (mux & 3) << bit; data |= (mux & 3) << bit;
writel(data, reg); ret = regmap_write(info->regmap_base, reg, data);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
return 0; return ret;
} }
#define RK2928_PULL_OFFSET 0x118 #define RK2928_PULL_OFFSET 0x118
...@@ -406,11 +421,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) ...@@ -406,11 +421,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
#define RK2928_PULL_BANK_STRIDE 8 #define RK2928_PULL_BANK_STRIDE 8
static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 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; 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 += bank->bank_num * RK2928_PULL_BANK_STRIDE;
*reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4; *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, ...@@ -423,19 +440,23 @@ static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
#define RK3188_PULL_BANK_STRIDE 16 #define RK3188_PULL_BANK_STRIDE 16
static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 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; struct rockchip_pinctrl *info = bank->drvdata;
/* The first 12 pins of the first bank are located elsewhere */ /* The first 12 pins of the first bank are located elsewhere */
if (bank->bank_type == RK3188_BANK0 && pin_num < 12) { if (bank->bank_type == RK3188_BANK0 && pin_num < 12) {
*reg = bank->reg_pull + *regmap = bank->regmap_pull;
((pin_num / RK3188_PULL_PINS_PER_REG) * 4); *reg = 0;
*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
*bit = pin_num % RK3188_PULL_PINS_PER_REG; *bit = pin_num % RK3188_PULL_PINS_PER_REG;
*bit *= RK3188_PULL_BITS_PER_PIN; *bit *= RK3188_PULL_BITS_PER_PIN;
} else { } else {
*reg = info->reg_pull ? info->reg_pull *regmap = info->regmap_pull ? info->regmap_pull
: info->reg_base + RK3188_PULL_OFFSET; : info->regmap_base;
*reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET;
/* correct the offset, as it is the 2nd pull register */ /* correct the offset, as it is the 2nd pull register */
*reg -= 4; *reg -= 4;
*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; *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) ...@@ -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_pinctrl *info = bank->drvdata;
struct rockchip_pin_ctrl *ctrl = info->ctrl; struct rockchip_pin_ctrl *ctrl = info->ctrl;
void __iomem *reg; struct regmap *regmap;
int reg, ret;
u8 bit; u8 bit;
u32 data; u32 data;
...@@ -463,15 +485,19 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) ...@@ -463,15 +485,19 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
if (ctrl->type == RK3066B) if (ctrl->type == RK3066B)
return PIN_CONFIG_BIAS_DISABLE; return PIN_CONFIG_BIAS_DISABLE;
ctrl->pull_calc_reg(bank, pin_num, &reg, &bit); ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
ret = regmap_read(regmap, reg, &data);
if (ret)
return ret;
switch (ctrl->type) { switch (ctrl->type) {
case RK2928: case RK2928:
return !(readl_relaxed(reg) & BIT(bit)) return !(data & BIT(bit))
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT ? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
: PIN_CONFIG_BIAS_DISABLE; : PIN_CONFIG_BIAS_DISABLE;
case RK3188: case RK3188:
data = readl_relaxed(reg) >> bit; data >>= bit;
data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
switch (data) { switch (data) {
...@@ -498,7 +524,8 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, ...@@ -498,7 +524,8 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
{ {
struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pinctrl *info = bank->drvdata;
struct rockchip_pin_ctrl *ctrl = info->ctrl; struct rockchip_pin_ctrl *ctrl = info->ctrl;
void __iomem *reg; struct regmap *regmap;
int reg, ret;
unsigned long flags; unsigned long flags;
u8 bit; u8 bit;
u32 data; u32 data;
...@@ -510,7 +537,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, ...@@ -510,7 +537,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
if (ctrl->type == RK3066B) if (ctrl->type == RK3066B)
return pull ? -EINVAL : 0; return pull ? -EINVAL : 0;
ctrl->pull_calc_reg(bank, pin_num, &reg, &bit); ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
switch (ctrl->type) { switch (ctrl->type) {
case RK2928: case RK2928:
...@@ -519,7 +546,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, ...@@ -519,7 +546,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
data = BIT(bit + 16); data = BIT(bit + 16);
if (pull == PIN_CONFIG_BIAS_DISABLE) if (pull == PIN_CONFIG_BIAS_DISABLE)
data |= BIT(bit); data |= BIT(bit);
writel(data, reg); ret = regmap_write(regmap, reg, data);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
break; break;
...@@ -548,7 +575,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, ...@@ -548,7 +575,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
return -EINVAL; return -EINVAL;
} }
writel(data, reg); ret = regmap_write(regmap, reg, data);
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
break; break;
...@@ -557,7 +584,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, ...@@ -557,7 +584,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
return -EINVAL; return -EINVAL;
} }
return 0; return ret;
} }
/* /*
...@@ -1416,6 +1443,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, ...@@ -1416,6 +1443,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
struct device *dev) struct device *dev)
{ {
struct resource res; struct resource res;
void __iomem *base;
if (of_address_to_resource(bank->of_node, 0, &res)) { if (of_address_to_resource(bank->of_node, 0, &res)) {
dev_err(dev, "cannot find IO resource for bank\n"); 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, ...@@ -1440,9 +1468,14 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
return -ENOENT; return -ENOENT;
} }
bank->reg_pull = devm_ioremap_resource(dev, &res); base = devm_ioremap_resource(dev, &res);
if (IS_ERR(bank->reg_pull)) if (IS_ERR(base))
return PTR_ERR(bank->reg_pull); 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 { } else {
bank->bank_type = COMMON_BANK; bank->bank_type = COMMON_BANK;
} }
...@@ -1507,6 +1540,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) ...@@ -1507,6 +1540,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct rockchip_pin_ctrl *ctrl; struct rockchip_pin_ctrl *ctrl;
struct resource *res; struct resource *res;
void __iomem *base;
int ret; int ret;
if (!dev->of_node) { if (!dev->of_node) {
...@@ -1527,19 +1561,29 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) ...@@ -1527,19 +1561,29 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
info->dev = dev; info->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
info->reg_base = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(info->reg_base)) if (IS_ERR(base))
return PTR_ERR(info->reg_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 */ /* to check for the old dt-bindings */
info->reg_size = resource_size(res); info->reg_size = resource_size(res);
/* Honor the old binding, with pull registers as 2nd resource */ /* 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); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
info->reg_pull = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(info->reg_pull)) if (IS_ERR(base))
return PTR_ERR(info->reg_pull); 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); ret = rockchip_gpiolib_register(pdev, info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment