]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
pinctrl: rockchip: Add rk3506 pinctrl support
authorYe Zhang <ye.zhang@rock-chips.com>
Tue, 4 Nov 2025 02:12:22 +0000 (10:12 +0800)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 10 Nov 2025 22:24:06 +0000 (23:24 +0100)
Add support for the 5 rk3506 GPIO banks.

Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinctrl-rockchip.h

index 7a68a6237649c175dee815363b754b9f3b82f47d..e44ef262beec6ed7ee19e29a71d71a6e8aa7da2f 100644 (file)
                .pull_type[3] = pull3,                                  \
        }
 
+#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(id, pins, label, iom0,   \
+                                              iom1, iom2, iom3,        \
+                                              offset0, offset1,        \
+                                              offset2, offset3, drv0,  \
+                                              drv1, drv2, drv3)        \
+       {                                                               \
+               .bank_num       = id,                                   \
+               .nr_pins        = pins,                                 \
+               .name           = label,                                \
+               .iomux          = {                                     \
+                       { .type = iom0, .offset = offset0 },            \
+                       { .type = iom1, .offset = offset1 },            \
+                       { .type = iom2, .offset = offset2 },            \
+                       { .type = iom3, .offset = offset3 },            \
+               },                                                      \
+               .drv            = {                                     \
+                       { .drv_type = drv0, .offset = -1 },             \
+                       { .drv_type = drv1, .offset = -1 },             \
+                       { .drv_type = drv2, .offset = -1 },             \
+                       { .drv_type = drv3, .offset = -1 },             \
+               },                                                      \
+       }
+
 #define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
        {                                                               \
                .bank_num       = id,                                   \
                .pull_type[3] = pull3,                                  \
        }
 
+#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(id, pins,     \
+                                               label, iom0, iom1,      \
+                                               iom2, iom3, offset0,    \
+                                               offset1, offset2,       \
+                                               offset3, drv0, drv1,    \
+                                               drv2, drv3, pull0,      \
+                                               pull1, pull2, pull3)    \
+       {                                                               \
+               .bank_num       = id,                                   \
+               .nr_pins        = pins,                                 \
+               .name           = label,                                \
+               .iomux          = {                                     \
+                       { .type = iom0, .offset = offset0 },            \
+                       { .type = iom1, .offset = offset1 },            \
+                       { .type = iom2, .offset = offset2 },            \
+                       { .type = iom3, .offset = offset3 },            \
+               },                                                      \
+               .drv            = {                                     \
+                       { .drv_type = drv0, .offset = -1 },             \
+                       { .drv_type = drv1, .offset = -1 },             \
+                       { .drv_type = drv2, .offset = -1 },             \
+                       { .drv_type = drv3, .offset = -1 },             \
+               },                                                      \
+               .pull_type[0] = pull0,                                  \
+               .pull_type[1] = pull1,                                  \
+               .pull_type[2] = pull2,                                  \
+               .pull_type[3] = pull3,                                  \
+       }
+
 #define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG)                \
        {                                                               \
                .bank_num       = ID,                                   \
@@ -1120,6 +1172,13 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
        else
                regmap = info->regmap_base;
 
+       if (ctrl->type == RK3506) {
+               if (bank->bank_num == 1)
+                       regmap = info->regmap_ioc1;
+               else if (bank->bank_num == 4)
+                       return 0;
+       }
+
        /* get basic quadrupel of mux registers and the correct reg inside */
        mux_type = bank->iomux[iomux_num].type;
        reg = bank->iomux[iomux_num].offset;
@@ -1239,6 +1298,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
        else
                regmap = info->regmap_base;
 
+       if (ctrl->type == RK3506) {
+               if (bank->bank_num == 1)
+                       regmap = info->regmap_ioc1;
+               else if (bank->bank_num == 4)
+                       return 0;
+       }
+
        /* get basic quadrupel of mux registers and the correct reg inside */
        mux_type = bank->iomux[iomux_num].type;
        reg = bank->iomux[iomux_num].offset;
@@ -2003,6 +2069,262 @@ static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
        return 0;
 }
 
