uboot/drivers/gpio/altera_pio.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015  Thomas Chou <thomas@wytron.com.tw>
   3 * Copyright (C) 2011  Missing Link Electronics
   4 *                     Joachim Foerster <joachim@missinglinkelectronics.com>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8#include <common.h>
   9#include <dm.h>
  10#include <errno.h>
  11#include <malloc.h>
  12#include <fdtdec.h>
  13#include <asm/io.h>
  14#include <asm/gpio.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18struct altera_pio_regs {
  19        u32     data;                   /* Data register */
  20        u32     direction;              /* Direction register */
  21};
  22
  23struct altera_pio_platdata {
  24        struct altera_pio_regs *regs;
  25        int gpio_count;
  26        const char *bank_name;
  27};
  28
  29static int altera_pio_direction_input(struct udevice *dev, unsigned pin)
  30{
  31        struct altera_pio_platdata *plat = dev_get_platdata(dev);
  32        struct altera_pio_regs *const regs = plat->regs;
  33
  34        clrbits_le32(&regs->direction, 1 << pin);
  35
  36        return 0;
  37}
  38
  39static int altera_pio_direction_output(struct udevice *dev, unsigned pin,
  40                                     int val)
  41{
  42        struct altera_pio_platdata *plat = dev_get_platdata(dev);
  43        struct altera_pio_regs *const regs = plat->regs;
  44
  45        if (val)
  46                setbits_le32(&regs->data, 1 << pin);
  47        else
  48                clrbits_le32(&regs->data, 1 << pin);
  49        /* change the data first, then the direction. to avoid glitch */
  50        setbits_le32(&regs->direction, 1 << pin);
  51
  52        return 0;
  53}
  54
  55static int altera_pio_get_value(struct udevice *dev, unsigned pin)
  56{
  57        struct altera_pio_platdata *plat = dev_get_platdata(dev);
  58        struct altera_pio_regs *const regs = plat->regs;
  59
  60        return readl(&regs->data) & (1 << pin);
  61}
  62
  63
  64static int altera_pio_set_value(struct udevice *dev, unsigned pin, int val)
  65{
  66        struct altera_pio_platdata *plat = dev_get_platdata(dev);
  67        struct altera_pio_regs *const regs = plat->regs;
  68
  69        if (val)
  70                setbits_le32(&regs->data, 1 << pin);
  71        else
  72                clrbits_le32(&regs->data, 1 << pin);
  73
  74        return 0;
  75}
  76
  77static int altera_pio_probe(struct udevice *dev)
  78{
  79        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  80        struct altera_pio_platdata *plat = dev_get_platdata(dev);
  81
  82        uc_priv->gpio_count = plat->gpio_count;
  83        uc_priv->bank_name = plat->bank_name;
  84
  85        return 0;
  86}
  87
  88static int altera_pio_ofdata_to_platdata(struct udevice *dev)
  89{
  90        struct altera_pio_platdata *plat = dev_get_platdata(dev);
  91
  92        plat->regs = map_physmem(devfdt_get_addr(dev),
  93                                 sizeof(struct altera_pio_regs),
  94                                 MAP_NOCACHE);
  95        plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
  96                "altr,gpio-bank-width", 32);
  97        plat->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
  98                "gpio-bank-name", NULL);
  99
 100        return 0;
 101}
 102
 103static const struct dm_gpio_ops altera_pio_ops = {
 104        .direction_input        = altera_pio_direction_input,
 105        .direction_output       = altera_pio_direction_output,
 106        .get_value              = altera_pio_get_value,
 107        .set_value              = altera_pio_set_value,
 108};
 109
 110static const struct udevice_id altera_pio_ids[] = {
 111        { .compatible = "altr,pio-1.0" },
 112        { }
 113};
 114
 115U_BOOT_DRIVER(altera_pio) = {
 116        .name           = "altera_pio",
 117        .id             = UCLASS_GPIO,
 118        .of_match       = altera_pio_ids,
 119        .ops            = &altera_pio_ops,
 120        .ofdata_to_platdata = altera_pio_ofdata_to_platdata,
 121        .platdata_auto_alloc_size = sizeof(struct altera_pio_platdata),
 122        .probe          = altera_pio_probe,
 123};
 124