diff options
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 55 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 22 |
2 files changed, 57 insertions, 20 deletions
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 4ae3286..ebab43e 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -45,18 +45,18 @@ static const struct mtk_drive_desc mtk_drive[] = { static const char *mtk_pinctrl_dummy_name = "_dummy"; -static void mtk_w32(struct udevice *dev, u32 reg, u32 val) +static void mtk_w32(struct udevice *dev, u8 i, u32 reg, u32 val) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - __raw_writel(val, priv->base + reg); + __raw_writel(val, priv->base[i] + reg); } -static u32 mtk_r32(struct udevice *dev, u32 reg) +static u32 mtk_r32(struct udevice *dev, u8 i, u32 reg) { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); - return __raw_readl(priv->base + reg); + return __raw_readl(priv->base[i] + reg); } static inline int get_count_order(unsigned int count) @@ -71,20 +71,27 @@ static inline int get_count_order(unsigned int count) void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set) { + return mtk_i_rmw(dev, 0, reg, mask, set); +} + +void mtk_i_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set) +{ u32 val; - val = mtk_r32(dev, reg); + val = mtk_r32(dev, i, reg); val &= ~mask; val |= set; - mtk_w32(dev, reg, val); + mtk_w32(dev, i, reg, val); } static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin, const struct mtk_pin_reg_calc *rc, struct mtk_pin_field *pfd) { + struct mtk_pinctrl_priv *priv = dev_get_priv(dev); const struct mtk_pin_field_calc *c, *e; u32 bits; + u32 base_calc = priv->soc->base_calc; c = rc->range; e = c + rc->nranges; @@ -111,6 +118,11 @@ static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin, pfd->bitpos = bits % c->sz_reg; pfd->mask = (1 << c->x_bits) - 1; + if (base_calc) + pfd->index = c->i_base; + else + pfd->index = 0; + /* pfd->next is used for indicating that bit wrapping-around happens * which requires the manipulation for bit 0 starting in the next * register to form the complete field read/write. @@ -150,10 +162,10 @@ static void mtk_hw_write_cross_field(struct udevice *dev, mtk_hw_bits_part(pf, &nbits_h, &nbits_l); - mtk_rmw(dev, pf->offset, pf->mask << pf->bitpos, + mtk_i_rmw(dev, pf->index, pf->offset, pf->mask << pf->bitpos, (value & pf->mask) << pf->bitpos); - mtk_rmw(dev, pf->offset + pf->next, BIT(nbits_h) - 1, + mtk_i_rmw(dev, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1, (value & pf->mask) >> nbits_l); } @@ -164,8 +176,8 @@ static void mtk_hw_read_cross_field(struct udevice *dev, mtk_hw_bits_part(pf, &nbits_h, &nbits_l); - l = (mtk_r32(dev, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); - h = (mtk_r32(dev, pf->offset + pf->next)) & (BIT(nbits_h) - 1); + l = (mtk_r32(dev, pf->index, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); + h = (mtk_r32(dev, pf->index, pf->offset + pf->next)) & (BIT(nbits_h) - 1); *value = (h << nbits_l) | l; } @@ -181,7 +193,7 @@ static int mtk_hw_set_value(struct udevice *dev, int pin, int field, return err; if (!pf.next) - mtk_rmw(dev, pf.offset, pf.mask << pf.bitpos, + mtk_i_rmw(dev, pf.index, pf.offset, pf.mask << pf.bitpos, (value & pf.mask) << pf.bitpos); else mtk_hw_write_cross_field(dev, &pf, value); @@ -200,7 +212,7 @@ static int mtk_hw_get_value(struct udevice *dev, int pin, int field, return err; if (!pf.next) - *value = (mtk_r32(dev, pf.offset) >> pf.bitpos) & pf.mask; + *value = (mtk_r32(dev, pf.index, pf.offset) >> pf.bitpos) & pf.mask; else mtk_hw_read_cross_field(dev, &pf, value); @@ -236,7 +248,6 @@ static int mtk_get_pin_muxing(struct udevice *dev, unsigned int selector, char *buf, int size) { int val, err; - err = mtk_hw_get_value(dev, selector, PINCTRL_PIN_REG_MODE, &val); if (err) return err; @@ -722,13 +733,23 @@ int mtk_pinctrl_common_probe(struct udevice *dev, { struct mtk_pinctrl_priv *priv = dev_get_priv(dev); int ret = 0; - - priv->base = dev_read_addr_ptr(dev); - if (!priv->base) - return -EINVAL; + u32 i = 0; + fdt_addr_t addr; + u32 base_calc = soc->base_calc; + u32 nbase_names = soc->nbase_names; priv->soc = soc; + if (!base_calc) + nbase_names = 1; + + for (i = 0; i < nbase_names; i++) { + addr = devfdt_get_addr_index(dev, i); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + priv->base[i] = (void __iomem *)addr; + } + #if CONFIG_IS_ENABLED(DM_GPIO) || \ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO)) ret = mtk_gpiochip_register(dev); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 735fb6f..91a8c05 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -8,6 +8,8 @@ #define MTK_PINCTRL_V0 0x0 #define MTK_PINCTRL_V1 0x1 +#define BASE_CALC_NONE 0 +#define MAX_BASE_CALC 10 #define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), } #define MTK_PIN(_number, _name, _drv_n) { \ @@ -24,10 +26,11 @@ id##_funcs, \ } -#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \ - _x_bits, _sz_reg, _fixed) { \ +#define PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, \ + _s_bit, _x_bits, _sz_reg, _fixed) { \ .s_pin = _s_pin, \ .e_pin = _e_pin, \ + .i_base = _i_base, \ .s_addr = _s_addr, \ .x_addrs = _x_addrs, \ .s_bit = _s_bit, \ @@ -36,6 +39,11 @@ .fixed = _fixed, \ } +#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \ + _x_bits, _sz_reg, _fixed) \ + PIN_FIELD_BASE_CALC(_s_pin, _e_pin, BASE_CALC_NONE, _s_addr, \ + _x_addrs, _s_bit, _x_bits, _sz_reg, _fixed) + /* List these attributes which could be modified for the pin */ enum { PINCTRL_PIN_REG_MODE, @@ -70,6 +78,7 @@ enum { /** * struct mtk_pin_field - the structure that holds the information of the field * used to describe the attribute for the pin + * @index: the index pointing to the entry in base address list * @offset: the register offset relative to the base address * @mask: the mask used to filter out the field from the register * @bitpos: the start bit relative to the register @@ -77,6 +86,7 @@ enum { next register */ struct mtk_pin_field { + u8 index; u32 offset; u32 mask; u8 bitpos; @@ -88,6 +98,7 @@ struct mtk_pin_field { * the guide used to look up the relevant field * @s_pin: the start pin within the range * @e_pin: the end pin within the range + * @i_base: the index pointing to the entry in base address list * @s_addr: the start address for the range * @x_addrs: the address distance between two consecutive registers * within the range @@ -101,6 +112,7 @@ struct mtk_pin_field { struct mtk_pin_field_calc { u16 s_pin; u16 e_pin; + u8 i_base; u32 s_addr; u8 x_addrs; u8 s_bit; @@ -171,7 +183,10 @@ struct mtk_pinctrl_soc { const struct mtk_function_desc *funcs; int nfuncs; int gpio_mode; + const char * const *base_names; + unsigned int nbase_names; int rev; + int base_calc; }; /** @@ -181,7 +196,7 @@ struct mtk_pinctrl_soc { * @soc: SoC specific data */ struct mtk_pinctrl_priv { - void __iomem *base; + void __iomem *base[MAX_BASE_CALC]; struct mtk_pinctrl_soc *soc; }; @@ -189,6 +204,7 @@ extern const struct pinctrl_ops mtk_pinctrl_ops; /* A common read-modify-write helper for MediaTek chips */ void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set); +void mtk_i_rmw(struct udevice *dev, u8 i, u32 reg, u32 mask, u32 set); int mtk_pinctrl_common_probe(struct udevice *dev, struct mtk_pinctrl_soc *soc); |