uboot/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <mapmem.h>
   9#include <linux/io.h>
  10#include <linux/err.h>
  11#include <linux/sizes.h>
  12#include <dm/device.h>
  13#include <dm/pinctrl.h>
  14
  15#include "pinctrl-uniphier.h"
  16
  17static const char *uniphier_pinctrl_dummy_name = "_dummy";
  18
  19static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
  20{
  21        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  22
  23        return priv->socdata->groups_count;
  24}
  25
  26static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
  27                                                   unsigned selector)
  28{
  29        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  30
  31        if (!priv->socdata->groups[selector].name)
  32                return uniphier_pinctrl_dummy_name;
  33
  34        return priv->socdata->groups[selector].name;
  35}
  36
  37static int uniphier_pinmux_get_functions_count(struct udevice *dev)
  38{
  39        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  40
  41        return priv->socdata->functions_count;
  42}
  43
  44static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
  45                                                     unsigned selector)
  46{
  47        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  48
  49        if (!priv->socdata->functions[selector])
  50                return uniphier_pinctrl_dummy_name;
  51
  52        return priv->socdata->functions[selector];
  53}
  54
  55static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
  56                                                 unsigned pin)
  57{
  58        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  59        unsigned reg;
  60        u32 mask, tmp;
  61
  62        reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
  63        mask = BIT(pin % 32);
  64
  65        tmp = readl(priv->base + reg);
  66        tmp |= mask;
  67        writel(tmp, priv->base + reg);
  68}
  69
  70static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
  71                                                 unsigned pin)
  72{
  73        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  74        int pins_count = priv->socdata->pins_count;
  75        const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
  76        int i;
  77
  78        for (i = 0; i < pins_count; i++) {
  79                if (pins[i].number == pin) {
  80                        unsigned int iectrl;
  81                        u32 tmp;
  82
  83                        iectrl = uniphier_pin_get_iectrl(pins[i].data);
  84                        tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
  85                        tmp |= 1 << iectrl;
  86                        writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
  87                }
  88        }
  89}
  90
  91static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
  92{
  93        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  94
  95        if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
  96                uniphier_pinconf_input_enable_perpin(dev, pin);
  97        else
  98                uniphier_pinconf_input_enable_legacy(dev, pin);
  99}
 100
 101static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
 102                                    int muxval)
 103{
 104        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 105        unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
 106        bool load_pinctrl;
 107        u32 tmp;
 108
 109        /* some pins need input-enabling */
 110        uniphier_pinconf_input_enable(dev, pin);
 111
 112        if (muxval < 0)
 113                return;         /* dedicated pin; nothing to do for pin-mux */
 114
 115        if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
 116                /*
 117                 *  Mode       offset        bit
 118                 *  Normal     4 * n     shift+3:shift
 119                 *  Debug      4 * n     shift+7:shift+4
 120                 */
 121                mux_bits = 4;
 122                reg_stride = 8;
 123                load_pinctrl = true;
 124        } else {
 125                /*
 126                 *  Mode       offset           bit
 127                 *  Normal     8 * n        shift+3:shift
 128                 *  Debug      8 * n + 4    shift+3:shift
 129                 */
 130                mux_bits = 8;
 131                reg_stride = 4;
 132                load_pinctrl = false;
 133        }
 134
 135        reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
 136        reg_end = reg + reg_stride;
 137        shift = pin * mux_bits % 32;
 138        mask = (1U << mux_bits) - 1;
 139
 140        /*
 141         * If reg_stride is greater than 4, the MSB of each pinsel shall be
 142         * stored in the offset+4.
 143         */
 144        for (; reg < reg_end; reg += 4) {
 145                tmp = readl(priv->base + reg);
 146                tmp &= ~(mask << shift);
 147                tmp |= (mask & muxval) << shift;
 148                writel(tmp, priv->base + reg);
 149
 150                muxval >>= mux_bits;
 151        }
 152
 153        if (load_pinctrl)
 154                writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
 155}
 156
 157static int uniphier_pinmux_group_set(struct udevice *dev,
 158                                     unsigned group_selector,
 159                                     unsigned func_selector)
 160{
 161        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 162        const struct uniphier_pinctrl_group *grp =
 163                                        &priv->socdata->groups[group_selector];
 164        int i;
 165
 166        for (i = 0; i < grp->num_pins; i++)
 167                uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
 168
 169        return 0;
 170}
 171
 172const struct pinctrl_ops uniphier_pinctrl_ops = {
 173        .get_groups_count = uniphier_pinctrl_get_groups_count,
 174        .get_group_name = uniphier_pinctrl_get_group_name,
 175        .get_functions_count = uniphier_pinmux_get_functions_count,
 176        .get_function_name = uniphier_pinmux_get_function_name,
 177        .pinmux_group_set = uniphier_pinmux_group_set,
 178        .set_state = pinctrl_generic_set_state,
 179};
 180
 181int uniphier_pinctrl_probe(struct udevice *dev,
 182                           struct uniphier_pinctrl_socdata *socdata)
 183{
 184        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 185        fdt_addr_t addr;
 186
 187        addr = dev_get_addr(dev->parent);
 188        if (addr == FDT_ADDR_T_NONE)
 189                return -EINVAL;
 190
 191        priv->base = map_sysmem(addr, SZ_4K);
 192        if (!priv->base)
 193                return -ENOMEM;
 194
 195        priv->socdata = socdata;
 196
 197        return 0;
 198}
 199
 200int uniphier_pinctrl_remove(struct udevice *dev)
 201{
 202        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 203
 204        unmap_sysmem(priv->base);
 205
 206        return 0;
 207}
 208