pinctrl: rockchip: use regmaps instead of raw mappings
This allows us to use syscons in the future. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Max Schwarz <max.schwarz@online.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
bfc7a42a0e
commit
751a99aba4
|
@ -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"
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <dt-bindings/pinctrl/rockchip.h>
|
||||
|
||||
#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,9 +1561,14 @@ 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);
|
||||
|
@ -1537,9 +1576,14 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
|
|||
/* Honor the old binding, with pull registers as 2nd resource */
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue