Skip to content

Commit

Permalink
pinctrl: rockchip: add support for 4bit wide iomux settings
Browse files Browse the repository at this point in the history
In the upcoming rk3288 SoC some iomux settings are 4bit wide instead of
the regular 2bit. Therefore add a flag to mark iomuxes as such and adapt
the mux-access as well as the offset calculation accordingly.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Heiko Stübner authored and Linus Walleij committed Jul 11, 2014
1 parent 6bc0d12 commit 03716e1
Showing 1 changed file with 26 additions and 8 deletions.
34 changes: 26 additions & 8 deletions drivers/pinctrl/pinctrl-rockchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ enum rockchip_pinctrl_type {
* Encode variants of iomux registers into a type variable
*/
#define IOMUX_GPIO_ONLY BIT(0)
#define IOMUX_WIDTH_4BIT BIT(1)

/**
* @type: iomux variant using IOMUX_* constants
Expand Down Expand Up @@ -376,7 +377,7 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
struct rockchip_pinctrl *info = bank->drvdata;
int iomux_num = (pin / 8);
unsigned int val;
int reg, ret;
int reg, ret, mask;
u8 bit;

if (iomux_num > 3)
Expand All @@ -386,14 +387,21 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
return RK_FUNC_GPIO;

/* get basic quadrupel of mux registers and the correct reg inside */
mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
reg = bank->iomux[iomux_num].offset;
bit = (pin % 8) * 2;
if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
if ((pin % 8) >= 4)
reg += 0x4;
bit = (pin % 4) * 4;
} else {
bit = (pin % 8) * 2;
}

ret = regmap_read(info->regmap_base, reg, &val);
if (ret)
return ret;

return ((val >> bit) & 3);
return ((val >> bit) & mask);
}

/*
Expand All @@ -413,7 +421,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
{
struct rockchip_pinctrl *info = bank->drvdata;
int iomux_num = (pin / 8);
int reg, ret;
int reg, ret, mask;
unsigned long flags;
u8 bit;
u32 data;
Expand All @@ -435,13 +443,20 @@ 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 */
mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
reg = bank->iomux[iomux_num].offset;
bit = (pin % 8) * 2;
if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
if ((pin % 8) >= 4)
reg += 0x4;
bit = (pin % 4) * 4;
} else {
bit = (pin % 8) * 2;
}

spin_lock_irqsave(&bank->slock, flags);

data = (3 << (bit + 16));
data |= (mux & 3) << bit;
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(info->regmap_base, reg, data);

spin_unlock_irqrestore(&bank->slock, flags);
Expand Down Expand Up @@ -1556,6 +1571,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
/* calculate iomux offsets */
for (j = 0; j < 4; j++) {
struct rockchip_iomux *iom = &bank->iomux[j];
int inc;

if (bank_pins >= bank->nr_pins)
break;
Expand All @@ -1572,8 +1588,10 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(

/*
* Increase offset according to iomux width.
* 4bit iomux'es are spread over two registers.
*/
grf_offs += 4;
inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4;
grf_offs += inc;

bank_pins += 8;
}
Expand Down

0 comments on commit 03716e1

Please sign in to comment.