uboot/drivers/gpio/mxc_gpio.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009
   3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
   4 *
   5 * Copyright (C) 2011
   6 * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10#include <common.h>
  11#include <errno.h>
  12#include <dm.h>
  13#include <malloc.h>
  14#include <asm/arch/imx-regs.h>
  15#include <asm/gpio.h>
  16#include <asm/io.h>
  17
  18enum mxc_gpio_direction {
  19        MXC_GPIO_DIRECTION_IN,
  20        MXC_GPIO_DIRECTION_OUT,
  21};
  22
  23#define GPIO_PER_BANK                   32
  24
  25struct mxc_gpio_plat {
  26        int bank_index;
  27        struct gpio_regs *regs;
  28};
  29
  30struct mxc_bank_info {
  31        struct gpio_regs *regs;
  32};
  33
  34#ifndef CONFIG_DM_GPIO
  35#define GPIO_TO_PORT(n)         (n / 32)
  36
  37/* GPIO port description */
  38static unsigned long gpio_ports[] = {
  39        [0] = GPIO1_BASE_ADDR,
  40        [1] = GPIO2_BASE_ADDR,
  41        [2] = GPIO3_BASE_ADDR,
  42#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
  43                defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
  44                defined(CONFIG_MX7)
  45        [3] = GPIO4_BASE_ADDR,
  46#endif
  47#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
  48                defined(CONFIG_MX7)
  49        [4] = GPIO5_BASE_ADDR,
  50#ifndef CONFIG_MX6UL
  51        [5] = GPIO6_BASE_ADDR,
  52#endif
  53#endif
  54#if defined(CONFIG_MX53) || defined(CONFIG_MX6) || defined(CONFIG_MX7)
  55#ifndef CONFIG_MX6UL
  56        [6] = GPIO7_BASE_ADDR,
  57#endif
  58#endif
  59};
  60
  61static int mxc_gpio_direction(unsigned int gpio,
  62        enum mxc_gpio_direction direction)
  63{
  64        unsigned int port = GPIO_TO_PORT(gpio);
  65        struct gpio_regs *regs;
  66        u32 l;
  67
  68        if (port >= ARRAY_SIZE(gpio_ports))
  69                return -1;
  70
  71        gpio &= 0x1f;
  72
  73        regs = (struct gpio_regs *)gpio_ports[port];
  74
  75        l = readl(&regs->gpio_dir);
  76
  77        switch (direction) {
  78        case MXC_GPIO_DIRECTION_OUT:
  79                l |= 1 << gpio;
  80                break;
  81        case MXC_GPIO_DIRECTION_IN:
  82                l &= ~(1 << gpio);
  83        }
  84        writel(l, &regs->gpio_dir);
  85
  86        return 0;
  87}
  88
  89int gpio_set_value(unsigned gpio, int value)
  90{
  91        unsigned int port = GPIO_TO_PORT(gpio);
  92        struct gpio_regs *regs;
  93        u32 l;
  94
  95        if (port >= ARRAY_SIZE(gpio_ports))
  96                return -1;
  97
  98        gpio &= 0x1f;
  99
 100        regs = (struct gpio_regs *)gpio_ports[port];
 101
 102        l = readl(&regs->gpio_dr);
 103        if (value)
 104                l |= 1 << gpio;
 105        else
 106                l &= ~(1 << gpio);
 107        writel(l, &regs->gpio_dr);
 108
 109        return 0;
 110}
 111
 112int gpio_get_value(unsigned gpio)
 113{
 114        unsigned int port = GPIO_TO_PORT(gpio);
 115        struct gpio_regs *regs;
 116        u32 val;
 117
 118        if (port >= ARRAY_SIZE(gpio_ports))
 119                return -1;
 120
 121        gpio &= 0x1f;
 122
 123        regs = (struct gpio_regs *)gpio_ports[port];
 124
 125        val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
 126
 127        return val;
 128}
 129
 130int gpio_request(unsigned gpio, const char *label)
 131{
 132        unsigned int port = GPIO_TO_PORT(gpio);
 133        if (port >= ARRAY_SIZE(gpio_ports))
 134                return -1;
 135        return 0;
 136}
 137
 138int gpio_free(unsigned gpio)
 139{
 140        return 0;
 141}
 142
 143int gpio_direction_input(unsigned gpio)
 144{
 145        return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
 146}
 147
 148int gpio_direction_output(unsigned gpio, int value)
 149{
 150        int ret = gpio_set_value(gpio, value);
 151
 152        if (ret < 0)
 153                return ret;
 154
 155        return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
 156}
 157#endif
 158
 159#ifdef CONFIG_DM_GPIO
 160#include <fdtdec.h>
 161DECLARE_GLOBAL_DATA_PTR;
 162
 163static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
 164{
 165        u32 val;
 166
 167        val = readl(&regs->gpio_dir);
 168
 169        return val & (1 << offset) ? 1 : 0;
 170}
 171
 172static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
 173                                    enum mxc_gpio_direction direction)
 174{
 175        u32 l;
 176
 177        l = readl(&regs->gpio_dir);
 178
 179        switch (direction) {
 180        case MXC_GPIO_DIRECTION_OUT:
 181                l |= 1 << offset;
 182                break;
 183        case MXC_GPIO_DIRECTION_IN:
 184                l &= ~(1 << offset);
 185        }
 186        writel(l, &regs->gpio_dir);
 187}
 188
 189static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
 190                                    int value)
 191{
 192        u32 l;
 193
 194        l = readl(&regs->gpio_dr);
 195        if (value)
 196                l |= 1 << offset;
 197        else
 198                l &= ~(1 << offset);
 199        writel(l, &regs->gpio_dr);
 200}
 201
 202static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
 203{
 204        return (readl(&regs->gpio_psr) >> offset) & 0x01;
 205}
 206
 207/* set GPIO pin 'gpio' as an input */
 208static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
 209{
 210        struct mxc_bank_info *bank = dev_get_priv(dev);
 211
 212        /* Configure GPIO direction as input. */
 213        mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
 214
 215        return 0;
 216}
 217
 218/* set GPIO pin 'gpio' as an output, with polarity 'value' */
 219static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
 220                                       int value)
 221{
 222        struct mxc_bank_info *bank = dev_get_priv(dev);
 223
 224        /* Configure GPIO output value. */
 225        mxc_gpio_bank_set_value(bank->regs, offset, value);
 226
 227        /* Configure GPIO direction as output. */
 228        mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
 229
 230        return 0;
 231}
 232
 233/* read GPIO IN value of pin 'gpio' */
 234static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
 235{
 236        struct mxc_bank_info *bank = dev_get_priv(dev);
 237
 238        return mxc_gpio_bank_get_value(bank->regs, offset);
 239}
 240
 241/* write GPIO OUT value to pin 'gpio' */
 242static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
 243                                 int value)
 244{
 245        struct mxc_bank_info *bank = dev_get_priv(dev);
 246
 247        mxc_gpio_bank_set_value(bank->regs, offset, value);
 248
 249        return 0;
 250}
 251
 252static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
 253{
 254        struct mxc_bank_info *bank = dev_get_priv(dev);
 255
 256        /* GPIOF_FUNC is not implemented yet */
 257        if (mxc_gpio_is_output(bank->regs, offset))
 258                return GPIOF_OUTPUT;
 259        else
 260                return GPIOF_INPUT;
 261}
 262
 263static const struct dm_gpio_ops gpio_mxc_ops = {
 264        .direction_input        = mxc_gpio_direction_input,
 265        .direction_output       = mxc_gpio_direction_output,
 266        .get_value              = mxc_gpio_get_value,
 267        .set_value              = mxc_gpio_set_value,
 268        .get_function           = mxc_gpio_get_function,
 269};
 270
 271static int mxc_gpio_probe(struct udevice *dev)
 272{
 273        struct mxc_bank_info *bank = dev_get_priv(dev);
 274        struct mxc_gpio_plat *plat = dev_get_platdata(dev);
 275        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 276        int banknum;
 277        char name[18], *str;
 278
 279        banknum = plat->bank_index;
 280        sprintf(name, "GPIO%d_", banknum + 1);
 281        str = strdup(name);
 282        if (!str)
 283                return -ENOMEM;
 284        uc_priv->bank_name = str;
 285        uc_priv->gpio_count = GPIO_PER_BANK;
 286        bank->regs = plat->regs;
 287
 288        return 0;
 289}
 290
 291static int mxc_gpio_bind(struct udevice *dev)
 292{
 293        struct mxc_gpio_plat *plat = dev->platdata;
 294        fdt_addr_t addr;
 295
 296        /*
 297         * If platdata already exsits, directly return.
 298         * Actually only when DT is not supported, platdata
 299         * is statically initialized in U_BOOT_DEVICES.Here
 300         * will return.
 301         */
 302        if (plat)
 303                return 0;
 304
 305        addr = dev_get_addr(dev);
 306        if (addr == FDT_ADDR_T_NONE)
 307                return -ENODEV;
 308
 309        /*
 310         * TODO:
 311         * When every board is converted to driver model and DT is supported,
 312         * this can be done by auto-alloc feature, but not using calloc
 313         * to alloc memory for platdata.
 314         */
 315        plat = calloc(1, sizeof(*plat));
 316        if (!plat)
 317                return -ENOMEM;
 318
 319        plat->regs = (struct gpio_regs *)addr;
 320        plat->bank_index = dev->req_seq;
 321        dev->platdata = plat;
 322
 323        return 0;
 324}
 325
 326static const struct udevice_id mxc_gpio_ids[] = {
 327        { .compatible = "fsl,imx35-gpio" },
 328        { }
 329};
 330
 331U_BOOT_DRIVER(gpio_mxc) = {
 332        .name   = "gpio_mxc",
 333        .id     = UCLASS_GPIO,
 334        .ops    = &gpio_mxc_ops,
 335        .probe  = mxc_gpio_probe,
 336        .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
 337        .of_match = mxc_gpio_ids,
 338        .bind   = mxc_gpio_bind,
 339};
 340
 341#if !CONFIG_IS_ENABLED(OF_CONTROL)
 342static const struct mxc_gpio_plat mxc_plat[] = {
 343        { 0, (struct gpio_regs *)GPIO1_BASE_ADDR },
 344        { 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
 345        { 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
 346#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
 347                defined(CONFIG_MX53) || defined(CONFIG_MX6)
 348        { 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
 349#endif
 350#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
 351        { 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
 352        { 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
 353#endif
 354#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
 355        { 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
 356#endif
 357};
 358
 359U_BOOT_DEVICES(mxc_gpios) = {
 360        { "gpio_mxc", &mxc_plat[0] },
 361        { "gpio_mxc", &mxc_plat[1] },
 362        { "gpio_mxc", &mxc_plat[2] },
 363#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
 364                defined(CONFIG_MX53) || defined(CONFIG_MX6)
 365        { "gpio_mxc", &mxc_plat[3] },
 366#endif
 367#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
 368        { "gpio_mxc", &mxc_plat[4] },
 369        { "gpio_mxc", &mxc_plat[5] },
 370#endif
 371#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
 372        { "gpio_mxc", &mxc_plat[6] },
 373#endif
 374};
 375#endif
 376#endif
 377