{
struct resource *res;
struct mtk_pinctrl *hw;
- int err;
+ int err, i;
hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return -ENOMEM;
hw->soc = soc;
+ hw->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "missing IO resource\n");
- return -ENXIO;
+ if (!hw->soc->nbase_names) {
+ dev_err(&pdev->dev,
+ "SoC should be assigned at least one register base\n");
+ return -EINVAL;
}
- hw->dev = &pdev->dev;
- hw->base = devm_ioremap_resource(&pdev->dev, res);
+ hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
+ sizeof(*hw->base), GFP_KERNEL);
if (IS_ERR(hw->base))
return PTR_ERR(hw->base);
+ for (i = 0; i < hw->soc->nbase_names; i++) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ hw->soc->base_names[i]);
+ if (!res) {
+ dev_err(&pdev->dev, "missing IO resource\n");
+ return -ENXIO;
+ }
+
+ hw->base[i] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hw->base[i]))
+ return PTR_ERR(hw->base[i]);
+ }
+
+ hw->nbase = hw->soc->nbase_names;
+
/* Setup pins descriptions per SoC types */
mtk_desc.pins = (const struct pinctrl_pin_desc *)hw->soc->pins;
mtk_desc.npins = hw->soc->npins;
.gpio_m = 1,
.eint_m = 1,
.ies_present = false,
+ .base_names = mtk_default_register_base_names,
+ .nbase_names = ARRAY_SIZE(mtk_default_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
.bias_disable_get = mtk_pinconf_bias_disable_get,
.bias_set = mtk_pinconf_bias_set,
#define BOND_MSDC0E_CLR 0x1
#define PIN_FIELD15(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
- PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
+ PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
_x_bits, 15, false)
#define PIN_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
- PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
+ PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
_x_bits, 16, 0)
-#define PINS_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)\
- PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
+#define PINS_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
+ PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
_x_bits, 16, 1)
#define MT7623_PIN(_number, _name, _eint_n, _drv_grp) \
.gpio_m = 0,
.eint_m = 0,
.ies_present = true,
+ .base_names = mtk_default_register_base_names,
+ .nbase_names = ARRAY_SIZE(mtk_default_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set_rev1,
.bias_disable_get = mtk_pinconf_bias_disable_get_rev1,
.bias_set = mtk_pinconf_bias_set_rev1,
{
struct mtk_pinctrl *hw = platform_get_drvdata(pdev);
- mtk_rmw(hw, PIN_BOND_REG0, BOND_PCIE_CLR, BOND_PCIE_CLR);
- mtk_rmw(hw, PIN_BOND_REG1, BOND_I2S_CLR, BOND_I2S_CLR);
- mtk_rmw(hw, PIN_BOND_REG2, BOND_MSDC0E_CLR, BOND_MSDC0E_CLR);
+ mtk_rmw(hw, 0, PIN_BOND_REG0, BOND_PCIE_CLR, BOND_PCIE_CLR);
+ mtk_rmw(hw, 0, PIN_BOND_REG1, BOND_I2S_CLR, BOND_I2S_CLR);
+ mtk_rmw(hw, 0, PIN_BOND_REG2, BOND_MSDC0E_CLR, BOND_MSDC0E_CLR);
}
static const struct of_device_id mt7623_pctrl_match[] = {
[DRV_GRP4] = { 2, 16, 2, 1 },
};
-static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
+static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val)
{
- writel_relaxed(val, pctl->base + reg);
+ writel_relaxed(val, pctl->base[i] + reg);
}
-static u32 mtk_r32(struct mtk_pinctrl *pctl, u32 reg)
+static u32 mtk_r32(struct mtk_pinctrl *pctl, u8 i, u32 reg)
{
- return readl_relaxed(pctl->base + reg);
+ return readl_relaxed(pctl->base[i] + reg);
}
-void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set)
+void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set)
{
u32 val;
- val = mtk_r32(pctl, reg);
+ val = mtk_r32(pctl, i, reg);
val &= ~mask;
val |= set;
- mtk_w32(pctl, reg, val);
+ mtk_w32(pctl, i, reg, val);
}
static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
return -EINVAL;
}
+ if (c->i_base > hw->nbase - 1) {
+ dev_err(hw->dev, "Invalid base is found for pin = %d (%s)\n",
+ desc->number, desc->name);
+ return -EINVAL;
+ }
+
/* Calculated bits as the overall offset the pin is located at,
* if c->fixed is held, that determines the all the pins in the
* range use the same field with the s_pin.
/* Fill pfd from bits. For example 32-bit register applied is assumed
* when c->sz_reg is equal to 32.
*/
+ pfd->index = c->i_base;
pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
pfd->bitpos = bits % c->sz_reg;
pfd->mask = (1 << c->x_bits) - 1;
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
- mtk_rmw(hw, pf->offset, pf->mask << pf->bitpos,
+ mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos,
(value & pf->mask) << pf->bitpos);
- mtk_rmw(hw, pf->offset + pf->next, BIT(nbits_h) - 1,
+ mtk_rmw(hw, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1,
(value & pf->mask) >> nbits_l);
}
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
- l = (mtk_r32(hw, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
- h = (mtk_r32(hw, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
+ l = (mtk_r32(hw, pf->index, pf->offset)
+ >> pf->bitpos) & (BIT(nbits_l) - 1);
+ h = (mtk_r32(hw, pf->index, pf->offset + pf->next))
+ & (BIT(nbits_h) - 1);
*value = (h << nbits_l) | l;
}
return err;
if (!pf.next)
- mtk_rmw(hw, pf.offset, pf.mask << pf.bitpos,
+ mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
(value & pf.mask) << pf.bitpos);
else
mtk_hw_write_cross_field(hw, &pf, value);
return err;
if (!pf.next)
- *value = (mtk_r32(hw, pf.offset) >> pf.bitpos) & pf.mask;
+ *value = (mtk_r32(hw, pf.index, pf.offset)
+ >> pf.bitpos) & pf.mask;
else
mtk_hw_read_cross_field(hw, &pf, value);
#define EINT_NA -1
-#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
- _x_bits, _sz_reg, _fixed) { \
+#define PIN_FIELD_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, \
}
#define PIN_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
- PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
+ PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 0)
#define PINS_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
- PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
+ PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 1)
/* List these attributes which could be modified for the pin */
DRV_GRP_MAX,
};
+static const char * const mtk_default_register_base_names[] = {
+ "base",
+};
+
/* struct mtk_pin_field - the structure that holds the information of the field
* used to describe the attribute for the pin
+ * @base: 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
next register
*/
struct mtk_pin_field {
+ u8 index;
u32 offset;
u32 mask;
u8 bitpos;
* 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
struct mtk_pin_field_calc {
u16 s_pin;
u16 e_pin;
+ u8 i_base;
u32 s_addr;
u8 x_addrs;
u8 s_bit;
u8 gpio_m;
u8 eint_m;
bool ies_present;
+ const char * const *base_names;
+ unsigned int nbase_names;
/* Specific pinconfig operations */
int (*bias_disable_set)(struct mtk_pinctrl *hw,
struct mtk_pinctrl {
struct pinctrl_dev *pctrl;
- void __iomem *base;
+ void __iomem **base;
+ u8 nbase;
struct device *dev;
struct gpio_chip chip;
const struct mtk_pin_soc *soc;
struct mtk_eint *eint;
};
-void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set);
+void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set);
int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
int field, int value);