xref: /openbmc/linux/drivers/gpio/gpio-lpc32xx.c (revision 2e6d8456)
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>
28eef80f33SLinus Walleij #include <linux/platform_data/gpio-lpc32xx.h>
29f80cb526SLinus Walleij 
30f80cb526SLinus Walleij #include <mach/hardware.h>
31f80cb526SLinus Walleij #include <mach/platform.h>
320bdfeddcSRoland Stigge #include <mach/irqs.h>
33f80cb526SLinus Walleij 
34f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
35f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
36f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
37f80cb526SLinus Walleij #define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
38f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
39f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
40f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
41f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
42f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
43f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
44f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
45f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
46f80cb526SLinus Walleij #define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
47f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
48f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
49f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
50f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
51f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
52f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
53f80cb526SLinus Walleij #define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
54f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
55f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
56f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
57f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
58f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
59f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
60f80cb526SLinus Walleij #define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
61f80cb526SLinus Walleij 
62f80cb526SLinus Walleij #define GPIO012_PIN_TO_BIT(x)			(1 << (x))
63f80cb526SLinus Walleij #define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
64f80cb526SLinus Walleij #define GPO3_PIN_TO_BIT(x)			(1 << (x))
65f80cb526SLinus Walleij #define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
66f80cb526SLinus Walleij #define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
678e5fb37bSRoland Stigge #define GPIO3_PIN_IN_SEL(x, y)			(((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)
68f80cb526SLinus Walleij #define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
69f80cb526SLinus Walleij #define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
7046158aadSRoland Stigge #define GPO3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
71f80cb526SLinus Walleij 
72f80cb526SLinus Walleij struct gpio_regs {
73f80cb526SLinus Walleij 	void __iomem *inp_state;
7446158aadSRoland Stigge 	void __iomem *outp_state;
75f80cb526SLinus Walleij 	void __iomem *outp_set;
76f80cb526SLinus Walleij 	void __iomem *outp_clr;
77f80cb526SLinus Walleij 	void __iomem *dir_set;
78f80cb526SLinus Walleij 	void __iomem *dir_clr;
79f80cb526SLinus Walleij };
80f80cb526SLinus Walleij 
81f80cb526SLinus Walleij /*
82f80cb526SLinus Walleij  * GPIO names
83f80cb526SLinus Walleij  */
84f80cb526SLinus Walleij static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
85f80cb526SLinus Walleij 	"p0.0", "p0.1", "p0.2", "p0.3",
86f80cb526SLinus Walleij 	"p0.4", "p0.5", "p0.6", "p0.7"
87f80cb526SLinus Walleij };
88f80cb526SLinus Walleij 
89f80cb526SLinus Walleij static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
90f80cb526SLinus Walleij 	"p1.0", "p1.1", "p1.2", "p1.3",
91f80cb526SLinus Walleij 	"p1.4", "p1.5", "p1.6", "p1.7",
92f80cb526SLinus Walleij 	"p1.8", "p1.9", "p1.10", "p1.11",
93f80cb526SLinus Walleij 	"p1.12", "p1.13", "p1.14", "p1.15",
94f80cb526SLinus Walleij 	"p1.16", "p1.17", "p1.18", "p1.19",
95f80cb526SLinus Walleij 	"p1.20", "p1.21", "p1.22", "p1.23",
96f80cb526SLinus Walleij };
97f80cb526SLinus Walleij 
98f80cb526SLinus Walleij static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
99f80cb526SLinus Walleij 	"p2.0", "p2.1", "p2.2", "p2.3",
100f80cb526SLinus Walleij 	"p2.4", "p2.5", "p2.6", "p2.7",
101f80cb526SLinus Walleij 	"p2.8", "p2.9", "p2.10", "p2.11",
102f80cb526SLinus Walleij 	"p2.12"
103f80cb526SLinus Walleij };
104f80cb526SLinus Walleij 
105f80cb526SLinus Walleij static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
10695120d5dSRoland Stigge 	"gpio00", "gpio01", "gpio02", "gpio03",
107f80cb526SLinus Walleij 	"gpio04", "gpio05"
108f80cb526SLinus Walleij };
109f80cb526SLinus Walleij 
110f80cb526SLinus Walleij static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
111f80cb526SLinus Walleij 	"gpi00", "gpi01", "gpi02", "gpi03",
112f80cb526SLinus Walleij 	"gpi04", "gpi05", "gpi06", "gpi07",
113f80cb526SLinus Walleij 	"gpi08", "gpi09",  NULL,    NULL,
114f80cb526SLinus Walleij 	 NULL,    NULL,    NULL,   "gpi15",
115f80cb526SLinus Walleij 	"gpi16", "gpi17", "gpi18", "gpi19",
116f80cb526SLinus Walleij 	"gpi20", "gpi21", "gpi22", "gpi23",
11771fde000SRoland Stigge 	"gpi24", "gpi25", "gpi26", "gpi27",
11871fde000SRoland Stigge 	"gpi28"
119f80cb526SLinus Walleij };
120f80cb526SLinus Walleij 
121f80cb526SLinus Walleij static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
122f80cb526SLinus Walleij 	"gpo00", "gpo01", "gpo02", "gpo03",
123f80cb526SLinus Walleij 	"gpo04", "gpo05", "gpo06", "gpo07",
124f80cb526SLinus Walleij 	"gpo08", "gpo09", "gpo10", "gpo11",
125f80cb526SLinus Walleij 	"gpo12", "gpo13", "gpo14", "gpo15",
126f80cb526SLinus Walleij 	"gpo16", "gpo17", "gpo18", "gpo19",
127f80cb526SLinus Walleij 	"gpo20", "gpo21", "gpo22", "gpo23"
128f80cb526SLinus Walleij };
129f80cb526SLinus Walleij 
130f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p0 = {
131f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
132f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
133f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
134f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
135f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
136f80cb526SLinus Walleij };
137f80cb526SLinus Walleij 
138f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p1 = {
139f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
140f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
141f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
142f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
143f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
144f80cb526SLinus Walleij };
145f80cb526SLinus Walleij 
146f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p2 = {
147f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
148f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
149f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
150f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
151f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
152f80cb526SLinus Walleij };
153f80cb526SLinus Walleij 
154f80cb526SLinus Walleij static struct gpio_regs gpio_grp_regs_p3 = {
155f80cb526SLinus Walleij 	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
15646158aadSRoland Stigge 	.outp_state	= LPC32XX_GPIO_P3_OUTP_STATE,
157f80cb526SLinus Walleij 	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
158f80cb526SLinus Walleij 	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
159f80cb526SLinus Walleij 	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
160f80cb526SLinus Walleij 	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
161f80cb526SLinus Walleij };
162f80cb526SLinus Walleij 
163f80cb526SLinus Walleij struct lpc32xx_gpio_chip {
164f80cb526SLinus Walleij 	struct gpio_chip	chip;
165f80cb526SLinus Walleij 	struct gpio_regs	*gpio_grp;
166f80cb526SLinus Walleij };
167f80cb526SLinus Walleij 
168f80cb526SLinus Walleij static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
169f80cb526SLinus Walleij 	struct gpio_chip *gpc)
170f80cb526SLinus Walleij {
171f80cb526SLinus Walleij 	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
172f80cb526SLinus Walleij }
173f80cb526SLinus Walleij 
174f80cb526SLinus Walleij static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
175f80cb526SLinus Walleij 	unsigned pin, int input)
176f80cb526SLinus Walleij {
177f80cb526SLinus Walleij 	if (input)
178f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
179f80cb526SLinus Walleij 			group->gpio_grp->dir_clr);
180f80cb526SLinus Walleij 	else
181f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
182f80cb526SLinus Walleij 			group->gpio_grp->dir_set);
183f80cb526SLinus Walleij }
184f80cb526SLinus Walleij 
185f80cb526SLinus Walleij static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
186f80cb526SLinus Walleij 	unsigned pin, int input)
187f80cb526SLinus Walleij {
188f80cb526SLinus Walleij 	u32 u = GPIO3_PIN_TO_BIT(pin);
189f80cb526SLinus Walleij 
190f80cb526SLinus Walleij 	if (input)
191f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->dir_clr);
192f80cb526SLinus Walleij 	else
193f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->dir_set);
194f80cb526SLinus Walleij }
195f80cb526SLinus Walleij 
196f80cb526SLinus Walleij static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
197f80cb526SLinus Walleij 	unsigned pin, int high)
198f80cb526SLinus Walleij {
199f80cb526SLinus Walleij 	if (high)
200f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
201f80cb526SLinus Walleij 			group->gpio_grp->outp_set);
202f80cb526SLinus Walleij 	else
203f80cb526SLinus Walleij 		__raw_writel(GPIO012_PIN_TO_BIT(pin),
204f80cb526SLinus Walleij 			group->gpio_grp->outp_clr);
205f80cb526SLinus Walleij }
206f80cb526SLinus Walleij 
207f80cb526SLinus Walleij static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
208f80cb526SLinus Walleij 	unsigned pin, int high)
209f80cb526SLinus Walleij {
210f80cb526SLinus Walleij 	u32 u = GPIO3_PIN_TO_BIT(pin);
211f80cb526SLinus Walleij 
212f80cb526SLinus Walleij 	if (high)
213f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->outp_set);
214f80cb526SLinus Walleij 	else
215f80cb526SLinus Walleij 		__raw_writel(u, group->gpio_grp->outp_clr);
216f80cb526SLinus Walleij }
217f80cb526SLinus Walleij 
218f80cb526SLinus Walleij static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
219f80cb526SLinus Walleij 	unsigned pin, int high)
220f80cb526SLinus Walleij {
221f80cb526SLinus Walleij 	if (high)
222f80cb526SLinus Walleij 		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
223f80cb526SLinus Walleij 	else
224f80cb526SLinus Walleij 		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
225f80cb526SLinus Walleij }
226f80cb526SLinus Walleij 
227f80cb526SLinus Walleij static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
228f80cb526SLinus Walleij 	unsigned pin)
229f80cb526SLinus Walleij {
230f80cb526SLinus Walleij 	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
231f80cb526SLinus Walleij 		pin);
232f80cb526SLinus Walleij }
233f80cb526SLinus Walleij 
234f80cb526SLinus Walleij static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
235f80cb526SLinus Walleij 	unsigned pin)
236f80cb526SLinus Walleij {
237f80cb526SLinus Walleij 	int state = __raw_readl(group->gpio_grp->inp_state);
238f80cb526SLinus Walleij 
239f80cb526SLinus Walleij 	/*
240f80cb526SLinus Walleij 	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
241f80cb526SLinus Walleij 	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
242f80cb526SLinus Walleij 	 */
243f80cb526SLinus Walleij 	return GPIO3_PIN_IN_SEL(state, pin);
244f80cb526SLinus Walleij }
245f80cb526SLinus Walleij 
246f80cb526SLinus Walleij static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
247f80cb526SLinus Walleij 	unsigned pin)
248f80cb526SLinus Walleij {
249f80cb526SLinus Walleij 	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
250f80cb526SLinus Walleij }
251f80cb526SLinus Walleij 
25246158aadSRoland Stigge static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
25346158aadSRoland Stigge 	unsigned pin)
25446158aadSRoland Stigge {
25546158aadSRoland Stigge 	return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin);
25646158aadSRoland Stigge }
25746158aadSRoland Stigge 
258f80cb526SLinus Walleij /*
2597fd2bf3dSAlexandre Courbot  * GPIO primitives.
260f80cb526SLinus Walleij  */
261f80cb526SLinus Walleij static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
262f80cb526SLinus Walleij 	unsigned pin)
263f80cb526SLinus Walleij {
264f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
265f80cb526SLinus Walleij 
266f80cb526SLinus Walleij 	__set_gpio_dir_p012(group, pin, 1);
267f80cb526SLinus Walleij 
268f80cb526SLinus Walleij 	return 0;
269f80cb526SLinus Walleij }
270f80cb526SLinus Walleij 
271f80cb526SLinus Walleij static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
272f80cb526SLinus Walleij 	unsigned pin)
273f80cb526SLinus Walleij {
274f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
275f80cb526SLinus Walleij 
276f80cb526SLinus Walleij 	__set_gpio_dir_p3(group, pin, 1);
277f80cb526SLinus Walleij 
278f80cb526SLinus Walleij 	return 0;
279f80cb526SLinus Walleij }
280f80cb526SLinus Walleij 
281f80cb526SLinus Walleij static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
282f80cb526SLinus Walleij 	unsigned pin)
283f80cb526SLinus Walleij {
284f80cb526SLinus Walleij 	return 0;
285f80cb526SLinus Walleij }
286f80cb526SLinus Walleij 
287f80cb526SLinus Walleij static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
288f80cb526SLinus Walleij {
289f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
290f80cb526SLinus Walleij 
2912e6d8456SLinus Walleij 	return !!__get_gpio_state_p012(group, pin);
292f80cb526SLinus Walleij }
293f80cb526SLinus Walleij 
294f80cb526SLinus Walleij static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
295f80cb526SLinus Walleij {
296f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
297f80cb526SLinus Walleij 
2982e6d8456SLinus Walleij 	return !!__get_gpio_state_p3(group, pin);
299f80cb526SLinus Walleij }
300f80cb526SLinus Walleij 
301f80cb526SLinus Walleij static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
302f80cb526SLinus Walleij {
303f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
304f80cb526SLinus Walleij 
3052e6d8456SLinus Walleij 	return !!__get_gpi_state_p3(group, pin);
306f80cb526SLinus Walleij }
307f80cb526SLinus Walleij 
308f80cb526SLinus Walleij static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
309f80cb526SLinus Walleij 	int value)
310f80cb526SLinus Walleij {
311f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
312f80cb526SLinus Walleij 
313b1268d37SRoland Stigge 	__set_gpio_level_p012(group, pin, value);
314f80cb526SLinus Walleij 	__set_gpio_dir_p012(group, pin, 0);
315f80cb526SLinus Walleij 
316f80cb526SLinus Walleij 	return 0;
317f80cb526SLinus Walleij }
318f80cb526SLinus Walleij 
319f80cb526SLinus Walleij static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
320f80cb526SLinus Walleij 	int value)
321f80cb526SLinus Walleij {
322f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
323f80cb526SLinus Walleij 
324b1268d37SRoland Stigge 	__set_gpio_level_p3(group, pin, value);
325f80cb526SLinus Walleij 	__set_gpio_dir_p3(group, pin, 0);
326f80cb526SLinus Walleij 
327f80cb526SLinus Walleij 	return 0;
328f80cb526SLinus Walleij }
329f80cb526SLinus Walleij 
330f80cb526SLinus Walleij static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
331f80cb526SLinus Walleij 	int value)
332f80cb526SLinus Walleij {
333b1268d37SRoland Stigge 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
334b1268d37SRoland Stigge 
335b1268d37SRoland Stigge 	__set_gpo_level_p3(group, pin, value);
336f80cb526SLinus Walleij 	return 0;
337f80cb526SLinus Walleij }
338f80cb526SLinus Walleij 
339f80cb526SLinus Walleij static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
340f80cb526SLinus Walleij 	int value)
341f80cb526SLinus Walleij {
342f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
343f80cb526SLinus Walleij 
344f80cb526SLinus Walleij 	__set_gpio_level_p012(group, pin, value);
345f80cb526SLinus Walleij }
346f80cb526SLinus Walleij 
347f80cb526SLinus Walleij static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
348f80cb526SLinus Walleij 	int value)
349f80cb526SLinus Walleij {
350f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
351f80cb526SLinus Walleij 
352f80cb526SLinus Walleij 	__set_gpio_level_p3(group, pin, value);
353f80cb526SLinus Walleij }
354f80cb526SLinus Walleij 
355f80cb526SLinus Walleij static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
356f80cb526SLinus Walleij 	int value)
357f80cb526SLinus Walleij {
358f80cb526SLinus Walleij 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
359f80cb526SLinus Walleij 
360f80cb526SLinus Walleij 	__set_gpo_level_p3(group, pin, value);
361f80cb526SLinus Walleij }
362f80cb526SLinus Walleij 
36346158aadSRoland Stigge static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)
36446158aadSRoland Stigge {
36546158aadSRoland Stigge 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
36646158aadSRoland Stigge 
3672e6d8456SLinus Walleij 	return !!__get_gpo_state_p3(group, pin);
36846158aadSRoland Stigge }
36946158aadSRoland Stigge 
370f80cb526SLinus Walleij static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
371f80cb526SLinus Walleij {
372f80cb526SLinus Walleij 	if (pin < chip->ngpio)
373f80cb526SLinus Walleij 		return 0;
374f80cb526SLinus Walleij 
375f80cb526SLinus Walleij 	return -EINVAL;
376f80cb526SLinus Walleij }
377f80cb526SLinus Walleij 
3780bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
3790bdfeddcSRoland Stigge {
3800bdfeddcSRoland Stigge 	return IRQ_LPC32XX_P0_P1_IRQ;
3810bdfeddcSRoland Stigge }
3820bdfeddcSRoland Stigge 
3830bdfeddcSRoland Stigge static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = {
3840bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPIO_00,
3850bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPIO_01,
3860bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPIO_02,
3870bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPIO_03,
3880bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPIO_04,
3890bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPIO_05,
3900bdfeddcSRoland Stigge };
3910bdfeddcSRoland Stigge 
3920bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
3930bdfeddcSRoland Stigge {
3940bdfeddcSRoland Stigge 	if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table))
3950bdfeddcSRoland Stigge 		return lpc32xx_gpio_to_irq_gpio_p3_table[offset];
3960bdfeddcSRoland Stigge 	return -ENXIO;
3970bdfeddcSRoland Stigge }
3980bdfeddcSRoland Stigge 
3990bdfeddcSRoland Stigge static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = {
4000bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_00,
4010bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_01,
4020bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_02,
4030bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_03,
4040bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_04,
4050bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_05,
4060bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_06,
4070bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_07,
4080bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_08,
4090bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_09,
4100bdfeddcSRoland Stigge 	-ENXIO, /* 10 */
4110bdfeddcSRoland Stigge 	-ENXIO, /* 11 */
4120bdfeddcSRoland Stigge 	-ENXIO, /* 12 */
4130bdfeddcSRoland Stigge 	-ENXIO, /* 13 */
4140bdfeddcSRoland Stigge 	-ENXIO, /* 14 */
4150bdfeddcSRoland Stigge 	-ENXIO, /* 15 */
4160bdfeddcSRoland Stigge 	-ENXIO, /* 16 */
4170bdfeddcSRoland Stigge 	-ENXIO, /* 17 */
4180bdfeddcSRoland Stigge 	-ENXIO, /* 18 */
4190bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_19,
4200bdfeddcSRoland Stigge 	-ENXIO, /* 20 */
4210bdfeddcSRoland Stigge 	-ENXIO, /* 21 */
4220bdfeddcSRoland Stigge 	-ENXIO, /* 22 */
4230bdfeddcSRoland Stigge 	-ENXIO, /* 23 */
4240bdfeddcSRoland Stigge 	-ENXIO, /* 24 */
4250bdfeddcSRoland Stigge 	-ENXIO, /* 25 */
4260bdfeddcSRoland Stigge 	-ENXIO, /* 26 */
4270bdfeddcSRoland Stigge 	-ENXIO, /* 27 */
4280bdfeddcSRoland Stigge 	IRQ_LPC32XX_GPI_28,
4290bdfeddcSRoland Stigge };
4300bdfeddcSRoland Stigge 
4310bdfeddcSRoland Stigge static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
4320bdfeddcSRoland Stigge {
4330bdfeddcSRoland Stigge 	if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table))
4340bdfeddcSRoland Stigge 		return lpc32xx_gpio_to_irq_gpi_p3_table[offset];
4350bdfeddcSRoland Stigge 	return -ENXIO;
4360bdfeddcSRoland Stigge }
4370bdfeddcSRoland Stigge 
438f80cb526SLinus Walleij static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
439f80cb526SLinus Walleij 	{
440f80cb526SLinus Walleij 		.chip = {
441f80cb526SLinus Walleij 			.label			= "gpio_p0",
442f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
443f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
444f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
445f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
446f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4470bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_p01,
448f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P0_GRP,
449f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P0_MAX,
450f80cb526SLinus Walleij 			.names			= gpio_p0_names,
4519fb1f39eSLinus Walleij 			.can_sleep		= false,
452f80cb526SLinus Walleij 		},
453f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p0,
454f80cb526SLinus Walleij 	},
455f80cb526SLinus Walleij 	{
456f80cb526SLinus Walleij 		.chip = {
457f80cb526SLinus Walleij 			.label			= "gpio_p1",
458f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
459f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
460f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
461f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
462f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4630bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_p01,
464f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P1_GRP,
465f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P1_MAX,
466f80cb526SLinus Walleij 			.names			= gpio_p1_names,
4679fb1f39eSLinus Walleij 			.can_sleep		= false,
468f80cb526SLinus Walleij 		},
469f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p1,
470f80cb526SLinus Walleij 	},
471f80cb526SLinus Walleij 	{
472f80cb526SLinus Walleij 		.chip = {
473f80cb526SLinus Walleij 			.label			= "gpio_p2",
474f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p012,
475f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p012,
476f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p012,
477f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p012,
478f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
479f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P2_GRP,
480f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P2_MAX,
481f80cb526SLinus Walleij 			.names			= gpio_p2_names,
4829fb1f39eSLinus Walleij 			.can_sleep		= false,
483f80cb526SLinus Walleij 		},
484f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p2,
485f80cb526SLinus Walleij 	},
486f80cb526SLinus Walleij 	{
487f80cb526SLinus Walleij 		.chip = {
488f80cb526SLinus Walleij 			.label			= "gpio_p3",
489f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_input_p3,
490f80cb526SLinus Walleij 			.get			= lpc32xx_gpio_get_value_p3,
491f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_output_p3,
492f80cb526SLinus Walleij 			.set			= lpc32xx_gpio_set_value_p3,
493f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
4940bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_gpio_p3,
495f80cb526SLinus Walleij 			.base			= LPC32XX_GPIO_P3_GRP,
496f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPIO_P3_MAX,
497f80cb526SLinus Walleij 			.names			= gpio_p3_names,
4989fb1f39eSLinus Walleij 			.can_sleep		= false,
499f80cb526SLinus Walleij 		},
500f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
501f80cb526SLinus Walleij 	},
502f80cb526SLinus Walleij 	{
503f80cb526SLinus Walleij 		.chip = {
504f80cb526SLinus Walleij 			.label			= "gpi_p3",
505f80cb526SLinus Walleij 			.direction_input	= lpc32xx_gpio_dir_in_always,
506f80cb526SLinus Walleij 			.get			= lpc32xx_gpi_get_value,
507f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
5080bdfeddcSRoland Stigge 			.to_irq			= lpc32xx_gpio_to_irq_gpi_p3,
509f80cb526SLinus Walleij 			.base			= LPC32XX_GPI_P3_GRP,
510f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPI_P3_MAX,
511f80cb526SLinus Walleij 			.names			= gpi_p3_names,
5129fb1f39eSLinus Walleij 			.can_sleep		= false,
513f80cb526SLinus Walleij 		},
514f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
515f80cb526SLinus Walleij 	},
516f80cb526SLinus Walleij 	{
517f80cb526SLinus Walleij 		.chip = {
518f80cb526SLinus Walleij 			.label			= "gpo_p3",
519f80cb526SLinus Walleij 			.direction_output	= lpc32xx_gpio_dir_out_always,
520f80cb526SLinus Walleij 			.set			= lpc32xx_gpo_set_value,
52146158aadSRoland Stigge 			.get			= lpc32xx_gpo_get_value,
522f80cb526SLinus Walleij 			.request		= lpc32xx_gpio_request,
523f80cb526SLinus Walleij 			.base			= LPC32XX_GPO_P3_GRP,
524f80cb526SLinus Walleij 			.ngpio			= LPC32XX_GPO_P3_MAX,
525f80cb526SLinus Walleij 			.names			= gpo_p3_names,
5269fb1f39eSLinus Walleij 			.can_sleep		= false,
527f80cb526SLinus Walleij 		},
528f80cb526SLinus Walleij 		.gpio_grp = &gpio_grp_regs_p3,
529f80cb526SLinus Walleij 	},
530f80cb526SLinus Walleij };
531f80cb526SLinus Walleij 
532e92935e1SRoland Stigge static int lpc32xx_of_xlate(struct gpio_chip *gc,
533e92935e1SRoland Stigge 			    const struct of_phandle_args *gpiospec, u32 *flags)
534e92935e1SRoland Stigge {
535e92935e1SRoland Stigge 	/* Is this the correct bank? */
536e92935e1SRoland Stigge 	u32 bank = gpiospec->args[0];
537fdc7a9f8SAxel Lin 	if ((bank >= ARRAY_SIZE(lpc32xx_gpiochip) ||
538e92935e1SRoland Stigge 	    (gc != &lpc32xx_gpiochip[bank].chip)))
539e92935e1SRoland Stigge 		return -EINVAL;
540e92935e1SRoland Stigge 
541e92935e1SRoland Stigge 	if (flags)
542e92935e1SRoland Stigge 		*flags = gpiospec->args[2];
543e92935e1SRoland Stigge 	return gpiospec->args[1];
544e92935e1SRoland Stigge }
545e92935e1SRoland Stigge 
5463836309dSBill Pemberton static int lpc32xx_gpio_probe(struct platform_device *pdev)
547e92935e1SRoland Stigge {
548f80cb526SLinus Walleij 	int i;
549f80cb526SLinus Walleij 
550e92935e1SRoland Stigge 	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
551e92935e1SRoland Stigge 		if (pdev->dev.of_node) {
552e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
553e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
554e92935e1SRoland Stigge 			lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
555e92935e1SRoland Stigge 		}
556f80cb526SLinus Walleij 		gpiochip_add(&lpc32xx_gpiochip[i].chip);
557f80cb526SLinus Walleij 	}
558e92935e1SRoland Stigge 
559e92935e1SRoland Stigge 	return 0;
560e92935e1SRoland Stigge }
561e92935e1SRoland Stigge 
562e92935e1SRoland Stigge #ifdef CONFIG_OF
563e95c7c45SJingoo Han static const struct of_device_id lpc32xx_gpio_of_match[] = {
564e92935e1SRoland Stigge 	{ .compatible = "nxp,lpc3220-gpio", },
565e92935e1SRoland Stigge 	{ },
566e92935e1SRoland Stigge };
567e92935e1SRoland Stigge #endif
568e92935e1SRoland Stigge 
569e92935e1SRoland Stigge static struct platform_driver lpc32xx_gpio_driver = {
570e92935e1SRoland Stigge 	.driver		= {
571e92935e1SRoland Stigge 		.name	= "lpc32xx-gpio",
572e92935e1SRoland Stigge 		.of_match_table = of_match_ptr(lpc32xx_gpio_of_match),
573e92935e1SRoland Stigge 	},
574e92935e1SRoland Stigge 	.probe		= lpc32xx_gpio_probe,
575e92935e1SRoland Stigge };
576e92935e1SRoland Stigge 
577e92935e1SRoland Stigge module_platform_driver(lpc32xx_gpio_driver);
578