uboot/drivers/gpio/omap_gpio.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2009 Wind River Systems, Inc.
   3 * Tom Rix <Tom.Rix@windriver.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0
   6 *
   7 * This work is derived from the linux 2.6.27 kernel source
   8 * To fetch, use the kernel repository
   9 * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
  10 * Use the v2.6.27 tag.
  11 *
  12 * Below is the original's header including its copyright
  13 *
  14 *  linux/arch/arm/plat-omap/gpio.c
  15 *
  16 * Support functions for OMAP GPIO
  17 *
  18 * Copyright (C) 2003-2005 Nokia Corporation
  19 * Written by Juha Yrjölä <juha.yrjola@nokia.com>
  20 */
  21#include <common.h>
  22#include <dm.h>
  23#include <fdtdec.h>
  24#include <asm/gpio.h>
  25#include <asm/io.h>
  26#include <linux/errno.h>
  27#include <malloc.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31#define OMAP_GPIO_DIR_OUT       0
  32#define OMAP_GPIO_DIR_IN        1
  33
  34#ifdef CONFIG_DM_GPIO
  35
  36#define GPIO_PER_BANK                   32
  37
  38struct gpio_bank {
  39        /* TODO(sjg@chromium.org): Can we use a struct here? */
  40        void *base;     /* address of registers in physical memory */
  41};
  42
  43#endif
  44
  45static inline int get_gpio_index(int gpio)
  46{
  47        return gpio & 0x1f;
  48}
  49
  50int gpio_is_valid(int gpio)
  51{
  52        return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
  53}
  54
  55static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
  56                                int is_input)
  57{
  58        void *reg = bank->base;
  59        u32 l;
  60
  61        reg += OMAP_GPIO_OE;
  62
  63        l = __raw_readl(reg);
  64        if (is_input)
  65                l |= 1 << gpio;
  66        else
  67                l &= ~(1 << gpio);
  68        __raw_writel(l, reg);
  69}
  70
  71/**
  72 * Get the direction of the GPIO by reading the GPIO_OE register
  73 * corresponding to the specified bank.
  74 */
  75static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
  76{
  77        void *reg = bank->base;
  78        u32 v;
  79
  80        reg += OMAP_GPIO_OE;
  81
  82        v = __raw_readl(reg);
  83
  84        if (v & (1 << gpio))
  85                return OMAP_GPIO_DIR_IN;
  86        else
  87                return OMAP_GPIO_DIR_OUT;
  88}
  89
  90static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
  91                                int enable)
  92{
  93        void *reg = bank->base;
  94        u32 l = 0;
  95
  96        if (enable)
  97                reg += OMAP_GPIO_SETDATAOUT;
  98        else
  99                reg += OMAP_GPIO_CLEARDATAOUT;
 100
 101        l = 1 << gpio;
 102        __raw_writel(l, reg);
 103}
 104
 105static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
 106{
 107        void *reg = bank->base;
 108        int input;
 109
 110        input = _get_gpio_direction(bank, gpio);
 111        switch (input) {
 112        case OMAP_GPIO_DIR_IN:
 113                reg += OMAP_GPIO_DATAIN;
 114                break;
 115        case OMAP_GPIO_DIR_OUT:
 116                reg += OMAP_GPIO_DATAOUT;
 117                break;
 118        default:
 119                return -1;
 120        }
 121
 122        return (__raw_readl(reg) & (1 << gpio)) != 0;
 123}
 124
 125#ifndef CONFIG_DM_GPIO
 126
 127static inline const struct gpio_bank *get_gpio_bank(int gpio)
 128{
 129        return &omap_gpio_bank[gpio >> 5];
 130}
 131
 132static int check_gpio(int gpio)
 133{
 134        if (!gpio_is_valid(gpio)) {
 135                printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
 136                return -1;
 137        }
 138        return 0;
 139}
 140
 141/**
 142 * Set value of the specified gpio
 143 */
 144int gpio_set_value(unsigned gpio, int value)
 145{
 146        const struct gpio_bank *bank;
 147
 148        if (check_gpio(gpio) < 0)
 149                return -1;
 150        bank = get_gpio_bank(gpio);
 151        _set_gpio_dataout(bank, get_gpio_index(gpio), value);
 152
 153        return 0;
 154}
 155
 156/**
 157 * Get value of the specified gpio
 158 */
 159int gpio_get_value(unsigned gpio)
 160{
 161        const struct gpio_bank *bank;
 162
 163        if (check_gpio(gpio) < 0)
 164                return -1;
 165        bank = get_gpio_bank(gpio);
 166
 167        return _get_gpio_value(bank, get_gpio_index(gpio));
 168}
 169
 170/**
 171 * Set gpio direction as input
 172 */
 173int gpio_direction_input(unsigned gpio)
 174{
 175        const struct gpio_bank *bank;
 176
 177        if (check_gpio(gpio) < 0)
 178                return -1;
 179
 180        bank = get_gpio_bank(gpio);
 181        _set_gpio_direction(bank, get_gpio_index(gpio), 1);
 182
 183        return 0;
 184}
 185
 186/**
 187 * Set gpio direction as output
 188 */
 189int gpio_direction_output(unsigned gpio, int value)
 190{
 191        const struct gpio_bank *bank;
 192
 193        if (check_gpio(gpio) < 0)
 194                return -1;
 195
 196        bank = get_gpio_bank(gpio);
 197        _set_gpio_dataout(bank, get_gpio_index(gpio), value);
 198        _set_gpio_direction(bank, get_gpio_index(gpio), 0);
 199
 200        return 0;
 201}
 202
 203/**
 204 * Request a gpio before using it.
 205 *
 206 * NOTE: Argument 'label' is unused.
 207 */
 208int gpio_request(unsigned gpio, const char *label)
 209{
 210        if (check_gpio(gpio) < 0)
 211                return -1;
 212
 213        return 0;
 214}
 215
 216/**
 217 * Reset and free the gpio after using it.
 218 */
 219int gpio_free(unsigned gpio)
 220{
 221        return 0;
 222}
 223
 224#else /* new driver model interface CONFIG_DM_GPIO */
 225
 226/* set GPIO pin 'gpio' as an input */
 227static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
 228{
 229        struct gpio_bank *bank = dev_get_priv(dev);
 230
 231        /* Configure GPIO direction as input. */
 232        _set_gpio_direction(bank, offset, 1);
 233
 234        return 0;
 235}
 236
 237/* set GPIO pin 'gpio' as an output, with polarity 'value' */
 238static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
 239                                       int value)
 240{
 241        struct gpio_bank *bank = dev_get_priv(dev);
 242
 243        _set_gpio_dataout(bank, offset, value);
 244        _set_gpio_direction(bank, offset, 0);
 245
 246        return 0;
 247}
 248
 249/* read GPIO IN value of pin 'gpio' */
 250static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
 251{
 252        struct gpio_bank *bank = dev_get_priv(dev);
 253
 254        return _get_gpio_value(bank, offset);
 255}
 256
 257/* write GPIO OUT value to pin 'gpio' */
 258static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
 259                                 int value)
 260{
 261        struct gpio_bank *bank = dev_get_priv(dev);
 262
 263        _set_gpio_dataout(bank, offset, value);
 264
 265        return 0;
 266}
 267
 268static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
 269{
 270        struct gpio_bank *bank = dev_get_priv(dev);
 271
 272        /* GPIOF_FUNC is not implemented yet */
 273        if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT)
 274                return GPIOF_OUTPUT;
 275        else
 276                return GPIOF_INPUT;
 277}
 278
 279static const struct dm_gpio_ops gpio_omap_ops = {
 280        .direction_input        = omap_gpio_direction_input,
 281        .direction_output       = omap_gpio_direction_output,
 282        .get_value              = omap_gpio_get_value,
 283        .set_value              = omap_gpio_set_value,
 284        .get_function           = omap_gpio_get_function,
 285};
 286
 287static int omap_gpio_probe(struct udevice *dev)
 288{
 289        struct gpio_bank *bank = dev_get_priv(dev);
 290        struct omap_gpio_platdata *plat = dev_get_platdata(dev);
 291        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 292
 293        uc_priv->bank_name = plat->port_name;
 294        uc_priv->gpio_count = GPIO_PER_BANK;
 295        bank->base = (void *)plat->base;
 296
 297        return 0;
 298}
 299
 300static int omap_gpio_bind(struct udevice *dev)
 301{
 302        struct omap_gpio_platdata *plat = dev_get_platdata(dev);
 303        fdt_addr_t base_addr;
 304
 305        if (plat)
 306                return 0;
 307
 308        base_addr = devfdt_get_addr(dev);
 309        if (base_addr == FDT_ADDR_T_NONE)
 310                return -EINVAL;
 311
 312        /*
 313        * TODO:
 314        * When every board is converted to driver model and DT is
 315        * supported, this can be done by auto-alloc feature, but
 316        * not using calloc to alloc memory for platdata.
 317        *
 318        * For example am33xx_gpio uses platform data rather than device tree.
 319        *
 320        * NOTE: DO NOT COPY this code if you are using device tree.
 321        */
 322        plat = calloc(1, sizeof(*plat));
 323        if (!plat)
 324                return -ENOMEM;
 325
 326        plat->base = base_addr;
 327        plat->port_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL);
 328        dev->platdata = plat;
 329
 330        return 0;
 331}
 332
 333static const struct udevice_id omap_gpio_ids[] = {
 334        { .compatible = "ti,omap3-gpio" },
 335        { .compatible = "ti,omap4-gpio" },
 336        { .compatible = "ti,am4372-gpio" },
 337        { }
 338};
 339
 340U_BOOT_DRIVER(gpio_omap) = {
 341        .name   = "gpio_omap",
 342        .id     = UCLASS_GPIO,
 343        .ops    = &gpio_omap_ops,
 344        .of_match = omap_gpio_ids,
 345        .bind   = omap_gpio_bind,
 346        .probe  = omap_gpio_probe,
 347        .priv_auto_alloc_size = sizeof(struct gpio_bank),
 348};
 349
 350#endif /* CONFIG_DM_GPIO */
 351