uboot/drivers/pinctrl/pinctrl-sandbox.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
   4 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <dm/pinctrl.h>
  10#include <dt-bindings/pinctrl/sandbox-pinmux.h>
  11#include <log.h>
  12#include <linux/bitops.h>
  13
  14/*
  15 * This driver emulates a pin controller with the following rules:
  16 * - The pinctrl config for each pin must be set individually
  17 * - The first three pins (P0-P2) must be muxed as a group
  18 * - The next two pins (P3-P4) must be muxed as a group
  19 * - The last four pins (P5-P8) must be muxed individually
  20 */
  21
  22static const char * const sandbox_pins[] = {
  23#define PIN(x) \
  24        [x] = "P" #x
  25        PIN(0),
  26        PIN(1),
  27        PIN(2),
  28        PIN(3),
  29        PIN(4),
  30        PIN(5),
  31        PIN(6),
  32        PIN(7),
  33        PIN(8),
  34#undef PIN
  35};
  36
  37static const char * const sandbox_pins_muxing[][2] = {
  38        { "UART TX", "I2C SCL" },
  39        { "UART RX", "I2C SDA" },
  40        { "SPI SCLK", "I2S SCK" },
  41        { "SPI MOSI", "I2S SD" },
  42        { "SPI MISO", "I2S WS" },
  43        { "GPIO0", "SPI CS0" },
  44        { "GPIO1", "SPI CS1" },
  45        { "GPIO2", "PWM0" },
  46        { "GPIO3", "PWM1" },
  47};
  48
  49#define SANDBOX_GROUP_I2C_UART 0
  50#define SANDBOX_GROUP_SPI_I2S 1
  51
  52static const char * const sandbox_groups[] = {
  53        [SANDBOX_GROUP_I2C_UART] = "I2C_UART",
  54        [SANDBOX_GROUP_SPI_I2S] = "SPI_I2S",
  55};
  56
  57static const char * const sandbox_functions[] = {
  58#define FUNC(id) \
  59        [SANDBOX_PINMUX_##id] = #id
  60        FUNC(UART),
  61        FUNC(I2C),
  62        FUNC(SPI),
  63        FUNC(I2S),
  64        FUNC(GPIO),
  65        FUNC(CS),
  66        FUNC(PWM),
  67#undef FUNC
  68};
  69
  70static const struct pinconf_param sandbox_conf_params[] = {
  71        { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
  72        { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
  73        { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
  74        { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
  75        { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
  76        { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
  77        { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
  78        { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
  79        { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
  80        { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
  81        { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
  82};
  83
  84/* Bitfield used to save param and value of each pin/selector */
  85struct sandbox_pinctrl_priv {
  86        unsigned int mux;
  87        unsigned int pins_param[ARRAY_SIZE(sandbox_pins)];
  88        unsigned int pins_value[ARRAY_SIZE(sandbox_pins)];
  89};
  90
  91static int sandbox_get_pins_count(struct udevice *dev)
  92{
  93        return ARRAY_SIZE(sandbox_pins);
  94}
  95
  96static const char *sandbox_get_pin_name(struct udevice *dev, unsigned selector)
  97{
  98        return sandbox_pins[selector];
  99}
 100
 101static int sandbox_get_pin_muxing(struct udevice *dev,
 102                                  unsigned int selector,
 103                                  char *buf, int size)
 104{
 105        const struct pinconf_param *p;
 106        struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
 107        int i;
 108
 109        snprintf(buf, size, "%s",
 110                 sandbox_pins_muxing[selector][!!(priv->mux & BIT(selector))]);
 111
 112        if (priv->pins_param[selector]) {
 113                for (i = 0, p = sandbox_conf_params;
 114                     i < ARRAY_SIZE(sandbox_conf_params);
 115                     i++, p++) {
 116                        if ((priv->pins_param[selector] & BIT(p->param)) &&
 117                            (!!(priv->pins_value[selector] & BIT(p->param)) ==
 118                             p->default_value)) {
 119                                strncat(buf, " ", size);
 120                                strncat(buf, p->property, size);
 121                        }
 122                }
 123        }
 124        strncat(buf, ".", size);
 125
 126        return 0;
 127}
 128
 129static int sandbox_get_groups_count(struct udevice *dev)
 130{
 131        return ARRAY_SIZE(sandbox_groups);
 132}
 133
 134static const char *sandbox_get_group_name(struct udevice *dev,
 135                                          unsigned selector)
 136{
 137        return sandbox_groups[selector];
 138}
 139
 140static int sandbox_get_functions_count(struct udevice *dev)
 141{
 142        return ARRAY_SIZE(sandbox_functions);
 143}
 144
 145static const char *sandbox_get_function_name(struct udevice *dev,
 146                                             unsigned selector)
 147{
 148        return sandbox_functions[selector];
 149}
 150
 151static int sandbox_pinmux_set(struct udevice *dev, unsigned pin_selector,
 152                              unsigned func_selector)
 153{
 154        int mux;
 155        struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
 156
 157        debug("sandbox pinmux: pin = %d (%s), function = %d (%s)\n",
 158              pin_selector, sandbox_get_pin_name(dev, pin_selector),
 159              func_selector, sandbox_get_function_name(dev, func_selector));
 160
 161        if (pin_selector < 5)
 162                return -EINVAL;
 163
 164        switch (func_selector) {
 165        case SANDBOX_PINMUX_GPIO:
 166                mux = 0;
 167                break;
 168        case SANDBOX_PINMUX_CS:
 169        case SANDBOX_PINMUX_PWM:
 170                mux = BIT(pin_selector);
 171                break;
 172        default:
 173                return -EINVAL;
 174        }
 175
 176        priv->mux &= ~BIT(pin_selector);
 177        priv->mux |= mux;
 178        priv->pins_param[pin_selector] = 0;
 179        priv->pins_value[pin_selector] = 0;
 180
 181        return 0;
 182}
 183
 184static int sandbox_pinmux_group_set(struct udevice *dev,
 185                                    unsigned group_selector,
 186                                    unsigned func_selector)
 187{
 188        bool mux;
 189        int i, group_start, group_end;
 190        struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
 191        unsigned int mask;
 192
 193        debug("sandbox pinmux: group = %d (%s), function = %d (%s)\n",
 194              group_selector, sandbox_get_group_name(dev, group_selector),
 195              func_selector, sandbox_get_function_name(dev, func_selector));
 196
 197        if (group_selector == SANDBOX_GROUP_I2C_UART) {
 198                group_start = 0;
 199                group_end = 1;
 200
 201                if (func_selector == SANDBOX_PINMUX_UART)
 202                        mux = false;
 203                else if (func_selector == SANDBOX_PINMUX_I2C)
 204                        mux = true;
 205                else
 206                        return -EINVAL;
 207        } else if (group_selector == SANDBOX_GROUP_SPI_I2S) {
 208                group_start = 2;
 209                group_end = 4;
 210
 211                if (func_selector == SANDBOX_PINMUX_SPI)
 212                        mux = false;
 213                else if (func_selector == SANDBOX_PINMUX_I2S)
 214                        mux = true;
 215                else
 216                        return -EINVAL;
 217        } else {
 218                return -EINVAL;
 219        }
 220
 221        mask = GENMASK(group_end, group_start);
 222        priv->mux &= ~mask;
 223        priv->mux |= mux ? mask : 0;
 224
 225        for (i = group_start; i < group_end; i++) {
 226                priv->pins_param[i] = 0;
 227                priv->pins_value[i] = 0;
 228        }
 229
 230        return 0;
 231}
 232
 233static int sandbox_pinmux_property_set(struct udevice *dev, u32 pinmux_group)
 234{
 235        int ret;
 236        unsigned pin_selector = pinmux_group & 0xFFFF;
 237        unsigned func_selector = pinmux_group >> 16;
 238
 239        ret = sandbox_pinmux_set(dev, pin_selector, func_selector);
 240        return ret ? ret : pin_selector;
 241}
 242
 243static int sandbox_pinconf_set(struct udevice *dev, unsigned pin_selector,
 244                               unsigned param, unsigned argument)
 245{
 246        struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
 247
 248        debug("sandbox pinconf: pin = %d (%s), param = %d, arg = %d\n",
 249              pin_selector, sandbox_get_pin_name(dev, pin_selector),
 250              param, argument);
 251
 252        priv->pins_param[pin_selector] |= BIT(param);
 253        if (argument)
 254                priv->pins_value[pin_selector] |= BIT(param);
 255        else
 256                priv->pins_value[pin_selector] &= ~BIT(param);
 257
 258        return 0;
 259}
 260
 261static int sandbox_pinconf_group_set(struct udevice *dev,
 262                                     unsigned group_selector,
 263                                     unsigned param, unsigned argument)
 264{
 265        debug("sandbox pinconf: group = %d (%s), param = %d, arg = %d\n",
 266              group_selector, sandbox_get_group_name(dev, group_selector),
 267              param, argument);
 268
 269        return 0;
 270}
 271
 272const struct pinctrl_ops sandbox_pinctrl_ops = {
 273        .get_pins_count = sandbox_get_pins_count,
 274        .get_pin_name = sandbox_get_pin_name,
 275        .get_pin_muxing = sandbox_get_pin_muxing,
 276        .get_groups_count = sandbox_get_groups_count,
 277        .get_group_name = sandbox_get_group_name,
 278        .get_functions_count = sandbox_get_functions_count,
 279        .get_function_name = sandbox_get_function_name,
 280        .pinmux_set = sandbox_pinmux_set,
 281        .pinmux_group_set = sandbox_pinmux_group_set,
 282        .pinmux_property_set = sandbox_pinmux_property_set,
 283        .pinconf_num_params = ARRAY_SIZE(sandbox_conf_params),
 284        .pinconf_params = sandbox_conf_params,
 285        .pinconf_set = sandbox_pinconf_set,
 286        .pinconf_group_set = sandbox_pinconf_group_set,
 287        .set_state = pinctrl_generic_set_state,
 288};
 289
 290static const struct udevice_id sandbox_pinctrl_match[] = {
 291        { .compatible = "sandbox,pinctrl" },
 292        { /* sentinel */ }
 293};
 294
 295U_BOOT_DRIVER(sandbox_pinctrl) = {
 296        .name = "sandbox_pinctrl",
 297        .id = UCLASS_PINCTRL,
 298        .of_match = sandbox_pinctrl_match,
 299        .priv_auto      = sizeof(struct sandbox_pinctrl_priv),
 300        .ops = &sandbox_pinctrl_ops,
 301};
 302