Merge https://gitlab.denx.de/u-boot/custodians/u-boot-sh
[platform/kernel/u-boot.git] / drivers / pinctrl / renesas / pfc.c
index 69e4cec..7ba7849 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Pin Control driver for SuperH Pin Function Controller.
  *
@@ -6,8 +7,6 @@
  * Copyright (C) 2008 Magnus Damm
  * Copyright (C) 2009 - 2012 Paul Mundt
  * Copyright (C) 2017 Marek Vasut
- *
- * SPDX-License-Identifier:    GPL-2.0
  */
 
 #define DRV_NAME "sh-pfc"
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
 #include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
 
 #include "sh_pfc.h"
 
-DECLARE_GLOBAL_DATA_PTR;
-
 enum sh_pfc_model {
-       SH_PFC_R8A7795 = 0,
+       SH_PFC_R8A7790 = 0,
+       SH_PFC_R8A7791,
+       SH_PFC_R8A7792,
+       SH_PFC_R8A7793,
+       SH_PFC_R8A7794,
+       SH_PFC_R8A7795,
        SH_PFC_R8A7796,
+       SH_PFC_R8A774A1,
+       SH_PFC_R8A77965,
        SH_PFC_R8A77970,
+       SH_PFC_R8A77980,
+       SH_PFC_R8A77990,
        SH_PFC_R8A77995,
 };
 
@@ -116,12 +126,12 @@ void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
        BUG();
 }
 
-u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width)
+u32 sh_pfc_read(struct sh_pfc *pfc, u32 reg)
 {
-       return sh_pfc_read_raw_reg(pfc->regs + reg, width);
+       return sh_pfc_read_raw_reg((void __iomem *)(uintptr_t)reg, 32);
 }
 
-void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, u32 data)
+void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data)
 {
        void __iomem *unlock_reg =
                (void __iomem *)(uintptr_t)pfc->info->unlock_reg;
@@ -129,7 +139,7 @@ void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, u32 data)
        if (pfc->info->unlock_reg)
                sh_pfc_write_raw_reg(unlock_reg, 32, ~data);
 
-       sh_pfc_write_raw_reg(pfc->regs + reg, width, data);
+       sh_pfc_write_raw_reg((void __iomem *)(uintptr_t)reg, 32, data);
 }
 
 static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
@@ -331,17 +341,22 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
        return 0;
 }
 
-const struct sh_pfc_bias_info *
-sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info,
-                       unsigned int num, unsigned int pin)
+const struct pinmux_bias_reg *
+sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
+                      unsigned int *bit)
 {
-       unsigned int i;
+       unsigned int i, j;
 
-       for (i = 0; i < num; i++)
-               if (info[i].pin == pin)
-                       return &info[i];
+       for (i = 0; pfc->info->bias_regs[i].puen; i++) {
+               for (j = 0; j < ARRAY_SIZE(pfc->info->bias_regs[i].pins); j++) {
+                       if (pfc->info->bias_regs[i].pins[j] == pin) {
+                               *bit = j;
+                               return &pfc->info->bias_regs[i];
+                       }
+               }
+       }
 
-       printf("Pin %u is not in bias info list\n", pin);
+       WARN_ONCE(1, "Pin %u is not in bias info list\n", pin);
 
        return NULL;
 }
@@ -450,16 +465,17 @@ static const char *sh_pfc_pinctrl_get_function_name(struct udevice *dev,
        return priv->pfc.info->functions[selector].name;
 }
 
