uboot/drivers/gpio/xilinx_gpio.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 Xilinx, Michal Simek
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <errno.h>
   9#include <malloc.h>
  10#include <linux/list.h>
  11#include <asm/io.h>
  12#include <asm/gpio.h>
  13
  14static LIST_HEAD(gpio_list);
  15
  16enum gpio_direction {
  17        GPIO_DIRECTION_OUT = 0,
  18        GPIO_DIRECTION_IN = 1,
  19};
  20
  21/* Gpio simple map */
  22struct gpio_regs {
  23        u32 gpiodata;
  24        u32 gpiodir;
  25};
  26
  27#define GPIO_NAME_SIZE  10
  28
  29struct gpio_names {
  30        char name[GPIO_NAME_SIZE];
  31};
  32
  33/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
  34struct xilinx_gpio_priv {
  35        struct gpio_regs *regs;
  36        u32 gpio_min;
  37        u32 gpio_max;
  38        u32 gpiodata_store;
  39        char name[GPIO_NAME_SIZE];
  40        struct list_head list;
  41        struct gpio_names *gpio_name;
  42};
  43
  44/* Store number of allocated gpio pins */
  45static u32 xilinx_gpio_max;
  46
  47/* Get associated gpio controller */
  48static struct xilinx_gpio_priv *gpio_get_controller(unsigned gpio)
  49{
  50        struct list_head *entry;
  51        struct xilinx_gpio_priv *priv = NULL;
  52
  53        list_for_each(entry, &gpio_list) {
  54                priv = list_entry(entry, struct xilinx_gpio_priv, list);
  55                if (gpio >= priv->gpio_min && gpio <= priv->gpio_max) {
  56                        debug("%s: reg: %x, min-max: %d-%d\n", __func__,
  57                              (u32)priv->regs, priv->gpio_min, priv->gpio_max);
  58                        return priv;
  59                }
  60        }
  61        puts("!!!Can't get gpio controller!!!\n");
  62        return NULL;
  63}
  64
  65/* Get gpio pin name if used/setup */
  66static char *get_name(unsigned gpio)
  67{
  68        u32 gpio_priv;
  69        struct xilinx_gpio_priv *priv;
  70
  71        debug("%s\n", __func__);
  72
  73        priv = gpio_get_controller(gpio);
  74        if (priv) {
  75                gpio_priv = gpio - priv->gpio_min;
  76
  77                return *priv->gpio_name[gpio_priv].name ?
  78                        priv->gpio_name[gpio_priv].name : "UNKNOWN";
  79        }
  80        return "UNKNOWN";
  81}
  82
  83/* Get output value */
  84static int gpio_get_output_value(unsigned gpio)
  85{
  86        u32 val, gpio_priv;
  87        struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
  88
  89        if (priv) {
  90                gpio_priv = gpio - priv->gpio_min;
  91                val = !!(priv->gpiodata_store & (1 << gpio_priv));
  92                debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
  93                      (u32)priv->regs, gpio_priv, val);
  94
  95                return val;
  96        }
  97        return -1;
  98}
  99
 100/* Get input value */
 101static int gpio_get_input_value(unsigned gpio)
 102{
 103        u32 val, gpio_priv;
 104        struct gpio_regs *regs;
 105        struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
 106
 107        if (priv) {
 108                regs = priv->regs;
 109                gpio_priv = gpio - priv->gpio_min;
 110                val = readl(&regs->gpiodata);
 111                val = !!(val & (1 << gpio_priv));
 112                debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
 113                      (u32)priv->regs, gpio_priv, val);
 114
 115                return val;
 116        }
 117        return -1;
 118}
 119
 120/* Set gpio direction */
 121static int gpio_set_direction(unsigned gpio, enum gpio_direction direction)
 122{
 123        u32 val, gpio_priv;
 124        struct gpio_regs *regs;
 125        struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
 126
 127        if (priv) {
 128                regs = priv->regs;
 129                val = readl(&regs->gpiodir);
 130
 131                gpio_priv = gpio - priv->gpio_min;
 132                if (direction == GPIO_DIRECTION_OUT)
 133                        val &= ~(1 << gpio_priv);
 134                else
 135                        val |= 1 << gpio_priv;
 136
 137                writel(val, &regs->gpiodir);
 138                debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
 139                      (u32)priv->regs, gpio_priv, val);
 140
 141                return 0;
 142        }
 143
 144        return -1;
 145}
 146
 147/* Get gpio direction */
 148static int gpio_get_direction(unsigned gpio)
 149{
 150        u32 val, gpio_priv;
 151        struct gpio_regs *regs;
 152        struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
 153
 154        if (priv) {
 155                regs = priv->regs;
 156                gpio_priv = gpio - priv->gpio_min;
 157                val = readl(&regs->gpiodir);
 158                val = !!(val & (1 << gpio_priv));
 159                debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
 160                      (u32)priv->regs, gpio_priv, val);
 161
 162                return val;
 163        }
 164
 165        return -1;
 166}
 167
 168/*
 169 * Get input value
 170 * for example gpio setup to output only can't get input value
 171 * which is breaking gpio toggle command
 172 */
 173int gpio_get_value(unsigned gpio)
 174{
 175        u32 val;
 176
 177        if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
 178                val = gpio_get_output_value(gpio);
 179        else
 180                val = gpio_get_input_value(gpio);
 181
 182        return val;
 183}
 184
 185/* Set output value */
 186static int gpio_set_output_value(unsigned gpio, int value)
 187{
 188        u32 val, gpio_priv;
 189        struct gpio_regs *regs;
 190        struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
 191
 192        if (priv) {
 193                regs = priv->regs;
 194                gpio_priv = gpio - priv->gpio_min;
 195                val = priv->gpiodata_store;
 196                if (value)
 197                        val |= 1 << gpio_priv;
 198                else
 199                        val &= ~(1 << gpio_priv);
 200
 201                writel(val, &regs->gpiodata);
 202                debug("%s: reg: %x, gpio_no: %d, output_val: %d\n", __func__,
 203                      (u32)priv->regs, gpio_priv, val);
 204                priv->gpiodata_store = val;
 205
 206                return 0;
 207        }
 208
 209        return -1;
 210}
 211
 212int gpio_set_value(unsigned gpio, int value)
 213{
 214        if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
 215                return gpio_set_output_value(gpio, value);
 216
 217        return -1;
 218}
 219
 220/* Set GPIO as input */
 221int gpio_direction_input(unsigned gpio)
 222{
 223        debug("%s\n", __func__);
 224        return gpio_set_direction(gpio, GPIO_DIRECTION_IN);
 225}
 226
 227/* Setup GPIO as output and set output value */
 228int gpio_direction_output(unsigned gpio, int value)
 229{
 230        int ret = gpio_set_direction(gpio, GPIO_DIRECTION_OUT);
 231
 232        debug("%s\n", __func__);
 233
 234        if (ret < 0)
 235                return ret;
 236
 237        return gpio_set_output_value(gpio, value);
 238}
 239
 240/* Show gpio status */
 241void gpio_info(void)
 242{
 243        unsigned gpio;
 244
 245        struct list_head *entry;
 246        struct xilinx_gpio_priv *priv = NULL;
 247
 248        list_for_each(entry, &gpio_list) {
 249                priv = list_entry(entry, struct xilinx_gpio_priv, list);
 250                printf("\n%s: %s/%x (%d-%d)\n", __func__, priv->name,
 251                       (u32)priv->regs, priv->gpio_min, priv->gpio_max);
 252
 253                for (gpio = priv->gpio_min; gpio <= priv->gpio_max; gpio++) {
 254                        printf("GPIO_%d:\t%s is an ", gpio, get_name(gpio));
 255                        if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
 256                                printf("OUTPUT value = %d\n",
 257                                       gpio_get_output_value(gpio));
 258                        else
 259                                printf("INPUT value = %d\n",
 260                                       gpio_get_input_value(gpio));
 261                }
 262        }
 263}
 264
 265int gpio_request(unsigned gpio, const char *label)
 266{
 267        u32 gpio_priv;
 268        struct xilinx_gpio_priv *priv;
 269
 270        if (gpio >= xilinx_gpio_max)
 271                return -EINVAL;
 272
 273        priv = gpio_get_controller(gpio);
 274        if (priv) {
 275                gpio_priv = gpio - priv->gpio_min;
 276
 277                if (label != NULL) {
 278                        strncpy(priv->gpio_name[gpio_priv].name, label,
 279                                GPIO_NAME_SIZE);
 280                        priv->gpio_name[gpio_priv].name[GPIO_NAME_SIZE - 1] =
 281                                        '\0';
 282                }
 283                return 0;
 284        }
 285
 286        return -1;
 287}
 288
 289int gpio_free(unsigned gpio)
 290{
 291        u32 gpio_priv;
 292        struct xilinx_gpio_priv *priv;
 293
 294        if (gpio >= xilinx_gpio_max)
 295                return -EINVAL;
 296
 297        priv = gpio_get_controller(gpio);
 298        if (priv) {
 299                gpio_priv = gpio - priv->gpio_min;
 300                priv->gpio_name[gpio_priv].name[0] = '\0';
 301
 302                /* Do nothing here */
 303                return 0;
 304        }
 305
 306        return -1;
 307}
 308
 309int gpio_alloc(u32 baseaddr, const char *name, u32 gpio_no)
 310{
 311        struct xilinx_gpio_priv *priv;
 312
 313        priv = calloc(1, sizeof(struct xilinx_gpio_priv));
 314
 315        /* Setup gpio name */
 316        if (name != NULL) {
 317                strncpy(priv->name, name, GPIO_NAME_SIZE);
 318                priv->name[GPIO_NAME_SIZE - 1] = '\0';
 319        }
 320        priv->regs = (struct gpio_regs *)baseaddr;
 321
 322        priv->gpio_min = xilinx_gpio_max;
 323        xilinx_gpio_max = priv->gpio_min + gpio_no;
 324        priv->gpio_max = xilinx_gpio_max - 1;
 325
 326        priv->gpio_name = calloc(gpio_no, sizeof(struct gpio_names));
 327
 328        INIT_LIST_HEAD(&priv->list);
 329        list_add_tail(&priv->list, &gpio_list);
 330
 331        printf("%s: Add %s (%d-%d)\n", __func__, name,
 332               priv->gpio_min, priv->gpio_max);
 333
 334        /* Return the first gpio allocated for this device */
 335        return priv->gpio_min;
 336}
 337
 338/* Dual channel gpio is one IP with two independent channels */
 339int gpio_alloc_dual(u32 baseaddr, const char *name, u32 gpio_no0, u32 gpio_no1)
 340{
 341        int ret;
 342
 343        ret = gpio_alloc(baseaddr, name, gpio_no0);
 344        gpio_alloc(baseaddr + 8, strcat((char *)name, "_1"), gpio_no1);
 345
 346        /* Return the first gpio allocated for this device */
 347        return ret;
 348}
 349