1 // SPDX-License-Identifier: GPL-2.0+
4 * GPIO driver for the AMD G series FCH (eg. GX-412TC)
6 * Copyright (C) 2018 metux IT consult
7 * Author: Enrico Weigelt, metux IT consult <info@metux.net>
11 #include <linux/err.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>
20 #define AMD_FCH_MMIO_BASE 0xFED80000
21 #define AMD_FCH_GPIO_BANK0_BASE 0x1500
22 #define AMD_FCH_GPIO_SIZE 0x0300
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)
28 static struct resource amd_fch_gpio_iores
=
30 AMD_FCH_MMIO_BASE
+ AMD_FCH_GPIO_BANK0_BASE
,
32 "amd-fch-gpio-iomem");
34 struct amd_fch_gpio_priv
{
35 struct platform_device
*pdev
;
38 struct amd_fch_gpio_pdata
*pdata
;
42 static void __iomem
*amd_fch_gpio_addr(struct amd_fch_gpio_priv
*priv
,
45 return priv
->base
+ priv
->pdata
->gpio_reg
[gpio
]*sizeof(u32
);
48 static int amd_fch_gpio_direction_input(struct gpio_chip
*gc
,
52 struct amd_fch_gpio_priv
*priv
= gpiochip_get_data(gc
);
53 void __iomem
*ptr
= amd_fch_gpio_addr(priv
, offset
);
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
);
62 static int amd_fch_gpio_direction_output(struct gpio_chip
*gc
,
63 unsigned int gpio
, int value
)
66 struct amd_fch_gpio_priv
*priv
= gpiochip_get_data(gc
);
67 void __iomem
*ptr
= amd_fch_gpio_addr(priv
, gpio
);
70 spin_lock_irqsave(&priv
->lock
, flags
);
72 val
= readl_relaxed(ptr
);
74 val
|= AMD_FCH_GPIO_FLAG_WRITE
;
76 val
&= ~AMD_FCH_GPIO_FLAG_WRITE
;
78 writel_relaxed(val
| AMD_FCH_GPIO_FLAG_DIRECTION
, ptr
);
80 spin_unlock_irqrestore(&priv
->lock
, flags
);
85 static int amd_fch_gpio_get_direction(struct gpio_chip
*gc
, unsigned int gpio
)
89 struct amd_fch_gpio_priv
*priv
= gpiochip_get_data(gc
);
90 void __iomem
*ptr
= amd_fch_gpio_addr(priv
, gpio
);
92 spin_lock_irqsave(&priv
->lock
, flags
);
93 ret
= (readl_relaxed(ptr
) & AMD_FCH_GPIO_FLAG_DIRECTION
);
94 spin_unlock_irqrestore(&priv
->lock
, flags
);
99 static void amd_fch_gpio_set(struct gpio_chip
*gc
,
100 unsigned int gpio
, int value
)
103 struct amd_fch_gpio_priv
*priv
= gpiochip_get_data(gc
);
104 void __iomem
*ptr
= amd_fch_gpio_addr(priv
, gpio
);
107 spin_lock_irqsave(&priv
->lock
, flags
);
109 mask
= readl_relaxed(ptr
);
111 mask
|= AMD_FCH_GPIO_FLAG_WRITE
;
113 mask
&= ~AMD_FCH_GPIO_FLAG_WRITE
;
114 writel_relaxed(mask
, ptr
);
116 spin_unlock_irqrestore(&priv
->lock
, flags
);
119 static int amd_fch_gpio_get(struct gpio_chip
*gc
,
124 struct amd_fch_gpio_priv
*priv
= gpiochip_get_data(gc
);
125 void __iomem
*ptr
= amd_fch_gpio_addr(priv
, offset
);
127 spin_lock_irqsave(&priv
->lock
, flags
);
128 ret
= (readl_relaxed(ptr
) & AMD_FCH_GPIO_FLAG_READ
);
129 spin_unlock_irqrestore(&priv
->lock
, flags
);
134 static int amd_fch_gpio_request(struct gpio_chip
*chip
,
135 unsigned int gpio_pin
)
140 static int amd_fch_gpio_probe(struct platform_device
*pdev
)
142 struct amd_fch_gpio_priv
*priv
;
143 struct amd_fch_gpio_pdata
*pdata
;
145 pdata
= dev_get_platdata(&pdev
->dev
);
147 dev_err(&pdev
->dev
, "no platform_data\n");
151 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
158 priv
->gc
.owner
= THIS_MODULE
;
159 priv
->gc
.parent
= &pdev
->dev
;
160 priv
->gc
.label
= dev_name(&pdev
->dev
);
161 priv
->gc
.ngpio
= priv
->pdata
->gpio_num
;
162 priv
->gc
.names
= priv
->pdata
->gpio_names
;
164 priv
->gc
.request
= amd_fch_gpio_request
;
165 priv
->gc
.direction_input
= amd_fch_gpio_direction_input
;
166 priv
->gc
.direction_output
= amd_fch_gpio_direction_output
;
167 priv
->gc
.get_direction
= amd_fch_gpio_get_direction
;
168 priv
->gc
.get
= amd_fch_gpio_get
;
169 priv
->gc
.set
= amd_fch_gpio_set
;
171 spin_lock_init(&priv
->lock
);
173 priv
->base
= devm_ioremap_resource(&pdev
->dev
, &amd_fch_gpio_iores
);
174 if (IS_ERR(priv
->base
))
175 return PTR_ERR(priv
->base
);
177 platform_set_drvdata(pdev
, priv
);
179 return devm_gpiochip_add_data(&pdev
->dev
, &priv
->gc
, priv
);
182 static struct platform_driver amd_fch_gpio_driver
= {
184 .name
= AMD_FCH_GPIO_DRIVER_NAME
,
186 .probe
= amd_fch_gpio_probe
,
189 module_platform_driver(amd_fch_gpio_driver
);
191 MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
192 MODULE_DESCRIPTION("AMD G-series FCH GPIO driver");
193 MODULE_LICENSE("GPL");
194 MODULE_ALIAS("platform:" AMD_FCH_GPIO_DRIVER_NAME
);