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