pinctrl: mediatek: add multiple register bases support to pinctrl-mtk-common-v2.c
Certain SoC own multiple register base for accessing each pin groups, it's easy to be done with extend struct mtk_pin_field_calc to support the kind of SoC such as MT8183. Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
ea051eb384
commit
2bc47dfe4f
|
@ -713,25 +713,41 @@ int mtk_moore_pinctrl_probe(struct platform_device *pdev,
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct mtk_pinctrl *hw;
|
struct mtk_pinctrl *hw;
|
||||||
int err;
|
int err, i;
|
||||||
|
|
||||||
hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
|
hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
|
||||||
if (!hw)
|
if (!hw)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
hw->soc = soc;
|
hw->soc = soc;
|
||||||
|
hw->dev = &pdev->dev;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
if (!hw->soc->nbase_names) {
|
||||||
if (!res) {
|
dev_err(&pdev->dev,
|
||||||
dev_err(&pdev->dev, "missing IO resource\n");
|
"SoC should be assigned at least one register base\n");
|
||||||
return -ENXIO;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hw->dev = &pdev->dev;
|
hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
|
||||||
hw->base = devm_ioremap_resource(&pdev->dev, res);
|
sizeof(*hw->base), GFP_KERNEL);
|
||||||
if (IS_ERR(hw->base))
|
if (IS_ERR(hw->base))
|
||||||
return PTR_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 */
|
/* Setup pins descriptions per SoC types */
|
||||||
mtk_desc.pins = (const struct pinctrl_pin_desc *)hw->soc->pins;
|
mtk_desc.pins = (const struct pinctrl_pin_desc *)hw->soc->pins;
|
||||||
mtk_desc.npins = hw->soc->npins;
|
mtk_desc.npins = hw->soc->npins;
|
||||||
|
|
|
@ -768,6 +768,8 @@ static const struct mtk_pin_soc mt7622_data = {
|
||||||
.gpio_m = 1,
|
.gpio_m = 1,
|
||||||
.eint_m = 1,
|
.eint_m = 1,
|
||||||
.ies_present = false,
|
.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_set = mtk_pinconf_bias_disable_set,
|
||||||
.bias_disable_get = mtk_pinconf_bias_disable_get,
|
.bias_disable_get = mtk_pinconf_bias_disable_get,
|
||||||
.bias_set = mtk_pinconf_bias_set,
|
.bias_set = mtk_pinconf_bias_set,
|
||||||
|
|
|
@ -18,15 +18,15 @@
|
||||||
#define BOND_MSDC0E_CLR 0x1
|
#define BOND_MSDC0E_CLR 0x1
|
||||||
|
|
||||||
#define PIN_FIELD15(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
#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)
|
_x_bits, 15, false)
|
||||||
|
|
||||||
#define PIN_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
#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)
|
_x_bits, 16, 0)
|
||||||
|
|
||||||
#define PINS_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)\
|
#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, \
|
PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
|
||||||
_x_bits, 16, 1)
|
_x_bits, 16, 1)
|
||||||
|
|
||||||
#define MT7623_PIN(_number, _name, _eint_n, _drv_grp) \
|
#define MT7623_PIN(_number, _name, _eint_n, _drv_grp) \
|
||||||
|
@ -1383,6 +1383,8 @@ static struct mtk_pin_soc mt7623_data = {
|
||||||
.gpio_m = 0,
|
.gpio_m = 0,
|
||||||
.eint_m = 0,
|
.eint_m = 0,
|
||||||
.ies_present = true,
|
.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_set = mtk_pinconf_bias_disable_set_rev1,
|
||||||
.bias_disable_get = mtk_pinconf_bias_disable_get_rev1,
|
.bias_disable_get = mtk_pinconf_bias_disable_get_rev1,
|
||||||
.bias_set = mtk_pinconf_bias_set_rev1,
|
.bias_set = mtk_pinconf_bias_set_rev1,
|
||||||
|
@ -1402,9 +1404,9 @@ static void mt7623_bonding_disable(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct mtk_pinctrl *hw = platform_get_drvdata(pdev);
|
struct mtk_pinctrl *hw = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
mtk_rmw(hw, PIN_BOND_REG0, BOND_PCIE_CLR, BOND_PCIE_CLR);
|
mtk_rmw(hw, 0, PIN_BOND_REG0, BOND_PCIE_CLR, BOND_PCIE_CLR);
|
||||||
mtk_rmw(hw, PIN_BOND_REG1, BOND_I2S_CLR, BOND_I2S_CLR);
|
mtk_rmw(hw, 0, 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_REG2, BOND_MSDC0E_CLR, BOND_MSDC0E_CLR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id mt7623_pctrl_match[] = {
|
static const struct of_device_id mt7623_pctrl_match[] = {
|
||||||
|
|
|
@ -39,24 +39,24 @@ const struct mtk_drive_desc mtk_drive[] = {
|
||||||
[DRV_GRP4] = { 2, 16, 2, 1 },
|
[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;
|
u32 val;
|
||||||
|
|
||||||
val = mtk_r32(pctl, reg);
|
val = mtk_r32(pctl, i, reg);
|
||||||
val &= ~mask;
|
val &= ~mask;
|
||||||
val |= set;
|
val |= set;
|
||||||
mtk_w32(pctl, reg, val);
|
mtk_w32(pctl, i, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
|
static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
|
||||||
|
@ -82,6 +82,12 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
|
||||||
return -EINVAL;
|
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,
|
/* Calculated bits as the overall offset the pin is located at,
|
||||||
* if c->fixed is held, that determines the all the pins in the
|
* if c->fixed is held, that determines the all the pins in the
|
||||||
* range use the same field with the s_pin.
|
* range use the same field with the s_pin.
|
||||||
|
@ -92,6 +98,7 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
|
||||||
/* Fill pfd from bits. For example 32-bit register applied is assumed
|
/* Fill pfd from bits. For example 32-bit register applied is assumed
|
||||||
* when c->sz_reg is equal to 32.
|
* 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->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
|
||||||
pfd->bitpos = bits % c->sz_reg;
|
pfd->bitpos = bits % c->sz_reg;
|
||||||
pfd->mask = (1 << c->x_bits) - 1;
|
pfd->mask = (1 << c->x_bits) - 1;
|
||||||
|
@ -139,10 +146,10 @@ static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
|
||||||
|
|
||||||
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
|
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);
|
(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);
|
(value & pf->mask) >> nbits_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +160,10 @@ static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
|
||||||
|
|
||||||
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
|
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
|
||||||
|
|
||||||
l = (mtk_r32(hw, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
|
l = (mtk_r32(hw, pf->index, pf->offset)
|
||||||
h = (mtk_r32(hw, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
|
>> 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;
|
*value = (h << nbits_l) | l;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +179,7 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (!pf.next)
|
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);
|
(value & pf.mask) << pf.bitpos);
|
||||||
else
|
else
|
||||||
mtk_hw_write_cross_field(hw, &pf, value);
|
mtk_hw_write_cross_field(hw, &pf, value);
|
||||||
|
@ -189,7 +198,8 @@ int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (!pf.next)
|
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
|
else
|
||||||
mtk_hw_read_cross_field(hw, &pf, value);
|
mtk_hw_read_cross_field(hw, &pf, value);
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
|
|
||||||
#define EINT_NA -1
|
#define EINT_NA -1
|
||||||
|
|
||||||
#define PIN_FIELD_CALC(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, \
|
#define PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, \
|
||||||
_x_bits, _sz_reg, _fixed) { \
|
_s_bit, _x_bits, _sz_reg, _fixed) { \
|
||||||
.s_pin = _s_pin, \
|
.s_pin = _s_pin, \
|
||||||
.e_pin = _e_pin, \
|
.e_pin = _e_pin, \
|
||||||
|
.i_base = _i_base, \
|
||||||
.s_addr = _s_addr, \
|
.s_addr = _s_addr, \
|
||||||
.x_addrs = _x_addrs, \
|
.x_addrs = _x_addrs, \
|
||||||
.s_bit = _s_bit, \
|
.s_bit = _s_bit, \
|
||||||
|
@ -31,11 +32,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PIN_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
#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)
|
_x_bits, 32, 0)
|
||||||
|
|
||||||
#define PINS_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
#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)
|
_x_bits, 32, 1)
|
||||||
|
|
||||||
/* List these attributes which could be modified for the pin */
|
/* List these attributes which could be modified for the pin */
|
||||||
|
@ -73,8 +74,13 @@ enum {
|
||||||
DRV_GRP_MAX,
|
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
|
/* struct mtk_pin_field - the structure that holds the information of the field
|
||||||
* used to describe the attribute for the pin
|
* 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
|
* @offset: the register offset relative to the base address
|
||||||
* @mask: the mask used to filter out the field from the register
|
* @mask: the mask used to filter out the field from the register
|
||||||
* @bitpos: the start bit relative to the register
|
* @bitpos: the start bit relative to the register
|
||||||
|
@ -82,6 +88,7 @@ enum {
|
||||||
next register
|
next register
|
||||||
*/
|
*/
|
||||||
struct mtk_pin_field {
|
struct mtk_pin_field {
|
||||||
|
u8 index;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 mask;
|
u32 mask;
|
||||||
u8 bitpos;
|
u8 bitpos;
|
||||||
|
@ -92,6 +99,7 @@ struct mtk_pin_field {
|
||||||
* the guide used to look up the relevant field
|
* the guide used to look up the relevant field
|
||||||
* @s_pin: the start pin within the range
|
* @s_pin: the start pin within the range
|
||||||
* @e_pin: the end 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
|
* @s_addr: the start address for the range
|
||||||
* @x_addrs: the address distance between two consecutive registers
|
* @x_addrs: the address distance between two consecutive registers
|
||||||
* within the range
|
* within the range
|
||||||
|
@ -105,6 +113,7 @@ struct mtk_pin_field {
|
||||||
struct mtk_pin_field_calc {
|
struct mtk_pin_field_calc {
|
||||||
u16 s_pin;
|
u16 s_pin;
|
||||||
u16 e_pin;
|
u16 e_pin;
|
||||||
|
u8 i_base;
|
||||||
u32 s_addr;
|
u32 s_addr;
|
||||||
u8 x_addrs;
|
u8 x_addrs;
|
||||||
u8 s_bit;
|
u8 s_bit;
|
||||||
|
@ -157,6 +166,8 @@ struct mtk_pin_soc {
|
||||||
u8 gpio_m;
|
u8 gpio_m;
|
||||||
u8 eint_m;
|
u8 eint_m;
|
||||||
bool ies_present;
|
bool ies_present;
|
||||||
|
const char * const *base_names;
|
||||||
|
unsigned int nbase_names;
|
||||||
|
|
||||||
/* Specific pinconfig operations */
|
/* Specific pinconfig operations */
|
||||||
int (*bias_disable_set)(struct mtk_pinctrl *hw,
|
int (*bias_disable_set)(struct mtk_pinctrl *hw,
|
||||||
|
@ -183,14 +194,15 @@ struct mtk_pin_soc {
|
||||||
|
|
||||||
struct mtk_pinctrl {
|
struct mtk_pinctrl {
|
||||||
struct pinctrl_dev *pctrl;
|
struct pinctrl_dev *pctrl;
|
||||||
void __iomem *base;
|
void __iomem **base;
|
||||||
|
u8 nbase;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct gpio_chip chip;
|
struct gpio_chip chip;
|
||||||
const struct mtk_pin_soc *soc;
|
const struct mtk_pin_soc *soc;
|
||||||
struct mtk_eint *eint;
|
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 mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||||
int field, int value);
|
int field, int value);
|
||||||
|
|
Loading…
Reference in New Issue