Commit ea262ad6 authored by david.wu's avatar david.wu Committed by Linus Walleij

pinctrl: rockchip: Add mux recalculation support

Some pins are special at a bank so that add
IOMUX_RECALCED type to indicate which iomux source
of the bank need to be recalculated. If the mux
recalculateed callback and IOMUX_RECALCED type
were set, recalculate the pins' iomux by using
mux recalculated data struct.
Signed-off-by: default avatarDavid Wu <david.wu@rock-chips.com>
Reviewed-by: default avatarHeiko Stuebner <heiko@sntech.de>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 8b6c6f93
...@@ -76,6 +76,7 @@ enum rockchip_pinctrl_type { ...@@ -76,6 +76,7 @@ enum rockchip_pinctrl_type {
#define IOMUX_SOURCE_PMU BIT(2) #define IOMUX_SOURCE_PMU BIT(2)
#define IOMUX_UNROUTED BIT(3) #define IOMUX_UNROUTED BIT(3)
#define IOMUX_WIDTH_3BIT BIT(4) #define IOMUX_WIDTH_3BIT BIT(4)
#define IOMUX_RECALCED BIT(5)
/** /**
* @type: iomux variant using IOMUX_* constants * @type: iomux variant using IOMUX_* constants
...@@ -305,6 +306,8 @@ struct rockchip_pin_ctrl { ...@@ -305,6 +306,8 @@ struct rockchip_pin_ctrl {
void (*drv_calc_reg)(struct rockchip_pin_bank *bank, void (*drv_calc_reg)(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap, int pin_num, struct regmap **regmap,
int *reg, u8 *bit); int *reg, u8 *bit);
void (*iomux_recalc)(u8 bank_num, int pin, int *reg,
u8 *bit, int *mask);
}; };
struct rockchip_pin_config { struct rockchip_pin_config {
...@@ -356,6 +359,22 @@ struct rockchip_pinctrl { ...@@ -356,6 +359,22 @@ struct rockchip_pinctrl {
unsigned int nfunctions; unsigned int nfunctions;
}; };
/**
* struct rockchip_mux_recalced_data: represent a pin iomux data.
* @num: bank number.
* @pin: pin number.
* @bit: index at register.
* @reg: register offset.
* @mask: mask bit
*/
struct rockchip_mux_recalced_data {
u8 num;
u8 pin;
u8 reg;
u8 bit;
u8 mask;
};
static struct regmap_config rockchip_regmap_config = { static struct regmap_config rockchip_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
...@@ -518,10 +537,11 @@ static const struct pinctrl_ops rockchip_pctrl_ops = { ...@@ -518,10 +537,11 @@ 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;
struct rockchip_pin_ctrl *ctrl = info->ctrl;
int iomux_num = (pin / 8); int iomux_num = (pin / 8);
struct regmap *regmap; struct regmap *regmap;
unsigned int val; unsigned int val;
int reg, ret, mask; int reg, ret, mask, mux_type;
u8 bit; u8 bit;
if (iomux_num > 3) if (iomux_num > 3)
...@@ -539,13 +559,14 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) ...@@ -539,13 +559,14 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
? info->regmap_pmu : info->regmap_base; ? info->regmap_pmu : info->regmap_base;
/* get basic quadrupel of mux registers and the correct reg inside */ /* get basic quadrupel of mux registers and the correct reg inside */
mux_type = bank->iomux[iomux_num].type;
reg = bank->iomux[iomux_num].offset; reg = bank->iomux[iomux_num].offset;
if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) { if (mux_type & IOMUX_WIDTH_4BIT) {
if ((pin % 8) >= 4) if ((pin % 8) >= 4)
reg += 0x4; reg += 0x4;
bit = (pin % 4) * 4; bit = (pin % 4) * 4;
mask = 0xf; mask = 0xf;
} else if (bank->iomux[iomux_num].type & IOMUX_WIDTH_3BIT) { } else if (mux_type & IOMUX_WIDTH_3BIT) {
if ((pin % 8) >= 5) if ((pin % 8) >= 5)
reg += 0x4; reg += 0x4;
bit = (pin % 8 % 5) * 3; bit = (pin % 8 % 5) * 3;
...@@ -555,6 +576,9 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) ...@@ -555,6 +576,9 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
mask = 0x3; mask = 0x3;
} }
if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
ret = regmap_read(regmap, reg, &val); ret = regmap_read(regmap, reg, &val);
if (ret) if (ret)
return ret; return ret;
...@@ -578,9 +602,10 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) ...@@ -578,9 +602,10 @@ 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;
struct rockchip_pin_ctrl *ctrl = info->ctrl;
int iomux_num = (pin / 8); int iomux_num = (pin / 8);
struct regmap *regmap; struct regmap *regmap;
int reg, ret, mask; int reg, ret, mask, mux_type;
unsigned long flags; unsigned long flags;
u8 bit; u8 bit;
u32 data, rmask; u32 data, rmask;
...@@ -610,13 +635,14 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) ...@@ -610,13 +635,14 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
? info->regmap_pmu : info->regmap_base; ? info->regmap_pmu : info->regmap_base;
/* get basic quadrupel of mux registers and the correct reg inside */ /* get basic quadrupel of mux registers and the correct reg inside */
mux_type = bank->iomux[iomux_num].type;
reg = bank->iomux[iomux_num].offset; reg = bank->iomux[iomux_num].offset;
if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) { if (mux_type & IOMUX_WIDTH_4BIT) {
if ((pin % 8) >= 4) if ((pin % 8) >= 4)
reg += 0x4; reg += 0x4;
bit = (pin % 4) * 4; bit = (pin % 4) * 4;
mask = 0xf; mask = 0xf;
} else if (bank->iomux[iomux_num].type & IOMUX_WIDTH_3BIT) { } else if (mux_type & IOMUX_WIDTH_3BIT) {
if ((pin % 8) >= 5) if ((pin % 8) >= 5)
reg += 0x4; reg += 0x4;
bit = (pin % 8 % 5) * 3; bit = (pin % 8 % 5) * 3;
...@@ -626,6 +652,9 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) ...@@ -626,6 +652,9 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
mask = 0x3; mask = 0x3;
} }
if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
spin_lock_irqsave(&bank->slock, flags); spin_lock_irqsave(&bank->slock, flags);
data = (mask << (bit + 16)); data = (mask << (bit + 16));
......
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