aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c55
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.h22
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);