Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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"
+80 −36
Original line number Original line Diff line number Diff line
@@ -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 {
 */
 */
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 {
	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 {
};
};


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 {
	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 = {
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)
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)
						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)


	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)
#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,
#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)
{
{
	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)
	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,
{
{
	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,
	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,
		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,
			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,
		return -EINVAL;
		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 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,
			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)
	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,9 +1561,14 @@ 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);
@@ -1537,9 +1576,14 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
	/* 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);