uboot/drivers/gpio/nx_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2016 Nexell
   4 * DeokJin, Lee <truevirtue@nexell.co.kr>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <malloc.h>
  11#include <asm/global_data.h>
  12#include <asm/io.h>
  13#include <asm/gpio.h>
  14
  15DECLARE_GLOBAL_DATA_PTR;
  16
  17struct nx_gpio_regs {
  18        u32     data;           /* Data register */
  19        u32     outputenb;      /* Output Enable register */
  20        u32     detmode[2];     /* Detect Mode Register */
  21        u32     intenb;         /* Interrupt Enable Register */
  22        u32     det;            /* Event Detect Register */
  23        u32     pad;            /* Pad Status Register */
  24};
  25
  26struct nx_alive_gpio_regs {
  27        u32     pwrgate;        /* Power Gating Register */
  28        u32     reserved0[28];  /* Reserved0 */
  29        u32     outputenb_reset;/* Alive GPIO Output Enable Reset Register */
  30        u32     outputenb;      /* Alive GPIO Output Enable Register */
  31        u32     outputenb_read; /* Alive GPIO Output Read Register */
  32        u32     reserved1[3];   /* Reserved1 */
  33        u32     pad_reset;      /* Alive GPIO Output Reset Register */
  34        u32     data;           /* Alive GPIO Output Register */
  35        u32     pad_read;       /* Alive GPIO Pad Read Register */
  36        u32     reserved2[33];  /* Reserved2 */
  37        u32     pad;            /* Alive GPIO Input Value Register */
  38};
  39
  40struct nx_gpio_plat {
  41        void *regs;
  42        int gpio_count;
  43        const char *bank_name;
  44};
  45
  46static int nx_alive_gpio_is_check(struct udevice *dev)
  47{
  48        struct nx_gpio_plat *plat = dev_get_plat(dev);
  49        const char *bank_name = plat->bank_name;
  50
  51        if (!strcmp(bank_name, "gpio_alv"))
  52                return 1;
  53
  54        return 0;
  55}
  56
  57static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned int pin)
  58{
  59        struct nx_gpio_plat *plat = dev_get_plat(dev);
  60        struct nx_alive_gpio_regs *const regs = plat->regs;
  61
  62        setbits_le32(&regs->outputenb_reset, 1 << pin);
  63
  64        return 0;
  65}
  66
  67static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned int pin,
  68                                          int val)
  69{
  70        struct nx_gpio_plat *plat = dev_get_plat(dev);
  71        struct nx_alive_gpio_regs *const regs = plat->regs;
  72
  73        if (val)
  74                setbits_le32(&regs->data, 1 << pin);
  75        else
  76                setbits_le32(&regs->pad_reset, 1 << pin);
  77
  78        setbits_le32(&regs->outputenb, 1 << pin);
  79
  80        return 0;
  81}
  82
  83static int nx_alive_gpio_get_value(struct udevice *dev, unsigned int pin)
  84{
  85        struct nx_gpio_plat *plat = dev_get_plat(dev);
  86        struct nx_alive_gpio_regs *const regs = plat->regs;
  87        unsigned int mask = 1UL << pin;
  88        unsigned int value;
  89
  90        value = (readl(&regs->pad_read) & mask) >> pin;
  91
  92        return value;
  93}
  94
  95static int nx_alive_gpio_set_value(struct udevice *dev, unsigned int pin,
  96                                   int val)
  97{
  98        struct nx_gpio_plat *plat = dev_get_plat(dev);
  99        struct nx_alive_gpio_regs *const regs = plat->regs;
 100
 101        if (val)
 102                setbits_le32(&regs->data, 1 << pin);
 103        else
 104                clrbits_le32(&regs->pad_reset, 1 << pin);
 105
 106        return 0;
 107}
 108
 109static int nx_alive_gpio_get_function(struct udevice *dev, unsigned int pin)
 110{
 111        struct nx_gpio_plat *plat = dev_get_plat(dev);
 112        struct nx_alive_gpio_regs *const regs = plat->regs;
 113        unsigned int mask = (1UL << pin);
 114        unsigned int output;
 115
 116        output = readl(&regs->outputenb_read) & mask;
 117
 118        if (output)
 119                return GPIOF_OUTPUT;
 120        else
 121                return GPIOF_INPUT;
 122}
 123
 124static int nx_gpio_direction_input(struct udevice *dev, unsigned int pin)
 125{
 126        struct nx_gpio_plat *plat = dev_get_plat(dev);
 127        struct nx_gpio_regs *const regs = plat->regs;
 128
 129        if (nx_alive_gpio_is_check(dev))
 130                return nx_alive_gpio_direction_input(dev, pin);
 131
 132        clrbits_le32(&regs->outputenb, 1 << pin);
 133
 134        return 0;
 135}
 136
 137static int nx_gpio_direction_output(struct udevice *dev, unsigned int pin,
 138                                    int val)
 139{
 140        struct nx_gpio_plat *plat = dev_get_plat(dev);
 141        struct nx_gpio_regs *const regs = plat->regs;
 142
 143        if (nx_alive_gpio_is_check(dev))
 144                return nx_alive_gpio_direction_output(dev, pin, val);
 145
 146        if (val)
 147                setbits_le32(&regs->data, 1 << pin);
 148        else
 149                clrbits_le32(&regs->data, 1 << pin);
 150
 151        setbits_le32(&regs->outputenb, 1 << pin);
 152
 153        return 0;
 154}
 155
 156static int nx_gpio_get_value(struct udevice *dev, unsigned int pin)
 157{
 158        struct nx_gpio_plat *plat = dev_get_plat(dev);
 159        struct nx_gpio_regs *const regs = plat->regs;
 160        unsigned int mask = 1UL << pin;
 161        unsigned int value;
 162
 163        if (nx_alive_gpio_is_check(dev))
 164                return nx_alive_gpio_get_value(dev, pin);
 165
 166        value = (readl(&regs->pad) & mask) >> pin;
 167
 168        return value;
 169}
 170
 171static int nx_gpio_set_value(struct udevice *dev, unsigned int pin, int val)
 172{
 173        struct nx_gpio_plat *plat = dev_get_plat(dev);
 174        struct nx_gpio_regs *const regs = plat->regs;
 175
 176        if (nx_alive_gpio_is_check(dev))
 177                return nx_alive_gpio_set_value(dev, pin, val);
 178
 179        if (val)
 180                setbits_le32(&regs->data, 1 << pin);
 181        else
 182                clrbits_le32(&regs->data, 1 << pin);
 183
 184        return 0;
 185}
 186
 187static int nx_gpio_get_function(struct udevice *dev, unsigned int pin)
 188{
 189        struct nx_gpio_plat *plat = dev_get_plat(dev);
 190        struct nx_gpio_regs *const regs = plat->regs;
 191        unsigned int mask = (1UL << pin);
 192        unsigned int output;
 193
 194        if (nx_alive_gpio_is_check(dev))
 195                return nx_alive_gpio_get_function(dev, pin);
 196
 197        output = readl(&regs->outputenb) & mask;
 198
 199        if (output)
 200                return GPIOF_OUTPUT;
 201        else
 202                return GPIOF_INPUT;
 203}
 204
 205static int nx_gpio_probe(struct udevice *dev)
 206{
 207        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 208        struct nx_gpio_plat *plat = dev_get_plat(dev);
 209
 210        uc_priv->gpio_count = plat->gpio_count;
 211        uc_priv->bank_name = plat->bank_name;
 212
 213        return 0;
 214}
 215
 216static int nx_gpio_of_to_plat(struct udevice *dev)
 217{
 218        struct nx_gpio_plat *plat = dev_get_plat(dev);
 219
 220        plat->regs = map_physmem(devfdt_get_addr(dev),
 221                                 sizeof(struct nx_gpio_regs),
 222                                 MAP_NOCACHE);
 223        plat->gpio_count = dev_read_s32_default(dev, "nexell,gpio-bank-width",
 224                                                32);
 225        plat->bank_name = dev_read_string(dev, "gpio-bank-name");
 226
 227        return 0;
 228}
 229
 230static const struct dm_gpio_ops nx_gpio_ops = {
 231        .direction_input        = nx_gpio_direction_input,
 232        .direction_output       = nx_gpio_direction_output,
 233        .get_value              = nx_gpio_get_value,
 234        .set_value              = nx_gpio_set_value,
 235        .get_function           = nx_gpio_get_function,
 236};
 237
 238static const struct udevice_id nx_gpio_ids[] = {
 239        { .compatible = "nexell,nexell-gpio" },
 240        { }
 241};
 242
 243U_BOOT_DRIVER(nx_gpio) = {
 244        .name           = "nx_gpio",
 245        .id             = UCLASS_GPIO,
 246        .of_match       = nx_gpio_ids,
 247        .ops            = &nx_gpio_ops,
 248        .of_to_plat = nx_gpio_of_to_plat,
 249        .plat_auto      = sizeof(struct nx_gpio_plat),
 250        .probe          = nx_gpio_probe,
 251};
 252