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