Merge tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux
[sfrench/cifs-2.6.git] / drivers / pinctrl / pinctrl-rockchip.c
index 9dd981ddbb178d5516013e34e5b1746bcf483a58..e831647c56a69bea9998bbc36040f7c0e9679558 100644 (file)
@@ -143,6 +143,7 @@ struct rockchip_drv {
  * @gpio_chip: gpiolib chip
  * @grange: gpio range
  * @slock: spinlock for the gpio bank
+ * @route_mask: bits describing the routing pins of per bank
  */
 struct rockchip_pin_bank {
        void __iomem                    *reg_base;
@@ -165,6 +166,7 @@ struct rockchip_pin_bank {
        struct pinctrl_gpio_range       grange;
        raw_spinlock_t                  slock;
        u32                             toggle_edge_mode;
+       u32                             route_mask;
 };
 
 #define PIN_BANK(id, pins, label)                      \
@@ -287,6 +289,22 @@ struct rockchip_pin_bank {
                .pull_type[3] = pull3,                                  \
        }
 
+/**
+ * struct rockchip_mux_recalced_data: represent a pin iomux data.
+ * @bank_num: bank number.
+ * @pin: index at register or used to calc index.
+ * @func: the min pin.
+ * @route_offset: the max pin.
+ * @route_val: the register offset.
+ */
+struct rockchip_mux_route_data {
+       u8 bank_num;
+       u8 pin;
+       u8 func;
+       u32 route_offset;
+       u32 route_val;
+};
+
 /**
  */
 struct rockchip_pin_ctrl {
@@ -299,6 +317,8 @@ struct rockchip_pin_ctrl {
        int                             pmu_mux_offset;
        int                             grf_drv_offset;
        int                             pmu_drv_offset;
+       struct rockchip_mux_route_data *iomux_routes;
+       u32                             niomux_routes;
 
        void    (*pull_calc_reg)(struct rockchip_pin_bank *bank,
                                    int pin_num, struct regmap **regmap,
@@ -580,6 +600,280 @@ static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg,
        *bit = data->bit;
 }
 
+static struct rockchip_mux_route_data rk3228_mux_route_data[] = {
+       {
+               /* pwm0-0 */
+               .bank_num = 0,
+               .pin = 26,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16),
+       }, {
+               /* pwm0-1 */
+               .bank_num = 3,
+               .pin = 21,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16) | BIT(0),
+       }, {
+               /* pwm1-0 */
+               .bank_num = 0,
+               .pin = 27,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 1),
+       }, {
+               /* pwm1-1 */
+               .bank_num = 0,
+               .pin = 30,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 1) | BIT(1),
+       }, {
+               /* pwm2-0 */
+               .bank_num = 0,
+               .pin = 28,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 2),
+       }, {
+               /* pwm2-1 */
+               .bank_num = 1,
+               .pin = 12,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 2) | BIT(2),
+       }, {
+               /* pwm3-0 */
+               .bank_num = 3,
+               .pin = 26,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 3),
+       }, {
+               /* pwm3-1 */
+               .bank_num = 1,
+               .pin = 11,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 3) | BIT(3),
+       }, {
+               /* sdio-0_d0 */
+               .bank_num = 1,
+               .pin = 1,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 4),
+       }, {
+               /* sdio-1_d0 */
+               .bank_num = 3,
+               .pin = 2,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 4) | BIT(4),
+       }, {
+               /* spi-0_rx */
+               .bank_num = 0,
+               .pin = 13,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 5),
+       }, {
+               /* spi-1_rx */
+               .bank_num = 2,
+               .pin = 0,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 5) | BIT(5),
+       }, {
+               /* emmc-0_cmd */
+               .bank_num = 1,
+               .pin = 22,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 7),
+       }, {
+               /* emmc-1_cmd */
+               .bank_num = 2,
+               .pin = 4,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 7) | BIT(7),
+       }, {
+               /* uart2-0_rx */
+               .bank_num = 1,
+               .pin = 19,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 8),
+       }, {
+               /* uart2-1_rx */
+               .bank_num = 1,
+               .pin = 10,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 8) | BIT(8),
+       }, {
+               /* uart1-0_rx */
+               .bank_num = 1,
+               .pin = 10,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 11),
+       }, {
+               /* uart1-1_rx */
+               .bank_num = 3,
+               .pin = 13,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 11) | BIT(11),
+       },
+};
+
+static struct rockchip_mux_route_data rk3328_mux_route_data[] = {
+       {
+               /* uart2dbg_rxm0 */
+               .bank_num = 1,
+               .pin = 1,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16) | BIT(16 + 1),
+       }, {
+               /* uart2dbg_rxm1 */
+               .bank_num = 2,
+               .pin = 1,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16) | BIT(16 + 1) | BIT(0),
+       }, {
+               /* gmac-m1-optimized_rxd0 */
+               .bank_num = 1,
+               .pin = 11,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 2) | BIT(16 + 10) | BIT(2) | BIT(10),
+       }, {
+               /* pdm_sdi0m0 */
+               .bank_num = 2,
+               .pin = 19,
+               .func = 2,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 3),
+       }, {
+               /* pdm_sdi0m1 */
+               .bank_num = 1,
+               .pin = 23,
+               .func = 3,
+               .route_offset = 0x50,
+               .route_val =  BIT(16 + 3) | BIT(3),
+       }, {
+               /* spi_rxdm2 */
+               .bank_num = 3,
+               .pin = 2,
+               .func = 4,
+               .route_offset = 0x50,
+               .route_val =  BIT(16 + 4) | BIT(16 + 5) | BIT(5),
+       }, {
+               /* i2s2_sdim0 */
+               .bank_num = 1,
+               .pin = 24,
+               .func = 1,
+               .route_offset = 0x50,
+               .route_val = BIT(16 + 6),
+       }, {
+               /* i2s2_sdim1 */
+               .bank_num = 3,
+               .pin = 2,
+               .func = 6,
+               .route_offset = 0x50,
+               .route_val =  BIT(16 + 6) | BIT(6),
+       }, {
+               /* card_iom1 */
+               .bank_num = 2,
+               .pin = 22,
+               .func = 3,
+               .route_offset = 0x50,
+               .route_val =  BIT(16 + 7) | BIT(7),
+       }, {
+               /* tsp_d5m1 */
+               .bank_num = 2,
+               .pin = 16,
+               .func = 3,
+               .route_offset = 0x50,
+               .route_val =  BIT(16 + 8) | BIT(8),
+       }, {
+               /* cif_data5m1 */
+               .bank_num = 2,
+               .pin = 16,
+               .func = 4,
+               .route_offset = 0x50,
+               .route_val =  BIT(16 + 9) | BIT(9),
+       },
+};
+
+static struct rockchip_mux_route_data rk3399_mux_route_data[] = {
+       {
+               /* uart2dbga_rx */
+               .bank_num = 4,
+               .pin = 8,
+               .func = 2,
+               .route_offset = 0xe21c,
+               .route_val = BIT(16 + 10) | BIT(16 + 11),
+       }, {
+               /* uart2dbgb_rx */
+               .bank_num = 4,
+               .pin = 16,
+               .func = 2,
+               .route_offset = 0xe21c,
+               .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10),
+       }, {
+               /* uart2dbgc_rx */
+               .bank_num = 4,
+               .pin = 19,
+               .func = 1,
+               .route_offset = 0xe21c,
+               .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11),
+       }, {
+               /* pcie_clkreqn */
+               .bank_num = 2,
+               .pin = 26,
+               .func = 2,
+               .route_offset = 0xe21c,
+               .route_val = BIT(16 + 14),
+       }, {
+               /* pcie_clkreqnb */
+               .bank_num = 4,
+               .pin = 24,
+               .func = 1,
+               .route_offset = 0xe21c,
+               .route_val = BIT(16 + 14) | BIT(14),
+       },
+};
+
+static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+                                  int mux, u32 *reg, u32 *value)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       struct rockchip_pin_ctrl *ctrl = info->ctrl;
+       struct rockchip_mux_route_data *data;
+       int i;
+
+       for (i = 0; i < ctrl->niomux_routes; i++) {
+               data = &ctrl->iomux_routes[i];
+               if ((data->bank_num == bank->bank_num) &&
+                   (data->pin == pin) && (data->func == mux))
+                       break;
+       }
+
+       if (i >= ctrl->niomux_routes)
+               return false;
+
+       *reg = data->route_offset;
+       *value = data->route_val;
+
+       return true;
+}
+
 static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
 {
        struct rockchip_pinctrl *info = bank->drvdata;
@@ -678,7 +972,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
        struct regmap *regmap;
        int reg, ret, mask, mux_type;
        u8 bit;
-       u32 data, rmask;
+       u32 data, rmask, route_reg, route_val;
 
        ret = rockchip_verify_mux(bank, pin, mux);
        if (ret < 0)
@@ -714,6 +1008,15 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
        if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
                ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
 
+       if (bank->route_mask & BIT(pin)) {
+               if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
+                                          &route_val)) {
+                       ret = regmap_write(regmap, route_reg, route_val);
+                       if (ret)
+                               return ret;
+               }
+       }
+
        data = (mask << (bit + 16));
        rmask = data | (data >> 16);
        data |= (mux & mask) << bit;
