summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorEnrico Weigelt, metux IT consult <info@metux.net>2019-02-22 04:54:15 -0500
committerLinus Walleij <linus.walleij@linaro.org>2019-02-22 11:26:52 -0500
commite09d168f13f0d63df7fe095d52be04c16cbe1cef (patch)
treeb9cd8fb3c7f2ba769a5d6f135a8ca8b41477cba1 /drivers/gpio
parent837ccda3480d2861c09aabc5fa014be18df9dd3c (diff)
gpio: AMD G-Series PCH gpio driver
GPIO platform driver for the AMD G-series PCH (eg. on GX-412TC) This driver doesn't registers itself automatically, as it needs to be provided with platform specific configuration, provided by some board driver setup code. Didn't implement oftree probing yet, as it's rarely found on x86. Cc: linux-gpio@vger.kernel.org Cc: linus.walleij@linaro.org Cc: bgolaszewski@baylibre.com Cc: dvhart@infradead.org Cc: platform-driver-x86@vger.kernel.org Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig9
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-amd-fch.c185
3 files changed, 195 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 486d9de2716a..3f50526a771f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -655,6 +655,15 @@ config GPIO_LOONGSON1
655 help 655 help
656 Say Y or M here to support GPIO on Loongson1 SoCs. 656 Say Y or M here to support GPIO on Loongson1 SoCs.
657 657
658config GPIO_AMD_FCH
659 tristate "GPIO support for AMD Fusion Controller Hub (G-series SOCs)"
660 help
661 This option enables driver for GPIO on AMDs Fusion Controller Hub,
662 as found on G-series SOCs (eg. GX-412TC)
663
664 Note: This driver doesn't registers itself automatically, as it
665 needs to be provided with platform specific configuration.
666 (See eg. CONFIG_PCENGINES_APU2.)
658endmenu 667endmenu
659 668
660menu "Port-mapped I/O GPIO drivers" 669menu "Port-mapped I/O GPIO drivers"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9655927a3dcf..54d55274b93a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
27obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o 27obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
28obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o 28obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
29obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o 29obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
30obj-$(CONFIG_GPIO_AMD_FCH) += gpio-amd-fch.o
30obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o 31obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
31obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o 32obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
32obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o 33obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
diff --git a/drivers/gpio/gpio-amd-fch.c b/drivers/gpio/gpio-amd-fch.c
new file mode 100644
index 000000000000..3b4fdce325c1
--- /dev/null
+++ b/drivers/gpio/gpio-amd-fch.c
@@ -0,0 +1,185 @@
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
28static 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
34struct amd_fch_gpio_priv {
35 struct platform_device *pdev;
36 struct gpio_chip gc;
37 void __iomem *base;
38 struct amd_fch_gpio_pdata *pdata;
39 spinlock_t lock;
40};
41
42static void *amd_fch_gpio_addr(struct amd_fch_gpio_priv *priv,
43 unsigned int gpio)
44{
45 return priv->base + priv->pdata->gpio_reg[gpio]*sizeof(u32);
46}
47
48static int amd_fch_gpio_direction_input(struct gpio_chip *gc,
49 unsigned int offset)
50{
51 unsigned long flags;
52 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
53 void *ptr = amd_fch_gpio_addr(priv, offset);
54
55 spin_lock_irqsave(&priv->lock, flags);
56 writel_relaxed(readl_relaxed(ptr) & ~AMD_FCH_GPIO_FLAG_DIRECTION, ptr);
57 spin_unlock_irqrestore(&priv->lock, flags);
58
59 return 0;
60}
61
62static int amd_fch_gpio_direction_output(struct gpio_chip *gc,
63 unsigned int gpio, int value)
64{
65 unsigned long flags;
66 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
67 void *ptr = amd_fch_gpio_addr(priv, gpio);
68
69 spin_lock_irqsave(&priv->lock, flags);
70 writel_relaxed(readl_relaxed(ptr) | AMD_FCH_GPIO_FLAG_DIRECTION, ptr);
71 spin_unlock_irqrestore(&priv->lock, flags);
72
73 return 0;
74}
75
76static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
77{
78 int ret;
79 unsigned long flags;
80 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
81 void *ptr = amd_fch_gpio_addr(priv, gpio);
82
83 spin_lock_irqsave(&priv->lock, flags);
84 ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
85 spin_unlock_irqrestore(&priv->lock, flags);
86
87 return ret;
88}
89
90static void amd_fch_gpio_set(struct gpio_chip *gc,
91 unsigned int gpio, int value)
92{
93 unsigned long flags;
94 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
95 void *ptr = amd_fch_gpio_addr(priv, gpio);
96 u32 mask;
97
98 spin_lock_irqsave(&priv->lock, flags);
99
100 mask = readl_relaxed(ptr);
101 if (value)
102 mask |= AMD_FCH_GPIO_FLAG_WRITE;
103 else
104 mask &= ~AMD_FCH_GPIO_FLAG_WRITE;
105 writel_relaxed(mask, ptr);
106
107 spin_unlock_irqrestore(&priv->lock, flags);
108}
109
110static int amd_fch_gpio_get(struct gpio_chip *gc,
111 unsigned int offset)
112{
113 unsigned long flags;
114 int ret;
115 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
116 void *ptr = amd_fch_gpio_addr(priv, offset);
117
118 spin_lock_irqsave(&priv->lock, flags);
119 ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_READ);
120 spin_unlock_irqrestore(&priv->lock, flags);
121
122 return ret;
123}
124
125static int amd_fch_gpio_request(struct gpio_chip *chip,
126 unsigned int gpio_pin)
127{
128 return 0;
129}
130
131static int amd_fch_gpio_probe(struct platform_device *pdev)
132{
133 struct amd_fch_gpio_priv *priv;
134 struct amd_fch_gpio_pdata *pdata;
135
136 pdata = dev_get_platdata(&pdev->dev);
137 if (!pdata) {
138 dev_err(&pdev->dev, "no platform_data\n");
139 return -ENOENT;
140 }
141
142 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
143 if (!priv)
144 return -ENOMEM;
145
146 priv->pdata = pdata;
147 priv->pdev = pdev;
148
149 priv->gc.owner = THIS_MODULE;
150 priv->gc.parent = &pdev->dev;
151 priv->gc.label = dev_name(&pdev->dev);
152 priv->gc.ngpio = priv->pdata->gpio_num;
153 priv->gc.names = priv->pdata->gpio_names;
154 priv->gc.base = -1;
155 priv->gc.request = amd_fch_gpio_request;
156 priv->gc.direction_input = amd_fch_gpio_direction_input;
157 priv->gc.direction_output = amd_fch_gpio_direction_output;
158 priv->gc.get_direction = amd_fch_gpio_get_direction;
159 priv->gc.get = amd_fch_gpio_get;
160 priv->gc.set = amd_fch_gpio_set;
161
162 spin_lock_init(&priv->lock);
163
164 priv->base = devm_ioremap_resource(&pdev->dev, &amd_fch_gpio_iores);
165 if (IS_ERR(priv->base))
166 return PTR_ERR(priv->base);
167
168 platform_set_drvdata(pdev, priv);
169
170 return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
171}
172
173static struct platform_driver amd_fch_gpio_driver = {
174 .driver = {
175 .name = AMD_FCH_GPIO_DRIVER_NAME,
176 },
177 .probe = amd_fch_gpio_probe,
178};
179
180module_platform_driver(amd_fch_gpio_driver);
181
182MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
183MODULE_DESCRIPTION("AMD G-series FCH GPIO driver");
184MODULE_LICENSE("GPL");
185MODULE_ALIAS("platform:" AMD_FCH_GPIO_DRIVER_NAME);