uboot/drivers/gpio/mvebu_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 Stefan Roese <sr@denx.de>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <asm/gpio.h>
   9#include <asm/io.h>
  10#include <errno.h>
  11#include <linux/bitops.h>
  12
  13#define MVEBU_GPIOS_PER_BANK    32
  14
  15struct mvebu_gpio_regs {
  16        u32 data_out;
  17        u32 io_conf;
  18        u32 blink_en;
  19        u32 in_pol;
  20        u32 data_in;
  21};
  22
  23struct mvebu_gpio_priv {
  24        struct mvebu_gpio_regs *regs;
  25        char name[2];
  26};
  27
  28static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
  29{
  30        struct mvebu_gpio_priv *priv = dev_get_priv(dev);
  31        struct mvebu_gpio_regs *regs = priv->regs;
  32
  33        setbits_le32(&regs->io_conf, BIT(gpio));
  34
  35        return 0;
  36}
  37
  38static int mvebu_gpio_direction_output(struct udevice *dev, unsigned gpio,
  39                                       int value)
  40{
  41        struct mvebu_gpio_priv *priv = dev_get_priv(dev);
  42        struct mvebu_gpio_regs *regs = priv->regs;
  43
  44        if (value)
  45                setbits_le32(&regs->data_out, BIT(gpio));
  46        else
  47                clrbits_le32(&regs->data_out, BIT(gpio));
  48        clrbits_le32(&regs->io_conf, BIT(gpio));
  49
  50        return 0;
  51}
  52
  53static int mvebu_gpio_get_function(struct udevice *dev, unsigned gpio)
  54{
  55        struct mvebu_gpio_priv *priv = dev_get_priv(dev);
  56        struct mvebu_gpio_regs *regs = priv->regs;
  57        u32 val;
  58
  59        val = readl(&regs->io_conf) & BIT(gpio);
  60        if (val)
  61                return GPIOF_INPUT;
  62        else
  63                return GPIOF_OUTPUT;
  64}
  65
  66static int mvebu_gpio_set_value(struct udevice *dev, unsigned gpio,
  67                                int value)
  68{
  69        struct mvebu_gpio_priv *priv = dev_get_priv(dev);
  70        struct mvebu_gpio_regs *regs = priv->regs;
  71
  72        if (value)
  73                setbits_le32(&regs->data_out, BIT(gpio));
  74        else
  75                clrbits_le32(&regs->data_out, BIT(gpio));
  76
  77        return 0;
  78}
  79
  80static int mvebu_gpio_get_value(struct udevice *dev, unsigned gpio)
  81{
  82        struct mvebu_gpio_priv *priv = dev_get_priv(dev);
  83        struct mvebu_gpio_regs *regs = priv->regs;
  84
  85        return !!(readl(&regs->data_in) & BIT(gpio));
  86}
  87
  88static int mvebu_gpio_probe(struct udevice *dev)
  89{
  90        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  91        struct mvebu_gpio_priv *priv = dev_get_priv(dev);
  92
  93        priv->regs = dev_read_addr_ptr(dev);
  94        uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
  95        priv->name[0] = 'A' + dev->req_seq;
  96        uc_priv->bank_name = priv->name;
  97
  98        return 0;
  99}
 100
 101static const struct dm_gpio_ops mvebu_gpio_ops = {
 102        .direction_input        = mvebu_gpio_direction_input,
 103        .direction_output       = mvebu_gpio_direction_output,
 104        .get_function           = mvebu_gpio_get_function,
 105        .get_value              = mvebu_gpio_get_value,
 106        .set_value              = mvebu_gpio_set_value,
 107};
 108
 109static const struct udevice_id mvebu_gpio_ids[] = {
 110        { .compatible = "marvell,orion-gpio" },
 111        { }
 112};
 113
 114U_BOOT_DRIVER(gpio_mvebu) = {
 115        .name                   = "gpio_mvebu",
 116        .id                     = UCLASS_GPIO,
 117        .of_match               = mvebu_gpio_ids,
 118        .ops                    = &mvebu_gpio_ops,
 119        .probe                  = mvebu_gpio_probe,
 120        .priv_auto_alloc_size   = sizeof(struct mvebu_gpio_priv),
 121};
 122