diff options
Diffstat (limited to 'drivers/pinctrl/rockchip/pinctrl-rk3288.c')
-rw-r--r-- | drivers/pinctrl/rockchip/pinctrl-rk3288.c | 163 |
1 files changed, 125 insertions, 38 deletions
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3288.c b/drivers/pinctrl/rockchip/pinctrl-rk3288.c index 8b6ce11a63..7ae147f304 100644 --- a/drivers/pinctrl/rockchip/pinctrl-rk3288.c +++ b/drivers/pinctrl/rockchip/pinctrl-rk3288.c @@ -7,7 +7,6 @@ #include <dm.h> #include <dm/pinctrl.h> #include <regmap.h> -#include <syscon.h> #include "pinctrl-rockchip.h" @@ -29,6 +28,47 @@ static struct rockchip_mux_route_data rk3288_mux_route_data[] = { }, }; +static int rk3288_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) +{ + struct rockchip_pinctrl_priv *priv = bank->priv; + int iomux_num = (pin / 8); + struct regmap *regmap; + int reg, ret, mask, mux_type; + u8 bit; + u32 data, route_reg, route_val; + + regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) + ? priv->regmap_pmu : priv->regmap_base; + + /* 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 += rockchip_get_mux_data(mux_type, pin, &bit, &mask); + + if (bank->route_mask & BIT(pin)) { + if (rockchip_get_mux_route(bank, pin, mux, &route_reg, + &route_val)) { + ret = regmap_write(regmap, route_reg, route_val); + if (ret) + return ret; + } + } + + /* bank0 is special, there are no higher 16 bit writing bits. */ + if (bank->bank_num == 0) { + regmap_read(regmap, reg, &data); + data &= ~(mask << bit); + } else { + /* enable the write to the equivalent lower bits */ + data = (mask << (bit + 16)); + } + + data |= (mux & mask) << bit; + ret = regmap_write(regmap, reg, data); + + return ret; +} + #define RK3288_PULL_OFFSET 0x140 #define RK3288_PULL_PMU_OFFSET 0x64 @@ -42,10 +82,6 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, if (bank->bank_num == 0) { *regmap = priv->regmap_pmu; *reg = RK3288_PULL_PMU_OFFSET; - - *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); - *bit = pin_num % ROCKCHIP_PULL_PINS_PER_REG; - *bit *= ROCKCHIP_PULL_BITS_PER_PIN; } else { *regmap = priv->regmap_base; *reg = RK3288_PULL_OFFSET; @@ -53,11 +89,46 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, /* correct the offset, as we're starting with the 2nd bank */ *reg -= 0x10; *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; - *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); + } + + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); + + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; +} + +static int rk3288_set_pull(struct rockchip_pin_bank *bank, + int pin_num, int pull) +{ + struct regmap *regmap; + int reg, ret; + u8 bit, type; + u32 data; + + if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) + return -ENOTSUPP; + + rk3288_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); + type = bank->pull_type[pin_num / 8]; + ret = rockchip_translate_pull_value(type, pull); + if (ret < 0) { + debug("unsupported pull setting %d\n", pull); + return ret; + } - *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); - *bit *= ROCKCHIP_PULL_BITS_PER_PIN; + /* bank0 is special, there are no higher 16 bit writing bits */ + if (bank->bank_num == 0) { + regmap_read(regmap, reg, &data); + data &= ~(((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << bit); + } else { + /* enable the write to the equivalent lower bits */ + data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); } + + data |= (ret << bit); + ret = regmap_write(regmap, reg, data); + + return ret; } #define RK3288_DRV_PMU_OFFSET 0x70 @@ -73,10 +144,6 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, if (bank->bank_num == 0) { *regmap = priv->regmap_pmu; *reg = RK3288_DRV_PMU_OFFSET; - - *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); - *bit = pin_num % ROCKCHIP_DRV_PINS_PER_REG; - *bit *= ROCKCHIP_DRV_BITS_PER_PIN; } else { *regmap = priv->regmap_base; *reg = RK3288_DRV_GRF_OFFSET; @@ -84,27 +151,48 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, /* correct the offset, as we're starting with the 2nd bank */ *reg -= 0x10; *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; - *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); + } - *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); - *bit *= ROCKCHIP_DRV_BITS_PER_PIN; + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); + *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; +} + +static int rk3288_set_drive(struct rockchip_pin_bank *bank, + int pin_num, int strength) +{ + struct regmap *regmap; + int reg, ret; + u32 data; + u8 bit; + int type = bank->drv[pin_num / 8].drv_type; + + rk3288_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); + ret = rockchip_translate_drive_value(type, strength); + if (ret < 0) { + debug("unsupported driver strength %d\n", strength); + return ret; + } + + /* bank0 is special, there are no higher 16 bit writing bits. */ + if (bank->bank_num == 0) { + regmap_read(regmap, reg, &data); + data &= ~(((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << bit); + } else { + /* enable the write to the equivalent lower bits */ + data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16); } + + data |= (ret << bit); + ret = regmap_write(regmap, reg, data); + return ret; } static struct rockchip_pin_bank rk3288_pin_banks[] = { - PIN_BANK_IOMUX_DRV_PULL_FLAGS(0, 24, "gpio0", - IOMUX_SOURCE_PMU | IOMUX_WRITABLE_32BIT, - IOMUX_SOURCE_PMU | IOMUX_WRITABLE_32BIT, - IOMUX_SOURCE_PMU | IOMUX_WRITABLE_32BIT, - IOMUX_UNROUTED, - DRV_TYPE_WRITABLE_32BIT, - DRV_TYPE_WRITABLE_32BIT, - DRV_TYPE_WRITABLE_32BIT, - 0, - PULL_TYPE_WRITABLE_32BIT, - PULL_TYPE_WRITABLE_32BIT, - PULL_TYPE_WRITABLE_32BIT, - 0 + PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU, + IOMUX_SOURCE_PMU, + IOMUX_SOURCE_PMU, + IOMUX_UNROUTED ), PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED, IOMUX_UNROUTED, @@ -133,16 +221,15 @@ static struct rockchip_pin_bank rk3288_pin_banks[] = { }; static struct rockchip_pin_ctrl rk3288_pin_ctrl = { - .pin_banks = rk3288_pin_banks, - .nr_banks = ARRAY_SIZE(rk3288_pin_banks), - .label = "RK3288-GPIO", - .type = RK3288, - .grf_mux_offset = 0x0, - .pmu_mux_offset = 0x84, - .iomux_routes = rk3288_mux_route_data, - .niomux_routes = ARRAY_SIZE(rk3288_mux_route_data), - .pull_calc_reg = rk3288_calc_pull_reg_and_bit, - .drv_calc_reg = rk3288_calc_drv_reg_and_bit, + .pin_banks = rk3288_pin_banks, + .nr_banks = ARRAY_SIZE(rk3288_pin_banks), + .grf_mux_offset = 0x0, + .pmu_mux_offset = 0x84, + .iomux_routes = rk3288_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3288_mux_route_data), + .set_mux = rk3288_set_mux, + .set_pull = rk3288_set_pull, + .set_drive = rk3288_set_drive, }; static const struct udevice_id rk3288_pinctrl_ids[] = { |