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