uboot/drivers/gpio/xilinx_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2013 - 2018 Xilinx, Michal Simek
   4 */
   5
   6#include <common.h>
   7#include <errno.h>
   8#include <malloc.h>
   9#include <linux/list.h>
  10#include <asm/io.h>
  11#include <asm/gpio.h>
  12#include <dm.h>
  13#include <dt-bindings/gpio/gpio.h>
  14
  15#define XILINX_GPIO_MAX_BANK    2
  16
  17/* Gpio simple map */
  18struct gpio_regs {
  19        u32 gpiodata;
  20        u32 gpiodir;
  21};
  22
  23struct xilinx_gpio_platdata {
  24        struct gpio_regs *regs;
  25        int bank_max[XILINX_GPIO_MAX_BANK];
  26        int bank_input[XILINX_GPIO_MAX_BANK];
  27        int bank_output[XILINX_GPIO_MAX_BANK];
  28        u32 dout_default[XILINX_GPIO_MAX_BANK];
  29};
  30
  31struct xilinx_gpio_privdata {
  32        u32 output_val[XILINX_GPIO_MAX_BANK];
  33};
  34
  35static int xilinx_gpio_get_bank_pin(unsigned offset, u32 *bank_num,
  36                                    u32 *bank_pin_num, struct udevice *dev)
  37{
  38        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
  39        u32 bank, max_pins;
  40        /* the first gpio is 0 not 1 */
  41        u32 pin_num = offset;
  42
  43        for (bank = 0; bank < XILINX_GPIO_MAX_BANK; bank++) {
  44                max_pins = platdata->bank_max[bank];
  45                if (pin_num < max_pins) {
  46                        debug("%s: found at bank 0x%x pin 0x%x\n", __func__,
  47                              bank, pin_num);
  48                        *bank_num = bank;
  49                        *bank_pin_num = pin_num;
  50                        return 0;
  51                }
  52                pin_num -= max_pins;
  53        }
  54
  55        return -EINVAL;
  56}
  57
  58static int xilinx_gpio_set_value(struct udevice *dev, unsigned offset,
  59                                 int value)
  60{
  61        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
  62        struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
  63        int val, ret;
  64        u32 bank, pin;
  65
  66        ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
  67        if (ret)
  68                return ret;
  69
  70        val = priv->output_val[bank];
  71
  72        debug("%s: regs: %lx, value: %x, gpio: %x, bank %x, pin %x, out %x\n",
  73              __func__, (ulong)platdata->regs, value, offset, bank, pin, val);
  74
  75        if (value)
  76                val = val | (1 << pin);
  77        else
  78                val = val & ~(1 << pin);
  79
  80        writel(val, &platdata->regs->gpiodata + bank * 2);
  81
  82        priv->output_val[bank] = val;
  83
  84        return 0;
  85};
  86
  87static int xilinx_gpio_get_value(struct udevice *dev, unsigned offset)
  88{
  89        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
  90        struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
  91        int val, ret;
  92        u32 bank, pin;
  93
  94        ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
  95        if (ret)
  96                return ret;
  97
  98        debug("%s: regs: %lx, gpio: %x, bank %x, pin %x\n", __func__,
  99              (ulong)platdata->regs, offset, bank, pin);
 100
 101        if (platdata->bank_output[bank]) {
 102                debug("%s: Read saved output value\n", __func__);
 103                val = priv->output_val[bank];
 104        } else {
 105                debug("%s: Read input value from reg\n", __func__);
 106                val = readl(&platdata->regs->gpiodata + bank * 2);
 107        }
 108
 109        val = !!(val & (1 << pin));
 110
 111        return val;
 112};
 113
 114static int xilinx_gpio_get_function(struct udevice *dev, unsigned offset)
 115{
 116        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
 117        int val, ret;
 118        u32 bank, pin;
 119
 120        ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
 121        if (ret)
 122                return ret;
 123
 124        /* Check if all pins are inputs */
 125        if (platdata->bank_input[bank])
 126                return GPIOF_INPUT;
 127
 128        /* Check if all pins are outputs */
 129        if (platdata->bank_output[bank])
 130                return GPIOF_OUTPUT;
 131
 132        /* FIXME test on dual */
 133        val = readl(&platdata->regs->gpiodir + bank * 2);
 134        val = !(val & (1 << pin));
 135
 136        /* input is 1 in reg but GPIOF_INPUT is 0 */
 137        /* output is 0 in reg but GPIOF_OUTPUT is 1 */
 138
 139        return val;
 140}
 141
 142static int xilinx_gpio_direction_output(struct udevice *dev, unsigned offset,
 143                                        int value)
 144{
 145        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
 146        int val, ret;
 147        u32 bank, pin;
 148
 149        ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
 150        if (ret)
 151                return ret;
 152
 153        /* can't change it if all is input by default */
 154        if (platdata->bank_input[bank])
 155                return -EINVAL;
 156
 157        xilinx_gpio_set_value(dev, offset, value);
 158
 159        if (!platdata->bank_output[bank]) {
 160                val = readl(&platdata->regs->gpiodir + bank * 2);
 161                val = val & ~(1 << pin);
 162                writel(val, &platdata->regs->gpiodir + bank * 2);
 163        }
 164
 165        return 0;
 166}
 167
 168static int xilinx_gpio_direction_input(struct udevice *dev, unsigned offset)
 169{
 170        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
 171        int val, ret;
 172        u32 bank, pin;
 173
 174        ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
 175        if (ret)
 176                return ret;
 177
 178        /* Already input */
 179        if (platdata->bank_input[bank])
 180                return 0;
 181
 182        /* can't change it if all is output by default */
 183        if (platdata->bank_output[bank])
 184                return -EINVAL;
 185
 186        val = readl(&platdata->regs->gpiodir + bank * 2);
 187        val = val | (1 << pin);
 188        writel(val, &platdata->regs->gpiodir + bank * 2);
 189
 190        return 0;
 191}
 192
 193static int xilinx_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
 194                             struct ofnode_phandle_args *args)
 195{
 196        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
 197
 198        desc->offset = args->args[0];
 199
 200        debug("%s: argc: %x, [0]: %x, [1]: %x, [2]: %x\n", __func__,
 201              args->args_count, args->args[0], args->args[1], args->args[2]);
 202
 203        /*
 204         * The second cell is channel offset:
 205         *  0 is first channel, 8 is second channel
 206         *
 207         * U-Boot driver just combine channels together that's why simply
 208         * add amount of pins in second channel if present.
 209         */
 210        if (args->args[1]) {
 211                if (!platdata->bank_max[1]) {
 212                        printf("%s: %s has no second channel\n",
 213                               __func__, dev->name);
 214                        return -EINVAL;
 215                }
 216
 217                desc->offset += platdata->bank_max[0];
 218        }
 219
 220        /* The third cell is optional */
 221        if (args->args_count > 2)
 222                desc->flags = (args->args[2] &
 223                               GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0);
 224
 225        debug("%s: offset %x, flags %lx\n",
 226              __func__, desc->offset, desc->flags);
 227        return 0;
 228}
 229
 230static const struct dm_gpio_ops xilinx_gpio_ops = {
 231        .direction_input = xilinx_gpio_direction_input,
 232        .direction_output = xilinx_gpio_direction_output,
 233        .get_value = xilinx_gpio_get_value,
 234        .set_value = xilinx_gpio_set_value,
 235        .get_function = xilinx_gpio_get_function,
 236        .xlate = xilinx_gpio_xlate,
 237};
 238
 239static int xilinx_gpio_probe(struct udevice *dev)
 240{
 241        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
 242        struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
 243        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 244        const void *label_ptr;
 245
 246        label_ptr = dev_read_prop(dev, "label", NULL);
 247        if (label_ptr) {
 248                uc_priv->bank_name = strdup(label_ptr);
 249                if (!uc_priv->bank_name)
 250                        return -ENOMEM;
 251        } else {
 252                uc_priv->bank_name = dev->name;
 253        }
 254
 255        uc_priv->gpio_count = platdata->bank_max[0] + platdata->bank_max[1];
 256
 257        priv->output_val[0] = platdata->dout_default[0];
 258
 259        if (platdata->bank_max[1])
 260                priv->output_val[1] = platdata->dout_default[1];
 261
 262        return 0;
 263}
 264
 265static int xilinx_gpio_ofdata_to_platdata(struct udevice *dev)
 266{
 267        struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
 268        int is_dual;
 269
 270        platdata->regs = (struct gpio_regs *)dev_read_addr(dev);
 271
 272        platdata->bank_max[0] = dev_read_u32_default(dev,
 273                                                     "xlnx,gpio-width", 0);
 274        platdata->bank_input[0] = dev_read_u32_default(dev,
 275                                                       "xlnx,all-inputs", 0);
 276        platdata->bank_output[0] = dev_read_u32_default(dev,
 277                                                        "xlnx,all-outputs", 0);
 278        platdata->dout_default[0] = dev_read_u32_default(dev,
 279                                                         "xlnx,dout-default",
 280                                                         0);
 281
 282        is_dual = dev_read_u32_default(dev, "xlnx,is-dual", 0);
 283        if (is_dual) {
 284                platdata->bank_max[1] = dev_read_u32_default(dev,
 285                                                "xlnx,gpio2-width", 0);
 286                platdata->bank_input[1] = dev_read_u32_default(dev,
 287                                                "xlnx,all-inputs-2", 0);
 288                platdata->bank_output[1] = dev_read_u32_default(dev,
 289                                                "xlnx,all-outputs-2", 0);
 290                platdata->dout_default[1] = dev_read_u32_default(dev,
 291                                                "xlnx,dout-default-2", 0);
 292        }
 293
 294        return 0;
 295}
 296
 297static const struct udevice_id xilinx_gpio_ids[] = {
 298        { .compatible = "xlnx,xps-gpio-1.00.a",},
 299        { }
 300};
 301
 302U_BOOT_DRIVER(xilinx_gpio) = {
 303        .name = "xlnx_gpio",
 304        .id = UCLASS_GPIO,
 305        .ops = &xilinx_gpio_ops,
 306        .of_match = xilinx_gpio_ids,
 307        .ofdata_to_platdata = xilinx_gpio_ofdata_to_platdata,
 308        .probe = xilinx_gpio_probe,
 309        .platdata_auto_alloc_size = sizeof(struct xilinx_gpio_platdata),
 310        .priv_auto_alloc_size = sizeof(struct xilinx_gpio_privdata),
 311};
 312