uboot/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015-2016 Socionext Inc.
   4 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <dm/device_compat.h>
  10#include <linux/bitops.h>
  11#include <linux/bug.h>
  12#include <linux/io.h>
  13#include <linux/err.h>
  14#include <linux/kernel.h>
  15#include <linux/sizes.h>
  16#include <dm/pinctrl.h>
  17
  18#include "pinctrl-uniphier.h"
  19
  20#define UNIPHIER_PINCTRL_PINMUX_BASE    0x1000
  21#define UNIPHIER_PINCTRL_LOAD_PINMUX    0x1700
  22#define UNIPHIER_PINCTRL_DRVCTRL_BASE   0x1800
  23#define UNIPHIER_PINCTRL_DRV2CTRL_BASE  0x1900
  24#define UNIPHIER_PINCTRL_DRV3CTRL_BASE  0x1980
  25#define UNIPHIER_PINCTRL_PUPDCTRL_BASE  0x1a00
  26#define UNIPHIER_PINCTRL_IECTRL         0x1d00
  27
  28static const char *uniphier_pinctrl_dummy_name = "_dummy";
  29
  30static int uniphier_pinctrl_get_pins_count(struct udevice *dev)
  31{
  32        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  33        const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
  34        int pins_count = priv->socdata->pins_count;
  35
  36        /*
  37         * We do not list all pins in the pin table to save memory footprint.
  38         * Report the max pin number + 1 to fake the framework.
  39         */
  40        return pins[pins_count - 1].number + 1;
  41}
  42
  43static const char *uniphier_pinctrl_get_pin_name(struct udevice *dev,
  44                                                 unsigned int selector)
  45{
  46        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  47        const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
  48        int pins_count = priv->socdata->pins_count;
  49        int i;
  50
  51        for (i = 0; i < pins_count; i++)
  52                if (pins[i].number == selector)
  53                        return pins[i].name;
  54
  55        return uniphier_pinctrl_dummy_name;
  56}
  57
  58static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
  59{
  60        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  61
  62        return priv->socdata->groups_count;
  63}
  64
  65static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
  66                                                   unsigned selector)
  67{
  68        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  69
  70        if (!priv->socdata->groups[selector].name)
  71                return uniphier_pinctrl_dummy_name;
  72
  73        return priv->socdata->groups[selector].name;
  74}
  75
  76static int uniphier_pinmux_get_functions_count(struct udevice *dev)
  77{
  78        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  79
  80        return priv->socdata->functions_count;
  81}
  82
  83static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
  84                                                     unsigned selector)
  85{
  86        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  87
  88        if (!priv->socdata->functions[selector])
  89                return uniphier_pinctrl_dummy_name;
  90
  91        return priv->socdata->functions[selector];
  92}
  93
  94static int uniphier_pinconf_input_enable_perpin(struct udevice *dev,
  95                                                unsigned int pin, int enable)
  96{
  97        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
  98        unsigned reg;
  99        u32 mask, tmp;
 100
 101        reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
 102        mask = BIT(pin % 32);
 103
 104        tmp = readl(priv->base + reg);
 105        if (enable)
 106                tmp |= mask;
 107        else
 108                tmp &= ~mask;
 109        writel(tmp, priv->base + reg);
 110
 111        return 0;
 112}
 113
 114static int uniphier_pinconf_input_enable_legacy(struct udevice *dev,
 115                                                unsigned int pin, int enable)
 116{
 117        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 118
 119        /*
 120         * Multiple pins share one input enable, per-pin disabling is
 121         * impossible.
 122         */
 123        if (!enable)
 124                return -EINVAL;
 125
 126        /* Set all bits instead of having a bunch of pin data */
 127        writel(U32_MAX, priv->base + UNIPHIER_PINCTRL_IECTRL);
 128
 129        return 0;
 130}
 131
 132static int uniphier_pinconf_input_enable(struct udevice *dev,
 133                                         unsigned int pin, int enable)
 134{
 135        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 136
 137        if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
 138                return uniphier_pinconf_input_enable_perpin(dev, pin, enable);
 139        else
 140                return uniphier_pinconf_input_enable_legacy(dev, pin, enable);
 141}
 142
 143#if CONFIG_IS_ENABLED(PINCONF)
 144
 145static const struct pinconf_param uniphier_pinconf_params[] = {
 146        { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
 147        { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
 148        { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
 149        { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
 150        { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
 151        { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
 152        { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
 153};
 154
 155static const struct uniphier_pinctrl_pin *
 156uniphier_pinctrl_pin_get(struct uniphier_pinctrl_priv *priv, unsigned int pin)
 157{
 158        const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
 159        int pins_count = priv->socdata->pins_count;
 160        int i;
 161
 162        for (i = 0; i < pins_count; i++)
 163                if (pins[i].number == pin)
 164                        return &pins[i];
 165
 166        return NULL;
 167}
 168
 169static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
 170                                     unsigned int param, unsigned int arg)
 171{
 172        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 173        unsigned int enable = 1;
 174        unsigned int reg;
 175        u32 mask, tmp;
 176
 177        if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE))
 178                return -ENOTSUPP;
 179
 180        switch (param) {
 181        case PIN_CONFIG_BIAS_DISABLE:
 182                enable = 0;
 183                break;
 184        case PIN_CONFIG_BIAS_PULL_UP:
 185        case PIN_CONFIG_BIAS_PULL_DOWN:
 186                if (arg == 0)   /* total bias is not supported */
 187                        return -EINVAL;
 188                break;
 189        case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 190                if (arg == 0)   /* configuration ignored */
 191                        return 0;
 192        default:
 193                BUG();
 194        }
 195
 196        reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4;
 197        mask = BIT(pin % 32);
 198
 199        tmp = readl(priv->base + reg);
 200        if (enable)
 201                tmp |= mask;
 202        else
 203                tmp &= ~mask;
 204        writel(tmp, priv->base + reg);
 205
 206        return 0;
 207}
 208
 209static const unsigned int uniphier_pinconf_drv_strengths_1bit[] = {
 210        4, 8,
 211};
 212
 213static const unsigned int uniphier_pinconf_drv_strengths_2bit[] = {
 214        8, 12, 16, 20,
 215};
 216
 217static const unsigned int uniphier_pinconf_drv_strengths_3bit[] = {
 218        4, 5, 7, 9, 11, 12, 14, 16,
 219};
 220
 221static int uniphier_pinconf_drive_set(struct udevice *dev, unsigned int pin,
 222                                      unsigned int strength)
 223{
 224        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 225        const struct uniphier_pinctrl_pin *desc;
 226        const unsigned int *strengths;
 227        unsigned int base, stride, width, drvctrl, reg, shift;
 228        u32 val, mask, tmp;
 229
 230        desc = uniphier_pinctrl_pin_get(priv, pin);
 231        if (WARN_ON(!desc))
 232                return -EINVAL;
 233
 234        switch (uniphier_pin_get_drv_type(desc->data)) {
 235        case UNIPHIER_PIN_DRV_1BIT:
 236                strengths = uniphier_pinconf_drv_strengths_1bit;
 237                base = UNIPHIER_PINCTRL_DRVCTRL_BASE;
 238                stride = 1;
 239                width = 1;
 240                break;
 241        case UNIPHIER_PIN_DRV_2BIT:
 242                strengths = uniphier_pinconf_drv_strengths_2bit;
 243                base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
 244                stride = 2;
 245                width = 2;
 246                break;
 247        case UNIPHIER_PIN_DRV_3BIT:
 248                strengths = uniphier_pinconf_drv_strengths_3bit;
 249                base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
 250                stride = 4;
 251                width = 3;
 252                break;
 253        default:
 254                /* drive strength control is not supported for this pin */
 255                return -EINVAL;
 256        }
 257
 258        drvctrl = uniphier_pin_get_drvctrl(desc->data);
 259        drvctrl *= stride;
 260
 261        reg = base + drvctrl / 32 * 4;
 262        shift = drvctrl % 32;
 263        mask = (1U << width) - 1;
 264
 265        for (val = 0; val <= mask; val++) {
 266                if (strengths[val] > strength)
 267                        break;
 268        }
 269
 270        if (val == 0) {
 271                dev_err(dev, "unsupported drive strength %u mA for pin %s\n",
 272                        strength, desc->name);
 273                return -EINVAL;
 274        }
 275
 276        if (!mask)
 277                return 0;
 278
 279        val--;
 280
 281        tmp = readl(priv->base + reg);
 282        tmp &= ~(mask << shift);
 283        tmp |= (mask & val) << shift;
 284        writel(tmp, priv->base + reg);
 285
 286        return 0;
 287}
 288
 289static int uniphier_pinconf_set(struct udevice *dev, unsigned int pin,
 290                                unsigned int param, unsigned int arg)
 291{
 292        int ret;
 293
 294        switch (param) {
 295        case PIN_CONFIG_BIAS_DISABLE:
 296        case PIN_CONFIG_BIAS_PULL_UP:
 297        case PIN_CONFIG_BIAS_PULL_DOWN:
 298        case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 299                ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
 300                break;
 301        case PIN_CONFIG_DRIVE_STRENGTH:
 302                ret = uniphier_pinconf_drive_set(dev, pin, arg);
 303                break;
 304        case PIN_CONFIG_INPUT_ENABLE:
 305                ret = uniphier_pinconf_input_enable(dev, pin, arg);
 306                break;
 307        default:
 308                dev_err(dev, "unsupported configuration parameter %u\n", param);
 309                return -EINVAL;
 310        }
 311
 312        return ret;
 313}
 314
 315static int uniphier_pinconf_group_set(struct udevice *dev,
 316                                      unsigned int group_selector,
 317                                      unsigned int param, unsigned int arg)
 318{
 319        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 320        const struct uniphier_pinctrl_group *grp =
 321                                        &priv->socdata->groups[group_selector];
 322        int i, ret;
 323
 324        for (i = 0; i < grp->num_pins; i++) {
 325                ret = uniphier_pinconf_set(dev, grp->pins[i], param, arg);
 326                if (ret)
 327                        return ret;
 328        }
 329
 330        return 0;
 331}
 332
 333#endif /* CONFIG_IS_ENABLED(PINCONF) */
 334
 335static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
 336                                    int muxval)
 337{
 338        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 339        unsigned reg, reg_end, shift, mask;
 340        unsigned mux_bits = 8;
 341        unsigned reg_stride = 4;
 342        bool load_pinctrl = false;
 343        u32 tmp;
 344
 345        /* some pins need input-enabling */
 346        uniphier_pinconf_input_enable(dev, pin, 1);
 347
 348        if (muxval < 0)
 349                return;         /* dedicated pin; nothing to do for pin-mux */
 350
 351        if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_MUX_4BIT)
 352                mux_bits = 4;
 353
 354        if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
 355                /*
 356                 *  Mode       offset        bit
 357                 *  Normal     4 * n     shift+3:shift
 358                 *  Debug      4 * n     shift+7:shift+4
 359                 */
 360                mux_bits /= 2;
 361                reg_stride = 8;
 362                load_pinctrl = true;
 363        }
 364
 365        reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
 366        reg_end = reg + reg_stride;
 367        shift = pin * mux_bits % 32;
 368        mask = (1U << mux_bits) - 1;
 369
 370        /*
 371         * If reg_stride is greater than 4, the MSB of each pinsel shall be
 372         * stored in the offset+4.
 373         */
 374        for (; reg < reg_end; reg += 4) {
 375                tmp = readl(priv->base + reg);
 376                tmp &= ~(mask << shift);
 377                tmp |= (mask & muxval) << shift;
 378                writel(tmp, priv->base + reg);
 379
 380                muxval >>= mux_bits;
 381        }
 382
 383        if (load_pinctrl)
 384                writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
 385}
 386
 387static int uniphier_pinmux_group_set(struct udevice *dev,
 388                                     unsigned group_selector,
 389                                     unsigned func_selector)
 390{
 391        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 392        const struct uniphier_pinctrl_group *grp =
 393                                        &priv->socdata->groups[group_selector];
 394        int i;
 395
 396        for (i = 0; i < grp->num_pins; i++)
 397                uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
 398
 399        return 0;
 400}
 401
 402const struct pinctrl_ops uniphier_pinctrl_ops = {
 403        .get_pins_count = uniphier_pinctrl_get_pins_count,
 404        .get_pin_name = uniphier_pinctrl_get_pin_name,
 405        .get_groups_count = uniphier_pinctrl_get_groups_count,
 406        .get_group_name = uniphier_pinctrl_get_group_name,
 407        .get_functions_count = uniphier_pinmux_get_functions_count,
 408        .get_function_name = uniphier_pinmux_get_function_name,
 409        .pinmux_group_set = uniphier_pinmux_group_set,
 410#if CONFIG_IS_ENABLED(PINCONF)
 411        .pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
 412        .pinconf_params = uniphier_pinconf_params,
 413        .pinconf_set = uniphier_pinconf_set,
 414        .pinconf_group_set = uniphier_pinconf_group_set,
 415#endif
 416        .set_state = pinctrl_generic_set_state,
 417};
 418
 419int uniphier_pinctrl_probe(struct udevice *dev,
 420                           struct uniphier_pinctrl_socdata *socdata)
 421{
 422        struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 423        fdt_addr_t addr;
 424
 425        addr = dev_read_addr(dev->parent);
 426        if (addr == FDT_ADDR_T_NONE)
 427                return -EINVAL;
 428
 429        priv->base = devm_ioremap(dev, addr, SZ_4K);
 430        if (!priv->base)
 431                return -ENOMEM;
 432
 433        priv->socdata = socdata;
 434
 435        return 0;
 436}
 437