uboot/drivers/gpio/mxs_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Freescale i.MX28 GPIO control code
   4 *
   5 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
   6 * on behalf of DENX Software Engineering GmbH
   7 */
   8
   9#include <common.h>
  10#include <log.h>
  11#include <malloc.h>
  12#include <linux/bitops.h>
  13#include <linux/errno.h>
  14#include <asm/io.h>
  15#include <asm/arch/iomux.h>
  16#include <asm/arch/imx-regs.h>
  17
  18#if     defined(CONFIG_MX23)
  19#define PINCTRL_BANKS           3
  20#define PINCTRL_DOUT(n)         (0x0500 + ((n) * 0x10))
  21#define PINCTRL_DIN(n)          (0x0600 + ((n) * 0x10))
  22#define PINCTRL_DOE(n)          (0x0700 + ((n) * 0x10))
  23#define PINCTRL_PIN2IRQ(n)      (0x0800 + ((n) * 0x10))
  24#define PINCTRL_IRQEN(n)        (0x0900 + ((n) * 0x10))
  25#define PINCTRL_IRQSTAT(n)      (0x0c00 + ((n) * 0x10))
  26#elif   defined(CONFIG_MX28)
  27#define PINCTRL_BANKS           5
  28#define PINCTRL_DOUT(n)         (0x0700 + ((n) * 0x10))
  29#define PINCTRL_DIN(n)          (0x0900 + ((n) * 0x10))
  30#define PINCTRL_DOE(n)          (0x0b00 + ((n) * 0x10))
  31#define PINCTRL_PIN2IRQ(n)      (0x1000 + ((n) * 0x10))
  32#define PINCTRL_IRQEN(n)        (0x1100 + ((n) * 0x10))
  33#define PINCTRL_IRQSTAT(n)      (0x1400 + ((n) * 0x10))
  34#else
  35#error "Please select CONFIG_MX23 or CONFIG_MX28"
  36#endif
  37
  38#define GPIO_INT_FALL_EDGE      0x0
  39#define GPIO_INT_LOW_LEV        0x1
  40#define GPIO_INT_RISE_EDGE      0x2
  41#define GPIO_INT_HIGH_LEV       0x3
  42#define GPIO_INT_LEV_MASK       (1 << 0)
  43#define GPIO_INT_POL_MASK       (1 << 1)
  44
  45void mxs_gpio_init(void)
  46{
  47        int i;
  48
  49        for (i = 0; i < PINCTRL_BANKS; i++) {
  50                writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
  51                writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
  52                /* Use SCT address here to clear the IRQSTAT bits */
  53                writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
  54        }
  55}
  56
  57#if !CONFIG_IS_ENABLED(DM_GPIO)
  58int gpio_get_value(unsigned gpio)
  59{
  60        uint32_t bank = PAD_BANK(gpio);
  61        uint32_t offset = PINCTRL_DIN(bank);
  62        struct mxs_register_32 *reg =
  63                (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
  64
  65        return (readl(&reg->reg) >> PAD_PIN(gpio)) & 1;
  66}
  67
  68void gpio_set_value(unsigned gpio, int value)
  69{
  70        uint32_t bank = PAD_BANK(gpio);
  71        uint32_t offset = PINCTRL_DOUT(bank);
  72        struct mxs_register_32 *reg =
  73                (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
  74
  75        if (value)
  76                writel(1 << PAD_PIN(gpio), &reg->reg_set);
  77        else
  78                writel(1 << PAD_PIN(gpio), &reg->reg_clr);
  79}
  80
  81int gpio_direction_input(unsigned gpio)
  82{
  83        uint32_t bank = PAD_BANK(gpio);
  84        uint32_t offset = PINCTRL_DOE(bank);
  85        struct mxs_register_32 *reg =
  86                (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
  87
  88        writel(1 << PAD_PIN(gpio), &reg->reg_clr);
  89
  90        return 0;
  91}
  92
  93int gpio_direction_output(unsigned gpio, int value)
  94{
  95        uint32_t bank = PAD_BANK(gpio);
  96        uint32_t offset = PINCTRL_DOE(bank);
  97        struct mxs_register_32 *reg =
  98                (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
  99
 100        gpio_set_value(gpio, value);
 101
 102        writel(1 << PAD_PIN(gpio), &reg->reg_set);
 103
 104        return 0;
 105}
 106
 107int gpio_request(unsigned gpio, const char *label)
 108{
 109        if (PAD_BANK(gpio) >= PINCTRL_BANKS)
 110                return -1;
 111
 112        return 0;
 113}
 114
 115int gpio_free(unsigned gpio)
 116{
 117        return 0;
 118}
 119
 120int name_to_gpio(const char *name)
 121{
 122        unsigned bank, pin;
 123        char *end;
 124
 125        bank = simple_strtoul(name, &end, 10);
 126
 127        if (!*end || *end != ':')
 128                return bank;
 129
 130        pin = simple_strtoul(end + 1, NULL, 10);
 131
 132        return (bank << MXS_PAD_BANK_SHIFT) | (pin << MXS_PAD_PIN_SHIFT);
 133}
 134#else /* DM_GPIO */
 135#include <dm.h>
 136#include <asm/gpio.h>
 137#include <dt-structs.h>
 138#include <asm/arch/gpio.h>
 139#define MXS_MAX_GPIO_PER_BANK           32
 140
 141DECLARE_GLOBAL_DATA_PTR;
 142/*
 143 * According to i.MX28 Reference Manual:
 144 * 'i.MX28 Applications Processor Reference Manual, Rev. 1, 2010'
 145 * The i.MX28 has following number of GPIOs available:
 146 * Bank 0: 0-28 -> 29 PINS
 147 * Bank 1: 0-31 -> 32 PINS
 148 * Bank 2: 0-27 -> 28 PINS
 149 * Bank 3: 0-30 -> 31 PINS
 150 * Bank 4: 0-20 -> 21 PINS
 151 */
 152
 153struct mxs_gpio_platdata {
 154#if CONFIG_IS_ENABLED(OF_PLATDATA)
 155        struct dtd_fsl_imx23_gpio dtplat;
 156#endif
 157        unsigned int bank;
 158        int gpio_ranges;
 159};
 160
 161struct mxs_gpio_priv {
 162        unsigned int bank;
 163};
 164
 165static int mxs_gpio_get_value(struct udevice *dev, unsigned offset)
 166{
 167        struct mxs_gpio_priv *priv = dev_get_priv(dev);
 168        struct mxs_register_32 *reg =
 169                (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
 170                                           PINCTRL_DIN(priv->bank));
 171
 172        return (readl(&reg->reg) >> offset) & 1;
 173}
 174
 175static int mxs_gpio_set_value(struct udevice *dev, unsigned offset,
 176                              int value)
 177{
 178        struct mxs_gpio_priv *priv = dev_get_priv(dev);
 179        struct mxs_register_32 *reg =
 180                (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
 181                                           PINCTRL_DOUT(priv->bank));
 182        if (value)
 183                writel(BIT(offset), &reg->reg_set);
 184        else
 185                writel(BIT(offset), &reg->reg_clr);
 186
 187        return 0;
 188}
 189
 190static int mxs_gpio_direction_input(struct udevice *dev, unsigned offset)
 191{
 192        struct mxs_gpio_priv *priv = dev_get_priv(dev);
 193        struct mxs_register_32 *reg =
 194                (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
 195                                           PINCTRL_DOE(priv->bank));
 196
 197        writel(BIT(offset), &reg->reg_clr);
 198
 199        return 0;
 200}
 201
 202static int mxs_gpio_direction_output(struct udevice *dev, unsigned offset,
 203                                     int value)
 204{
 205        struct mxs_gpio_priv *priv = dev_get_priv(dev);
 206        struct mxs_register_32 *reg =
 207                (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
 208                                           PINCTRL_DOE(priv->bank));
 209
 210        mxs_gpio_set_value(dev, offset, value);
 211
 212        writel(BIT(offset), &reg->reg_set);
 213
 214        return 0;
 215}
 216
 217static int mxs_gpio_get_function(struct udevice *dev, unsigned offset)
 218{
 219        struct mxs_gpio_priv *priv = dev_get_priv(dev);
 220        struct mxs_register_32 *reg =
 221                (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
 222                                           PINCTRL_DOE(priv->bank));
 223        bool is_output = !!(readl(&reg->reg) >> offset);
 224
 225        return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
 226}
 227
 228static const struct dm_gpio_ops gpio_mxs_ops = {
 229        .direction_input        = mxs_gpio_direction_input,
 230        .direction_output       = mxs_gpio_direction_output,
 231        .get_value              = mxs_gpio_get_value,
 232        .set_value              = mxs_gpio_set_value,
 233        .get_function           = mxs_gpio_get_function,
 234};
 235
 236static int mxs_gpio_probe(struct udevice *dev)
 237{
 238        struct mxs_gpio_platdata *plat = dev_get_platdata(dev);
 239        struct mxs_gpio_priv *priv = dev_get_priv(dev);
 240        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 241        char name[16], *str;
 242
 243#if CONFIG_IS_ENABLED(OF_PLATDATA)
 244        struct dtd_fsl_imx23_gpio *dtplat = &plat->dtplat;
 245        priv->bank = (unsigned int)dtplat->reg[0];
 246        uc_priv->gpio_count = dtplat->gpio_ranges[3];
 247#else
 248        priv->bank = (unsigned int)plat->bank;
 249        uc_priv->gpio_count = plat->gpio_ranges;
 250#endif
 251        snprintf(name, sizeof(name), "GPIO%d_", priv->bank);
 252        str = strdup(name);
 253        if (!str)
 254                return -ENOMEM;
 255
 256        uc_priv->bank_name = str;
 257
 258        debug("%s: %s: %d pins base: 0x%x\n", __func__, uc_priv->bank_name,
 259              uc_priv->gpio_count, priv->bank);
 260
 261        return 0;
 262}
 263
 264#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 265static int mxs_ofdata_to_platdata(struct udevice *dev)
 266{
 267        struct mxs_gpio_platdata *plat = dev->platdata;
 268        struct fdtdec_phandle_args args;
 269        int node = dev_of_offset(dev);
 270        int ret;
 271
 272        plat->bank = dev_read_addr(dev);
 273        if (plat->bank == FDT_ADDR_T_NONE) {
 274                printf("%s: No 'reg' property defined!\n", __func__);
 275                return -EINVAL;
 276        }
 277
 278        ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node, "gpio-ranges",
 279                                             NULL, 3, 0, &args);
 280        if (ret)
 281                printf("%s: 'gpio-ranges' not defined - using default!\n",
 282                       __func__);
 283
 284        plat->gpio_ranges = ret == 0 ? args.args[2] : MXS_MAX_GPIO_PER_BANK;
 285
 286        return 0;
 287}
 288
 289static const struct udevice_id mxs_gpio_ids[] = {
 290        { .compatible = "fsl,imx23-gpio" },
 291        { .compatible = "fsl,imx28-gpio" },
 292        { }
 293};
 294#endif
 295
 296U_BOOT_DRIVER(fsl_imx23_gpio) = {
 297        .name = "fsl_imx23_gpio",
 298        .id     = UCLASS_GPIO,
 299        .ops    = &gpio_mxs_ops,
 300        .probe  = mxs_gpio_probe,
 301        .priv_auto_alloc_size = sizeof(struct mxs_gpio_priv),
 302        .platdata_auto_alloc_size = sizeof(struct mxs_gpio_platdata),
 303#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 304        .of_match = mxs_gpio_ids,
 305        .ofdata_to_platdata = mxs_ofdata_to_platdata,
 306#endif
 307};
 308
 309U_BOOT_DRIVER_ALIAS(fsl_imx23_gpio, fsl_imx28_gpio)
 310#endif /* DM_GPIO */
 311