@@ -2549,6 +2852,16 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
 
                        bank_pins += 8;
                }
+
+               /* calculate the per-bank route_mask */
+               for (j = 0; j < ctrl->niomux_routes; j++) {
+                       int pin = 0;
+
+                       if (ctrl->iomux_routes[j].bank_num == bank->bank_num) {
+                               pin = ctrl->iomux_routes[j].pin;
+                               bank->route_mask |= BIT(pin);
+                       }
+               }
        }
 
        return ctrl;
@@ -2799,6 +3112,8 @@ static struct rockchip_pin_ctrl rk3228_pin_ctrl = {
                .label                  = "RK3228-GPIO",
                .type                   = RK3288,
                .grf_mux_offset         = 0x0,
+               .iomux_routes           = rk3228_mux_route_data,
+               .niomux_routes          = ARRAY_SIZE(rk3228_mux_route_data),
                .pull_calc_reg          = rk3228_calc_pull_reg_and_bit,
                .drv_calc_reg           = rk3228_calc_drv_reg_and_bit,
 };
@@ -2866,6 +3181,8 @@ static struct rockchip_pin_ctrl rk3328_pin_ctrl = {
                .label                  = "RK3328-GPIO",
                .type                   = RK3288,
                .grf_mux_offset         = 0x0,
+               .iomux_routes           = rk3328_mux_route_data,
+               .niomux_routes          = ARRAY_SIZE(rk3328_mux_route_data),
                .pull_calc_reg          = rk3228_calc_pull_reg_and_bit,
                .drv_calc_reg           = rk3228_calc_drv_reg_and_bit,
                .iomux_recalc           = rk3328_recalc_mux,
@@ -2956,33 +3273,35 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
                .pmu_mux_offset         = 0x0,
                .grf_drv_offset         = 0xe100,
                .pmu_drv_offset         = 0x80,
+               .iomux_routes           = rk3399_mux_route_data,
+               .niomux_routes          = ARRAY_SIZE(rk3399_mux_route_data),
                .pull_calc_reg          = rk3399_calc_pull_reg_and_bit,
                .drv_calc_reg           = rk3399_calc_drv_reg_and_bit,
 };
 
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
        { .compatible = "rockchip,rv1108-pinctrl",
-               .data = (void *)&rv1108_pin_ctrl },
+               .data = &rv1108_pin_ctrl },
        { .compatible = "rockchip,rk2928-pinctrl",
-               .data = (void *)&rk2928_pin_ctrl },
+               .data = &rk2928_pin_ctrl },
        { .compatible = "rockchip,rk3036-pinctrl",
-               .data = (void *)&rk3036_pin_ctrl },
+               .data = &rk3036_pin_ctrl },
        { .compatible = "rockchip,rk3066a-pinctrl",
-               .data = (void *)&rk3066a_pin_ctrl },
+               .data = &rk3066a_pin_ctrl },
        { .compatible = "rockchip,rk3066b-pinctrl",
-               .data = (void *)&rk3066b_pin_ctrl },
+               .data = &rk3066b_pin_ctrl },
        { .compatible = "rockchip,rk3188-pinctrl",
-               .data = (void *)&rk3188_pin_ctrl },
+               .data = &rk3188_pin_ctrl },
        { .compatible = "rockchip,rk3228-pinctrl",
-               .data = (void *)&rk3228_pin_ctrl },
+               .data = &rk3228_pin_ctrl },
        { .compatible = "rockchip,rk3288-pinctrl",
-               .data = (void *)&rk3288_pin_ctrl },
+               .data = &rk3288_pin_ctrl },
        { .compatible = "rockchip,rk3328-pinctrl",
-               .data = (void *)&rk3328_pin_ctrl },
+               .data = &rk3328_pin_ctrl },
        { .compatible = "rockchip,rk3368-pinctrl",
-               .data = (void *)&rk3368_pin_ctrl },
+               .data = &rk3368_pin_ctrl },
        { .compatible = "rockchip,rk3399-pinctrl",
-               .data = (void *)&rk3399_pin_ctrl },
+               .data = &rk3399_pin_ctrl },
        {},
 };