-int sh_pfc_config_mux_for_gpio(struct udevice *dev, unsigned pin_selector)
+static int sh_pfc_gpio_request_enable(struct udevice *dev,
+                                     unsigned pin_selector)
 {
        struct sh_pfc_pinctrl_priv *priv = dev_get_priv(dev);
        struct sh_pfc_pinctrl *pmx = &priv->pmx;
        struct sh_pfc *pfc = &priv->pfc;
        struct sh_pfc_pin_config *cfg;
        const struct sh_pfc_pin *pin = NULL;
-       int i, idx;
+       int i, ret, idx;
 
-       for (i = 1; i < pfc->info->nr_pins; i++) {
+       for (i = 0; i < pfc->info->nr_pins; i++) {
                if (priv->pfc.info->pins[i].pin != pin_selector)
                        continue;
 
@@ -476,7 +492,42 @@ int sh_pfc_config_mux_for_gpio(struct udevice *dev, unsigned pin_selector)
        if (cfg->type != PINMUX_TYPE_NONE)
                return -EBUSY;
 
-       return sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
+       ret = sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
+       if (ret)
+               return ret;
+
+       cfg->type = PINMUX_TYPE_GPIO;
+
+       return 0;
+}
+
+static int sh_pfc_gpio_disable_free(struct udevice *dev,
+                                   unsigned pin_selector)
+{
+       struct sh_pfc_pinctrl_priv *priv = dev_get_priv(dev);
+       struct sh_pfc_pinctrl *pmx = &priv->pmx;
+       struct sh_pfc *pfc = &priv->pfc;
+       struct sh_pfc_pin_config *cfg;
+       const struct sh_pfc_pin *pin = NULL;
+       int i, idx;
+
+       for (i = 0; i < pfc->info->nr_pins; i++) {
+               if (priv->pfc.info->pins[i].pin != pin_selector)
+                       continue;
+
+               pin = &priv->pfc.info->pins[i];
+               break;
+       }
+
+       if (!pin)
+               return -EINVAL;
+
+       idx = sh_pfc_get_pin_index(pfc, pin->pin);
+       cfg = &pmx->configs[idx];
+
+       cfg->type = PINMUX_TYPE_NONE;
+
+       return 0;
 }
 
 static int sh_pfc_pinctrl_pin_set(struct udevice *dev, unsigned pin_selector,
@@ -583,7 +634,7 @@ static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc,
        strength = strength / step - 1;
 
        val = sh_pfc_read_raw_reg(reg, 32);
-       val &= ~GENMASK(offset + size - 1, offset);
+       val &= ~GENMASK(offset + 4 - 1, offset);
        val |= strength << offset;
 
        if (unlock_reg)
@@ -737,6 +788,9 @@ static struct pinctrl_ops sh_pfc_pinctrl_ops = {
        .pinmux_set             = sh_pfc_pinctrl_pin_set,
        .pinmux_group_set       = sh_pfc_pinctrl_group_set,
        .set_state              = pinctrl_generic_set_state,
+
+       .gpio_request_enable    = sh_pfc_gpio_request_enable,
+       .gpio_disable_free      = sh_pfc_gpio_disable_free,
 };
 
 static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
@@ -772,6 +826,26 @@ static int sh_pfc_pinctrl_probe(struct udevice *dev)
        if (!priv->pfc.regs)
                return -ENOMEM;
 
+#ifdef CONFIG_PINCTRL_PFC_R8A7790
+       if (model == SH_PFC_R8A7790)
+               priv->pfc.info = &r8a7790_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7791
+       if (model == SH_PFC_R8A7791)
+               priv->pfc.info = &r8a7791_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7792
+       if (model == SH_PFC_R8A7792)
+               priv->pfc.info = &r8a7792_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7793
+       if (model == SH_PFC_R8A7793)
+               priv->pfc.info = &r8a7793_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7794
+       if (model == SH_PFC_R8A7794)
+               priv->pfc.info = &r8a7794_pinmux_info;
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A7795
        if (model == SH_PFC_R8A7795)
                priv->pfc.info = &r8a7795_pinmux_info;
@@ -780,10 +854,26 @@ static int sh_pfc_pinctrl_probe(struct udevice *dev)
        if (model == SH_PFC_R8A7796)
                priv->pfc.info = &r8a7796_pinmux_info;
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774A1
+       if (model == SH_PFC_R8A774A1)
+               priv->pfc.info = &r8a774a1_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77965
+       if (model == SH_PFC_R8A77965)
+               priv->pfc.info = &r8a77965_pinmux_info;
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A77970
        if (model == SH_PFC_R8A77970)
                priv->pfc.info = &r8a77970_pinmux_info;
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77980
+       if (model == SH_PFC_R8A77980)
+               priv->pfc.info = &r8a77980_pinmux_info;
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
+       if (model == SH_PFC_R8A77990)
+               priv->pfc.info = &r8a77990_pinmux_info;
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A77995
        if (model == SH_PFC_R8A77995)
                priv->pfc.info = &r8a77995_pinmux_info;
@@ -797,6 +887,36 @@ static int sh_pfc_pinctrl_probe(struct udevice *dev)
 }
 
 static const struct udevice_id sh_pfc_pinctrl_ids[] = {
+#ifdef CONFIG_PINCTRL_PFC_R8A7790
+       {
+               .compatible = "renesas,pfc-r8a7790",
+               .data = SH_PFC_R8A7790,
+       },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7791
+       {
+               .compatible = "renesas,pfc-r8a7791",
+               .data = SH_PFC_R8A7791,
+       },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7792
+       {
+               .compatible = "renesas,pfc-r8a7792",
+               .data = SH_PFC_R8A7792,
+       },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7793
+       {
+               .compatible = "renesas,pfc-r8a7793",
+               .data = SH_PFC_R8A7793,
+       },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7794
+       {
+               .compatible = "renesas,pfc-r8a7794",
+               .data = SH_PFC_R8A7794,
+       },
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A7795
        {
                .compatible = "renesas,pfc-r8a7795",
@@ -809,12 +929,36 @@ static const struct udevice_id sh_pfc_pinctrl_ids[] = {
                .data = SH_PFC_R8A7796,
        },
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A774A1
+       {
+               .compatible = "renesas,pfc-r8a774a1",
+               .data = SH_PFC_R8A774A1,
+       },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77965
+       {
+               .compatible = "renesas,pfc-r8a77965",
+               .data = SH_PFC_R8A77965,
+       },
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A77970
        {
                .compatible = "renesas,pfc-r8a77970",
                .data = SH_PFC_R8A77970,
        },
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77980
+       {
+               .compatible = "renesas,pfc-r8a77980",
+               .data = SH_PFC_R8A77980,
+       },
+#endif
+#ifdef CONFIG_PINCTRL_PFC_R8A77990
+       {
+               .compatible = "renesas,pfc-r8a77990",
+               .data = SH_PFC_R8A77990,
+       },
+#endif
 #ifdef CONFIG_PINCTRL_PFC_R8A77995
        {
                .compatible = "renesas,pfc-r8a77995",