+#define RK3506_DRV_BITS_PER_PIN                8
+#define RK3506_DRV_PINS_PER_REG                2
+#define RK3506_DRV_GPIO0_A_OFFSET      0x100
+#define RK3506_DRV_GPIO0_D_OFFSET      0x830
+#define RK3506_DRV_GPIO1_OFFSET                0x140
+#define RK3506_DRV_GPIO2_OFFSET                0x180
+#define RK3506_DRV_GPIO3_OFFSET                0x1c0
+#define RK3506_DRV_GPIO4_OFFSET                0x840
+
+static int rk3506_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+                                       int pin_num, struct regmap **regmap,
+                                       int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       int ret = 0;
+
+       switch (bank->bank_num) {
+       case 0:
+               *regmap = info->regmap_pmu;
+               if (pin_num > 24) {
+                       ret = -EINVAL;
+               } else if (pin_num < 24) {
+                       *reg = RK3506_DRV_GPIO0_A_OFFSET;
+               } else {
+                       *reg = RK3506_DRV_GPIO0_D_OFFSET;
+                       *bit = 3;
+
+                       return 0;
+               }
+               break;
+
+       case 1:
+               *regmap = info->regmap_ioc1;
+               if (pin_num < 28)
+                       *reg = RK3506_DRV_GPIO1_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 2:
+               *regmap = info->regmap_base;
+               if (pin_num < 17)
+                       *reg = RK3506_DRV_GPIO2_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 3:
+               *regmap = info->regmap_base;
+               if (pin_num < 15)
+                       *reg = RK3506_DRV_GPIO3_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 4:
+               *regmap = info->regmap_base;
+               if (pin_num < 8 || pin_num > 11) {
+                       ret = -EINVAL;
+               } else {
+                       *reg = RK3506_DRV_GPIO4_OFFSET;
+                       *bit = 10;
+
+                       return 0;
+               }
+               break;
+
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       if (ret) {
+               dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+
+               return ret;
+       }
+
+       *reg += ((pin_num / RK3506_DRV_PINS_PER_REG) * 4);
+       *bit = pin_num % RK3506_DRV_PINS_PER_REG;
+       *bit *= RK3506_DRV_BITS_PER_PIN;
+
+       return 0;
+}
+
+#define RK3506_PULL_BITS_PER_PIN       2
+#define RK3506_PULL_PINS_PER_REG       8
+#define RK3506_PULL_GPIO0_A_OFFSET     0x200
+#define RK3506_PULL_GPIO0_D_OFFSET     0x830
+#define RK3506_PULL_GPIO1_OFFSET       0x210
+#define RK3506_PULL_GPIO2_OFFSET       0x220
+#define RK3506_PULL_GPIO3_OFFSET       0x230
+#define RK3506_PULL_GPIO4_OFFSET       0x840
+
+static int rk3506_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+                                        int pin_num, struct regmap **regmap,
+                                        int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       int ret = 0;
+
+       switch (bank->bank_num) {
+       case 0:
+               *regmap = info->regmap_pmu;
+               if (pin_num > 24) {
+                       ret = -EINVAL;
+               } else if (pin_num < 24) {
+                       *reg = RK3506_PULL_GPIO0_A_OFFSET;
+               } else {
+                       *reg = RK3506_PULL_GPIO0_D_OFFSET;
+                       *bit = 5;
+
+                       return 0;
+               }
+               break;
+
+       case 1:
+               *regmap = info->regmap_ioc1;
+               if (pin_num < 28)
+                       *reg = RK3506_PULL_GPIO1_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 2:
+               *regmap = info->regmap_base;
+               if (pin_num < 17)
+                       *reg = RK3506_PULL_GPIO2_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 3:
+               *regmap = info->regmap_base;
+               if (pin_num < 15)
+                       *reg = RK3506_PULL_GPIO3_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 4:
+               *regmap = info->regmap_base;
+               if (pin_num < 8 || pin_num > 11) {
+                       ret = -EINVAL;
+               } else {
+                       *reg = RK3506_PULL_GPIO4_OFFSET;
+                       *bit = 13;
+
+                       return 0;
+               }
+               break;
+
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       if (ret) {
+               dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+
+               return ret;
+       }
+
+       *reg += ((pin_num / RK3506_PULL_PINS_PER_REG) * 4);
+       *bit = pin_num % RK3506_PULL_PINS_PER_REG;
+       *bit *= RK3506_PULL_BITS_PER_PIN;
+
+       return 0;
+}
+
+#define RK3506_SMT_BITS_PER_PIN                1
+#define RK3506_SMT_PINS_PER_REG                8
+#define RK3506_SMT_GPIO0_A_OFFSET      0x400
+#define RK3506_SMT_GPIO0_D_OFFSET      0x830
+#define RK3506_SMT_GPIO1_OFFSET                0x410
+#define RK3506_SMT_GPIO2_OFFSET                0x420
+#define RK3506_SMT_GPIO3_OFFSET                0x430
+#define RK3506_SMT_GPIO4_OFFSET                0x840
+
+static int rk3506_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+                                          int pin_num,
+                                          struct regmap **regmap,
+                                          int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       int ret = 0;
+
+       switch (bank->bank_num) {
+       case 0:
+               *regmap = info->regmap_pmu;
+               if (pin_num > 24) {
+                       ret = -EINVAL;
+               } else if (pin_num < 24) {
+                       *reg = RK3506_SMT_GPIO0_A_OFFSET;
+               } else {
+                       *reg = RK3506_SMT_GPIO0_D_OFFSET;
+                       *bit = 9;
+
+                       return 0;
+               }
+               break;
+
+       case 1:
+               *regmap = info->regmap_ioc1;
+               if (pin_num < 28)
+                       *reg = RK3506_SMT_GPIO1_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 2:
+               *regmap = info->regmap_base;
+               if (pin_num < 17)
+                       *reg = RK3506_SMT_GPIO2_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 3:
+               *regmap = info->regmap_base;
+               if (pin_num < 15)
+                       *reg = RK3506_SMT_GPIO3_OFFSET;
+               else
+                       ret = -EINVAL;
+               break;
+
+       case 4:
+               *regmap = info->regmap_base;
+               if (pin_num < 8 || pin_num > 11) {
+                       ret = -EINVAL;
+               } else {
+                       *reg = RK3506_SMT_GPIO4_OFFSET;
+                       *bit = 8;
+
+                       return 0;
+               }
+               break;
+
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       if (ret) {
+               dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+
+               return ret;
+       }
+
+       *reg += ((pin_num / RK3506_SMT_PINS_PER_REG) * 4);
+       *bit = pin_num % RK3506_SMT_PINS_PER_REG;
+       *bit *= RK3506_SMT_BITS_PER_PIN;
+
+       return 0;
+}
+
 #define RK3528_DRV_BITS_PER_PIN                8
 #define RK3528_DRV_PINS_PER_REG                2
 #define RK3528_DRV_GPIO0_OFFSET                0x100
