uboot/drivers/gpio/atmel_pio4.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Atmel PIO4 device driver
   4 *
   5 * Copyright (C) 2015 Atmel Corporation
   6 *               Wenyou.Yang <wenyou.yang@atmel.com>
   7 */
   8#include <common.h>
   9#include <clk.h>
  10#include <dm.h>
  11#include <fdtdec.h>
  12#include <asm/arch/hardware.h>
  13#include <asm/gpio.h>
  14#include <mach/gpio.h>
  15#include <mach/atmel_pio4.h>
  16
  17DECLARE_GLOBAL_DATA_PTR;
  18
  19static struct atmel_pio4_port *atmel_pio4_port_base(u32 port)
  20{
  21        struct atmel_pio4_port *base = NULL;
  22
  23        switch (port) {
  24        case AT91_PIO_PORTA:
  25                base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA;
  26                break;
  27        case AT91_PIO_PORTB:
  28                base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB;
  29                break;
  30        case AT91_PIO_PORTC:
  31                base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC;
  32                break;
  33        case AT91_PIO_PORTD:
  34                base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD;
  35                break;
  36        default:
  37                printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n",
  38                       port);
  39                break;
  40        }
  41
  42        return base;
  43}
  44
  45static int atmel_pio4_config_io_func(u32 port, u32 pin,
  46                                     u32 func, u32 config)
  47{
  48        struct atmel_pio4_port *port_base;
  49        u32 reg, mask;
  50
  51        if (pin >= ATMEL_PIO_NPINS_PER_BANK)
  52                return -EINVAL;
  53
  54        port_base = atmel_pio4_port_base(port);
  55        if (!port_base)
  56                return -EINVAL;
  57
  58        mask = 1 << pin;
  59        reg = func;
  60        reg |= config;
  61
  62        writel(mask, &port_base->mskr);
  63        writel(reg, &port_base->cfgr);
  64
  65        return 0;
  66}
  67
  68int atmel_pio4_set_gpio(u32 port, u32 pin, u32 config)
  69{
  70        return atmel_pio4_config_io_func(port, pin,
  71                                         ATMEL_PIO_CFGR_FUNC_GPIO,
  72                                         config);
  73}
  74
  75int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 config)
  76{
  77        return atmel_pio4_config_io_func(port, pin,
  78                                         ATMEL_PIO_CFGR_FUNC_PERIPH_A,
  79                                         config);
  80}
  81
  82int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 config)
  83{
  84        return atmel_pio4_config_io_func(port, pin,
  85                                         ATMEL_PIO_CFGR_FUNC_PERIPH_B,
  86                                         config);
  87}
  88
  89int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 config)
  90{
  91        return atmel_pio4_config_io_func(port, pin,
  92                                         ATMEL_PIO_CFGR_FUNC_PERIPH_C,
  93                                         config);
  94}
  95
  96int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 config)
  97{
  98        return atmel_pio4_config_io_func(port, pin,
  99                                         ATMEL_PIO_CFGR_FUNC_PERIPH_D,
 100                                         config);
 101}
 102
 103int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 config)
 104{
 105        return atmel_pio4_config_io_func(port, pin,
 106                                         ATMEL_PIO_CFGR_FUNC_PERIPH_E,
 107                                         config);
 108}
 109
 110int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 config)
 111{
 112        return atmel_pio4_config_io_func(port, pin,
 113                                         ATMEL_PIO_CFGR_FUNC_PERIPH_F,
 114                                         config);
 115}
 116
 117int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 config)
 118{
 119        return atmel_pio4_config_io_func(port, pin,
 120                                         ATMEL_PIO_CFGR_FUNC_PERIPH_G,
 121                                         config);
 122}
 123
 124int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value)
 125{
 126        struct atmel_pio4_port *port_base;
 127        u32 reg, mask;
 128
 129        if (pin >= ATMEL_PIO_NPINS_PER_BANK)
 130                return -EINVAL;
 131
 132        port_base = atmel_pio4_port_base(port);
 133        if (!port_base)
 134                return -EINVAL;
 135
 136        mask = 0x01 << pin;
 137        reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK;
 138
 139        writel(mask, &port_base->mskr);
 140        writel(reg, &port_base->cfgr);
 141
 142        if (value)
 143                writel(mask, &port_base->sodr);
 144        else
 145                writel(mask, &port_base->codr);
 146
 147        return 0;
 148}
 149
 150int atmel_pio4_get_pio_input(u32 port, u32 pin)
 151{
 152        struct atmel_pio4_port *port_base;
 153        u32 reg, mask;
 154
 155        if (pin >= ATMEL_PIO_NPINS_PER_BANK)
 156                return -EINVAL;
 157
 158        port_base = atmel_pio4_port_base(port);
 159        if (!port_base)
 160                return -EINVAL;
 161
 162        mask = 0x01 << pin;
 163        reg = ATMEL_PIO_CFGR_FUNC_GPIO;
 164
 165        writel(mask, &port_base->mskr);
 166        writel(reg, &port_base->cfgr);
 167
 168        return (readl(&port_base->pdsr) & mask) ? 1 : 0;
 169}
 170
 171#ifdef CONFIG_DM_GPIO
 172
 173struct atmel_pioctrl_data {
 174        u32 nbanks;
 175};
 176
 177struct atmel_pio4_platdata {
 178        struct atmel_pio4_port *reg_base;
 179};
 180
 181static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
 182                                                    u32 bank)
 183{
 184        struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
 185        struct atmel_pio4_port *port_base =
 186                        (struct atmel_pio4_port *)((u32)plat->reg_base +
 187                        ATMEL_PIO_BANK_OFFSET * bank);
 188
 189        return port_base;
 190}
 191
 192static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset)
 193{
 194        u32 bank = ATMEL_PIO_BANK(offset);
 195        u32 line = ATMEL_PIO_LINE(offset);
 196        struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
 197        u32 mask = BIT(line);
 198
 199        writel(mask, &port_base->mskr);
 200
 201        clrbits_le32(&port_base->cfgr,
 202                     ATMEL_PIO_CFGR_FUNC_MASK | ATMEL_PIO_DIR_MASK);
 203
 204        return 0;
 205}
 206
 207static int atmel_pio4_direction_output(struct udevice *dev,
 208                                       unsigned offset, int value)
 209{
 210        u32 bank = ATMEL_PIO_BANK(offset);
 211        u32 line = ATMEL_PIO_LINE(offset);
 212        struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
 213        u32 mask = BIT(line);
 214
 215        writel(mask, &port_base->mskr);
 216
 217        clrsetbits_le32(&port_base->cfgr,
 218                        ATMEL_PIO_CFGR_FUNC_MASK, ATMEL_PIO_DIR_MASK);
 219
 220        if (value)
 221                writel(mask, &port_base->sodr);
 222        else
 223                writel(mask, &port_base->codr);
 224
 225        return 0;
 226}
 227
 228static int atmel_pio4_get_value(struct udevice *dev, unsigned offset)
 229{
 230        u32 bank = ATMEL_PIO_BANK(offset);
 231        u32 line = ATMEL_PIO_LINE(offset);
 232        struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
 233        u32 mask = BIT(line);
 234
 235        return (readl(&port_base->pdsr) & mask) ? 1 : 0;
 236}
 237
 238static int atmel_pio4_set_value(struct udevice *dev,
 239                                unsigned offset, int value)
 240{
 241        u32 bank = ATMEL_PIO_BANK(offset);
 242        u32 line = ATMEL_PIO_LINE(offset);
 243        struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
 244        u32 mask = BIT(line);
 245
 246        if (value)
 247                writel(mask, &port_base->sodr);
 248        else
 249                writel(mask, &port_base->codr);
 250
 251        return 0;
 252}
 253
 254static int atmel_pio4_get_function(struct udevice *dev, unsigned offset)
 255{
 256        u32 bank = ATMEL_PIO_BANK(offset);
 257        u32 line = ATMEL_PIO_LINE(offset);
 258        struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
 259        u32 mask = BIT(line);
 260
 261        writel(mask, &port_base->mskr);
 262
 263        return (readl(&port_base->cfgr) &
 264                ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT;
 265}
 266
 267static const struct dm_gpio_ops atmel_pio4_ops = {
 268        .direction_input        = atmel_pio4_direction_input,
 269        .direction_output       = atmel_pio4_direction_output,
 270        .get_value              = atmel_pio4_get_value,
 271        .set_value              = atmel_pio4_set_value,
 272        .get_function           = atmel_pio4_get_function,
 273};
 274
 275static int atmel_pio4_bind(struct udevice *dev)
 276{
 277        return dm_scan_fdt_dev(dev);
 278}
 279
 280static int atmel_pio4_probe(struct udevice *dev)
 281{
 282        struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
 283        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 284        struct atmel_pioctrl_data *pioctrl_data;
 285        struct clk clk;
 286        fdt_addr_t addr_base;
 287        u32 nbanks;
 288        int ret;
 289
 290        ret = clk_get_by_index(dev, 0, &clk);
 291        if (ret)
 292                return ret;
 293
 294        ret = clk_enable(&clk);
 295        if (ret)
 296                return ret;
 297
 298        clk_free(&clk);
 299
 300        addr_base = devfdt_get_addr(dev);
 301        if (addr_base == FDT_ADDR_T_NONE)
 302                return -EINVAL;
 303
 304        plat->reg_base = (struct atmel_pio4_port *)addr_base;
 305
 306        pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev);
 307        nbanks = pioctrl_data->nbanks;
 308
 309        uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev),
 310                                          NULL);
 311        uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK;
 312
 313        return 0;
 314}
 315
 316/*
 317 * The number of banks can be different from a SoC to another one.
 318 * We can have up to 16 banks.
 319 */
 320static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
 321        .nbanks = 4,
 322};
 323
 324static const struct udevice_id atmel_pio4_ids[] = {
 325        {
 326                .compatible = "atmel,sama5d2-gpio",
 327                .data = (ulong)&atmel_sama5d2_pioctrl_data,
 328        },
 329        {}
 330};
 331
 332U_BOOT_DRIVER(gpio_atmel_pio4) = {
 333        .name   = "gpio_atmel_pio4",
 334        .id     = UCLASS_GPIO,
 335        .ops    = &atmel_pio4_ops,
 336        .probe  = atmel_pio4_probe,
 337        .bind   = atmel_pio4_bind,
 338        .of_match = atmel_pio4_ids,
 339        .platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
 340};
 341
 342#endif
 343