xref: /openbmc/linux/drivers/gpio/gpio-lpc32xx.c (revision ca6b0d99)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f80cb526SLinus Walleij /*
3da03d740SRoland Stigge  * GPIO driver for LPC32xx SoC
4f80cb526SLinus Walleij  *
5f80cb526SLinus Walleij  * Author: Kevin Wells <kevin.wells@nxp.com>
6f80cb526SLinus Walleij  *
7f80cb526SLinus Walleij  * Copyright (C) 2010 NXP Semiconductors
8f80cb526SLinus Walleij  */
9f80cb526SLinus Walleij 
10f80cb526SLinus Walleij #include <linux/kernel.h>
11f80cb526SLinus Walleij #include <linux/init.h>
12f80cb526SLinus Walleij #include <linux/io.h>
13f80cb526SLinus Walleij #include <linux/errno.h>
1411975f9eSLinus Walleij #include <linux/gpio/driver.h>
15831cbd7aSSachin Kamat #include <linux/of.h>
16e92935e1SRoland Stigge #include <linux/platform_device.h>
17e92935e1SRoland Stigge #include <linux/module.h>
18f80cb526SLinus Walleij 
19f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P3_INP_STATE		(0x000)
20f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P3_OUTP_SET		(0x004)
21f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P3_OUTP_CLR		(0x008)
22f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P3_OUTP_STATE		(0x00C)
23f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_DIR_SET			(0x010)
24f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_DIR_CLR			(0x014)
25f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_DIR_STATE		(0x018)
26f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_INP_STATE		(0x01C)
27f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_OUTP_SET		(0x020)
28f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_OUTP_CLR		(0x024)
29f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_MUX_SET			(0x028)
30f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_MUX_CLR			(0x02C)
31f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P2_MUX_STATE		(0x030)
32f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_INP_STATE		(0x040)
33f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_OUTP_SET		(0x044)
34f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_OUTP_CLR		(0x048)
35f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_OUTP_STATE		(0x04C)
36f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_DIR_SET			(0x050)
37f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_DIR_CLR			(0x054)
38f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P0_DIR_STATE		(0x058)
39f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_INP_STATE		(0x060)
40f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_OUTP_SET		(0x064)
41f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_OUTP_CLR		(0x068)
42f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_OUTP_STATE		(0x06C)
43f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_DIR_SET			(0x070)
44f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_DIR_CLR			(0x074)
45f2ee7314SArnd Bergmann #define LPC32XX_GPIO_P1_DIR_STATE		(0x078)
46f80cb526SLinus Walleij 
47f80cb526SLinus Walleij #define GPIO012_PIN_TO_BIT(x)			(1 << (x))
48f80cb526SLinus Walleij #define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
49f80cb526SLinus Walleij #define GPO3_PIN_TO_BIT(x)			(1 << (x))
50f80cb526SLinus Walleij #define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
51f80cb526SLinus Walleij #define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
528e5fb37bSRoland Stigge #define GPIO3_PIN_IN_SEL(x, y)			(((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)
53f80cb526SLinus Walleij #define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
54f80cb526SLinus Walleij #define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
5546158aadSRoland Stigge #define GPO3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
56f80cb526SLinus Walleij 
5714bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P0_MAX	8
5814bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P1_MAX	24
5914bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P2_MAX	13
6014bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P3_MAX	6
6114bf873eSVladimir Zapolskiy #define LPC32XX_GPI_P3_MAX	29
6214bf873eSVladimir Zapolskiy #define LPC32XX_GPO_P3_MAX	24
6314bf873eSVladimir Zapolskiy 
6414bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P0_GRP	0
6514bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P1_GRP	(LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
6614bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P2_GRP	(LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
6714bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P3_GRP	(LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
6814bf873eSVladimir Zapolskiy #define LPC32XX_GPI_P3_GRP	(LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
6914bf873eSVladimir Zapolskiy #define LPC32XX_GPO_P3_GRP	(LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
7014bf873eSVladimir Zapolskiy 
71f80cb526SLinus Walleij struct gpio_regs {
72f2ee7314SArnd Bergmann 	unsigned long inp_state;
73f2ee7314SArnd Bergmann 	unsigned long outp_state;
74f2ee7314SArnd Bergmann 	unsigned long outp_set;
75f2ee7314SArnd Bergmann 	unsigned long outp_clr;
76f2ee7314SArnd Bergmann 	unsigned long dir_set;
77f2ee7314SArnd Bergmann 	unsigned long dir_clr;
78f80cb526SLinus Walleij };
79f80cb526SLinus Walleij 
80f80cb526SLinus Walleij /*
81f80cb526SLinus Walleij  * GPIO names
82f80cb526SLinus Walleij  */
83f80cb526SLinus Walleij static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
84f80cb526SLinus Walleij 	"p0.0", "p0.1", "p0.2", "p0.3",
85f80cb526SLinus Walleij 	"p0.4", "p0.5", "p0.6", "p0.7"
86f80cb526SLinus Walleij };
87f80cb526SLinus Walleij 
88f80cb526SLinus Walleij static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
89f80cb526SLinus Walleij 	"p1.0", "p1.1", "p1.2", "p1.3",
90f80cb526SLinus Walleij 	"p1.4", "p1.5", "p1.6", "p1.7",
91f80cb526SLinus Walleij 	"p1.8", "p1.9", "p1.10", "p1.11",
92f80cb526SLinus Walleij 	"p1.12", "p1.13", "p1.14", "p1.15",
93f80cb526SLinus Walleij 	"p1.16", "p1.17", "p1.18", "p1.19",
94f80cb526SLinus Walleij 	"p1.20", "p1.21", "p1.22", "p1.23",
95f80cb526SLinus Walleij };
96f80cb526SLinus Walleij 
97f80cb526SLinus Walleij static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
98f80cb526SLinus Walleij 	"p2.0", "p2.1", "p2.2", "p2.3",
99f80cb526SLinus Walleij 	"p2.4", "p2.5", "p2.6", "p2.7",
100f80cb526SLinus Walleij 	"p2.8", "p2.9", "p2.10", "p2.11",
101f80cb526SLinus Walleij 	"p2.12"
102f80cb526SLinus Walleij };
103f80cb526SLinus Walleij 
104f80cb526SLinus Walleij static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
10595120d5dSRoland Stigge 	"gpio00", "gpio01", "gpio02", "gpio03",
106f80cb526SLinus Walleij 	"gpio04", "gpio05"
107f80cb526SLinus Walleij };
108f80cb526SLinus Walleij 
109f80cb526SLinus Walleij static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
110f80cb526SLinus Walleij 	"gpi00", "gpi01", "gpi02", "gpi03",
111f80cb526SLinus Walleij 	"gpi04", "gpi05", "gpi06", "gpi07",
112f80cb526SLinus Walleij 	"gpi08", "gpi09",  NULL,    NULL,
113f80cb526SLinus Walleij 	 NULL,    NULL,    NULL,   "gpi15",
114f80cb526SLinus Walleij 	"gpi16", "gpi17", "gpi18", "gpi19",
115f80cb526SLinus Walleij 	"gpi20", "gpi21", "gpi22", "gpi23",
11671fde000SRoland Stigge 	"gpi24", "gpi25", "gpi26", "gpi27",
11771fde000SRoland Stigge 	"gpi28"
118f80cb526SLinus Walleij };
119f80cb526SLinus Walleij 
120f80cb526SLinus Walleij static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
121f80cb526SLinus Walleij 	"gpo00", "gpo01", "gpo02", "gpo03",
122f80cb526SLinus Walleij 	"gpo04", "gpo05", "gpo06", "gpo07",
123f80cb526SLinus Walleij 	"gpo08", "gpo09", "gpo10", "gpo11",
124f80cb526SLinus Walleij 	"gpo12", "gpo13", "gpo14", "gpo15",
125f80cb526SLinus Walleij 	"gpo16", "gpo17", "gpo18", "gpo19",
126f80cb526SLinus Walleij 	"gpo20", "gpo21", "gpo22", "gpo23"
127f80cb526SLinus Walleij };
128f80cb526SLinus Walleij 
129f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p0 = {
130f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
131f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
132f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
133f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
134f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
135f80cb526SLinus Walleij };
136f80cb526SLinus Walleij 
137f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p1 = {
138f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
139f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
140f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
141f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
142f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
143f80cb526SLinus Walleij };
144f80cb526SLinus Walleij 
145f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p2 = {
146f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
147f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
148f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
149f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
150f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
151f80cb526SLinus Walleij };
152f80cb526SLinus Walleij 
153f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p3 = {
154f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
15546158aadSRoland Stigge 	.outp_state	= LPC32XX_GPIO_P3_OUTP_STATE,
156f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
157f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
158f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
159f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
160f80cb526SLinus Walleij };
161f80cb526SLinus Walleij 
162f80cb526SLinus Walleij struct lpc32xx_gpio_chip {
163f80cb526SLinus Walleij 	struct gpio_chip	chip;
164f80cb526SLinus Walleij 	struct gpio_regs	*gpio_grp;
165f2ee7314SArnd Bergmann 	void __iomem		*reg_base;
166f80cb526SLinus Walleij };
167f80cb526SLinus Walleij 
gpreg_read(struct lpc32xx_gpio_chip * group,unsigned long offset)168f2ee7314SArnd Bergmann static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset)
169f2ee7314SArnd Bergmann {
170f2ee7314SArnd Bergmann 	return __raw_readl(group->reg_base + offset);
171f2ee7314SArnd Bergmann }
172f2ee7314SArnd Bergmann 
gpreg_write(struct lpc32xx_gpio_chip * group,u32 val,unsigned long offset)173f2ee7314SArnd Bergmann static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset)
174f2ee7314SArnd Bergmann {
175f2ee7314SArnd Bergmann 	__raw_writel(val, group->reg_base + offset);
176f2ee7314SArnd Bergmann }
177f2ee7314SArnd Bergmann 
__set_gpio_dir_p012(struct lpc32xx_gpio_chip * group,unsigned pin,int input)178f80cb526SLinus Walleij static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
179f80cb526SLinus Walleij 	unsigned pin, int input)
180f80cb526SLinus Walleij {
181f80cb526SLinus Walleij 	if (input)
182f2ee7314SArnd Bergmann 		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
183f80cb526SLinus Walleij 			group->gpio_grp->dir_clr);
184f80cb526SLinus Walleij 	else
185f2ee7314SArnd Bergmann 		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
186f80cb526SLinus Walleij 			group->gpio_grp->dir_set);
187f80cb526SLinus Walleij }
188f80cb526SLinus Walleij 
__set_gpio_dir_p3(struct lpc32xx_gpio_chip * group,unsigned pin,int input)189f80cb526SLinus Walleij static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
190f80cb526SLinus Walleij 	unsigned pin, int input)
191f80cb526SLinus Walleij {
192f80cb526SLinus Walleij 	u32 u = GPIO3_PIN_TO_BIT(pin);
193f80cb526SLinus Walleij 
194f80cb526SLinus Walleij 	if (input)
195f2ee7314SArnd Bergmann 		gpreg_write(group, u, group->gpio_grp->dir_clr);
196f80cb526SLinus Walleij 	else
197f2ee7314SArnd Bergmann 		gpreg_write(group, u, group->gpio_grp->dir_set);
198f80cb526SLinus Walleij }
199f80cb526SLinus Walleij 
__set_gpio_level_p012(struct lpc32xx_gpio_chip * group,unsigned pin,int high)200f80cb526SLinus Walleij static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
201f80cb526SLinus Walleij 	unsigned pin, int high)
202f80cb526SLinus Walleij {
203f80cb526SLinus Walleij 	if (high)
204f2ee7314SArnd Bergmann 		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
205f80cb526SLinus Walleij 			group->gpio_grp->outp_set);
206f80cb526SLinus Walleij 	else
207f2ee7314SArnd Bergmann 		gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
208f80cb526SLinus Walleij 			group->gpio_grp->outp_clr);
209f80cb526SLinus Walleij }
210f80cb526SLinus Walleij 
__set_gpio_level_p3(struct lpc32xx_gpio_chip * group,unsigned pin,int high)211f80cb526SLinus Walleij static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
212f80cb526SLinus Walleij 	unsigned pin, int high)
213f80cb526SLinus Walleij {
214f80cb526SLinus Walleij 	u32 u = GPIO3_PIN_TO_BIT(pin);
215f80cb526SLinus Walleij 
216f80cb526SLinus Walleij 	if (high)
217f2ee7314SArnd Bergmann 		gpreg_write(group, u, group->gpio_grp->outp_set);
218f80cb526SLinus Walleij 	else
219f2ee7314SArnd Bergmann 		gpreg_write(group, u, group->gpio_grp->outp_clr);
220f80cb526SLinus Walleij }
221f80cb526SLinus Walleij 
__set_gpo_level_p3(struct lpc32xx_gpio_chip * group,unsigned pin,int high)222f80cb526SLinus Walleij static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
223f80cb526SLinus Walleij 	unsigned pin, int high)
224f80cb526SLinus Walleij {
225f80cb526SLinus Walleij 	if (high)
226f2ee7314SArnd Bergmann 		gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
227f80cb526SLinus Walleij 	else
228f2ee7314SArnd Bergmann 		gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
229f80cb526SLinus Walleij }
230f80cb526SLinus Walleij 
__get_gpio_state_p012(struct lpc32xx_gpio_chip * group,unsigned pin)231f80cb526SLinus Walleij static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
232f80cb526SLinus Walleij 	unsigned pin)
233f80cb526SLinus Walleij {
234f2ee7314SArnd Bergmann 	return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state),
235f80cb526SLinus Walleij 		pin);
236f80cb526SLinus Walleij }
237f80cb526SLinus Walleij 
__get_gpio_state_p3(struct lpc32xx_gpio_chip * group,unsigned pin)238f80cb526SLinus Walleij static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
239f80cb526SLinus Walleij 	unsigned pin)
240f80cb526SLinus Walleij {
241f2ee7314SArnd Bergmann 	int state = gpreg_read(group, group->gpio_grp->inp_state);
242f80cb526SLinus Walleij 
243f80cb526SLinus Walleij 	/*
244f80cb526SLinus Walleij 	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
245f80cb526SLinus Walleij 	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
246f80cb526SLinus Walleij 	 */
247f80cb526SLinus Walleij 	return GPIO3_PIN_IN_SEL(state, pin);
248f80cb526SLinus Walleij }
249f80cb526SLinus Walleij 
__get_gpi_state_p3(struct lpc32xx_gpio_chip * group,unsigned pin)250f80cb526SLinus Walleij static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
251f80cb526SLinus Walleij 	unsigned pin)
252f80cb526SLinus Walleij {
253f2ee7314SArnd Bergmann 	return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin);
254f80cb526SLinus Walleij }
255f80cb526SLinus Walleij 
__get_gpo_state_p3(struct lpc32xx_gpio_chip * group,unsigned pin)25646158aadSRoland Stigge static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
25746158aadSRoland Stigge 	unsigned pin)
25846158aadSRoland Stigge {
259f2ee7314SArnd Bergmann 	return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin);
26046158aadSRoland Stigge }
26146158aadSRoland Stigge 
262f80cb526SLinus Walleij /*
2637fd2bf3dSAlexandre Courbot  * GPIO primitives.
264f80cb526SLinus Walleij  */
lpc32xx_gpio_dir_input_p012(struct gpio_chip * chip,unsigned pin)265f80cb526SLinus Walleij static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
266f80cb526SLinus Walleij 	unsigned pin)
267f80cb526SLinus Walleij {
268a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
269f80cb526SLinus Walleij 
270f80cb526SLinus Walleij 	__set_gpio_dir_p012(group, pin, 1);
271f80cb526SLinus Walleij 
272f80cb526SLinus Walleij 	return 0;
273f80cb526SLinus Walleij }
274f80cb526SLinus Walleij 
lpc32xx_gpio_dir_input_p3(struct gpio_chip * chip,unsigned pin)275f80cb526SLinus Walleij static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
276f80cb526SLinus Walleij 	unsigned pin)
277f80cb526SLinus Walleij {
278a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
279f80cb526SLinus Walleij 
280f80cb526SLinus Walleij 	__set_gpio_dir_p3(group, pin, 1);
281f80cb526SLinus Walleij 
282f80cb526SLinus Walleij 	return 0;
283f80cb526SLinus Walleij }
284f80cb526SLinus Walleij 
lpc32xx_gpio_dir_in_always(struct gpio_chip * chip,unsigned pin)285f80cb526SLinus Walleij static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
286f80cb526SLinus Walleij 	unsigned pin)
287f80cb526SLinus Walleij {
288f80cb526SLinus Walleij 	return 0;
289f80cb526SLinus Walleij }
290f80cb526SLinus Walleij 
lpc32xx_gpio_get_value_p012(struct gpio_chip * chip,unsigned pin)291f80cb526SLinus Walleij static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
292f80cb526SLinus Walleij {
293a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
294f80cb526SLinus Walleij 
2952e6d8456SLinus Walleij 	return !!__get_gpio_state_p012(group, pin);
296f80cb526SLinus Walleij }
297f80cb526SLinus Walleij 
lpc32xx_gpio_get_value_p3(struct gpio_chip * chip,unsigned pin)298f80cb526SLinus Walleij static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
299f80cb526SLinus Walleij {
300a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
301f80cb526SLinus Walleij 
3022e6d8456SLinus Walleij 	return !!__get_gpio_state_p3(group, pin);
303f80cb526SLinus Walleij }
304f80cb526SLinus Walleij 
lpc32xx_gpi_get_value(struct gpio_chip * chip,unsigned pin)305f80cb526SLinus Walleij static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
306f80cb526SLinus Walleij {
307a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
308f80cb526SLinus Walleij 
3092e6d8456SLinus Walleij 	return !!__get_gpi_state_p3(group, pin);
310f80cb526SLinus Walleij }
311f80cb526SLinus Walleij 
lpc32xx_gpio_dir_output_p012(struct gpio_chip * chip,unsigned pin,int value)312f80cb526SLinus Walleij static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
313f80cb526SLinus Walleij 	int value)
314f80cb526SLinus Walleij {
315a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
316f80cb526SLinus Walleij 
317b1268d37SRoland Stigge 	__set_gpio_level_p012(group, pin, value);
318f80cb526SLinus Walleij 	__set_gpio_dir_p012(group, pin, 0);
319f80cb526SLinus Walleij 
320f80cb526SLinus Walleij 	return 0;
321f80cb526SLinus Walleij }
322f80cb526SLinus Walleij 
lpc32xx_gpio_dir_output_p3(struct gpio_chip * chip,unsigned pin,int value)323f80cb526SLinus Walleij static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
324f80cb526SLinus Walleij 	int value)
325f80cb526SLinus Walleij {
326a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
327f80cb526SLinus Walleij 
328b1268d37SRoland Stigge 	__set_gpio_level_p3(group, pin, value);
329f80cb526SLinus Walleij 	__set_gpio_dir_p3(group, pin, 0);
330f80cb526SLinus Walleij 
331f80cb526SLinus Walleij 	return 0;
332f80cb526SLinus Walleij }
333f80cb526SLinus Walleij 
lpc32xx_gpio_dir_out_always(struct gpio_chip * chip,unsigned pin,int value)334f80cb526SLinus Walleij static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
335f80cb526SLinus Walleij 	int value)
336f80cb526SLinus Walleij {
337a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
338b1268d37SRoland Stigge 
339b1268d37SRoland Stigge 	__set_gpo_level_p3(group, pin, value);
340f80cb526SLinus Walleij 	return 0;
341f80cb526SLinus Walleij }
342f80cb526SLinus Walleij 
lpc32xx_gpio_set_value_p012(struct gpio_chip * chip,unsigned pin,int value)343f80cb526SLinus Walleij static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
344f80cb526SLinus Walleij 	int value)
345f80cb526SLinus Walleij {
346a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
347f80cb526SLinus Walleij 
348f80cb526SLinus Walleij 	__set_gpio_level_p012(group, pin, value);
349f80cb526SLinus Walleij }
350f80cb526SLinus Walleij 
lpc32xx_gpio_set_value_p3(struct gpio_chip * chip,unsigned pin,int value)351f80cb526SLinus Walleij static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
352f80cb526SLinus Walleij 	int value)
353f80cb526SLinus Walleij {
354a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
355f80cb526SLinus Walleij 
356f80cb526SLinus Walleij 	__set_gpio_level_p3(group, pin, value);
357f80cb526SLinus Walleij }
358f80cb526SLinus Walleij 
lpc32xx_gpo_set_value(struct gpio_chip * chip,unsigned pin,int value)359f80cb526SLinus Walleij static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
360f80cb526SLinus Walleij 	int value)
361f80cb526SLinus Walleij {
362a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
363f80cb526SLinus Walleij 
364f80cb526SLinus Walleij 	__set_gpo_level_p3(group, pin, value);
365f80cb526SLinus Walleij }
366f80cb526SLinus Walleij 
lpc32xx_gpo_get_value(struct gpio_chip * chip,unsigned pin)36746158aadSRoland Stigge static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)
36846158aadSRoland Stigge {
369a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
37046158aadSRoland Stigge 
3712e6d8456SLinus Walleij 	return !!__get_gpo_state_p3(group, pin);
37246158aadSRoland Stigge }
37346158aadSRoland Stigge 
lpc32xx_gpio_request(struct gpio_chip * chip,unsigned pin)374f80cb526SLinus Walleij static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
375f80cb526SLinus Walleij {
376f80cb526SLinus Walleij 	if (pin < chip->ngpio)
377f80cb526SLinus Walleij 		return 0;
378f80cb526SLinus Walleij 
379f80cb526SLinus Walleij 	return -EINVAL;
380f80cb526SLinus Walleij }
381f80cb526SLinus Walleij 
lpc32xx_gpio_to_irq_p01(struct gpio_chip * chip,unsigned offset)3820bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
3830bdfeddcSRoland Stigge {
3840bdfeddcSRoland Stigge 	return -ENXIO;
3850bdfeddcSRoland Stigge }
3860bdfeddcSRoland Stigge 
lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip * chip,unsigned offset)387320a6480SSylvain Lemieux static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
388320a6480SSylvain Lemieux {
389320a6480SSylvain Lemieux 	return -ENXIO;
390320a6480SSylvain Lemieux }
3910bdfeddcSRoland Stigge 
lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip * chip,unsigned offset)3920bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
3930bdfeddcSRoland Stigge {
3940bdfeddcSRoland Stigge 	return -ENXIO;
3950bdfeddcSRoland Stigge }
3960bdfeddcSRoland Stigge 
397f80cb526SLinus Walleij static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
398f80cb526SLinus Walleij 	{
399f80cb526SLinus Walleij 		.chip = {
400f80cb526SLinus Walleij 			.label			= "gpio_p0",
401f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
402f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
403f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
404f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
405f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4060bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_p01,
407f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P0_GRP,
408f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P0_MAX,
409f80cb526SLinus Walleij 			.names			= gpio_p0_names,
4109fb1f39eSLinus Walleij 			.can_sleep		= false,
411f80cb526SLinus Walleij 		},
412f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p0,
413f80cb526SLinus Walleij 	},
414f80cb526SLinus Walleij 	{
415f80cb526SLinus Walleij 		.chip = {
416f80cb526SLinus Walleij 			.label			= "gpio_p1",
417f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
418f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
419f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
420f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
421f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4220bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_p01,
423f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P1_GRP,
424f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P1_MAX,
425f80cb526SLinus Walleij 			.names			= gpio_p1_names,
4269fb1f39eSLinus Walleij 			.can_sleep		= false,
427f80cb526SLinus Walleij 		},
428f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p1,
429f80cb526SLinus Walleij 	},
430f80cb526SLinus Walleij 	{
431f80cb526SLinus Walleij 		.chip = {
432f80cb526SLinus Walleij 			.label			= "gpio_p2",
433f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
434f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
435f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
436f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
437f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
438f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P2_GRP,
439f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P2_MAX,
440f80cb526SLinus Walleij 			.names			= gpio_p2_names,
4419fb1f39eSLinus Walleij 			.can_sleep		= false,
442f80cb526SLinus Walleij 		},
443f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p2,
444f80cb526SLinus Walleij 	},
445f80cb526SLinus Walleij 	{
446f80cb526SLinus Walleij 		.chip = {
447f80cb526SLinus Walleij 			.label			= "gpio_p3",
448f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p3,
449f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p3,
450f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p3,
451f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p3,
452f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4530bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_gpio_p3,
454f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P3_GRP,
455f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P3_MAX,
456f80cb526SLinus Walleij 			.names			= gpio_p3_names,
4579fb1f39eSLinus Walleij 			.can_sleep		= false,
458f80cb526SLinus Walleij 		},
459f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
460f80cb526SLinus Walleij 	},
461f80cb526SLinus Walleij 	{
462f80cb526SLinus Walleij 		.chip = {
463f80cb526SLinus Walleij 			.label			= "gpi_p3",
464f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_in_always,
465f80cb526SLinus Walleij 			.get			= lpc32xx_gpi_get_value,
466f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4670bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_gpi_p3,
468f80cb526SLinus Walleij 			.base			= LPC32XX_GPI_P3_GRP,
469f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPI_P3_MAX,
470f80cb526SLinus Walleij 			.names			= gpi_p3_names,
4719fb1f39eSLinus Walleij 			.can_sleep		= false,
472f80cb526SLinus Walleij 		},
473f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
474f80cb526SLinus Walleij 	},
475f80cb526SLinus Walleij 	{
476f80cb526SLinus Walleij 		.chip = {
477f80cb526SLinus Walleij 			.label			= "gpo_p3",
478f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_out_always,
479f80cb526SLinus Walleij 			.set			= lpc32xx_gpo_set_value,
48046158aadSRoland Stigge 			.get			= lpc32xx_gpo_get_value,
481f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
482f80cb526SLinus Walleij 			.base			= LPC32XX_GPO_P3_GRP,
483f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPO_P3_MAX,
484f80cb526SLinus Walleij 			.names			= gpo_p3_names,
4859fb1f39eSLinus Walleij 			.can_sleep		= false,
486f80cb526SLinus Walleij 		},
487f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
488f80cb526SLinus Walleij 	},
489f80cb526SLinus Walleij };
490f80cb526SLinus Walleij 
lpc32xx_of_xlate(struct gpio_chip * gc,const struct of_phandle_args * gpiospec,u32 * flags)491e92935e1SRoland Stigge static int lpc32xx_of_xlate(struct gpio_chip *gc,
492e92935e1SRoland Stigge 			    const struct of_phandle_args *gpiospec, u32 *flags)
493e92935e1SRoland Stigge {
494e92935e1SRoland Stigge 	/* Is this the correct bank? */
495e92935e1SRoland Stigge 	u32 bank = gpiospec->args[0];
496fdc7a9f8SAxel Lin 	if ((bank >= ARRAY_SIZE(lpc32xx_gpiochip) ||
497e92935e1SRoland Stigge 	    (gc != &lpc32xx_gpiochip[bank].chip)))
498e92935e1SRoland Stigge 		return -EINVAL;
499e92935e1SRoland Stigge 
500e92935e1SRoland Stigge 	if (flags)
501e92935e1SRoland Stigge 		*flags = gpiospec->args[2];
502e92935e1SRoland Stigge 	return gpiospec->args[1];
503e92935e1SRoland Stigge }
504e92935e1SRoland Stigge 
lpc32xx_gpio_probe(struct platform_device * pdev)5053836309dSBill Pemberton static int lpc32xx_gpio_probe(struct platform_device *pdev)
506e92935e1SRoland Stigge {
507f80cb526SLinus Walleij 	int i;
508f2ee7314SArnd Bergmann 	void __iomem *reg_base;
509f2ee7314SArnd Bergmann 
510f2ee7314SArnd Bergmann 	reg_base = devm_platform_ioremap_resource(pdev, 0);
511f2ee7314SArnd Bergmann 	if (IS_ERR(reg_base))
512f2ee7314SArnd Bergmann 		return PTR_ERR(reg_base);
513f80cb526SLinus Walleij 
514e92935e1SRoland Stigge 	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
51545a541a6SAndy Shevchenko 		lpc32xx_gpiochip[i].chip.parent = &pdev->dev;
516e92935e1SRoland Stigge 		if (pdev->dev.of_node) {
517e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
518e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
519f2ee7314SArnd Bergmann 			lpc32xx_gpiochip[i].reg_base = reg_base;
520e92935e1SRoland Stigge 		}
52169c0a0a5SLaxman Dewangan 		devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
522a9bc97e4SLinus Walleij 				  &lpc32xx_gpiochip[i]);
523f80cb526SLinus Walleij 	}
524e92935e1SRoland Stigge 
525e92935e1SRoland Stigge 	return 0;
526e92935e1SRoland Stigge }
527e92935e1SRoland Stigge 
528e95c7c45SJingoo Han static const struct of_device_id lpc32xx_gpio_of_match[] = {
529e92935e1SRoland Stigge 	{ .compatible = "nxp,lpc3220-gpio", },
530e92935e1SRoland Stigge 	{ },
531e92935e1SRoland Stigge };
532ca6b0d99SKrzysztof Kozlowski MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match);
533e92935e1SRoland Stigge 
534e92935e1SRoland Stigge static struct platform_driver lpc32xx_gpio_driver = {
535e92935e1SRoland Stigge 	.driver		= {
536e92935e1SRoland Stigge 		.name	= "lpc32xx-gpio",
537bcb6b9e5SZhu Wang 		.of_match_table = lpc32xx_gpio_of_match,
538e92935e1SRoland Stigge 	},
539e92935e1SRoland Stigge 	.probe		= lpc32xx_gpio_probe,
540e92935e1SRoland Stigge };
541e92935e1SRoland Stigge 
542e92935e1SRoland Stigge module_platform_driver(lpc32xx_gpio_driver);
543f2ee7314SArnd Bergmann 
544f2ee7314SArnd Bergmann MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
545f2ee7314SArnd Bergmann MODULE_LICENSE("GPL");
546f2ee7314SArnd Bergmann MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC");
547