pinctrl: mediatek: add multiple register bases support to pinctrl-mtk-common-v2.c
authorSean Wang <sean.wang@mediatek.com>
Sat, 8 Sep 2018 11:07:30 +0000 (19:07 +0800)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 18 Sep 2018 21:53:12 +0000 (14:53 -0700)
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>
drivers/pinctrl/mediatek/pinctrl-moore.c
drivers/pinctrl/mediatek/pinctrl-mt7622.c
drivers/pinctrl/mediatek/pinctrl-mt7623.c
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h

index 2f3e3b594f8cd2b8f8cc7f9f7cfa547aa65290fd..2817e470c431a6bf13b0ad3802feedb52175eab5 100644 (file)
@@ -713,25 +713,41 @@ int mtk_moore_pinctrl_probe(struct platform_device *pdev,
 {
        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;
index 9ac36ab3678cdece082d6a6473eb95163ff524a7..769b36aff91e2c4b3e999ba204eab1c472705ffa 100644 (file)
@@ -768,6 +768,8 @@ static const struct mtk_pin_soc mt7622_data = {
        .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,
index 30d2289137f40f4e32e2792a4ce30a2f2a0714ee..1f2030c3f782198e41ebe8b60c0c32feace98025 100644 (file)
 #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)                  \
@@ -1383,6 +1383,8 @@ static struct mtk_pin_soc mt7623_data = {
        .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,
@@ -1402,9 +1404,9 @@ static void mt7623_bonding_disable(struct platform_device *pdev)
 {
        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[] = {
index ed88b96eadeaf24c31fddd8f4c292038237e9d53..18a3548da009e214b0cf9c9a4552c7827da0e257 100644 (file)
@@ -39,24 +39,24 @@ const struct mtk_drive_desc mtk_drive[] = {
        [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,
@@ -82,6 +82,12 @@ 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.
@@ -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
         * 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;
@@ -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_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);
 }
 
@@ -153,8 +160,10 @@ static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
 
        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;
 }
@@ -170,7 +179,7 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
                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);
@@ -189,7 +198,8 @@ int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
                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);
 
index 6e66bdc4f9e75e54e6e24beb2ee0912110bb5b99..040c6b79fd71146c9e16b3791d143bde323bfd8b 100644 (file)
 
 #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 */
@@ -73,8 +74,13 @@ enum {
        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
@@ -82,6 +88,7 @@ enum {
                        next register
  */
 struct mtk_pin_field {
+       u8  index;
        u32 offset;
        u32 mask;
        u8  bitpos;
@@ -92,6 +99,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
@@ -105,6 +113,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;
@@ -157,6 +166,8 @@ struct mtk_pin_soc {
        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,
@@ -183,14 +194,15 @@ struct mtk_pin_soc {
 
 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);