uboot/drivers/gpio/s5p_gpio.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009 Samsung Electronics
   3 * Minkyu Kang <mk7.kang@samsung.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <asm/io.h>
  10#include <asm/gpio.h>
  11#include <asm/arch/gpio.h>
  12
  13#define S5P_GPIO_GET_PIN(x)     (x % GPIO_PER_BANK)
  14
  15#define CON_MASK(x)             (0xf << ((x) << 2))
  16#define CON_SFR(x, v)           ((v) << ((x) << 2))
  17
  18#define DAT_MASK(x)             (0x1 << (x))
  19#define DAT_SET(x)              (0x1 << (x))
  20
  21#define PULL_MASK(x)            (0x3 << ((x) << 1))
  22#define PULL_MODE(x, v)         ((v) << ((x) << 1))
  23
  24#define DRV_MASK(x)             (0x3 << ((x) << 1))
  25#define DRV_SET(x, m)           ((m) << ((x) << 1))
  26#define RATE_MASK(x)            (0x1 << (x + 16))
  27#define RATE_SET(x)             (0x1 << (x + 16))
  28
  29#define name_to_gpio(n) s5p_name_to_gpio(n)
  30static inline int s5p_name_to_gpio(const char *name)
  31{
  32        unsigned num, irregular_set_number, irregular_bank_base;
  33        const struct gpio_name_num_table *tabp;
  34        char this_bank, bank_name, irregular_bank_name;
  35        char *endp;
  36
  37        /*
  38         * The gpio name starts with either 'g' or 'gp' followed by the bank
  39         * name character. Skip one or two characters depending on the prefix.
  40         */
  41        if (name[0] == 'g' && name[1] == 'p')
  42                name += 2;
  43        else if (name[0] == 'g')
  44                name++;
  45        else
  46                return -1; /* Name must start with 'g' */
  47
  48        bank_name = *name++;
  49        if (!*name)
  50                return -1; /* At least one digit is required/expected. */
  51
  52        /*
  53         * On both exynos5 and exynos5420 architectures there is a bank of
  54         * GPIOs which does not fall into the regular address pattern. Those
  55         * banks are c4 on Exynos5 and y7 on Exynos5420. The rest of the below
  56         * assignments help to handle these irregularities.
  57         */
  58#if defined(CONFIG_EXYNOS4) || defined(CONFIG_EXYNOS5)
  59        if (cpu_is_exynos5()) {
  60                if (proid_is_exynos5420()) {
  61                        tabp = exynos5420_gpio_table;
  62                        irregular_bank_name = 'y';
  63                        irregular_set_number = '7';
  64                        irregular_bank_base = EXYNOS5420_GPIO_Y70;
  65                } else {
  66                        tabp = exynos5_gpio_table;
  67                        irregular_bank_name = 'c';
  68                        irregular_set_number = '4';
  69                        irregular_bank_base = EXYNOS5_GPIO_C40;
  70                }
  71        } else {
  72                if (proid_is_exynos4412())
  73                        tabp = exynos4x12_gpio_table;
  74                else
  75                        tabp = exynos4_gpio_table;
  76                irregular_bank_name = 0;
  77                irregular_set_number = 0;
  78                irregular_bank_base = 0;
  79        }
  80#else
  81        if (cpu_is_s5pc110())
  82                tabp = s5pc110_gpio_table;
  83        else
  84                tabp = s5pc100_gpio_table;
  85        irregular_bank_name = 0;
  86        irregular_set_number = 0;
  87        irregular_bank_base = 0;
  88#endif
  89
  90        this_bank = tabp->bank;
  91        do {
  92                if (bank_name == this_bank) {
  93                        unsigned pin_index; /* pin number within the bank */
  94                        if ((bank_name == irregular_bank_name) &&
  95                            (name[0] == irregular_set_number)) {
  96                                pin_index = name[1] - '0';
  97                                /* Irregular sets have 8 pins. */
  98                                if (pin_index >= GPIO_PER_BANK)
  99                                        return -1;
 100                                num = irregular_bank_base + pin_index;
 101                        } else {
 102                                pin_index = simple_strtoul(name, &endp, 8);
 103                                pin_index -= tabp->bank_offset;
 104                                /*
 105                                 * Sanity check: bunk 'z' has no set number,
 106                                 * for all other banks there must be exactly
 107                                 * two octal digits, and the resulting number
 108                                 * should not exceed the number of pins in the
 109                                 * bank.
 110                                 */
 111                                if (((bank_name != 'z') && !name[1]) ||
 112                                    *endp ||
 113                                    (pin_index >= tabp->bank_size))
 114                                        return -1;
 115                                num = tabp->base + pin_index;
 116                        }
 117                        return num;
 118                }
 119                this_bank = (++tabp)->bank;
 120        } while (this_bank);
 121
 122        return -1;
 123}
 124
 125static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
 126{
 127        unsigned int value;
 128
 129        value = readl(&bank->con);
 130        value &= ~CON_MASK(gpio);
 131        value |= CON_SFR(gpio, cfg);
 132        writel(value, &bank->con);
 133}
 134
 135static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
 136{
 137        unsigned int value;
 138
 139        value = readl(&bank->dat);
 140        value &= ~DAT_MASK(gpio);
 141        if (en)
 142                value |= DAT_SET(gpio);
 143        writel(value, &bank->dat);
 144}
 145
 146static void s5p_gpio_direction_output(struct s5p_gpio_bank *bank,
 147                                      int gpio, int en)
 148{
 149        s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_OUTPUT);
 150        s5p_gpio_set_value(bank, gpio, en);
 151}
 152
 153static void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
 154{
 155        s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_INPUT);
 156}
 157
 158static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
 159{
 160        unsigned int value;
 161
 162        value = readl(&bank->dat);
 163        return !!(value & DAT_MASK(gpio));
 164}
 165
 166static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
 167{
 168        unsigned int value;
 169
 170        value = readl(&bank->pull);
 171        value &= ~PULL_MASK(gpio);
 172
 173        switch (mode) {
 174        case S5P_GPIO_PULL_DOWN:
 175        case S5P_GPIO_PULL_UP:
 176                value |= PULL_MODE(gpio, mode);
 177                break;
 178        default:
 179                break;
 180        }
 181
 182        writel(value, &bank->pull);
 183}
 184
 185static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
 186{
 187        unsigned int value;
 188
 189        value = readl(&bank->drv);
 190        value &= ~DRV_MASK(gpio);
 191
 192        switch (mode) {
 193        case S5P_GPIO_DRV_1X:
 194        case S5P_GPIO_DRV_2X:
 195        case S5P_GPIO_DRV_3X:
 196        case S5P_GPIO_DRV_4X:
 197                value |= DRV_SET(gpio, mode);
 198                break;
 199        default:
 200                return;
 201        }
 202
 203        writel(value, &bank->drv);
 204}
 205
 206static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
 207{
 208        unsigned int value;
 209
 210        value = readl(&bank->drv);
 211        value &= ~RATE_MASK(gpio);
 212
 213        switch (mode) {
 214        case S5P_GPIO_DRV_FAST:
 215        case S5P_GPIO_DRV_SLOW:
 216                value |= RATE_SET(gpio);
 217                break;
 218        default:
 219                return;
 220        }
 221
 222        writel(value, &bank->drv);
 223}
 224
 225struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
 226{
 227        const struct gpio_info *data;
 228        unsigned int upto;
 229        int i, count;
 230
 231        data = get_gpio_data();
 232        count = get_bank_num();
 233        upto = 0;
 234
 235        for (i = 0; i < count; i++) {
 236                debug("i=%d, upto=%d\n", i, upto);
 237                if (gpio < data->max_gpio) {
 238                        struct s5p_gpio_bank *bank;
 239                        bank = (struct s5p_gpio_bank *)data->reg_addr;
 240                        bank += (gpio - upto) / GPIO_PER_BANK;
 241                        debug("gpio=%d, bank=%p\n", gpio, bank);
 242                        return bank;
 243                }
 244
 245                upto = data->max_gpio;
 246                data++;
 247        }
 248
 249        return NULL;
 250}
 251
 252int s5p_gpio_get_pin(unsigned gpio)
 253{
 254        return S5P_GPIO_GET_PIN(gpio);
 255}
 256
 257/* Common GPIO API */
 258
 259int gpio_request(unsigned gpio, const char *label)
 260{
 261        return 0;
 262}
 263
 264int gpio_free(unsigned gpio)
 265{
 266        return 0;
 267}
 268
 269int gpio_direction_input(unsigned gpio)
 270{
 271        s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
 272                                s5p_gpio_get_pin(gpio));
 273        return 0;
 274}
 275
 276int gpio_direction_output(unsigned gpio, int value)
 277{
 278        s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
 279                                 s5p_gpio_get_pin(gpio), value);
 280        return 0;
 281}
 282
 283int gpio_get_value(unsigned gpio)
 284{
 285        return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
 286                                       s5p_gpio_get_pin(gpio));
 287}
 288
 289int gpio_set_value(unsigned gpio, int value)
 290{
 291        s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
 292                          s5p_gpio_get_pin(gpio), value);
 293
 294        return 0;
 295}
 296
 297void gpio_set_pull(int gpio, int mode)
 298{
 299        s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
 300                          s5p_gpio_get_pin(gpio), mode);
 301}
 302
 303void gpio_set_drv(int gpio, int mode)
 304{
 305        s5p_gpio_set_drv(s5p_gpio_get_bank(gpio),
 306                         s5p_gpio_get_pin(gpio), mode);
 307}
 308
 309void gpio_cfg_pin(int gpio, int cfg)
 310{
 311        s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio),
 312                         s5p_gpio_get_pin(gpio), cfg);
 313}
 314
 315void gpio_set_rate(int gpio, int mode)
 316{
 317        s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
 318                          s5p_gpio_get_pin(gpio), mode);
 319}
 320