Merge git://git.denx.de/u-boot-socfpga
[platform/kernel/u-boot.git] / drivers / pinctrl / rockchip / pinctrl_rk3288.c
index 1fa1daa..a21b640 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/arch/periph.h>
 #include <asm/arch/pmu_rk3288.h>
 #include <dm/pinctrl.h>
-#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -403,6 +402,121 @@ static void pinctrl_rk3288_sdmmc_config(struct rk3288_grf *grf, int mmc_id)
        }
 }
 
+static void pinctrl_rk3288_gmac_config(struct rk3288_grf *grf, int gmac_id)
+{
+       switch (gmac_id) {
+       case PERIPH_ID_GMAC:
+               rk_clrsetreg(&grf->gpio3dl_iomux,
+                            GPIO3D3_MASK << GPIO3D3_SHIFT |
+                            GPIO3D2_MASK << GPIO3D2_SHIFT |
+                            GPIO3D2_MASK << GPIO3D1_SHIFT |
+                            GPIO3D0_MASK << GPIO3D0_SHIFT,
+                            GPIO3D3_MAC_RXD3 << GPIO3D3_SHIFT |
+                            GPIO3D2_MAC_RXD2 << GPIO3D2_SHIFT |
+                            GPIO3D1_MAC_TXD3 << GPIO3D1_SHIFT |
+                            GPIO3D0_MAC_TXD2 << GPIO3D0_SHIFT);
+
+               rk_clrsetreg(&grf->gpio3dh_iomux,
+                            GPIO3D7_MASK << GPIO3D7_SHIFT |
+                            GPIO3D6_MASK << GPIO3D6_SHIFT |
+                            GPIO3D5_MASK << GPIO3D5_SHIFT |
+                            GPIO3D4_MASK << GPIO3D4_SHIFT,
+                            GPIO3D7_MAC_RXD1 << GPIO3D7_SHIFT |
+                            GPIO3D6_MAC_RXD0 << GPIO3D6_SHIFT |
+                            GPIO3D5_MAC_TXD1 << GPIO3D5_SHIFT |
+                            GPIO3D4_MAC_TXD0 << GPIO3D4_SHIFT);
+
+               /* switch the Tx pins to 12ma drive-strength */
+               rk_clrsetreg(&grf->gpio1_e[2][3],
+                            GPIO_BIAS_MASK |
+                            (GPIO_BIAS_MASK << GPIO_BIAS_SHIFT(1)) |
+                            (GPIO_BIAS_MASK << GPIO_BIAS_SHIFT(4)) |
+                            (GPIO_BIAS_MASK << GPIO_BIAS_SHIFT(5)),
+                            (GPIO_BIAS_12MA << GPIO_BIAS_SHIFT(0)) |
+                            (GPIO_BIAS_12MA << GPIO_BIAS_SHIFT(1)) |
+                            (GPIO_BIAS_12MA << GPIO_BIAS_SHIFT(4)) |
+                            (GPIO_BIAS_12MA << GPIO_BIAS_SHIFT(5)));
+
+               /* Set normal pull for all GPIO3D pins */
+               rk_clrsetreg(&grf->gpio1_p[2][3],
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(0)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(1)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(2)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(3)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(4)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(5)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(5)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(7)),
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(0)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(1)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(2)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(3)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(4)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(5)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(6)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(7)));
+
+               rk_clrsetreg(&grf->gpio4al_iomux,
+                            GPIO4A3_MASK << GPIO4A3_SHIFT |
+                            GPIO4A1_MASK << GPIO4A1_SHIFT |
+                            GPIO4A0_MASK << GPIO4A0_SHIFT,
+                            GPIO4A3_MAC_CLK << GPIO4A3_SHIFT |
+                            GPIO4A1_MAC_TXDV << GPIO4A1_SHIFT |
+                            GPIO4A0_MAC_MDC << GPIO4A0_SHIFT);
+
+               rk_clrsetreg(&grf->gpio4ah_iomux,
+                            GPIO4A6_MASK << GPIO4A6_SHIFT |
+                            GPIO4A5_MASK << GPIO4A5_SHIFT |
+                            GPIO4A4_MASK << GPIO4A4_SHIFT,
+                            GPIO4A6_MAC_RXCLK << GPIO4A6_SHIFT |
+                            GPIO4A5_MAC_MDIO << GPIO4A5_SHIFT |
+                            GPIO4A4_MAC_TXEN << GPIO4A4_SHIFT);
+
+               /* switch GPIO4A4 to 12ma drive-strength */
+               rk_clrsetreg(&grf->gpio1_e[3][0],
+                            GPIO_BIAS_MASK << GPIO_BIAS_SHIFT(4),
+                            GPIO_BIAS_12MA << GPIO_BIAS_SHIFT(4));
+
+               /* Set normal pull for all GPIO4A pins */
+               rk_clrsetreg(&grf->gpio1_p[3][0],
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(0)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(1)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(2)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(3)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(4)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(5)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(5)) |
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(7)),
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(0)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(1)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(2)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(3)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(4)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(5)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(6)) |
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(7)));
+
+               rk_clrsetreg(&grf->gpio4bl_iomux,
+                           GPIO4B1_MASK << GPIO4B1_SHIFT,
+                           GPIO4B1_MAC_TXCLK << GPIO4B1_SHIFT);
+
+               /* switch GPIO4B1 to 12ma drive-strength */
+               rk_clrsetreg(&grf->gpio1_e[3][1],
+                            GPIO_BIAS_MASK << GPIO_BIAS_SHIFT(1),
+                            GPIO_BIAS_12MA << GPIO_BIAS_SHIFT(1));
+
+               /* Set pull normal for GPIO4B1 */
+               rk_clrsetreg(&grf->gpio1_p[3][1],
+                            (GPIO_PULL_MASK << GPIO_PULL_SHIFT(1)),
+                            (GPIO_PULL_NORMAL << GPIO_PULL_SHIFT(1)));
+
+               break;
+       default:
+               printf("gmac id = %d iomux error!\n", gmac_id);
+               break;
+       }
+}
+
 #ifndef CONFIG_SPL_BUILD
 static void pinctrl_rk3288_hdmi_config(struct rk3288_grf *grf, int hdmi_id)
 {
@@ -466,6 +580,9 @@ static int rk3288_pinctrl_request(struct udevice *dev, int func, int flags)
        case PERIPH_ID_SDMMC1:
                pinctrl_rk3288_sdmmc_config(priv->grf, func);
                break;
+       case PERIPH_ID_GMAC:
+               pinctrl_rk3288_gmac_config(priv->grf, func);
+               break;
        default:
                return -EINVAL;
        }