@@ -2749,7 +3071,8 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
                rmask_bits = RK3588_DRV_BITS_PER_PIN;
                ret = strength;
                goto config;
-       } else if (ctrl->type == RK3528 ||
+       } else if (ctrl->type == RK3506 ||
+                  ctrl->type == RK3528 ||
                   ctrl->type == RK3562 ||
                   ctrl->type == RK3568) {
                rmask_bits = RK3568_DRV_BITS_PER_PIN;
@@ -2828,12 +3151,37 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
        case DRV_TYPE_IO_1V8_ONLY:
                rmask_bits = RK3288_DRV_BITS_PER_PIN;
                break;
+       case DRV_TYPE_IO_LEVEL_2_BIT:
+               ret = regmap_read(regmap, reg, &data);
+               if (ret)
+                       return ret;
+               data >>= bit;
+
+               return data & 0x3;
+       case DRV_TYPE_IO_LEVEL_8_BIT:
+               ret = regmap_read(regmap, reg, &data);
+               if (ret)
+                       return ret;
+               data >>= bit;
+               data &= (1 << 8) - 1;
+
+               ret = hweight8(data);
+               if (ret > 0)
+                       return ret - 1;
+               else
+                       return -EINVAL;
        default:
                dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type);
                return -EINVAL;
        }
 
 config:
+       if (ctrl->type == RK3506) {
+               if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
+                       rmask_bits = 2;
+                       ret = strength;
+               }
+       }
        /* enable the write to the equivalent lower bits */
        data = ((1 << rmask_bits) - 1) << (bit + 16);
        rmask = data | (data >> 16);
@@ -2957,6 +3305,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
        case RK3328:
        case RK3368:
        case RK3399:
+       case RK3506:
        case RK3528:
        case RK3562:
        case RK3568:
@@ -3077,6 +3426,10 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
                break;
        }
 
+       if (ctrl->type == RK3506)
+               if ((bank->bank_num == 0 && pin_num == 24) ||  bank->bank_num == 4)
+                       return data & 0x3;
+
        return data & 0x1;
 }
 
@@ -3112,6 +3465,14 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
                break;
        }
 
+       if (ctrl->type == RK3506) {
+               if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
+                       data = 0x3 << (bit + 16);
+                       rmask = data | (data >> 16);
+                       data |= ((enable ? 0x3 : 0) << bit);
+               }
+       }
+
        return regmap_update_bits(regmap, reg, rmask, data);
 }
 
