uboot/drivers/gpio/adi_gpio2.c
<<
>>
Prefs
   1/*
   2 * ADI GPIO2 Abstraction Layer
   3 * Support BF54x, BF60x and future processors.
   4 *
   5 * Copyright 2008-2013 Analog Devices Inc.
   6 *
   7 * Licensed under the GPL-2 or later
   8 */
   9
  10#include <common.h>
  11#include <malloc.h>
  12#include <linux/bug.h>
  13#include <linux/errno.h>
  14#include <asm/gpio.h>
  15
  16#define RESOURCE_LABEL_SIZE     16
  17
  18static struct str_ident {
  19        char name[RESOURCE_LABEL_SIZE];
  20} str_ident[MAX_RESOURCES];
  21
  22static void gpio_error(unsigned gpio)
  23{
  24        printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio);
  25}
  26
  27static void set_label(unsigned short ident, const char *label)
  28{
  29        if (label) {
  30                strncpy(str_ident[ident].name, label,
  31                        RESOURCE_LABEL_SIZE);
  32                str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
  33        }
  34}
  35
  36static char *get_label(unsigned short ident)
  37{
  38        return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN";
  39}
  40
  41static int cmp_label(unsigned short ident, const char *label)
  42{
  43        if (label == NULL)
  44                printf("adi_gpio2: please provide none-null label\n");
  45
  46        if (label)
  47                return strcmp(str_ident[ident].name, label);
  48        else
  49                return -EINVAL;
  50}
  51
  52#define map_entry(m, i)      reserved_##m##_map[gpio_bank(i)]
  53#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
  54#define reserve(m, i)        (map_entry(m, i) |= gpio_bit(i))
  55#define unreserve(m, i)      (map_entry(m, i) &= ~gpio_bit(i))
  56#define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c]
  57
  58static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
  59static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
  60
  61inline int check_gpio(unsigned gpio)
  62{
  63#if defined(CONFIG_BF54x)
  64        if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 ||
  65                gpio == GPIO_PH14 || gpio == GPIO_PH15 ||
  66                gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
  67                return -EINVAL;
  68#endif
  69        if (gpio >= MAX_GPIOS)
  70                return -EINVAL;
  71        return 0;
  72}
  73
  74static void port_setup(unsigned gpio, unsigned short usage)
  75{
  76#if defined(CONFIG_BF54x)
  77        if (usage == GPIO_USAGE)
  78                gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
  79        else
  80                gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
  81#else
  82        if (usage == GPIO_USAGE)
  83                gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
  84        else
  85                gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
  86#endif
  87}
  88
  89inline void portmux_setup(unsigned short per)
  90{
  91        u32 pmux;
  92        u16 ident = P_IDENT(per);
  93        u16 function = P_FUNCT2MUX(per);
  94
  95        pmux = gpio_array[gpio_bank(ident)]->port_mux;
  96
  97        pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
  98        pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
  99
 100        gpio_array[gpio_bank(ident)]->port_mux = pmux;
 101}
 102
 103inline u16 get_portmux(unsigned short per)
 104{
 105        u32 pmux;
 106        u16 ident = P_IDENT(per);
 107
 108        pmux = gpio_array[gpio_bank(ident)]->port_mux;
 109
 110        return pmux >> (2 * gpio_sub_n(ident)) & 0x3;
 111}
 112
 113unsigned short get_gpio_dir(unsigned gpio)
 114{
 115        return 0x01 &
 116                (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio));
 117}
 118
 119/***********************************************************
 120*
 121* FUNCTIONS:    Peripheral Resource Allocation
 122*               and PortMux Setup
 123*
 124* INPUTS/OUTPUTS:
 125* per   Peripheral Identifier
 126* label String
 127*
 128* DESCRIPTION: Peripheral Resource Allocation and Setup API
 129**************************************************************/
 130
 131int peripheral_request(unsigned short per, const char *label)
 132{
 133        unsigned short ident = P_IDENT(per);
 134
 135        /*
 136         * Don't cares are pins with only one dedicated function
 137         */
 138
 139        if (per & P_DONTCARE)
 140                return 0;
 141
 142        if (!(per & P_DEFINED))
 143                return -EINVAL;
 144
 145        BUG_ON(ident >= MAX_RESOURCES);
 146
 147        /* If a pin can be muxed as either GPIO or peripheral, make
 148         * sure it is not already a GPIO pin when we request it.
 149         */
 150        if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
 151                printf("%s: Peripheral %d is already reserved as GPIO by %s!\n",
 152                       __func__, ident, get_label(ident));
 153                return -EBUSY;
 154        }
 155
 156        if (unlikely(is_reserved(peri, ident, 1))) {
 157                /*
 158                 * Pin functions like AMC address strobes my
 159                 * be requested and used by several drivers
 160                 */
 161
 162                if (!((per & P_MAYSHARE) &&
 163                        get_portmux(per) == P_FUNCT2MUX(per))) {
 164                        /*
 165                         * Allow that the identical pin function can
 166                         * be requested from the same driver twice
 167                         */
 168
 169                        if (cmp_label(ident, label) == 0)
 170                                goto anyway;
 171
 172                        printf("%s: Peripheral %d function %d is already "
 173                                "reserved by %s!\n", __func__, ident,
 174                                P_FUNCT2MUX(per), get_label(ident));
 175                        return -EBUSY;
 176                }
 177        }
 178
 179 anyway:
 180        reserve(peri, ident);
 181
 182        portmux_setup(per);
 183        port_setup(ident, PERIPHERAL_USAGE);
 184
 185        set_label(ident, label);
 186
 187        return 0;
 188}
 189
 190int peripheral_request_list(const unsigned short per[], const char *label)
 191{
 192        u16 cnt;
 193        int ret;
 194
 195        for (cnt = 0; per[cnt] != 0; cnt++) {
 196                ret = peripheral_request(per[cnt], label);
 197
 198                if (ret < 0) {
 199                        for (; cnt > 0; cnt--)
 200                                peripheral_free(per[cnt - 1]);
 201
 202                        return ret;
 203                }
 204        }
 205
 206        return 0;
 207}
 208
 209void peripheral_free(unsigned short per)
 210{
 211        unsigned short ident = P_IDENT(per);
 212
 213        if (per & P_DONTCARE)
 214                return;
 215
 216        if (!(per & P_DEFINED))
 217                return;
 218
 219        if (unlikely(!is_reserved(peri, ident, 0)))
 220                return;
 221
 222        if (!(per & P_MAYSHARE))
 223                port_setup(ident, GPIO_USAGE);
 224
 225        unreserve(peri, ident);
 226
 227        set_label(ident, "free");
 228}
 229
 230void peripheral_free_list(const unsigned short per[])
 231{
 232        u16 cnt;
 233        for (cnt = 0; per[cnt] != 0; cnt++)
 234                peripheral_free(per[cnt]);
 235}
 236
 237/***********************************************************
 238*
 239* FUNCTIONS: GPIO Driver
 240*
 241* INPUTS/OUTPUTS:
 242* gpio  PIO Number between 0 and MAX_GPIOS
 243* label String
 244*
 245* DESCRIPTION: GPIO Driver API
 246**************************************************************/
 247
 248int gpio_request(unsigned gpio, const char *label)
 249{
 250        if (check_gpio(gpio) < 0)
 251                return -EINVAL;
 252
 253        /*
 254         * Allow that the identical GPIO can
 255         * be requested from the same driver twice
 256         * Do nothing and return -
 257         */
 258
 259        if (cmp_label(gpio, label) == 0)
 260                return 0;
 261
 262        if (unlikely(is_reserved(gpio, gpio, 1))) {
 263                printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
 264                        gpio, get_label(gpio));
 265                return -EBUSY;
 266        }
 267        if (unlikely(is_reserved(peri, gpio, 1))) {
 268                printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
 269                        "by %s!\n", gpio, get_label(gpio));
 270                return -EBUSY;
 271        }
 272
 273        reserve(gpio, gpio);
 274        set_label(gpio, label);
 275
 276        port_setup(gpio, GPIO_USAGE);
 277
 278        return 0;
 279}
 280
 281int gpio_free(unsigned gpio)
 282{
 283        if (check_gpio(gpio) < 0)
 284                return -1;
 285
 286        if (unlikely(!is_reserved(gpio, gpio, 0))) {
 287                gpio_error(gpio);
 288                return -1;
 289        }
 290
 291        unreserve(gpio, gpio);
 292
 293        set_label(gpio, "free");
 294
 295        return 0;
 296}
 297
 298#ifdef ADI_SPECIAL_GPIO_BANKS
 299static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
 300
 301int special_gpio_request(unsigned gpio, const char *label)
 302{
 303        /*
 304         * Allow that the identical GPIO can
 305         * be requested from the same driver twice
 306         * Do nothing and return -
 307         */
 308
 309        if (cmp_label(gpio, label) == 0)
 310                return 0;
 311
 312        if (unlikely(is_reserved(special_gpio, gpio, 1))) {
 313                printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
 314                        gpio, get_label(gpio));
 315                return -EBUSY;
 316        }
 317        if (unlikely(is_reserved(peri, gpio, 1))) {
 318                printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
 319                        "by %s!\n", gpio, get_label(gpio));
 320
 321                return -EBUSY;
 322        }
 323
 324        reserve(special_gpio, gpio);
 325        reserve(peri, gpio);
 326
 327        set_label(gpio, label);
 328        port_setup(gpio, GPIO_USAGE);
 329
 330        return 0;
 331}
 332
 333void special_gpio_free(unsigned gpio)
 334{
 335        if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
 336                gpio_error(gpio);
 337                return;
 338        }
 339
 340        unreserve(special_gpio, gpio);
 341        unreserve(peri, gpio);
 342        set_label(gpio, "free");
 343}
 344#endif
 345
 346static inline void __gpio_direction_input(unsigned gpio)
 347{
 348        gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
 349#if defined(CONFIG_BF54x)
 350        gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
 351#else
 352        gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
 353#endif
 354}
 355
 356int gpio_direction_input(unsigned gpio)
 357{
 358        unsigned long flags;
 359
 360        if (!is_reserved(gpio, gpio, 0)) {
 361                gpio_error(gpio);
 362                return -EINVAL;
 363        }
 364
 365        local_irq_save(flags);
 366        __gpio_direction_input(gpio);
 367        local_irq_restore(flags);
 368
 369        return 0;
 370}
 371
 372int gpio_set_value(unsigned gpio, int arg)
 373{
 374        if (arg)
 375                gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
 376        else
 377                gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
 378
 379        return 0;
 380}
 381
 382int gpio_direction_output(unsigned gpio, int value)
 383{
 384        unsigned long flags;
 385
 386        if (!is_reserved(gpio, gpio, 0)) {
 387                gpio_error(gpio);
 388                return -EINVAL;
 389        }
 390
 391        local_irq_save(flags);
 392
 393#if defined(CONFIG_BF54x)
 394        gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
 395#else
 396        gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
 397#endif
 398        gpio_set_value(gpio, value);
 399        gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
 400
 401        local_irq_restore(flags);
 402
 403        return 0;
 404}
 405
 406int gpio_get_value(unsigned gpio)
 407{
 408        return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
 409}
 410
 411void gpio_labels(void)
 412{
 413        int c, gpio;
 414
 415        for (c = 0; c < MAX_RESOURCES; c++) {
 416                gpio = is_reserved(gpio, c, 1);
 417                if (!check_gpio(c) && gpio)
 418                        printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c),
 419                                get_gpio_dir(c) ? "OUTPUT" : "INPUT");
 420                else if (is_reserved(peri, c, 1))
 421                        printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
 422                else
 423                        continue;
 424        }
 425}
 426