@@ -476,15 +593,17 @@ static int rk3288_pinctrl_request(struct udevice *dev, int func, int flags)
 static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
                                        struct udevice *periph)
 {
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
        u32 cell[3];
        int ret;
 
-       ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
-                                  "interrupts", cell, ARRAY_SIZE(cell));
+       ret = dev_read_u32_array(periph, "interrupts", cell, ARRAY_SIZE(cell));
        if (ret < 0)
                return -EINVAL;
 
        switch (cell[1]) {
+       case 27:
+               return PERIPH_ID_GMAC;
        case 44:
                return PERIPH_ID_SPI0;
        case 45:
@@ -506,6 +625,7 @@ static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
        case 103:
                return PERIPH_ID_HDMI;
        }
+#endif
 
        return -ENOENT;
 }
@@ -587,6 +707,7 @@ static int rk3288_pinctrl_set_pins(struct udevice *dev, int banknum, int index,
        struct rk3288_pinctrl_priv *priv = dev_get_priv(dev);
        uint shift, ind = index;
        uint mask;
+       uint value;
        u32 *addr;
        int ret;
 
@@ -595,9 +716,20 @@ static int rk3288_pinctrl_set_pins(struct udevice *dev, int banknum, int index,
                                          &mask);
        if (ret)
                return ret;
-       rk_clrsetreg(addr, mask << shift, muxval << shift);
 
-       /* Handle pullup/pulldown */
+       /*
+        * PMU_GPIO0 registers cannot be selectively written so we cannot use
+        * rk_clrsetreg() here.  However, the upper 16 bits are reserved and
+        * are ignored when written, so we can use the same code as for the
+        * other GPIO banks providing that we preserve the value of the other
+        * bits.
+        */
+       value = readl(addr);
+       value &= ~(mask << shift);
+       value |= (mask << (shift + 16)) | (muxval << shift);
+       writel(value, addr);
+
+       /* Handle pullup/pulldown/drive-strength */
        if (flags) {
                uint val = 0;
 
@@ -605,15 +737,25 @@ static int rk3288_pinctrl_set_pins(struct udevice *dev, int banknum, int index,
                        val = 1;
                else if (flags & (1 << PIN_CONFIG_BIAS_PULL_DOWN))
                        val = 2;
+               else if (flags & (1 << PIN_CONFIG_DRIVE_STRENGTH))
+                       val = 3;
+
                shift = (index & 7) * 2;
                ind = index >> 3;
                if (banknum == 0)
                        addr = &priv->pmu->gpio0pull[ind];
+               else if (flags & (1 << PIN_CONFIG_DRIVE_STRENGTH))
+                       addr = &priv->grf->gpio1_e[banknum - 1][ind];
                else
                        addr = &priv->grf->gpio1_p[banknum - 1][ind];
                debug("%s: addr=%p, val=%x, shift=%x\n", __func__, addr, val,
                      shift);
-               rk_clrsetreg(addr, 3 << shift, val << shift);
+
+               /* As above, rk_clrsetreg() cannot be used here. */
+               value = readl(addr);
+               value &= ~(mask << shift);
+               value |= (3 << (shift + 16)) | (val << shift);
+               writel(value, addr);
        }
 
        return 0;
@@ -626,7 +768,7 @@ static int rk3288_pinctrl_set_state(struct udevice *dev, struct udevice *config)
        u32 cell[60], *ptr;
 
        debug("%s: %s %s\n", __func__, dev->name, config->name);
-       ret = fdtdec_get_int_array_count(blob, config->of_offset,
+       ret = fdtdec_get_int_array_count(blob, dev_of_offset(config),
                                         "rockchip,pins", cell,
                                         ARRAY_SIZE(cell));
        if (ret < 0) {
@@ -642,6 +784,9 @@ static int rk3288_pinctrl_set_state(struct udevice *dev, struct udevice *config)
                if (flags < 0)
                        return flags;
 
+               if (fdtdec_get_int(blob, pcfg_node, "drive-strength", 0) == 12)
+                       flags |= 1 << PIN_CONFIG_DRIVE_STRENGTH;
+
                ret = rk3288_pinctrl_set_pins(dev, ptr[0], ptr[1], ptr[2],
                                              flags);
                if (ret)
@@ -662,12 +807,6 @@ static struct pinctrl_ops rk3288_pinctrl_ops = {
        .get_periph_id  = rk3288_pinctrl_get_periph_id,
 };
 
-static int rk3288_pinctrl_bind(struct udevice *dev)
-{
-       /* scan child GPIO banks */
-       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 #ifndef CONFIG_SPL_BUILD
 static int rk3288_pinctrl_parse_tables(struct rk3288_pinctrl_priv *priv,
                                       struct rockchip_pin_bank *banks,
@@ -719,11 +858,13 @@ static const struct udevice_id rk3288_pinctrl_ids[] = {
 };
 
 U_BOOT_DRIVER(pinctrl_rk3288) = {
-       .name           = "pinctrl_rk3288",
+       .name           = "rockchip_rk3288_pinctrl",
        .id             = UCLASS_PINCTRL,
        .of_match       = rk3288_pinctrl_ids,
        .priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
        .ops            = &rk3288_pinctrl_ops,
-       .bind           = rk3288_pinctrl_bind,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+       .bind           = dm_scan_fdt_dev,
+#endif
        .probe          = rk3288_pinctrl_probe,
 };