@@ -3227,6 +3588,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
        case RK3328:
        case RK3368:
        case RK3399:
+       case RK3506:
        case RK3528:
        case RK3562:
        case RK3568:
@@ -3880,13 +4242,10 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
        }
 
        /* try to find the optional reference to the pmu syscon */
-       node = of_parse_phandle(np, "rockchip,pmu", 0);
-       if (node) {
-               info->regmap_pmu = syscon_node_to_regmap(node);
-               of_node_put(node);
-               if (IS_ERR(info->regmap_pmu))
-                       return PTR_ERR(info->regmap_pmu);
-       }
+       info->regmap_pmu = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,pmu");
+
+       /* try to find the optional reference to the ioc1 syscon */
+       info->regmap_ioc1 = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,ioc1");
 
        ret = rockchip_pinctrl_register(pdev, info);
        if (ret)
@@ -4350,6 +4709,71 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
                .drv_calc_reg           = rk3399_calc_drv_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3506_pin_banks[] = {
+       PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(0, 32, "gpio0",
+                                   IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+                                   IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+                                   IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+                                   IOMUX_WIDTH_2BIT | IOMUX_SOURCE_PMU,
+                                   0x0, 0x8, 0x10, 0x830,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_2_BIT,
+                                   0, 0, 0, 1),
+       PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(1, 32, "gpio1",
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   0x20, 0x28, 0x30, 0x38,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT),
+       PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(2, 32, "gpio2",
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   0x40, 0x48, 0x50, 0x58,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT),
+       PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(3, 32, "gpio3",
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   0x60, 0x68, 0x70, 0x78,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT,
+                                   DRV_TYPE_IO_LEVEL_8_BIT),
+       PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(4, 32, "gpio4",
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   IOMUX_WIDTH_4BIT,
+                                   0x80, 0x88, 0x90, 0x98,
+                                   DRV_TYPE_IO_LEVEL_2_BIT,
+                                   DRV_TYPE_IO_LEVEL_2_BIT,
+                                   DRV_TYPE_IO_LEVEL_2_BIT,
+                                   DRV_TYPE_IO_LEVEL_2_BIT,
+                                   1, 1, 1, 1),
+};
+
+static struct rockchip_pin_ctrl rk3506_pin_ctrl __maybe_unused = {
+       .pin_banks              = rk3506_pin_banks,
+       .nr_banks               = ARRAY_SIZE(rk3506_pin_banks),
+       .label                  = "RK3506-GPIO",
+       .type                   = RK3506,
+       .pull_calc_reg          = rk3506_calc_pull_reg_and_bit,
+       .drv_calc_reg           = rk3506_calc_drv_reg_and_bit,
+       .schmitt_calc_reg       = rk3506_calc_schmitt_reg_and_bit,
+};
+
 static struct rockchip_pin_bank rk3528_pin_banks[] = {
        PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
                                    IOMUX_WIDTH_4BIT,
@@ -4560,6 +4984,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
                .data = &rk3368_pin_ctrl },
        { .compatible = "rockchip,rk3399-pinctrl",
                .data = &rk3399_pin_ctrl },
+       { .compatible = "rockchip,rk3506-pinctrl",
+               .data = &rk3506_pin_ctrl },
        { .compatible = "rockchip,rk3528-pinctrl",
                .data = &rk3528_pin_ctrl },
        { .compatible = "rockchip,rk3562-pinctrl",
index 35cd38079d1e76eb0eacc65a64e805103871c3e7..4f4aff42a80a9c0f7137edce8ff71c96dcb7091c 100644 (file)
@@ -196,6 +196,7 @@ enum rockchip_pinctrl_type {
        RK3328,
        RK3368,
        RK3399,
+       RK3506,
        RK3528,
        RK3562,
        RK3568,
@@ -260,6 +261,8 @@ enum rockchip_pin_drv_type {
        DRV_TYPE_IO_1V8_ONLY,
        DRV_TYPE_IO_1V8_3V0_AUTO,
        DRV_TYPE_IO_3V3_ONLY,
+       DRV_TYPE_IO_LEVEL_2_BIT,
+       DRV_TYPE_IO_LEVEL_8_BIT,
        DRV_TYPE_MAX
 };
 
@@ -458,6 +461,7 @@ struct rockchip_pinctrl {
        int                             reg_size;
        struct regmap                   *regmap_pull;
        struct regmap                   *regmap_pmu;
+       struct regmap                   *regmap_ioc1;
        struct device                   *dev;
        struct rockchip_pin_ctrl        *ctrl;
        struct pinctrl_desc             pctl;