root/drivers/gpio/gpio-amd-fch.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amd_fch_gpio_addr
  2. amd_fch_gpio_direction_input
  3. amd_fch_gpio_direction_output
  4. amd_fch_gpio_get_direction
  5. amd_fch_gpio_set
  6. amd_fch_gpio_get
  7. amd_fch_gpio_request
  8. amd_fch_gpio_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 
   3 /*
   4  * GPIO driver for the AMD G series FCH (eg. GX-412TC)
   5  *
   6  * Copyright (C) 2018 metux IT consult
   7  * Author: Enrico Weigelt, metux IT consult <info@metux.net>
   8  *
   9  */
  10 
  11 #include <linux/err.h>
  12 #include <linux/io.h>
  13 #include <linux/kernel.h>
  14 #include <linux/module.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/gpio/driver.h>
  17 #include <linux/platform_data/gpio/gpio-amd-fch.h>
  18 #include <linux/spinlock.h>
  19 
  20 #define AMD_FCH_MMIO_BASE               0xFED80000
  21 #define AMD_FCH_GPIO_BANK0_BASE         0x1500
  22 #define AMD_FCH_GPIO_SIZE               0x0300
  23 
  24 #define AMD_FCH_GPIO_FLAG_DIRECTION     BIT(23)
  25 #define AMD_FCH_GPIO_FLAG_WRITE         BIT(22)
  26 #define AMD_FCH_GPIO_FLAG_READ          BIT(16)
  27 
  28 static const struct resource amd_fch_gpio_iores =
  29         DEFINE_RES_MEM_NAMED(
  30                 AMD_FCH_MMIO_BASE + AMD_FCH_GPIO_BANK0_BASE,
  31                 AMD_FCH_GPIO_SIZE,
  32                 "amd-fch-gpio-iomem");
  33 
  34 struct amd_fch_gpio_priv {
  35         struct gpio_chip                gc;
  36         void __iomem                    *base;
  37         struct amd_fch_gpio_pdata       *pdata;
  38         spinlock_t                      lock;
  39 };
  40 
  41 static void __iomem *amd_fch_gpio_addr(struct amd_fch_gpio_priv *priv,
  42                                        unsigned int gpio)
  43 {
  44         return priv->base + priv->pdata->gpio_reg[gpio]*sizeof(u32);
  45 }
  46 
  47 static int amd_fch_gpio_direction_input(struct gpio_chip *gc,
  48                                         unsigned int offset)
  49 {
  50         unsigned long flags;
  51         struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
  52         void __iomem *ptr = amd_fch_gpio_addr(priv, offset);
  53 
  54         spin_lock_irqsave(&priv->lock, flags);
  55         writel_relaxed(readl_relaxed(ptr) & ~AMD_FCH_GPIO_FLAG_DIRECTION, ptr);
  56         spin_unlock_irqrestore(&priv->lock, flags);
  57 
  58         return 0;
  59 }
  60 
  61 static int amd_fch_gpio_direction_output(struct gpio_chip *gc,
  62                                          unsigned int gpio, int value)
  63 {
  64         unsigned long flags;
  65         struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
  66         void __iomem *ptr = amd_fch_gpio_addr(priv, gpio);
  67         u32 val;
  68 
  69         spin_lock_irqsave(&priv->lock, flags);
  70 
  71         val = readl_relaxed(ptr);
  72         if (value)
  73                 val |= AMD_FCH_GPIO_FLAG_WRITE;
  74         else
  75                 val &= ~AMD_FCH_GPIO_FLAG_WRITE;
  76 
  77         writel_relaxed(val | AMD_FCH_GPIO_FLAG_DIRECTION, ptr);
  78 
  79         spin_unlock_irqrestore(&priv->lock, flags);
  80 
  81         return 0;
  82 }
  83 
  84 static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
  85 {
  86         int ret;
  87         unsigned long flags;
  88         struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
  89         void __iomem *ptr = amd_fch_gpio_addr(priv, gpio);
  90 
  91         spin_lock_irqsave(&priv->lock, flags);
  92         ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
  93         spin_unlock_irqrestore(&priv->lock, flags);
  94 
  95         return ret;
  96 }
  97 
  98 static void amd_fch_gpio_set(struct gpio_chip *gc,
  99                              unsigned int gpio, int value)
 100 {
 101         unsigned long flags;
 102         struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 103         void __iomem *ptr = amd_fch_gpio_addr(priv, gpio);
 104         u32 mask;
 105 
 106         spin_lock_irqsave(&priv->lock, flags);
 107 
 108         mask = readl_relaxed(ptr);
 109         if (value)
 110                 mask |= AMD_FCH_GPIO_FLAG_WRITE;
 111         else
 112                 mask &= ~AMD_FCH_GPIO_FLAG_WRITE;
 113         writel_relaxed(mask, ptr);
 114 
 115         spin_unlock_irqrestore(&priv->lock, flags);
 116 }
 117 
 118 static int amd_fch_gpio_get(struct gpio_chip *gc,
 119                             unsigned int offset)
 120 {
 121         unsigned long flags;
 122         int ret;
 123         struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 124         void __iomem *ptr = amd_fch_gpio_addr(priv, offset);
 125 
 126         spin_lock_irqsave(&priv->lock, flags);
 127         ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_READ);
 128         spin_unlock_irqrestore(&priv->lock, flags);
 129 
 130         return ret;
 131 }
 132 
 133 static int amd_fch_gpio_request(struct gpio_chip *chip,
 134                                 unsigned int gpio_pin)
 135 {
 136         return 0;
 137 }
 138 
 139 static int amd_fch_gpio_probe(struct platform_device *pdev)
 140 {
 141         struct amd_fch_gpio_priv *priv;
 142         struct amd_fch_gpio_pdata *pdata;
 143 
 144         pdata = dev_get_platdata(&pdev->dev);
 145         if (!pdata) {
 146                 dev_err(&pdev->dev, "no platform_data\n");
 147                 return -ENOENT;
 148         }
 149 
 150         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 151         if (!priv)
 152                 return -ENOMEM;
 153 
 154         priv->pdata     = pdata;
 155 
 156         priv->gc.owner                  = THIS_MODULE;
 157         priv->gc.parent                 = &pdev->dev;
 158         priv->gc.label                  = dev_name(&pdev->dev);
 159         priv->gc.ngpio                  = priv->pdata->gpio_num;
 160         priv->gc.names                  = priv->pdata->gpio_names;
 161         priv->gc.base                   = -1;
 162         priv->gc.request                = amd_fch_gpio_request;
 163         priv->gc.direction_input        = amd_fch_gpio_direction_input;
 164         priv->gc.direction_output       = amd_fch_gpio_direction_output;
 165         priv->gc.get_direction          = amd_fch_gpio_get_direction;
 166         priv->gc.get                    = amd_fch_gpio_get;
 167         priv->gc.set                    = amd_fch_gpio_set;
 168 
 169         spin_lock_init(&priv->lock);
 170 
 171         priv->base = devm_ioremap_resource(&pdev->dev, &amd_fch_gpio_iores);
 172         if (IS_ERR(priv->base))
 173                 return PTR_ERR(priv->base);
 174 
 175         platform_set_drvdata(pdev, priv);
 176 
 177         return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
 178 }
 179 
 180 static struct platform_driver amd_fch_gpio_driver = {
 181         .driver = {
 182                 .name = AMD_FCH_GPIO_DRIVER_NAME,
 183         },
 184         .probe = amd_fch_gpio_probe,
 185 };
 186 
 187 module_platform_driver(amd_fch_gpio_driver);
 188 
 189 MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
 190 MODULE_DESCRIPTION("AMD G-series FCH GPIO driver");
 191 MODULE_LICENSE("GPL");
 192 MODULE_ALIAS("platform:" AMD_FCH_GPIO_DRIVER_NAME);

/* [<][>][^][v][top][bottom][index][help] */