uboot/drivers/gpio/iproc_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier:      GPL-2.0+
   2/*
   3 * Copyright (C) 2020 Broadcom
   4 */
   5
   6#include <common.h>
   7#include <errno.h>
   8#include <asm/gpio.h>
   9#include <asm/io.h>
  10#include <dm.h>
  11#include <dm/device_compat.h>
  12#include <dm/devres.h>
  13#include <dm/pinctrl.h>
  14
  15/*
  16 * There are five GPIO bank register. Each bank can configure max of 32 gpios.
  17 * BANK0 - gpios 0 to 31
  18 * BANK1 - gpios 32 to 63
  19 * BANK2 - gpios 64 to 95
  20 * BANK3 - gpios 96 to 127
  21 * BANK4 - gpios 128 to 150
  22 *
  23 * Offset difference between consecutive bank register is 0x200
  24 */
  25#define NGPIO_PER_BANK          32
  26#define GPIO_BANK_SIZE          0x200
  27#define GPIO_BANK(pin)          ((pin) / NGPIO_PER_BANK)
  28#define GPIO_SHIFT(pin)         ((pin) % NGPIO_PER_BANK)
  29#define GPIO_REG(pin, reg)      (GPIO_BANK_SIZE * GPIO_BANK(pin) + (reg))
  30
  31/* device register offset */
  32#define DATA_IN_OFFSET   0x00
  33#define DATA_OUT_OFFSET  0x04
  34#define OUT_EN_OFFSET    0x08
  35
  36/**
  37 * struct iproc_gpio_pctrl_map - gpio and pinctrl mapping
  38 * @gpio_pin:   start of gpio number in gpio-ranges
  39 * @pctrl_pin:  start of pinctrl number in gpio-ranges
  40 * @npins:      total number of pins in gpio-ranges
  41 * @node:       list node
  42 */
  43struct iproc_gpio_pctrl_map {
  44        u32 gpio_pin;
  45        u32 pctrl_pin;
  46        u32 npins;
  47        struct list_head node;
  48};
  49
  50/**
  51 * struct iproc_gpio_pctrl_map - gpio device instance
  52 * @pinctrl_dev:pointer to pinctrl device
  53 * @gpiomap:    list node having mapping between gpio and pinctrl
  54 * @base:       I/O register base address of gpio device
  55 * @name:       gpio device name, ex GPIO0, GPIO1
  56 * @ngpios:     total number of gpios
  57 */
  58struct iproc_gpio_plat {
  59        struct udevice *pinctrl_dev;
  60        struct list_head gpiomap;
  61        void __iomem *base;
  62        char *name;
  63        u32 ngpios;
  64};
  65
  66/**
  67 * iproc_gpio_set_bit - set or clear one bit in an iproc GPIO register.
  68 *
  69 * The bit relates to a GPIO pin.
  70 *
  71 * @plat: iproc GPIO device
  72 * @reg: register offset
  73 * @gpio: GPIO pin
  74 * @set: set or clear
  75 */
  76static inline void iproc_gpio_set_bit(struct iproc_gpio_plat *plat,
  77                                      u32 reg, u32 gpio, bool set)
  78{
  79        u32 offset = GPIO_REG(gpio, reg);
  80        u32 shift = GPIO_SHIFT(gpio);
  81
  82        clrsetbits_le32(plat->base + offset, BIT(shift),
  83                        (set ? BIT(shift) : 0));
  84}
  85
  86static inline bool iproc_gpio_get_bit(struct iproc_gpio_plat *plat,
  87                                      u32 reg, u32 gpio)
  88{
  89        u32 offset = GPIO_REG(gpio, reg);
  90        u32 shift = GPIO_SHIFT(gpio);
  91
  92        return readl(plat->base + offset) & BIT(shift);
  93}
  94
  95/**
  96 * iproc_get_gpio_pctrl_mapping() - get associated pinctrl pin from gpio pin
  97 *
  98 * @plat: iproc GPIO device
  99 * @gpio: GPIO pin
 100 */
 101static u32 iproc_get_pctrl_from_gpio(struct iproc_gpio_plat *plat, u32 gpio)
 102{
 103        struct iproc_gpio_pctrl_map *range = NULL;
 104        struct list_head *pos, *tmp;
 105        u32 ret = 0;
 106
 107        list_for_each_safe(pos, tmp, &plat->gpiomap) {
 108                range = list_entry(pos, struct iproc_gpio_pctrl_map, node);
 109                if (gpio == range->gpio_pin ||
 110                    gpio < (range->gpio_pin + range->npins)) {
 111                        ret = range->pctrl_pin + (gpio - range->gpio_pin);
 112                        break;
 113                }
 114        }
 115
 116        return ret;
 117}
 118
 119/**
 120 * iproc_get_gpio_pctrl_mapping() - get mapping between gpio and pinctrl
 121 *
 122 * Read dt node "gpio-ranges" to get gpio and pinctrl mapping and store
 123 * in private data structure to use it later while enabling gpio.
 124 *
 125 * @dev: pointer to GPIO device
 126 * Return: 0 on success and -ENOMEM on failure
 127 */
 128static int iproc_get_gpio_pctrl_mapping(struct udevice *dev)
 129{
 130        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 131        struct iproc_gpio_pctrl_map *range = NULL;
 132        struct ofnode_phandle_args args;
 133        int index = 0, ret;
 134
 135        for (;; index++) {
 136                ret = dev_read_phandle_with_args(dev, "gpio-ranges",
 137                                                 NULL, 3, index, &args);
 138                if (ret)
 139                        break;
 140
 141                range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
 142                if (!range)
 143                        return -ENOMEM;
 144
 145                range->gpio_pin = args.args[0];
 146                range->pctrl_pin = args.args[1];
 147                range->npins = args.args[2];
 148                list_add_tail(&range->node, &plat->gpiomap);
 149        }
 150
 151        return 0;
 152}
 153
 154static int iproc_gpio_request(struct udevice *dev, u32 gpio, const char *label)
 155{
 156        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 157        u32 pctrl;
 158
 159        /* nothing to do if there is no corresponding pinctrl device */
 160        if (!plat->pinctrl_dev)
 161                return 0;
 162
 163        pctrl = iproc_get_pctrl_from_gpio(plat, gpio);
 164
 165        return pinctrl_request(plat->pinctrl_dev, pctrl, 0);
 166}
 167
 168static int iproc_gpio_direction_input(struct udevice *dev, u32 gpio)
 169{
 170        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 171
 172        iproc_gpio_set_bit(plat, OUT_EN_OFFSET, gpio, false);
 173        dev_dbg(dev, "gpio:%u set input\n", gpio);
 174
 175        return 0;
 176}
 177
 178static int iproc_gpio_direction_output(struct udevice *dev, u32 gpio, int value)
 179{
 180        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 181
 182        iproc_gpio_set_bit(plat, OUT_EN_OFFSET, gpio, true);
 183        iproc_gpio_set_bit(plat, DATA_OUT_OFFSET, gpio, value);
 184        dev_dbg(dev, "gpio:%u set output, value:%d\n", gpio, value);
 185
 186        return 0;
 187}
 188
 189static int iproc_gpio_get_value(struct udevice *dev, u32 gpio)
 190{
 191        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 192        int value;
 193
 194        value = iproc_gpio_get_bit(plat, DATA_IN_OFFSET, gpio);
 195        dev_dbg(dev, "gpio:%u get, value:%d\n", gpio, value);
 196
 197        return value;
 198}
 199
 200static int iproc_gpio_set_value(struct udevice *dev, u32 gpio, int value)
 201{
 202        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 203
 204        if (iproc_gpio_get_bit(plat, OUT_EN_OFFSET, gpio))
 205                iproc_gpio_set_bit(plat, DATA_OUT_OFFSET, gpio, value);
 206
 207        dev_dbg(dev, "gpio:%u set, value:%d\n", gpio, value);
 208        return 0;
 209}
 210
 211static int iproc_gpio_get_function(struct udevice *dev, u32 gpio)
 212{
 213        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 214
 215        if (iproc_gpio_get_bit(plat, OUT_EN_OFFSET, gpio))
 216                return GPIOF_OUTPUT;
 217        else
 218                return GPIOF_INPUT;
 219}
 220
 221static int iproc_gpio_of_to_plat(struct udevice *dev)
 222{
 223        struct iproc_gpio_plat *plat = dev_get_plat(dev);
 224        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 225        int ret;
 226        char name[10];
 227
 228        plat->base = dev_read_addr_ptr(dev);
 229        if (!plat->base) {
 230                debug("%s: Failed to get base address\n", __func__);
 231                return -EINVAL;
 232        }
 233
 234        ret = dev_read_u32(dev, "ngpios", &plat->ngpios);
 235        if (ret < 0) {
 236                dev_err(dev, "%s: Failed to get ngpios\n", __func__);
 237                return ret;
 238        }
 239
 240        uclass_get_device_by_phandle(UCLASS_PINCTRL, dev, "gpio-ranges",
 241                                     &plat->pinctrl_dev);
 242        if (ret < 0) {
 243                dev_err(dev, "%s: Failed to get pinctrl phandle\n", __func__);
 244                return ret;
 245        }
 246
 247        INIT_LIST_HEAD(&plat->gpiomap);
 248        ret = iproc_get_gpio_pctrl_mapping(dev);
 249        if (ret < 0) {
 250                dev_err(dev, "%s: Failed to get gpio to pctrl map ret(%d)\n",
 251                        __func__, ret);
 252                return ret;
 253        }
 254
 255        snprintf(name, sizeof(name), "GPIO%d", dev_seq(dev));
 256        plat->name = strdup(name);
 257        if (!plat->name)
 258                return -ENOMEM;
 259
 260        uc_priv->gpio_count = plat->ngpios;
 261        uc_priv->bank_name = plat->name;
 262
 263        dev_info(dev, ":bank name(%s) base %p, #gpios %d\n",
 264                 plat->name, plat->base, plat->ngpios);
 265
 266        return 0;
 267}
 268
 269static const struct dm_gpio_ops iproc_gpio_ops = {
 270        .request                = iproc_gpio_request,
 271        .direction_input        = iproc_gpio_direction_input,
 272        .direction_output       = iproc_gpio_direction_output,
 273        .get_value              = iproc_gpio_get_value,
 274        .set_value              = iproc_gpio_set_value,
 275        .get_function           = iproc_gpio_get_function,
 276};
 277
 278static const struct udevice_id iproc_gpio_ids[] = {
 279        { .compatible = "brcm,iproc-gpio" },
 280        { }
 281};
 282
 283U_BOOT_DRIVER(iproc_gpio) = {
 284        .name                   = "iproc_gpio",
 285        .id                     = UCLASS_GPIO,
 286        .of_match               = iproc_gpio_ids,
 287        .ops                    = &iproc_gpio_ops,
 288        .of_to_plat     = iproc_gpio_of_to_plat,
 289        .plat_auto      = sizeof(struct iproc_gpio_plat),
 290};
 291