uboot/drivers/pinctrl/pinctrl-stmfx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
   4 *
   5 * Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander
   6 * based on Linux driver : pinctrl/pinctrl-stmfx.c
   7 */
   8#include <common.h>
   9#include <dm.h>
  10#include <i2c.h>
  11#include <asm/gpio.h>
  12#include <dm/device.h>
  13#include <dm/device-internal.h>
  14#include <dm/device_compat.h>
  15#include <dm/lists.h>
  16#include <dm/pinctrl.h>
  17#include <linux/bitfield.h>
  18#include <linux/bitops.h>
  19#include <linux/delay.h>
  20#include <power/regulator.h>
  21
  22/* STMFX pins = GPIO[15:0] + aGPIO[7:0] */
  23#define STMFX_MAX_GPIO                  16
  24#define STMFX_MAX_AGPIO                 8
  25
  26/* General */
  27#define STMFX_REG_CHIP_ID               0x00 /* R */
  28#define STMFX_REG_FW_VERSION_MSB        0x01 /* R */
  29#define STMFX_REG_FW_VERSION_LSB        0x02 /* R */
  30#define STMFX_REG_SYS_CTRL              0x40 /* RW */
  31
  32/* MFX boot time is around 10ms, so after reset, we have to wait this delay */
  33#define STMFX_BOOT_TIME_MS 10
  34
  35/* GPIOs expander */
  36/* GPIO_STATE1 0x10, GPIO_STATE2 0x11, GPIO_STATE3 0x12 */
  37#define STMFX_REG_GPIO_STATE            0x10 /* R */
  38/* GPIO_DIR1 0x60, GPIO_DIR2 0x61, GPIO_DIR3 0x63 */
  39#define STMFX_REG_GPIO_DIR              0x60 /* RW */
  40/* GPIO_TYPE1 0x64, GPIO_TYPE2 0x65, GPIO_TYPE3 0x66 */
  41#define STMFX_REG_GPIO_TYPE             0x64 /* RW */
  42/* GPIO_PUPD1 0x68, GPIO_PUPD2 0x69, GPIO_PUPD3 0x6A */
  43#define STMFX_REG_GPIO_PUPD             0x68 /* RW */
  44/* GPO_SET1 0x6C, GPO_SET2 0x6D, GPO_SET3 0x6E */
  45#define STMFX_REG_GPO_SET               0x6C /* RW */
  46/* GPO_CLR1 0x70, GPO_CLR2 0x71, GPO_CLR3 0x72 */
  47#define STMFX_REG_GPO_CLR               0x70 /* RW */
  48
  49/* STMFX_REG_CHIP_ID bitfields */
  50#define STMFX_REG_CHIP_ID_MASK          GENMASK(7, 0)
  51
  52/* STMFX_REG_SYS_CTRL bitfields */
  53#define STMFX_REG_SYS_CTRL_GPIO_EN      BIT(0)
  54#define STMFX_REG_SYS_CTRL_ALTGPIO_EN   BIT(3)
  55#define STMFX_REG_SYS_CTRL_SWRST        BIT(7)
  56
  57#define NR_GPIO_REGS                    3
  58#define NR_GPIOS_PER_REG                8
  59#define get_reg(offset)                 ((offset) / NR_GPIOS_PER_REG)
  60#define get_shift(offset)               ((offset) % NR_GPIOS_PER_REG)
  61#define get_mask(offset)                (BIT(get_shift(offset)))
  62
  63struct stmfx_pinctrl {
  64        struct udevice *gpio;
  65};
  66
  67static int stmfx_read(struct udevice *dev, uint offset)
  68{
  69        return  dm_i2c_reg_read(dev_get_parent(dev), offset);
  70}
  71
  72static int stmfx_write(struct udevice *dev, uint offset, unsigned int val)
  73{
  74        return dm_i2c_reg_write(dev_get_parent(dev), offset, val);
  75}
  76
  77static int stmfx_read_reg(struct udevice *dev, u8 reg_base, uint offset)
  78{
  79        u8 reg = reg_base + get_reg(offset);
  80        u32 mask = get_mask(offset);
  81        int ret;
  82
  83        ret = stmfx_read(dev, reg);
  84        if (ret < 0)
  85                return ret;
  86
  87        return ret < 0 ? ret : !!(ret & mask);
  88}
  89
  90static int stmfx_write_reg(struct udevice *dev, u8 reg_base, uint offset,
  91                           uint val)
  92{
  93        u8 reg = reg_base + get_reg(offset);
  94        u32 mask = get_mask(offset);
  95        int ret;
  96
  97        ret = stmfx_read(dev, reg);
  98        if (ret < 0)
  99                return ret;
 100        ret = (ret & ~mask) | (val ? mask : 0);
 101
 102        return stmfx_write(dev, reg, ret);
 103}
 104
 105static int stmfx_conf_set_pupd(struct udevice *dev, unsigned int offset,
 106                               uint pupd)
 107{
 108        return stmfx_write_reg(dev, STMFX_REG_GPIO_PUPD, offset, pupd);
 109}
 110
 111static int stmfx_conf_get_pupd(struct udevice *dev, unsigned int offset)
 112{
 113        return stmfx_read_reg(dev, STMFX_REG_GPIO_PUPD, offset);
 114}
 115
 116static int stmfx_conf_set_type(struct udevice *dev, unsigned int offset,
 117                               uint type)
 118{
 119        return stmfx_write_reg(dev, STMFX_REG_GPIO_TYPE, offset, type);
 120}
 121
 122static int stmfx_conf_get_type(struct udevice *dev, unsigned int offset)
 123{
 124        return stmfx_read_reg(dev, STMFX_REG_GPIO_TYPE, offset);
 125}
 126
 127static int stmfx_gpio_get(struct udevice *dev, unsigned int offset)
 128{
 129        return stmfx_read_reg(dev, STMFX_REG_GPIO_STATE, offset);
 130}
 131
 132static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
 133{
 134        u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR;
 135        u32 mask = get_mask(offset);
 136
 137        return stmfx_write(dev, reg + get_reg(offset), mask);
 138}
 139
 140static int stmfx_gpio_get_function(struct udevice *dev, unsigned int offset)
 141{
 142        int ret = stmfx_read_reg(dev, STMFX_REG_GPIO_DIR, offset);
 143
 144        if (ret < 0)
 145                return ret;
 146        /* On stmfx, gpio pins direction is (0)input, (1)output. */
 147
 148        return ret ? GPIOF_OUTPUT : GPIOF_INPUT;
 149}
 150
 151static int stmfx_gpio_direction_input(struct udevice *dev, unsigned int offset)
 152{
 153        return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 0);
 154}
 155
 156static int stmfx_gpio_direction_output(struct udevice *dev,
 157                                       unsigned int offset, int value)
 158{
 159        int ret = stmfx_gpio_set(dev, offset, value);
 160        if (ret < 0)
 161                return ret;
 162
 163        return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
 164}
 165
 166static int stmfx_gpio_set_flags(struct udevice *dev, unsigned int offset,
 167                                ulong flags)
 168{
 169        int ret = -ENOTSUPP;
 170
 171        if (flags & GPIOD_IS_OUT) {
 172                bool value = flags & GPIOD_IS_OUT_ACTIVE;
 173
 174                if (flags & GPIOD_OPEN_SOURCE)
 175                        return -ENOTSUPP;
 176                if (flags & GPIOD_OPEN_DRAIN)
 177                        ret = stmfx_conf_set_type(dev, offset, 0);
 178                else /* PUSH-PULL */
 179                        ret = stmfx_conf_set_type(dev, offset, 1);
 180                if (ret)
 181                        return ret;
 182                ret = stmfx_gpio_direction_output(dev, offset, value);
 183        } else if (flags & GPIOD_IS_IN) {
 184                ret = stmfx_gpio_direction_input(dev, offset);
 185                if (ret)
 186                        return ret;
 187                if (flags & GPIOD_PULL_UP) {
 188                        ret = stmfx_conf_set_type(dev, offset, 1);
 189                        if (ret)
 190                                return ret;
 191                        ret = stmfx_conf_set_pupd(dev, offset, 1);
 192                } else if (flags & GPIOD_PULL_DOWN) {
 193                        ret = stmfx_conf_set_type(dev, offset, 1);
 194                        if (ret)
 195                                return ret;
 196                        ret = stmfx_conf_set_pupd(dev, offset, 0);
 197                }
 198        }
 199
 200        return ret;
 201}
 202
 203static int stmfx_gpio_get_flags(struct udevice *dev, unsigned int offset,
 204                                ulong *flagsp)
 205{
 206        ulong dir_flags = 0;
 207        int ret;
 208
 209        if (stmfx_gpio_get_function(dev, offset) == GPIOF_OUTPUT) {
 210                dir_flags |= GPIOD_IS_OUT;
 211                ret = stmfx_conf_get_type(dev, offset);
 212                if (ret < 0)
 213                        return ret;
 214                if (ret == 0)
 215                        dir_flags |= GPIOD_OPEN_DRAIN;
 216                        /* 1 = push-pull (default), open source not supported */
 217                ret = stmfx_gpio_get(dev, offset);
 218                if (ret < 0)
 219                        return ret;
 220                if (ret)
 221                        dir_flags |= GPIOD_IS_OUT_ACTIVE;
 222        } else {
 223                dir_flags |= GPIOD_IS_IN;
 224                ret = stmfx_conf_get_type(dev, offset);
 225                if (ret < 0)
 226                        return ret;
 227                if (ret == 1) {
 228                        ret = stmfx_conf_get_pupd(dev, offset);
 229                        if (ret < 0)
 230                                return ret;
 231                        if (ret == 1)
 232                                dir_flags |= GPIOD_PULL_UP;
 233                        else
 234                                dir_flags |= GPIOD_PULL_DOWN;
 235                }
 236        }
 237        *flagsp = dir_flags;
 238
 239        return 0;
 240}
 241
 242static int stmfx_gpio_probe(struct udevice *dev)
 243{
 244        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 245        struct ofnode_phandle_args args;
 246        u8 sys_ctrl;
 247
 248        uc_priv->bank_name = "stmfx";
 249        uc_priv->gpio_count = STMFX_MAX_GPIO + STMFX_MAX_AGPIO;
 250        if (!dev_read_phandle_with_args(dev, "gpio-ranges",
 251                                        NULL, 3, 0, &args)) {
 252                uc_priv->gpio_count = args.args[2];
 253        }
 254
 255        /* enable GPIO function */
 256        sys_ctrl = STMFX_REG_SYS_CTRL_GPIO_EN;
 257        if (uc_priv->gpio_count > STMFX_MAX_GPIO)
 258                sys_ctrl |= STMFX_REG_SYS_CTRL_ALTGPIO_EN;
 259        stmfx_write(dev, STMFX_REG_SYS_CTRL, sys_ctrl);
 260
 261        return 0;
 262}
 263
 264static const struct dm_gpio_ops stmfx_gpio_ops = {
 265        .set_value = stmfx_gpio_set,
 266        .get_value = stmfx_gpio_get,
 267        .get_function = stmfx_gpio_get_function,
 268        .direction_input = stmfx_gpio_direction_input,
 269        .direction_output = stmfx_gpio_direction_output,
 270        .set_flags = stmfx_gpio_set_flags,
 271        .get_flags = stmfx_gpio_get_flags,
 272};
 273
 274U_BOOT_DRIVER(stmfx_gpio) = {
 275        .name   = "stmfx-gpio",
 276        .id     = UCLASS_GPIO,
 277        .probe  = stmfx_gpio_probe,
 278        .ops    = &stmfx_gpio_ops,
 279};
 280
 281#if CONFIG_IS_ENABLED(PINCONF)
 282static const struct pinconf_param stmfx_pinctrl_conf_params[] = {
 283        { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
 284        { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 },
 285        { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0 },
 286        { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 },
 287        { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
 288        { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
 289        { "output-high", PIN_CONFIG_OUTPUT, 1 },
 290        { "output-low", PIN_CONFIG_OUTPUT, 0 },
 291};
 292
 293static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
 294                                  unsigned int param, unsigned int arg)
 295{
 296        int ret, dir;
 297        struct stmfx_pinctrl *plat = dev_get_plat(dev);
 298
 299        dir = stmfx_gpio_get_function(plat->gpio, pin);
 300
 301        if (dir < 0)
 302                return dir;
 303
 304        switch (param) {
 305        case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 306        case PIN_CONFIG_BIAS_DISABLE:
 307        case PIN_CONFIG_DRIVE_PUSH_PULL:
 308                ret = stmfx_conf_set_type(dev, pin, 0);
 309                break;
 310        case PIN_CONFIG_BIAS_PULL_DOWN:
 311                ret = stmfx_conf_set_type(dev, pin, 1);
 312                if (ret)
 313                        return ret;
 314                ret = stmfx_conf_set_pupd(dev, pin, 0);
 315                break;
 316        case PIN_CONFIG_BIAS_PULL_UP:
 317                ret = stmfx_conf_set_type(dev, pin, 1);
 318                if (ret)
 319                        return ret;
 320                ret = stmfx_conf_set_pupd(dev, pin, 1);
 321                break;
 322        case PIN_CONFIG_DRIVE_OPEN_DRAIN:
 323                ret = stmfx_conf_set_type(dev, pin, 1);
 324                break;
 325        case PIN_CONFIG_OUTPUT:
 326                ret = stmfx_gpio_direction_output(plat->gpio, pin, arg);
 327                break;
 328        default:
 329                return -ENOTSUPP;
 330        }
 331
 332        return ret;
 333}
 334#endif
 335
 336static int stmfx_pinctrl_get_pins_count(struct udevice *dev)
 337{
 338        struct stmfx_pinctrl *plat = dev_get_plat(dev);
 339        struct gpio_dev_priv *uc_priv;
 340
 341        uc_priv = dev_get_uclass_priv(plat->gpio);
 342
 343        return uc_priv->gpio_count;
 344}
 345
 346/*
 347 * STMFX pins[15:0] are called "gpio[15:0]"
 348 * and STMFX pins[23:16] are called "agpio[7:0]"
 349 */
 350static char pin_name[PINNAME_SIZE];
 351static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev,
 352                                              unsigned int selector)
 353{
 354        if (selector < STMFX_MAX_GPIO)
 355                snprintf(pin_name, PINNAME_SIZE, "gpio%u", selector);
 356        else
 357                snprintf(pin_name, PINNAME_SIZE, "agpio%u", selector - 16);
 358        return pin_name;
 359}
 360
 361static const char *stmfx_pinctrl_get_pin_conf(struct udevice *dev,
 362                                              unsigned int pin, int func)
 363{
 364        int pupd, type;
 365
 366        type = stmfx_conf_get_type(dev, pin);
 367        if (type < 0)
 368                return "";
 369
 370        if (func == GPIOF_OUTPUT) {
 371                if (type)
 372                        return "drive-open-drain";
 373                else
 374                        return ""; /* default: push-pull*/
 375        }
 376        if (!type)
 377                return ""; /* default: bias-disable*/
 378
 379        pupd = stmfx_conf_get_pupd(dev, pin);
 380        if (pupd < 0)
 381                return "";
 382
 383        if (pupd)
 384                return "bias-pull-up";
 385        else
 386                return "bias-pull-down";
 387}
 388
 389static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
 390                                        unsigned int selector,
 391                                        char *buf, int size)
 392{
 393        struct stmfx_pinctrl *plat = dev_get_plat(dev);
 394        int func;
 395
 396        func = stmfx_gpio_get_function(plat->gpio, selector);
 397        if (func < 0)
 398                return func;
 399
 400        snprintf(buf, size, "%s ", func == GPIOF_INPUT ? "input" : "output");
 401
 402        strncat(buf, stmfx_pinctrl_get_pin_conf(dev, selector, func), size);
 403
 404        return 0;
 405}
 406
 407static int stmfx_pinctrl_bind(struct udevice *dev)
 408{
 409        struct stmfx_pinctrl *plat = dev_get_plat(dev);
 410
 411        /* subnode name is not explicit: use father name */
 412        device_set_name(dev, dev->parent->name);
 413
 414        return device_bind_driver_to_node(dev->parent,
 415                                          "stmfx-gpio", dev->parent->name,
 416                                          dev_ofnode(dev), &plat->gpio);
 417};
 418
 419static int stmfx_pinctrl_probe(struct udevice *dev)
 420{
 421        struct stmfx_pinctrl *plat = dev_get_plat(dev);
 422
 423        return device_probe(plat->gpio);
 424};
 425
 426const struct pinctrl_ops stmfx_pinctrl_ops = {
 427        .get_pins_count = stmfx_pinctrl_get_pins_count,
 428        .get_pin_name = stmfx_pinctrl_get_pin_name,
 429        .set_state = pinctrl_generic_set_state,
 430        .get_pin_muxing = stmfx_pinctrl_get_pin_muxing,
 431#if CONFIG_IS_ENABLED(PINCONF)
 432        .pinconf_set = stmfx_pinctrl_conf_set,
 433        .pinconf_num_params = ARRAY_SIZE(stmfx_pinctrl_conf_params),
 434        .pinconf_params = stmfx_pinctrl_conf_params,
 435#endif
 436};
 437
 438static const struct udevice_id stmfx_pinctrl_match[] = {
 439        { .compatible = "st,stmfx-0300-pinctrl", },
 440};
 441
 442U_BOOT_DRIVER(stmfx_pinctrl) = {
 443        .name = "stmfx-pinctrl",
 444        .id = UCLASS_PINCTRL,
 445        .of_match = of_match_ptr(stmfx_pinctrl_match),
 446        .bind = stmfx_pinctrl_bind,
 447        .probe = stmfx_pinctrl_probe,
 448        .ops = &stmfx_pinctrl_ops,
 449        .plat_auto      = sizeof(struct stmfx_pinctrl),
 450};
 451
 452static int stmfx_chip_init(struct udevice *dev)
 453{
 454        u8 id;
 455        u8 version[2];
 456        int ret;
 457        struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
 458
 459        ret = dm_i2c_reg_read(dev, STMFX_REG_CHIP_ID);
 460        if (ret < 0) {
 461                dev_err(dev, "error reading chip id: %d\n", ret);
 462                return ret;
 463        }
 464        id = (u8)ret;
 465        /*
 466         * Check that ID is the complement of the I2C address:
 467         * STMFX I2C address follows the 7-bit format (MSB), that's why
 468         * client->addr is shifted.
 469         *
 470         * STMFX_I2C_ADDR|       STMFX         |        Linux
 471         *   input pin   | I2C device address  | I2C device address
 472         *---------------------------------------------------------
 473         *       0       | b: 1000 010x h:0x84 |       0x42
 474         *       1       | b: 1000 011x h:0x86 |       0x43
 475         */
 476        if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (chip->chip_addr << 1)) {
 477                dev_err(dev, "unknown chip id: %#x\n", id);
 478                return -EINVAL;
 479        }
 480
 481        ret = dm_i2c_read(dev, STMFX_REG_FW_VERSION_MSB,
 482                          version, sizeof(version));
 483        if (ret) {
 484                dev_err(dev, "error reading fw version: %d\n", ret);
 485                return ret;
 486        }
 487
 488        dev_info(dev, "STMFX id: %#x, fw version: %x.%02x\n",
 489                 id, version[0], version[1]);
 490
 491        ret = dm_i2c_reg_read(dev, STMFX_REG_SYS_CTRL);
 492
 493        if (ret < 0)
 494                return ret;
 495
 496        ret = dm_i2c_reg_write(dev, STMFX_REG_SYS_CTRL,
 497                               ret | STMFX_REG_SYS_CTRL_SWRST);
 498        if (ret)
 499                return ret;
 500
 501        mdelay(STMFX_BOOT_TIME_MS);
 502
 503        return ret;
 504}
 505
 506static int stmfx_probe(struct udevice *dev)
 507{
 508        struct udevice *vdd;
 509        int ret;
 510
 511        ret = device_get_supply_regulator(dev, "vdd-supply", &vdd);
 512        if (ret && ret != -ENOENT) {
 513                dev_err(dev, "vdd regulator error:%d\n", ret);
 514                return ret;
 515        }
 516        if (!ret) {
 517                ret = regulator_set_enable(vdd, true);
 518                if (ret) {
 519                        dev_err(dev, "vdd enable failed: %d\n", ret);
 520                        return ret;
 521                }
 522        }
 523
 524        return stmfx_chip_init(dev);
 525}
 526
 527static const struct udevice_id stmfx_match[] = {
 528        { .compatible = "st,stmfx-0300", },
 529};
 530
 531U_BOOT_DRIVER(stmfx) = {
 532        .name = "stmfx",
 533        .id = UCLASS_I2C_GENERIC,
 534        .of_match = of_match_ptr(stmfx_match),
 535        .probe = stmfx_probe,
 536        .bind = dm_scan_fdt_dev,
 537};
 538