xref: /openbmc/linux/drivers/gpio/gpio-lpc32xx.c (revision 11975f9e)
1f80cb526SLinus Walleij /*
2da03d740SRoland Stigge  * GPIO driver for LPC32xx SoC
3f80cb526SLinus Walleij  *
4f80cb526SLinus Walleij  * Author: Kevin Wells <kevin.wells@nxp.com>
5f80cb526SLinus Walleij  *
6f80cb526SLinus Walleij  * Copyright (C) 2010 NXP Semiconductors
7f80cb526SLinus Walleij  *
8f80cb526SLinus Walleij  * This program is free software; you can redistribute it and/or modify
9f80cb526SLinus Walleij  * it under the terms of the GNU General Public License as published by
10f80cb526SLinus Walleij  * the Free Software Foundation; either version 2 of the License, or
11f80cb526SLinus Walleij  * (at your option) any later version.
12f80cb526SLinus Walleij  *
13f80cb526SLinus Walleij  * This program is distributed in the hope that it will be useful,
14f80cb526SLinus Walleij  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15f80cb526SLinus Walleij  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f80cb526SLinus Walleij  * GNU General Public License for more details.
17f80cb526SLinus Walleij  */
18f80cb526SLinus Walleij 
19f80cb526SLinus Walleij #include <linux/kernel.h>
20f80cb526SLinus Walleij #include <linux/init.h>
21f80cb526SLinus Walleij #include <linux/io.h>
22f80cb526SLinus Walleij #include <linux/errno.h>
2311975f9eSLinus Walleij #include <linux/gpio/driver.h>
24831cbd7aSSachin Kamat #include <linux/of.h>
25e92935e1SRoland Stigge #include <linux/platform_device.h>
26e92935e1SRoland Stigge #include <linux/module.h>
27f80cb526SLinus Walleij 
28f80cb526SLinus Walleij #include <mach/hardware.h>
29f80cb526SLinus Walleij #include <mach/platform.h>
30f80cb526SLinus Walleij 
31f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
32f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
33f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
34f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
35f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
36f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
37f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
38f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
39f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
40f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
41f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
42f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
43f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
44f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
45f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
46f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
47f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
48f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
49f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
50f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
51f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
52f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
53f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
54f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
55f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
56f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
57f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
58f80cb526SLinus Walleij 
59f80cb526SLinus Walleij #define GPIO012_PIN_TO_BIT(x)			(1 << (x))
60f80cb526SLinus Walleij #define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
61f80cb526SLinus Walleij #define GPO3_PIN_TO_BIT(x)			(1 << (x))
62f80cb526SLinus Walleij #define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
63f80cb526SLinus Walleij #define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
648e5fb37bSRoland Stigge #define GPIO3_PIN_IN_SEL(x, y)			(((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)
65f80cb526SLinus Walleij #define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
66f80cb526SLinus Walleij #define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
6746158aadSRoland Stigge #define GPO3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
68f80cb526SLinus Walleij 
6914bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P0_MAX	8
7014bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P1_MAX	24
7114bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P2_MAX	13
7214bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P3_MAX	6
7314bf873eSVladimir Zapolskiy #define LPC32XX_GPI_P3_MAX	29
7414bf873eSVladimir Zapolskiy #define LPC32XX_GPO_P3_MAX	24
7514bf873eSVladimir Zapolskiy 
7614bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P0_GRP	0
7714bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P1_GRP	(LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
7814bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P2_GRP	(LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
7914bf873eSVladimir Zapolskiy #define LPC32XX_GPIO_P3_GRP	(LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
8014bf873eSVladimir Zapolskiy #define LPC32XX_GPI_P3_GRP	(LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
8114bf873eSVladimir Zapolskiy #define LPC32XX_GPO_P3_GRP	(LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
8214bf873eSVladimir Zapolskiy 
83f80cb526SLinus Walleij struct gpio_regs {
84f80cb526SLinus Walleij 	void __iomem *inp_state;
8546158aadSRoland Stigge 	void __iomem *outp_state;
86f80cb526SLinus Walleij 	void __iomem *outp_set;
87f80cb526SLinus Walleij 	void __iomem *outp_clr;
88f80cb526SLinus Walleij 	void __iomem *dir_set;
89f80cb526SLinus Walleij 	void __iomem *dir_clr;
90f80cb526SLinus Walleij };
91f80cb526SLinus Walleij 
92f80cb526SLinus Walleij /*
93f80cb526SLinus Walleij  * GPIO names
94f80cb526SLinus Walleij  */
95f80cb526SLinus Walleij static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
96f80cb526SLinus Walleij 	"p0.0", "p0.1", "p0.2", "p0.3",
97f80cb526SLinus Walleij 	"p0.4", "p0.5", "p0.6", "p0.7"
98f80cb526SLinus Walleij };
99f80cb526SLinus Walleij 
100f80cb526SLinus Walleij static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
101f80cb526SLinus Walleij 	"p1.0", "p1.1", "p1.2", "p1.3",
102f80cb526SLinus Walleij 	"p1.4", "p1.5", "p1.6", "p1.7",
103f80cb526SLinus Walleij 	"p1.8", "p1.9", "p1.10", "p1.11",
104f80cb526SLinus Walleij 	"p1.12", "p1.13", "p1.14", "p1.15",
105f80cb526SLinus Walleij 	"p1.16", "p1.17", "p1.18", "p1.19",
106f80cb526SLinus Walleij 	"p1.20", "p1.21", "p1.22", "p1.23",
107f80cb526SLinus Walleij };
108f80cb526SLinus Walleij 
109f80cb526SLinus Walleij static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
110f80cb526SLinus Walleij 	"p2.0", "p2.1", "p2.2", "p2.3",
111f80cb526SLinus Walleij 	"p2.4", "p2.5", "p2.6", "p2.7",
112f80cb526SLinus Walleij 	"p2.8", "p2.9", "p2.10", "p2.11",
113f80cb526SLinus Walleij 	"p2.12"
114f80cb526SLinus Walleij };
115f80cb526SLinus Walleij 
116f80cb526SLinus Walleij static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
11795120d5dSRoland Stigge 	"gpio00", "gpio01", "gpio02", "gpio03",
118f80cb526SLinus Walleij 	"gpio04", "gpio05"
119f80cb526SLinus Walleij };
120f80cb526SLinus Walleij 
121f80cb526SLinus Walleij static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
122f80cb526SLinus Walleij 	"gpi00", "gpi01", "gpi02", "gpi03",
123f80cb526SLinus Walleij 	"gpi04", "gpi05", "gpi06", "gpi07",
124f80cb526SLinus Walleij 	"gpi08", "gpi09",  NULL,    NULL,
125f80cb526SLinus Walleij 	 NULL,    NULL,    NULL,   "gpi15",
126f80cb526SLinus Walleij 	"gpi16", "gpi17", "gpi18", "gpi19",
127f80cb526SLinus Walleij 	"gpi20", "gpi21", "gpi22", "gpi23",
12871fde000SRoland Stigge 	"gpi24", "gpi25", "gpi26", "gpi27",
12971fde000SRoland Stigge 	"gpi28"
130f80cb526SLinus Walleij };
131f80cb526SLinus Walleij 
132f80cb526SLinus Walleij static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
133f80cb526SLinus Walleij 	"gpo00", "gpo01", "gpo02", "gpo03",
134f80cb526SLinus Walleij 	"gpo04", "gpo05", "gpo06", "gpo07",
135f80cb526SLinus Walleij 	"gpo08", "gpo09", "gpo10", "gpo11",
136f80cb526SLinus Walleij 	"gpo12", "gpo13", "gpo14", "gpo15",
137f80cb526SLinus Walleij 	"gpo16", "gpo17", "gpo18", "gpo19",
138f80cb526SLinus Walleij 	"gpo20", "gpo21", "gpo22", "gpo23"
139f80cb526SLinus Walleij };
140f80cb526SLinus Walleij 
141f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p0 = {
142f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
143f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
144f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
145f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
146f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
147f80cb526SLinus Walleij };
148f80cb526SLinus Walleij 
149f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p1 = {
150f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
151f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
152f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
153f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
154f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
155f80cb526SLinus Walleij };
156f80cb526SLinus Walleij 
157f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p2 = {
158f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
159f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
160f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
161f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
162f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
163f80cb526SLinus Walleij };
164f80cb526SLinus Walleij 
165f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p3 = {
166f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
16746158aadSRoland Stigge 	.outp_state	= LPC32XX_GPIO_P3_OUTP_STATE,
168f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
169f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
170f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
171f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
172f80cb526SLinus Walleij };
173f80cb526SLinus Walleij 
174f80cb526SLinus Walleij struct lpc32xx_gpio_chip {
175f80cb526SLinus Walleij 	struct gpio_chip	chip;
176f80cb526SLinus Walleij 	struct gpio_regs	*gpio_grp;
177f80cb526SLinus Walleij };
178f80cb526SLinus Walleij 
179f80cb526SLinus Walleij static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
180f80cb526SLinus Walleij 	unsigned pin, int input)
181f80cb526SLinus Walleij {
182f80cb526SLinus Walleij 	if (input)
183f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
184f80cb526SLinus Walleij 			group->gpio_grp->dir_clr);
185f80cb526SLinus Walleij 	else
186f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
187f80cb526SLinus Walleij 			group->gpio_grp->dir_set);
188f80cb526SLinus Walleij }
189f80cb526SLinus Walleij 
190f80cb526SLinus Walleij static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
191f80cb526SLinus Walleij 	unsigned pin, int input)
192f80cb526SLinus Walleij {
193f80cb526SLinus Walleij 	u32 u = GPIO3_PIN_TO_BIT(pin);
194f80cb526SLinus Walleij 
195f80cb526SLinus Walleij 	if (input)
196f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->dir_clr);
197f80cb526SLinus Walleij 	else
198f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->dir_set);
199f80cb526SLinus Walleij }
200f80cb526SLinus Walleij 
201f80cb526SLinus Walleij static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
202f80cb526SLinus Walleij 	unsigned pin, int high)
203f80cb526SLinus Walleij {
204f80cb526SLinus Walleij 	if (high)
205f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
206f80cb526SLinus Walleij 			group->gpio_grp->outp_set);
207f80cb526SLinus Walleij 	else
208f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
209f80cb526SLinus Walleij 			group->gpio_grp->outp_clr);
210f80cb526SLinus Walleij }
211f80cb526SLinus Walleij 
212f80cb526SLinus Walleij static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
213f80cb526SLinus Walleij 	unsigned pin, int high)
214f80cb526SLinus Walleij {
215f80cb526SLinus Walleij 	u32 u = GPIO3_PIN_TO_BIT(pin);
216f80cb526SLinus Walleij 
217f80cb526SLinus Walleij 	if (high)
218f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->outp_set);
219f80cb526SLinus Walleij 	else
220f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->outp_clr);
221f80cb526SLinus Walleij }
222f80cb526SLinus Walleij 
223f80cb526SLinus Walleij static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
224f80cb526SLinus Walleij 	unsigned pin, int high)
225f80cb526SLinus Walleij {
226f80cb526SLinus Walleij 	if (high)
227f80cb526SLinus Walleij 		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
228f80cb526SLinus Walleij 	else
229f80cb526SLinus Walleij 		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
230f80cb526SLinus Walleij }
231f80cb526SLinus Walleij 
232f80cb526SLinus Walleij static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
233f80cb526SLinus Walleij 	unsigned pin)
234f80cb526SLinus Walleij {
235f80cb526SLinus Walleij 	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
236f80cb526SLinus Walleij 		pin);
237f80cb526SLinus Walleij }
238f80cb526SLinus Walleij 
239f80cb526SLinus Walleij static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
240f80cb526SLinus Walleij 	unsigned pin)
241f80cb526SLinus Walleij {
242f80cb526SLinus Walleij 	int state = __raw_readl(group->gpio_grp->inp_state);
243f80cb526SLinus Walleij 
244f80cb526SLinus Walleij 	/*
245f80cb526SLinus Walleij 	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
246f80cb526SLinus Walleij 	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
247f80cb526SLinus Walleij 	 */
248f80cb526SLinus Walleij 	return GPIO3_PIN_IN_SEL(state, pin);
249f80cb526SLinus Walleij }
250f80cb526SLinus Walleij 
251f80cb526SLinus Walleij static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
252f80cb526SLinus Walleij 	unsigned pin)
253f80cb526SLinus Walleij {
254f80cb526SLinus Walleij 	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
255f80cb526SLinus Walleij }
256f80cb526SLinus Walleij 
25746158aadSRoland Stigge static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
25846158aadSRoland Stigge 	unsigned pin)
25946158aadSRoland Stigge {
26046158aadSRoland Stigge 	return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin);
26146158aadSRoland Stigge }
26246158aadSRoland Stigge 
263f80cb526SLinus Walleij /*
2647fd2bf3dSAlexandre Courbot  * GPIO primitives.
265f80cb526SLinus Walleij  */
266f80cb526SLinus Walleij static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
267f80cb526SLinus Walleij 	unsigned pin)
268f80cb526SLinus Walleij {
269a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
270f80cb526SLinus Walleij 
271f80cb526SLinus Walleij 	__set_gpio_dir_p012(group, pin, 1);
272f80cb526SLinus Walleij 
273f80cb526SLinus Walleij 	return 0;
274f80cb526SLinus Walleij }
275f80cb526SLinus Walleij 
276f80cb526SLinus Walleij static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
277f80cb526SLinus Walleij 	unsigned pin)
278f80cb526SLinus Walleij {
279a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
280f80cb526SLinus Walleij 
281f80cb526SLinus Walleij 	__set_gpio_dir_p3(group, pin, 1);
282f80cb526SLinus Walleij 
283f80cb526SLinus Walleij 	return 0;
284f80cb526SLinus Walleij }
285f80cb526SLinus Walleij 
286f80cb526SLinus Walleij static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
287f80cb526SLinus Walleij 	unsigned pin)
288f80cb526SLinus Walleij {
289f80cb526SLinus Walleij 	return 0;
290f80cb526SLinus Walleij }
291f80cb526SLinus Walleij 
292f80cb526SLinus Walleij static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
293f80cb526SLinus Walleij {
294a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
295f80cb526SLinus Walleij 
2962e6d8456SLinus Walleij 	return !!__get_gpio_state_p012(group, pin);
297f80cb526SLinus Walleij }
298f80cb526SLinus Walleij 
299f80cb526SLinus Walleij static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
300f80cb526SLinus Walleij {
301a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
302f80cb526SLinus Walleij 
3032e6d8456SLinus Walleij 	return !!__get_gpio_state_p3(group, pin);
304f80cb526SLinus Walleij }
305f80cb526SLinus Walleij 
306f80cb526SLinus Walleij static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
307f80cb526SLinus Walleij {
308a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
309f80cb526SLinus Walleij 
3102e6d8456SLinus Walleij 	return !!__get_gpi_state_p3(group, pin);
311f80cb526SLinus Walleij }
312f80cb526SLinus Walleij 
313f80cb526SLinus Walleij static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
314f80cb526SLinus Walleij 	int value)
315f80cb526SLinus Walleij {
316a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
317f80cb526SLinus Walleij 
318b1268d37SRoland Stigge 	__set_gpio_level_p012(group, pin, value);
319f80cb526SLinus Walleij 	__set_gpio_dir_p012(group, pin, 0);
320f80cb526SLinus Walleij 
321f80cb526SLinus Walleij 	return 0;
322f80cb526SLinus Walleij }
323f80cb526SLinus Walleij 
324f80cb526SLinus Walleij static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
325f80cb526SLinus Walleij 	int value)
326f80cb526SLinus Walleij {
327a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
328f80cb526SLinus Walleij 
329b1268d37SRoland Stigge 	__set_gpio_level_p3(group, pin, value);
330f80cb526SLinus Walleij 	__set_gpio_dir_p3(group, pin, 0);
331f80cb526SLinus Walleij 
332f80cb526SLinus Walleij 	return 0;
333f80cb526SLinus Walleij }
334f80cb526SLinus Walleij 
335f80cb526SLinus Walleij static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
336f80cb526SLinus Walleij 	int value)
337f80cb526SLinus Walleij {
338a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
339b1268d37SRoland Stigge 
340b1268d37SRoland Stigge 	__set_gpo_level_p3(group, pin, value);
341f80cb526SLinus Walleij 	return 0;
342f80cb526SLinus Walleij }
343f80cb526SLinus Walleij 
344f80cb526SLinus Walleij static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
345f80cb526SLinus Walleij 	int value)
346f80cb526SLinus Walleij {
347a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
348f80cb526SLinus Walleij 
349f80cb526SLinus Walleij 	__set_gpio_level_p012(group, pin, value);
350f80cb526SLinus Walleij }
351f80cb526SLinus Walleij 
352f80cb526SLinus Walleij static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
353f80cb526SLinus Walleij 	int value)
354f80cb526SLinus Walleij {
355a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
356f80cb526SLinus Walleij 
357f80cb526SLinus Walleij 	__set_gpio_level_p3(group, pin, value);
358f80cb526SLinus Walleij }
359f80cb526SLinus Walleij 
360f80cb526SLinus Walleij static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
361f80cb526SLinus Walleij 	int value)
362f80cb526SLinus Walleij {
363a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
364f80cb526SLinus Walleij 
365f80cb526SLinus Walleij 	__set_gpo_level_p3(group, pin, value);
366f80cb526SLinus Walleij }
367f80cb526SLinus Walleij 
36846158aadSRoland Stigge static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)
36946158aadSRoland Stigge {
370a9bc97e4SLinus Walleij 	struct lpc32xx_gpio_chip *group = gpiochip_get_data(chip);
37146158aadSRoland Stigge 
3722e6d8456SLinus Walleij 	return !!__get_gpo_state_p3(group, pin);
37346158aadSRoland Stigge }
37446158aadSRoland Stigge 
375f80cb526SLinus Walleij static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
376f80cb526SLinus Walleij {
377f80cb526SLinus Walleij 	if (pin < chip->ngpio)
378f80cb526SLinus Walleij 		return 0;
379f80cb526SLinus Walleij 
380f80cb526SLinus Walleij 	return -EINVAL;
381f80cb526SLinus Walleij }
382f80cb526SLinus Walleij 
3830bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
3840bdfeddcSRoland Stigge {
3850bdfeddcSRoland Stigge 	return -ENXIO;
3860bdfeddcSRoland Stigge }
3870bdfeddcSRoland Stigge 
388320a6480SSylvain Lemieux static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
389320a6480SSylvain Lemieux {
390320a6480SSylvain Lemieux 	return -ENXIO;
391320a6480SSylvain Lemieux }
3920bdfeddcSRoland Stigge 
3930bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
3940bdfeddcSRoland Stigge {
3950bdfeddcSRoland Stigge 	return -ENXIO;
3960bdfeddcSRoland Stigge }
3970bdfeddcSRoland Stigge 
398f80cb526SLinus Walleij static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
399f80cb526SLinus Walleij 	{
400f80cb526SLinus Walleij 		.chip = {
401f80cb526SLinus Walleij 			.label			= "gpio_p0",
402f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
403f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
404f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
405f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
406f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4070bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_p01,
408f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P0_GRP,
409f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P0_MAX,
410f80cb526SLinus Walleij 			.names			= gpio_p0_names,
4119fb1f39eSLinus Walleij 			.can_sleep		= false,
412f80cb526SLinus Walleij 		},
413f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p0,
414f80cb526SLinus Walleij 	},
415f80cb526SLinus Walleij 	{
416f80cb526SLinus Walleij 		.chip = {
417f80cb526SLinus Walleij 			.label			= "gpio_p1",
418f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
419f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
420f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
421f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
422f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4230bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_p01,
424f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P1_GRP,
425f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P1_MAX,
426f80cb526SLinus Walleij 			.names			= gpio_p1_names,
4279fb1f39eSLinus Walleij 			.can_sleep		= false,
428f80cb526SLinus Walleij 		},
429f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p1,
430f80cb526SLinus Walleij 	},
431f80cb526SLinus Walleij 	{
432f80cb526SLinus Walleij 		.chip = {
433f80cb526SLinus Walleij 			.label			= "gpio_p2",
434f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
435f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
436f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
437f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
438f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
439f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P2_GRP,
440f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P2_MAX,
441f80cb526SLinus Walleij 			.names			= gpio_p2_names,
4429fb1f39eSLinus Walleij 			.can_sleep		= false,
443f80cb526SLinus Walleij 		},
444f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p2,
445f80cb526SLinus Walleij 	},
446f80cb526SLinus Walleij 	{
447f80cb526SLinus Walleij 		.chip = {
448f80cb526SLinus Walleij 			.label			= "gpio_p3",
449f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p3,
450f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p3,
451f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p3,
452f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p3,
453f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4540bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_gpio_p3,
455f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P3_GRP,
456f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P3_MAX,
457f80cb526SLinus Walleij 			.names			= gpio_p3_names,
4589fb1f39eSLinus Walleij 			.can_sleep		= false,
459f80cb526SLinus Walleij 		},
460f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
461f80cb526SLinus Walleij 	},
462f80cb526SLinus Walleij 	{
463f80cb526SLinus Walleij 		.chip = {
464f80cb526SLinus Walleij 			.label			= "gpi_p3",
465f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_in_always,
466f80cb526SLinus Walleij 			.get			= lpc32xx_gpi_get_value,
467f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4680bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_gpi_p3,
469f80cb526SLinus Walleij 			.base			= LPC32XX_GPI_P3_GRP,
470f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPI_P3_MAX,
471f80cb526SLinus Walleij 			.names			= gpi_p3_names,
4729fb1f39eSLinus Walleij 			.can_sleep		= false,
473f80cb526SLinus Walleij 		},
474f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
475f80cb526SLinus Walleij 	},
476f80cb526SLinus Walleij 	{
477f80cb526SLinus Walleij 		.chip = {
478f80cb526SLinus Walleij 			.label			= "gpo_p3",
479f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_out_always,
480f80cb526SLinus Walleij 			.set			= lpc32xx_gpo_set_value,
48146158aadSRoland Stigge 			.get			= lpc32xx_gpo_get_value,
482f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
483f80cb526SLinus Walleij 			.base			= LPC32XX_GPO_P3_GRP,
484f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPO_P3_MAX,
485f80cb526SLinus Walleij 			.names			= gpo_p3_names,
4869fb1f39eSLinus Walleij 			.can_sleep		= false,
487f80cb526SLinus Walleij 		},
488f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
489f80cb526SLinus Walleij 	},
490f80cb526SLinus Walleij };
491f80cb526SLinus Walleij 
492e92935e1SRoland Stigge static int lpc32xx_of_xlate(struct gpio_chip *gc,
493e92935e1SRoland Stigge 			    const struct of_phandle_args *gpiospec, u32 *flags)
494e92935e1SRoland Stigge {
495e92935e1SRoland Stigge 	/* Is this the correct bank? */
496e92935e1SRoland Stigge 	u32 bank = gpiospec->args[0];
497fdc7a9f8SAxel Lin 	if ((bank >= ARRAY_SIZE(lpc32xx_gpiochip) ||
498e92935e1SRoland Stigge 	    (gc != &lpc32xx_gpiochip[bank].chip)))
499e92935e1SRoland Stigge 		return -EINVAL;
500e92935e1SRoland Stigge 
501e92935e1SRoland Stigge 	if (flags)
502e92935e1SRoland Stigge 		*flags = gpiospec->args[2];
503e92935e1SRoland Stigge 	return gpiospec->args[1];
504e92935e1SRoland Stigge }
505e92935e1SRoland Stigge 
5063836309dSBill Pemberton static int lpc32xx_gpio_probe(struct platform_device *pdev)
507e92935e1SRoland Stigge {
508f80cb526SLinus Walleij 	int i;
509f80cb526SLinus Walleij 
510e92935e1SRoland Stigge 	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
511e92935e1SRoland Stigge 		if (pdev->dev.of_node) {
512e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
513e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
514e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
515e92935e1SRoland Stigge 		}
51669c0a0a5SLaxman Dewangan 		devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
517a9bc97e4SLinus Walleij 				  &lpc32xx_gpiochip[i]);
518f80cb526SLinus Walleij 	}
519e92935e1SRoland Stigge 
520e92935e1SRoland Stigge 	return 0;
521e92935e1SRoland Stigge }
522e92935e1SRoland Stigge 
523e92935e1SRoland Stigge #ifdef CONFIG_OF
524e95c7c45SJingoo Han static const struct of_device_id lpc32xx_gpio_of_match[] = {
525e92935e1SRoland Stigge 	{ .compatible = "nxp,lpc3220-gpio", },
526e92935e1SRoland Stigge 	{ },
527e92935e1SRoland Stigge };
528e92935e1SRoland Stigge #endif
529e92935e1SRoland Stigge 
530e92935e1SRoland Stigge static struct platform_driver lpc32xx_gpio_driver = {
531e92935e1SRoland Stigge 	.driver		= {
532e92935e1SRoland Stigge 		.name	= "lpc32xx-gpio",
533e92935e1SRoland Stigge 		.of_match_table = of_match_ptr(lpc32xx_gpio_of_match),
534e92935e1SRoland Stigge 	},
535e92935e1SRoland Stigge 	.probe		= lpc32xx_gpio_probe,
536e92935e1SRoland Stigge };
537e92935e1SRoland Stigge 
538e92935e1SRoland Stigge module_platform_driver(lpc32xx_gpio_driver);
539