Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpio/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  gpio-amd-fch.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+

/*
 * GPIO driver for the AMD G series FCH (eg. GX-412TC)
 *
 * Copyright (C) 2018 metux IT consult
 * Author: Enrico Weigelt, metux IT consult <info@metux.net>
 *
 */


#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio/driver.h>
#include <linux/platform_data/gpio/gpio-amd-fch.h>
#include <linux/spinlock.h>

#define AMD_FCH_MMIO_BASE  0xFED80000
#define AMD_FCH_GPIO_BANK0_BASE  0x1500
#define AMD_FCH_GPIO_SIZE  0x0300

#define AMD_FCH_GPIO_FLAG_DIRECTION BIT(23)
#define AMD_FCH_GPIO_FLAG_WRITE  BIT(22)
#define AMD_FCH_GPIO_FLAG_READ  BIT(16)

static const struct resource amd_fch_gpio_iores =
 DEFINE_RES_MEM_NAMED(
  AMD_FCH_MMIO_BASE + AMD_FCH_GPIO_BANK0_BASE,
  AMD_FCH_GPIO_SIZE,
  "amd-fch-gpio-iomem");

struct amd_fch_gpio_priv {
 struct gpio_chip  gc;
 void __iomem   *base;
 struct amd_fch_gpio_pdata *pdata;
 spinlock_t   lock;
};

static void __iomem *amd_fch_gpio_addr(struct amd_fch_gpio_priv *priv,
           unsigned int gpio)
{
 return priv->base + priv->pdata->gpio_reg[gpio]*sizeof(u32);
}

static int amd_fch_gpio_direction_input(struct gpio_chip *gc,
     unsigned int offset)
{
 unsigned long flags;
 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 void __iomem *ptr = amd_fch_gpio_addr(priv, offset);

 spin_lock_irqsave(&priv->lock, flags);
 writel_relaxed(readl_relaxed(ptr) & ~AMD_FCH_GPIO_FLAG_DIRECTION, ptr);
 spin_unlock_irqrestore(&priv->lock, flags);

 return 0;
}

static int amd_fch_gpio_direction_output(struct gpio_chip *gc,
      unsigned int gpio, int value)
{
 unsigned long flags;
 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 void __iomem *ptr = amd_fch_gpio_addr(priv, gpio);
 u32 val;

 spin_lock_irqsave(&priv->lock, flags);

 val = readl_relaxed(ptr);
 if (value)
  val |= AMD_FCH_GPIO_FLAG_WRITE;
 else
  val &= ~AMD_FCH_GPIO_FLAG_WRITE;

 writel_relaxed(val | AMD_FCH_GPIO_FLAG_DIRECTION, ptr);

 spin_unlock_irqrestore(&priv->lock, flags);

 return 0;
}

static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
{
 int ret;
 unsigned long flags;
 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 void __iomem *ptr = amd_fch_gpio_addr(priv, gpio);

 spin_lock_irqsave(&priv->lock, flags);
 ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
 spin_unlock_irqrestore(&priv->lock, flags);

 return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
}

static int amd_fch_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
{
 unsigned long flags;
 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 void __iomem *ptr = amd_fch_gpio_addr(priv, gpio);
 u32 mask;

 spin_lock_irqsave(&priv->lock, flags);

 mask = readl_relaxed(ptr);
 if (value)
  mask |= AMD_FCH_GPIO_FLAG_WRITE;
 else
  mask &= ~AMD_FCH_GPIO_FLAG_WRITE;
 writel_relaxed(mask, ptr);

 spin_unlock_irqrestore(&priv->lock, flags);

 return 0;
}

static int amd_fch_gpio_get(struct gpio_chip *gc,
       unsigned int offset)
{
 unsigned long flags;
 int ret;
 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
 void __iomem *ptr = amd_fch_gpio_addr(priv, offset);

 spin_lock_irqsave(&priv->lock, flags);
 ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_READ);
 spin_unlock_irqrestore(&priv->lock, flags);

 return ret;
}

static int amd_fch_gpio_request(struct gpio_chip *chip,
    unsigned int gpio_pin)
{
 return 0;
}

static int amd_fch_gpio_probe(struct platform_device *pdev)
{
 struct amd_fch_gpio_priv *priv;
 struct amd_fch_gpio_pdata *pdata;

 pdata = dev_get_platdata(&pdev->dev);
 if (!pdata) {
  dev_err(&pdev->dev, "no platform_data\n");
  return -ENOENT;
 }

 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 if (!priv)
  return -ENOMEM;

 priv->pdata = pdata;

 priv->gc.owner   = THIS_MODULE;
 priv->gc.parent   = &pdev->dev;
 priv->gc.label   = dev_name(&pdev->dev);
 priv->gc.ngpio   = priv->pdata->gpio_num;
 priv->gc.names   = priv->pdata->gpio_names;
 priv->gc.base   = -1;
 priv->gc.request  = amd_fch_gpio_request;
 priv->gc.direction_input = amd_fch_gpio_direction_input;
 priv->gc.direction_output = amd_fch_gpio_direction_output;
 priv->gc.get_direction  = amd_fch_gpio_get_direction;
 priv->gc.get   = amd_fch_gpio_get;
 priv->gc.set   = amd_fch_gpio_set;

 spin_lock_init(&priv->lock);

 priv->base = devm_ioremap_resource(&pdev->dev, &amd_fch_gpio_iores);
 if (IS_ERR(priv->base))
  return PTR_ERR(priv->base);

 platform_set_drvdata(pdev, priv);

 return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
}

static struct platform_driver amd_fch_gpio_driver = {
 .driver = {
  .name = AMD_FCH_GPIO_DRIVER_NAME,
 },
 .probe = amd_fch_gpio_probe,
};

module_platform_driver(amd_fch_gpio_driver);

MODULE_AUTHOR("Enrico Weigelt, metux IT consult ");
MODULE_DESCRIPTION("AMD G-series FCH GPIO driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" AMD_FCH_GPIO_DRIVER_NAME);

Messung V0.5
C=96 H=93 G=94

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.