uboot/drivers/gpio/rk_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2015 Google, Inc
   4 *
   5 * (C) Copyright 2008-2014 Rockchip Electronics
   6 * Peter, Software Engineering, <superpeter.cai@gmail.com>.
   7 */
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <syscon.h>
  12#include <linux/errno.h>
  13#include <asm/gpio.h>
  14#include <asm/io.h>
  15#include <asm/arch/clock.h>
  16#include <dm/pinctrl.h>
  17#include <dt-bindings/clock/rk3288-cru.h>
  18
  19enum {
  20        ROCKCHIP_GPIOS_PER_BANK         = 32,
  21};
  22
  23#define OFFSET_TO_BIT(bit)      (1UL << (bit))
  24
  25struct rockchip_gpio_priv {
  26        struct rockchip_gpio_regs *regs;
  27        struct udevice *pinctrl;
  28        int bank;
  29        char name[2];
  30};
  31
  32static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
  33{
  34        struct rockchip_gpio_priv *priv = dev_get_priv(dev);
  35        struct rockchip_gpio_regs *regs = priv->regs;
  36
  37        clrbits_le32(&regs->swport_ddr, OFFSET_TO_BIT(offset));
  38
  39        return 0;
  40}
  41
  42static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
  43                                          int value)
  44{
  45        struct rockchip_gpio_priv *priv = dev_get_priv(dev);
  46        struct rockchip_gpio_regs *regs = priv->regs;
  47        int mask = OFFSET_TO_BIT(offset);
  48
  49        clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
  50        setbits_le32(&regs->swport_ddr, mask);
  51
  52        return 0;
  53}
  54
  55static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
  56{
  57        struct rockchip_gpio_priv *priv = dev_get_priv(dev);
  58        struct rockchip_gpio_regs *regs = priv->regs;
  59
  60        return readl(&regs->ext_port) & OFFSET_TO_BIT(offset) ? 1 : 0;
  61}
  62
  63static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
  64                                   int value)
  65{
  66        struct rockchip_gpio_priv *priv = dev_get_priv(dev);
  67        struct rockchip_gpio_regs *regs = priv->regs;
  68        int mask = OFFSET_TO_BIT(offset);
  69
  70        clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
  71
  72        return 0;
  73}
  74
  75static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
  76{
  77#ifdef CONFIG_SPL_BUILD
  78        return -ENODATA;
  79#else
  80        struct rockchip_gpio_priv *priv = dev_get_priv(dev);
  81        struct rockchip_gpio_regs *regs = priv->regs;
  82        bool is_output;
  83        int ret;
  84
  85        ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
  86        if (ret)
  87                return ret;
  88        is_output = readl(&regs->swport_ddr) & OFFSET_TO_BIT(offset);
  89
  90        return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
  91#endif
  92}
  93
  94static int rockchip_gpio_probe(struct udevice *dev)
  95{
  96        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  97        struct rockchip_gpio_priv *priv = dev_get_priv(dev);
  98        char *end;
  99        int ret;
 100
 101        priv->regs = dev_read_addr_ptr(dev);
 102        ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
 103        if (ret)
 104                return ret;
 105
 106        uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK;
 107        end = strrchr(dev->name, '@');
 108        priv->bank = trailing_strtoln(dev->name, end);
 109        priv->name[0] = 'A' + priv->bank;
 110        uc_priv->bank_name = priv->name;
 111
 112        return 0;
 113}
 114
 115static const struct dm_gpio_ops gpio_rockchip_ops = {
 116        .direction_input        = rockchip_gpio_direction_input,
 117        .direction_output       = rockchip_gpio_direction_output,
 118        .get_value              = rockchip_gpio_get_value,
 119        .set_value              = rockchip_gpio_set_value,
 120        .get_function           = rockchip_gpio_get_function,
 121};
 122
 123static const struct udevice_id rockchip_gpio_ids[] = {
 124        { .compatible = "rockchip,gpio-bank" },
 125        { }
 126};
 127
 128U_BOOT_DRIVER(gpio_rockchip) = {
 129        .name   = "gpio_rockchip",
 130        .id     = UCLASS_GPIO,
 131        .of_match = rockchip_gpio_ids,
 132        .ops    = &gpio_rockchip_ops,
 133        .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv),
 134        .probe  = rockchip_gpio_probe,
 135};
 136