uboot/drivers/gpio/hsdk-creg-gpio.c
<<
>>
Prefs
   1/*
   2 * Synopsys HSDK SDP Generic PLL clock driver
   3 *
   4 * Copyright (C) 2017 Synopsys
   5 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
   6 *
   7 * This file is licensed under the terms of the GNU General Public
   8 * License version 2. This program is licensed "as is" without any
   9 * warranty of any kind, whether express or implied.
  10 */
  11
  12#include <asm-generic/gpio.h>
  13#include <asm/io.h>
  14#include <common.h>
  15#include <dm.h>
  16#include <errno.h>
  17#include <linux/printk.h>
  18
  19#define DRV_NAME        "gpio_creg"
  20
  21struct hsdk_creg_gpio {
  22        u32     *regs;
  23        u8      shift;
  24        u8      activate;
  25        u8      deactivate;
  26        u8      bit_per_gpio;
  27};
  28
  29static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val)
  30{
  31        struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
  32        u8 reg_shift = oft * hcg->bit_per_gpio + hcg->shift;
  33        u32 reg = readl(hcg->regs);
  34
  35        reg &= ~(GENMASK(hcg->bit_per_gpio - 1, 0) << reg_shift);
  36        reg |=  ((val ? hcg->deactivate : hcg->activate) << reg_shift);
  37
  38        writel(reg, hcg->regs);
  39
  40        return 0;
  41}
  42
  43static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft,
  44                                           int val)
  45{
  46        hsdk_creg_gpio_set_value(dev, oft, val);
  47
  48        return 0;
  49}
  50
  51static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
  52{
  53        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  54
  55        pr_err("%s can't be used as input!\n", uc_priv->bank_name);
  56
  57        return -ENOTSUPP;
  58}
  59
  60static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft)
  61{
  62        struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
  63        u32 val = readl(hcg->regs);
  64
  65        val >>= oft * hcg->bit_per_gpio + hcg->shift;
  66        val &= GENMASK(hcg->bit_per_gpio - 1, 0);
  67        return (val == hcg->deactivate) ? 1 : 0;
  68}
  69
  70static const struct dm_gpio_ops hsdk_creg_gpio_ops = {
  71        .direction_output       = hsdk_creg_gpio_direction_output,
  72        .direction_input        = hsdk_creg_gpio_direction_input,
  73        .set_value              = hsdk_creg_gpio_set_value,
  74        .get_value              = hsdk_creg_gpio_get_value,
  75};
  76
  77static int hsdk_creg_gpio_probe(struct udevice *dev)
  78{
  79        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  80        struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
  81        u32 shift, bit_per_gpio, activate, deactivate, gpio_count;
  82        const u8 *defaults;
  83
  84        hcg->regs = (u32 *)devfdt_get_addr_ptr(dev);
  85        gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
  86        shift = dev_read_u32_default(dev, "gpio-first-shift", 0);
  87        bit_per_gpio = dev_read_u32_default(dev, "gpio-bit-per-line", 1);
  88        activate = dev_read_u32_default(dev, "gpio-activate-val", 1);
  89        deactivate = dev_read_u32_default(dev, "gpio-deactivate-val", 0);
  90        defaults = dev_read_u8_array_ptr(dev, "gpio-default-val", gpio_count);
  91
  92        uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
  93        if (!uc_priv->bank_name)
  94                uc_priv->bank_name = dev_read_name(dev);
  95
  96        if (!bit_per_gpio) {
  97                pr_err("%s: 'gpio-bit-per-line' can't be 0\n",
  98                       uc_priv->bank_name);
  99
 100                return -EINVAL;
 101        }
 102
 103        if (!gpio_count) {
 104                pr_err("%s: 'gpio-count' can't be 0\n",
 105                       uc_priv->bank_name);
 106
 107                return -EINVAL;
 108        }
 109
 110        if ((gpio_count * bit_per_gpio + shift) > 32) {
 111                pr_err("%s: u32 io register overflow: try to use %u bits\n",
 112                       uc_priv->bank_name, gpio_count * bit_per_gpio + shift);
 113
 114                return -EINVAL;
 115        }
 116
 117        if (GENMASK(31, bit_per_gpio) & activate) {
 118                pr_err("%s: 'gpio-activate-val' can't be more than %lu\n",
 119                       uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
 120
 121                return -EINVAL;
 122        }
 123
 124        if (GENMASK(31, bit_per_gpio) & deactivate) {
 125                pr_err("%s: 'gpio-deactivate-val' can't be more than %lu\n",
 126                       uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
 127
 128                return -EINVAL;
 129        }
 130
 131        if (activate == deactivate) {
 132                pr_err("%s: 'gpio-deactivate-val' and 'gpio-activate-val' can't be equal\n",
 133                       uc_priv->bank_name);
 134
 135                return -EINVAL;
 136        }
 137
 138        hcg->shift = (u8)shift;
 139        hcg->bit_per_gpio = (u8)bit_per_gpio;
 140        hcg->activate = (u8)activate;
 141        hcg->deactivate = (u8)deactivate;
 142        uc_priv->gpio_count = gpio_count;
 143
 144        /* Setup default GPIO value if we have "gpio-default-val" array */
 145        if (defaults)
 146                for (u8 i = 0; i < gpio_count; i++)
 147                        hsdk_creg_gpio_set_value(dev, i, defaults[i]);
 148
 149        pr_debug("%s GPIO [0x%p] controller with %d gpios probed\n",
 150                 uc_priv->bank_name, hcg->regs, uc_priv->gpio_count);
 151
 152        return 0;
 153}
 154
 155static const struct udevice_id hsdk_creg_gpio_ids[] = {
 156        { .compatible = "snps,creg-gpio" },
 157        { }
 158};
 159
 160U_BOOT_DRIVER(gpio_hsdk_creg) = {
 161        .name   = DRV_NAME,
 162        .id     = UCLASS_GPIO,
 163        .ops    = &hsdk_creg_gpio_ops,
 164        .probe  = hsdk_creg_gpio_probe,
 165        .of_match = hsdk_creg_gpio_ids,
 166        .platdata_auto_alloc_size = sizeof(struct hsdk_creg_gpio),
 167};
 168