1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2354bf801SLinus Walleij /*
3354bf801SLinus Walleij * linux/arch/arm/plat-pxa/gpio.c
4354bf801SLinus Walleij *
5354bf801SLinus Walleij * Generic PXA GPIO handling
6354bf801SLinus Walleij *
7354bf801SLinus Walleij * Author: Nicolas Pitre
8354bf801SLinus Walleij * Created: Jun 15, 2001
9354bf801SLinus Walleij * Copyright: MontaVista Software Inc.
10354bf801SLinus Walleij */
117a4d5079SHaojian Zhuang #include <linux/module.h>
12389eda15SHaojian Zhuang #include <linux/clk.h>
13389eda15SHaojian Zhuang #include <linux/err.h>
1484bf021eSLinus Walleij #include <linux/gpio/driver.h>
15157d2644SHaojian Zhuang #include <linux/gpio-pxa.h>
16354bf801SLinus Walleij #include <linux/init.h>
17ae4f4cfdSRob Herring #include <linux/interrupt.h>
18354bf801SLinus Walleij #include <linux/irq.h>
197a4d5079SHaojian Zhuang #include <linux/irqdomain.h>
20de88cbb7SCatalin Marinas #include <linux/irqchip/chained_irq.h>
21354bf801SLinus Walleij #include <linux/io.h>
227a4d5079SHaojian Zhuang #include <linux/of.h>
23a770d946SRobert Jarzmik #include <linux/pinctrl/consumer.h>
24157d2644SHaojian Zhuang #include <linux/platform_device.h>
25354bf801SLinus Walleij #include <linux/syscore_ops.h>
26354bf801SLinus Walleij #include <linux/slab.h>
27354bf801SLinus Walleij
28157d2644SHaojian Zhuang /*
29157d2644SHaojian Zhuang * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
30157d2644SHaojian Zhuang * one set of registers. The register offsets are organized below:
31157d2644SHaojian Zhuang *
32157d2644SHaojian Zhuang * GPLR GPDR GPSR GPCR GRER GFER GEDR
33157d2644SHaojian Zhuang * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048
34157d2644SHaojian Zhuang * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C
35157d2644SHaojian Zhuang * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050
36157d2644SHaojian Zhuang *
37157d2644SHaojian Zhuang * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148
38157d2644SHaojian Zhuang * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C
39157d2644SHaojian Zhuang * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150
40157d2644SHaojian Zhuang *
41684bba2fSRob Herring * BANK 6 - 0x0200 0x020C 0x0218 0x0224 0x0230 0x023C 0x0248
42684bba2fSRob Herring *
43157d2644SHaojian Zhuang * NOTE:
44157d2644SHaojian Zhuang * BANK 3 is only available on PXA27x and later processors.
45684bba2fSRob Herring * BANK 4 and 5 are only available on PXA935, PXA1928
46684bba2fSRob Herring * BANK 6 is only available on PXA1928
47157d2644SHaojian Zhuang */
48157d2644SHaojian Zhuang
49157d2644SHaojian Zhuang #define GPLR_OFFSET 0x00
50157d2644SHaojian Zhuang #define GPDR_OFFSET 0x0C
51157d2644SHaojian Zhuang #define GPSR_OFFSET 0x18
52157d2644SHaojian Zhuang #define GPCR_OFFSET 0x24
53157d2644SHaojian Zhuang #define GRER_OFFSET 0x30
54157d2644SHaojian Zhuang #define GFER_OFFSET 0x3C
55157d2644SHaojian Zhuang #define GEDR_OFFSET 0x48
56157d2644SHaojian Zhuang #define GAFR_OFFSET 0x54
57be24168fSHaojian Zhuang #define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */
58157d2644SHaojian Zhuang
591e970b7dSRob Herring #define BANK_OFF(n) (((n) / 3) << 8) + (((n) % 3) << 2)
60f55be1bfSLinus Walleij
61354bf801SLinus Walleij int pxa_last_gpio;
629450be76SDaniel Mack static int irq_base;
63354bf801SLinus Walleij
64fc0589caSRobert Jarzmik struct pxa_gpio_bank {
65354bf801SLinus Walleij void __iomem *regbase;
66354bf801SLinus Walleij unsigned long irq_mask;
67354bf801SLinus Walleij unsigned long irq_edge_rise;
68354bf801SLinus Walleij unsigned long irq_edge_fall;
69354bf801SLinus Walleij
70354bf801SLinus Walleij #ifdef CONFIG_PM
71354bf801SLinus Walleij unsigned long saved_gplr;
72354bf801SLinus Walleij unsigned long saved_gpdr;
73354bf801SLinus Walleij unsigned long saved_grer;
74354bf801SLinus Walleij unsigned long saved_gfer;
75354bf801SLinus Walleij #endif
76354bf801SLinus Walleij };
77354bf801SLinus Walleij
78fc0589caSRobert Jarzmik struct pxa_gpio_chip {
79fc0589caSRobert Jarzmik struct device *dev;
80fc0589caSRobert Jarzmik struct gpio_chip chip;
81fc0589caSRobert Jarzmik struct pxa_gpio_bank *banks;
82384ca3c6SRobert Jarzmik struct irq_domain *irqdomain;
83fc0589caSRobert Jarzmik
84fc0589caSRobert Jarzmik int irq0;
85fc0589caSRobert Jarzmik int irq1;
86fc0589caSRobert Jarzmik int (*set_wake)(unsigned int gpio, unsigned int on);
87fc0589caSRobert Jarzmik };
88fc0589caSRobert Jarzmik
892cab0292SHaojian Zhuang enum pxa_gpio_type {
904929f5a8SHaojian Zhuang PXA25X_GPIO = 0,
914929f5a8SHaojian Zhuang PXA26X_GPIO,
924929f5a8SHaojian Zhuang PXA27X_GPIO,
934929f5a8SHaojian Zhuang PXA3XX_GPIO,
944929f5a8SHaojian Zhuang PXA93X_GPIO,
954929f5a8SHaojian Zhuang MMP_GPIO = 0x10,
962cab0292SHaojian Zhuang MMP2_GPIO,
97684bba2fSRob Herring PXA1928_GPIO,
982cab0292SHaojian Zhuang };
992cab0292SHaojian Zhuang
1002cab0292SHaojian Zhuang struct pxa_gpio_id {
1012cab0292SHaojian Zhuang enum pxa_gpio_type type;
1022cab0292SHaojian Zhuang int gpio_nums;
1034929f5a8SHaojian Zhuang };
1044929f5a8SHaojian Zhuang
105354bf801SLinus Walleij static DEFINE_SPINLOCK(gpio_lock);
106fc0589caSRobert Jarzmik static struct pxa_gpio_chip *pxa_gpio_chip;
1072cab0292SHaojian Zhuang static enum pxa_gpio_type gpio_type;
108354bf801SLinus Walleij
1092cab0292SHaojian Zhuang static struct pxa_gpio_id pxa25x_id = {
1102cab0292SHaojian Zhuang .type = PXA25X_GPIO,
1112cab0292SHaojian Zhuang .gpio_nums = 85,
1122cab0292SHaojian Zhuang };
1132cab0292SHaojian Zhuang
1142cab0292SHaojian Zhuang static struct pxa_gpio_id pxa26x_id = {
1152cab0292SHaojian Zhuang .type = PXA26X_GPIO,
1162cab0292SHaojian Zhuang .gpio_nums = 90,
1172cab0292SHaojian Zhuang };
1182cab0292SHaojian Zhuang
1192cab0292SHaojian Zhuang static struct pxa_gpio_id pxa27x_id = {
1202cab0292SHaojian Zhuang .type = PXA27X_GPIO,
1212cab0292SHaojian Zhuang .gpio_nums = 121,
1222cab0292SHaojian Zhuang };
1232cab0292SHaojian Zhuang
1242cab0292SHaojian Zhuang static struct pxa_gpio_id pxa3xx_id = {
1252cab0292SHaojian Zhuang .type = PXA3XX_GPIO,
1262cab0292SHaojian Zhuang .gpio_nums = 128,
1272cab0292SHaojian Zhuang };
1282cab0292SHaojian Zhuang
1292cab0292SHaojian Zhuang static struct pxa_gpio_id pxa93x_id = {
1302cab0292SHaojian Zhuang .type = PXA93X_GPIO,
1312cab0292SHaojian Zhuang .gpio_nums = 192,
1322cab0292SHaojian Zhuang };
1332cab0292SHaojian Zhuang
1342cab0292SHaojian Zhuang static struct pxa_gpio_id mmp_id = {
1352cab0292SHaojian Zhuang .type = MMP_GPIO,
1362cab0292SHaojian Zhuang .gpio_nums = 128,
1372cab0292SHaojian Zhuang };
1382cab0292SHaojian Zhuang
1392cab0292SHaojian Zhuang static struct pxa_gpio_id mmp2_id = {
1402cab0292SHaojian Zhuang .type = MMP2_GPIO,
1412cab0292SHaojian Zhuang .gpio_nums = 192,
1422cab0292SHaojian Zhuang };
1432cab0292SHaojian Zhuang
144684bba2fSRob Herring static struct pxa_gpio_id pxa1928_id = {
145684bba2fSRob Herring .type = PXA1928_GPIO,
146684bba2fSRob Herring .gpio_nums = 224,
147684bba2fSRob Herring };
148684bba2fSRob Herring
149fc0589caSRobert Jarzmik #define for_each_gpio_bank(i, b, pc) \
150fc0589caSRobert Jarzmik for (i = 0, b = pc->banks; i <= pxa_last_gpio; i += 32, b++)
151354bf801SLinus Walleij
chip_to_pxachip(struct gpio_chip * c)152fc0589caSRobert Jarzmik static inline struct pxa_gpio_chip *chip_to_pxachip(struct gpio_chip *c)
153354bf801SLinus Walleij {
15481d0c31dSLinus Walleij struct pxa_gpio_chip *pxa_chip = gpiochip_get_data(c);
155fc0589caSRobert Jarzmik
156fc0589caSRobert Jarzmik return pxa_chip;
157fc0589caSRobert Jarzmik }
15881d0c31dSLinus Walleij
gpio_bank_base(struct gpio_chip * c,int gpio)159fc0589caSRobert Jarzmik static inline void __iomem *gpio_bank_base(struct gpio_chip *c, int gpio)
160fc0589caSRobert Jarzmik {
16181d0c31dSLinus Walleij struct pxa_gpio_chip *p = gpiochip_get_data(c);
16281d0c31dSLinus Walleij struct pxa_gpio_bank *bank = p->banks + (gpio / 32);
163fc0589caSRobert Jarzmik
164fc0589caSRobert Jarzmik return bank->regbase;
165354bf801SLinus Walleij }
166354bf801SLinus Walleij
gpio_to_pxabank(struct gpio_chip * c,unsigned gpio)167fc0589caSRobert Jarzmik static inline struct pxa_gpio_bank *gpio_to_pxabank(struct gpio_chip *c,
168fc0589caSRobert Jarzmik unsigned gpio)
169354bf801SLinus Walleij {
170fc0589caSRobert Jarzmik return chip_to_pxachip(c)->banks + gpio / 32;
171354bf801SLinus Walleij }
172354bf801SLinus Walleij
gpio_is_mmp_type(int type)1734929f5a8SHaojian Zhuang static inline int gpio_is_mmp_type(int type)
1744929f5a8SHaojian Zhuang {
1754929f5a8SHaojian Zhuang return (type & MMP_GPIO) != 0;
1764929f5a8SHaojian Zhuang }
1774929f5a8SHaojian Zhuang
178157d2644SHaojian Zhuang /* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted,
179157d2644SHaojian Zhuang * as well as their Alternate Function value being '1' for GPIO in GAFRx.
180157d2644SHaojian Zhuang */
__gpio_is_inverted(int gpio)181157d2644SHaojian Zhuang static inline int __gpio_is_inverted(int gpio)
182157d2644SHaojian Zhuang {
183157d2644SHaojian Zhuang if ((gpio_type == PXA26X_GPIO) && (gpio > 85))
184157d2644SHaojian Zhuang return 1;
185157d2644SHaojian Zhuang return 0;
186157d2644SHaojian Zhuang }
187157d2644SHaojian Zhuang
188157d2644SHaojian Zhuang /*
189157d2644SHaojian Zhuang * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
190157d2644SHaojian Zhuang * function of a GPIO, and GPDRx cannot be altered once configured. It
191157d2644SHaojian Zhuang * is attributed as "occupied" here (I know this terminology isn't
192157d2644SHaojian Zhuang * accurate, you are welcome to propose a better one :-)
193157d2644SHaojian Zhuang */
__gpio_is_occupied(struct pxa_gpio_chip * pchip,unsigned gpio)194fc0589caSRobert Jarzmik static inline int __gpio_is_occupied(struct pxa_gpio_chip *pchip, unsigned gpio)
195157d2644SHaojian Zhuang {
196157d2644SHaojian Zhuang void __iomem *base;
197157d2644SHaojian Zhuang unsigned long gafr = 0, gpdr = 0;
198157d2644SHaojian Zhuang int ret, af = 0, dir = 0;
199157d2644SHaojian Zhuang
200fc0589caSRobert Jarzmik base = gpio_bank_base(&pchip->chip, gpio);
201157d2644SHaojian Zhuang gpdr = readl_relaxed(base + GPDR_OFFSET);
202157d2644SHaojian Zhuang
203157d2644SHaojian Zhuang switch (gpio_type) {
204157d2644SHaojian Zhuang case PXA25X_GPIO:
205157d2644SHaojian Zhuang case PXA26X_GPIO:
206157d2644SHaojian Zhuang case PXA27X_GPIO:
207157d2644SHaojian Zhuang gafr = readl_relaxed(base + GAFR_OFFSET);
208157d2644SHaojian Zhuang af = (gafr >> ((gpio & 0xf) * 2)) & 0x3;
209157d2644SHaojian Zhuang dir = gpdr & GPIO_bit(gpio);
210157d2644SHaojian Zhuang
211157d2644SHaojian Zhuang if (__gpio_is_inverted(gpio))
212157d2644SHaojian Zhuang ret = (af != 1) || (dir == 0);
213157d2644SHaojian Zhuang else
214157d2644SHaojian Zhuang ret = (af != 0) || (dir != 0);
215157d2644SHaojian Zhuang break;
216157d2644SHaojian Zhuang default:
217157d2644SHaojian Zhuang ret = gpdr & GPIO_bit(gpio);
218157d2644SHaojian Zhuang break;
219157d2644SHaojian Zhuang }
220157d2644SHaojian Zhuang return ret;
221157d2644SHaojian Zhuang }
222157d2644SHaojian Zhuang
pxa_irq_to_gpio(int irq)2234929f5a8SHaojian Zhuang int pxa_irq_to_gpio(int irq)
2244929f5a8SHaojian Zhuang {
225384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = pxa_gpio_chip;
226384ca3c6SRobert Jarzmik int irq_gpio0;
227384ca3c6SRobert Jarzmik
228384ca3c6SRobert Jarzmik irq_gpio0 = irq_find_mapping(pchip->irqdomain, 0);
229384ca3c6SRobert Jarzmik if (irq_gpio0 > 0)
230384ca3c6SRobert Jarzmik return irq - irq_gpio0;
231384ca3c6SRobert Jarzmik
232384ca3c6SRobert Jarzmik return irq_gpio0;
233384ca3c6SRobert Jarzmik }
234384ca3c6SRobert Jarzmik
pxa_gpio_has_pinctrl(void)2359dabfdd8SDaniel Mack static bool pxa_gpio_has_pinctrl(void)
2369dabfdd8SDaniel Mack {
2379dabfdd8SDaniel Mack switch (gpio_type) {
2389dabfdd8SDaniel Mack case PXA3XX_GPIO:
239af14b2c9SLubomir Rintel case MMP2_GPIO:
240*f0575116SDuje Mihanović case MMP_GPIO:
2419dabfdd8SDaniel Mack return false;
2429dabfdd8SDaniel Mack
2439dabfdd8SDaniel Mack default:
2449dabfdd8SDaniel Mack return true;
2459dabfdd8SDaniel Mack }
2469dabfdd8SDaniel Mack }
2479dabfdd8SDaniel Mack
pxa_gpio_to_irq(struct gpio_chip * chip,unsigned offset)248384ca3c6SRobert Jarzmik static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
249384ca3c6SRobert Jarzmik {
250384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = chip_to_pxachip(chip);
251384ca3c6SRobert Jarzmik
252384ca3c6SRobert Jarzmik return irq_find_mapping(pchip->irqdomain, offset);
2534929f5a8SHaojian Zhuang }
2544929f5a8SHaojian Zhuang
pxa_gpio_direction_input(struct gpio_chip * chip,unsigned offset)255354bf801SLinus Walleij static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
256354bf801SLinus Walleij {
257fc0589caSRobert Jarzmik void __iomem *base = gpio_bank_base(chip, offset);
258fc0589caSRobert Jarzmik uint32_t value, mask = GPIO_bit(offset);
259354bf801SLinus Walleij unsigned long flags;
260a770d946SRobert Jarzmik int ret;
261a770d946SRobert Jarzmik
2629dabfdd8SDaniel Mack if (pxa_gpio_has_pinctrl()) {
263a770d946SRobert Jarzmik ret = pinctrl_gpio_direction_input(chip->base + offset);
26470cdb6adSRobert Jarzmik if (ret)
26570cdb6adSRobert Jarzmik return ret;
2669dabfdd8SDaniel Mack }
267354bf801SLinus Walleij
268354bf801SLinus Walleij spin_lock_irqsave(&gpio_lock, flags);
269354bf801SLinus Walleij
270df664d20SHaojian Zhuang value = readl_relaxed(base + GPDR_OFFSET);
271354bf801SLinus Walleij if (__gpio_is_inverted(chip->base + offset))
272354bf801SLinus Walleij value |= mask;
273354bf801SLinus Walleij else
274354bf801SLinus Walleij value &= ~mask;
275df664d20SHaojian Zhuang writel_relaxed(value, base + GPDR_OFFSET);
276354bf801SLinus Walleij
277354bf801SLinus Walleij spin_unlock_irqrestore(&gpio_lock, flags);
278354bf801SLinus Walleij return 0;
279354bf801SLinus Walleij }
280354bf801SLinus Walleij
pxa_gpio_direction_output(struct gpio_chip * chip,unsigned offset,int value)281354bf801SLinus Walleij static int pxa_gpio_direction_output(struct gpio_chip *chip,
282354bf801SLinus Walleij unsigned offset, int value)
283354bf801SLinus Walleij {
284fc0589caSRobert Jarzmik void __iomem *base = gpio_bank_base(chip, offset);
285fc0589caSRobert Jarzmik uint32_t tmp, mask = GPIO_bit(offset);
286354bf801SLinus Walleij unsigned long flags;
287a770d946SRobert Jarzmik int ret;
288354bf801SLinus Walleij
289df664d20SHaojian Zhuang writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
290354bf801SLinus Walleij
2919dabfdd8SDaniel Mack if (pxa_gpio_has_pinctrl()) {
292a770d946SRobert Jarzmik ret = pinctrl_gpio_direction_output(chip->base + offset);
293c4e5ffb6SRobert Jarzmik if (ret)
294c4e5ffb6SRobert Jarzmik return ret;
2959dabfdd8SDaniel Mack }
296a770d946SRobert Jarzmik
297354bf801SLinus Walleij spin_lock_irqsave(&gpio_lock, flags);
298354bf801SLinus Walleij
299df664d20SHaojian Zhuang tmp = readl_relaxed(base + GPDR_OFFSET);
300354bf801SLinus Walleij if (__gpio_is_inverted(chip->base + offset))
301354bf801SLinus Walleij tmp &= ~mask;
302354bf801SLinus Walleij else
303354bf801SLinus Walleij tmp |= mask;
304df664d20SHaojian Zhuang writel_relaxed(tmp, base + GPDR_OFFSET);
305354bf801SLinus Walleij
306354bf801SLinus Walleij spin_unlock_irqrestore(&gpio_lock, flags);
307354bf801SLinus Walleij return 0;
308354bf801SLinus Walleij }
309354bf801SLinus Walleij
pxa_gpio_get(struct gpio_chip * chip,unsigned offset)310354bf801SLinus Walleij static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
311354bf801SLinus Walleij {
312fc0589caSRobert Jarzmik void __iomem *base = gpio_bank_base(chip, offset);
313fc0589caSRobert Jarzmik u32 gplr = readl_relaxed(base + GPLR_OFFSET);
314fc0589caSRobert Jarzmik
315fc0589caSRobert Jarzmik return !!(gplr & GPIO_bit(offset));
316354bf801SLinus Walleij }
317354bf801SLinus Walleij
pxa_gpio_set(struct gpio_chip * chip,unsigned offset,int value)318354bf801SLinus Walleij static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
319354bf801SLinus Walleij {
320fc0589caSRobert Jarzmik void __iomem *base = gpio_bank_base(chip, offset);
321fc0589caSRobert Jarzmik
322fc0589caSRobert Jarzmik writel_relaxed(GPIO_bit(offset),
323fc0589caSRobert Jarzmik base + (value ? GPSR_OFFSET : GPCR_OFFSET));
324354bf801SLinus Walleij }
325354bf801SLinus Walleij
32672121572SDaniel Mack #ifdef CONFIG_OF_GPIO
pxa_gpio_of_xlate(struct gpio_chip * gc,const struct of_phandle_args * gpiospec,u32 * flags)32772121572SDaniel Mack static int pxa_gpio_of_xlate(struct gpio_chip *gc,
32872121572SDaniel Mack const struct of_phandle_args *gpiospec,
32972121572SDaniel Mack u32 *flags)
33072121572SDaniel Mack {
33172121572SDaniel Mack if (gpiospec->args[0] > pxa_last_gpio)
33272121572SDaniel Mack return -EINVAL;
33372121572SDaniel Mack
33472121572SDaniel Mack if (flags)
33572121572SDaniel Mack *flags = gpiospec->args[1];
33672121572SDaniel Mack
337fc0589caSRobert Jarzmik return gpiospec->args[0];
33872121572SDaniel Mack }
33972121572SDaniel Mack #endif
34072121572SDaniel Mack
pxa_init_gpio_chip(struct pxa_gpio_chip * pchip,int ngpio,void __iomem * regbase)34145a541a6SAndy Shevchenko static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, void __iomem *regbase)
342354bf801SLinus Walleij {
343fc0589caSRobert Jarzmik int i, gpio, nbanks = DIV_ROUND_UP(ngpio, 32);
344fc0589caSRobert Jarzmik struct pxa_gpio_bank *bank;
345354bf801SLinus Walleij
346fc0589caSRobert Jarzmik pchip->banks = devm_kcalloc(pchip->dev, nbanks, sizeof(*pchip->banks),
347fc0589caSRobert Jarzmik GFP_KERNEL);
348fc0589caSRobert Jarzmik if (!pchip->banks)
349354bf801SLinus Walleij return -ENOMEM;
350fc0589caSRobert Jarzmik
35145a541a6SAndy Shevchenko pchip->chip.parent = pchip->dev;
352fc0589caSRobert Jarzmik pchip->chip.label = "gpio-pxa";
353fc0589caSRobert Jarzmik pchip->chip.direction_input = pxa_gpio_direction_input;
354fc0589caSRobert Jarzmik pchip->chip.direction_output = pxa_gpio_direction_output;
355fc0589caSRobert Jarzmik pchip->chip.get = pxa_gpio_get;
356fc0589caSRobert Jarzmik pchip->chip.set = pxa_gpio_set;
357fc0589caSRobert Jarzmik pchip->chip.to_irq = pxa_gpio_to_irq;
358fc0589caSRobert Jarzmik pchip->chip.ngpio = ngpio;
359ad5c3221SLinus Walleij pchip->chip.request = gpiochip_generic_request;
360ad5c3221SLinus Walleij pchip->chip.free = gpiochip_generic_free;
3619dabfdd8SDaniel Mack
362fc0589caSRobert Jarzmik #ifdef CONFIG_OF_GPIO
363fc0589caSRobert Jarzmik pchip->chip.of_xlate = pxa_gpio_of_xlate;
364fc0589caSRobert Jarzmik pchip->chip.of_gpio_n_cells = 2;
365fc0589caSRobert Jarzmik #endif
366354bf801SLinus Walleij
367354bf801SLinus Walleij for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
368fc0589caSRobert Jarzmik bank = pchip->banks + i;
369fc0589caSRobert Jarzmik bank->regbase = regbase + BANK_OFF(i);
370354bf801SLinus Walleij }
371fc0589caSRobert Jarzmik
37281d0c31dSLinus Walleij return gpiochip_add_data(&pchip->chip, pchip);
373354bf801SLinus Walleij }
374354bf801SLinus Walleij
375354bf801SLinus Walleij /* Update only those GRERx and GFERx edge detection register bits if those
376354bf801SLinus Walleij * bits are set in c->irq_mask
377354bf801SLinus Walleij */
update_edge_detect(struct pxa_gpio_bank * c)378fc0589caSRobert Jarzmik static inline void update_edge_detect(struct pxa_gpio_bank *c)
379354bf801SLinus Walleij {
380354bf801SLinus Walleij uint32_t grer, gfer;
381354bf801SLinus Walleij
382df664d20SHaojian Zhuang grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask;
383df664d20SHaojian Zhuang gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask;
384354bf801SLinus Walleij grer |= c->irq_edge_rise & c->irq_mask;
385354bf801SLinus Walleij gfer |= c->irq_edge_fall & c->irq_mask;
386df664d20SHaojian Zhuang writel_relaxed(grer, c->regbase + GRER_OFFSET);
387df664d20SHaojian Zhuang writel_relaxed(gfer, c->regbase + GFER_OFFSET);
388354bf801SLinus Walleij }
389354bf801SLinus Walleij
pxa_gpio_irq_type(struct irq_data * d,unsigned int type)390354bf801SLinus Walleij static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
391354bf801SLinus Walleij {
392384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
393384ca3c6SRobert Jarzmik unsigned int gpio = irqd_to_hwirq(d);
394fc0589caSRobert Jarzmik struct pxa_gpio_bank *c = gpio_to_pxabank(&pchip->chip, gpio);
395354bf801SLinus Walleij unsigned long gpdr, mask = GPIO_bit(gpio);
396354bf801SLinus Walleij
397354bf801SLinus Walleij if (type == IRQ_TYPE_PROBE) {
398354bf801SLinus Walleij /* Don't mess with enabled GPIOs using preconfigured edges or
399354bf801SLinus Walleij * GPIOs set to alternate function or to output during probe
400354bf801SLinus Walleij */
401354bf801SLinus Walleij if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
402354bf801SLinus Walleij return 0;
403354bf801SLinus Walleij
404fc0589caSRobert Jarzmik if (__gpio_is_occupied(pchip, gpio))
405354bf801SLinus Walleij return 0;
406354bf801SLinus Walleij
407354bf801SLinus Walleij type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
408354bf801SLinus Walleij }
409354bf801SLinus Walleij
410df664d20SHaojian Zhuang gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
411354bf801SLinus Walleij
412354bf801SLinus Walleij if (__gpio_is_inverted(gpio))
413df664d20SHaojian Zhuang writel_relaxed(gpdr | mask, c->regbase + GPDR_OFFSET);
414354bf801SLinus Walleij else
415df664d20SHaojian Zhuang writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET);
416354bf801SLinus Walleij
417354bf801SLinus Walleij if (type & IRQ_TYPE_EDGE_RISING)
418354bf801SLinus Walleij c->irq_edge_rise |= mask;
419354bf801SLinus Walleij else
420354bf801SLinus Walleij c->irq_edge_rise &= ~mask;
421354bf801SLinus Walleij
422354bf801SLinus Walleij if (type & IRQ_TYPE_EDGE_FALLING)
423354bf801SLinus Walleij c->irq_edge_fall |= mask;
424354bf801SLinus Walleij else
425354bf801SLinus Walleij c->irq_edge_fall &= ~mask;
426354bf801SLinus Walleij
427354bf801SLinus Walleij update_edge_detect(c);
428354bf801SLinus Walleij
429354bf801SLinus Walleij pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
430354bf801SLinus Walleij ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""),
431354bf801SLinus Walleij ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
432354bf801SLinus Walleij return 0;
433354bf801SLinus Walleij }
434354bf801SLinus Walleij
pxa_gpio_demux_handler(int in_irq,void * d)435384ca3c6SRobert Jarzmik static irqreturn_t pxa_gpio_demux_handler(int in_irq, void *d)
436354bf801SLinus Walleij {
437fc0589caSRobert Jarzmik int loop, gpio, n, handled = 0;
438354bf801SLinus Walleij unsigned long gedr;
439384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = d;
440fc0589caSRobert Jarzmik struct pxa_gpio_bank *c;
4410d2ee5d7SChao Xie
442354bf801SLinus Walleij do {
443354bf801SLinus Walleij loop = 0;
444fc0589caSRobert Jarzmik for_each_gpio_bank(gpio, c, pchip) {
445df664d20SHaojian Zhuang gedr = readl_relaxed(c->regbase + GEDR_OFFSET);
446354bf801SLinus Walleij gedr = gedr & c->irq_mask;
447df664d20SHaojian Zhuang writel_relaxed(gedr, c->regbase + GEDR_OFFSET);
448354bf801SLinus Walleij
449d724f1c9SWei Yongjun for_each_set_bit(n, &gedr, BITS_PER_LONG) {
450354bf801SLinus Walleij loop = 1;
451354bf801SLinus Walleij
452dbd1c54fSMarc Zyngier generic_handle_domain_irq(pchip->irqdomain,
453dbd1c54fSMarc Zyngier gpio + n);
454354bf801SLinus Walleij }
455354bf801SLinus Walleij }
456384ca3c6SRobert Jarzmik handled += loop;
457354bf801SLinus Walleij } while (loop);
4580d2ee5d7SChao Xie
459384ca3c6SRobert Jarzmik return handled ? IRQ_HANDLED : IRQ_NONE;
460384ca3c6SRobert Jarzmik }
461384ca3c6SRobert Jarzmik
pxa_gpio_direct_handler(int in_irq,void * d)462384ca3c6SRobert Jarzmik static irqreturn_t pxa_gpio_direct_handler(int in_irq, void *d)
463384ca3c6SRobert Jarzmik {
464384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = d;
465384ca3c6SRobert Jarzmik
466384ca3c6SRobert Jarzmik if (in_irq == pchip->irq0) {
467dbd1c54fSMarc Zyngier generic_handle_domain_irq(pchip->irqdomain, 0);
468384ca3c6SRobert Jarzmik } else if (in_irq == pchip->irq1) {
469dbd1c54fSMarc Zyngier generic_handle_domain_irq(pchip->irqdomain, 1);
470384ca3c6SRobert Jarzmik } else {
471384ca3c6SRobert Jarzmik pr_err("%s() unknown irq %d\n", __func__, in_irq);
472384ca3c6SRobert Jarzmik return IRQ_NONE;
473384ca3c6SRobert Jarzmik }
474384ca3c6SRobert Jarzmik return IRQ_HANDLED;
475354bf801SLinus Walleij }
476354bf801SLinus Walleij
pxa_ack_muxed_gpio(struct irq_data * d)477354bf801SLinus Walleij static void pxa_ack_muxed_gpio(struct irq_data *d)
478354bf801SLinus Walleij {
479384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
480384ca3c6SRobert Jarzmik unsigned int gpio = irqd_to_hwirq(d);
481fc0589caSRobert Jarzmik void __iomem *base = gpio_bank_base(&pchip->chip, gpio);
482354bf801SLinus Walleij
483fc0589caSRobert Jarzmik writel_relaxed(GPIO_bit(gpio), base + GEDR_OFFSET);
484354bf801SLinus Walleij }
485354bf801SLinus Walleij
pxa_mask_muxed_gpio(struct irq_data * d)486354bf801SLinus Walleij static void pxa_mask_muxed_gpio(struct irq_data *d)
487354bf801SLinus Walleij {
488384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
489384ca3c6SRobert Jarzmik unsigned int gpio = irqd_to_hwirq(d);
490fc0589caSRobert Jarzmik struct pxa_gpio_bank *b = gpio_to_pxabank(&pchip->chip, gpio);
491fc0589caSRobert Jarzmik void __iomem *base = gpio_bank_base(&pchip->chip, gpio);
492354bf801SLinus Walleij uint32_t grer, gfer;
493354bf801SLinus Walleij
494fc0589caSRobert Jarzmik b->irq_mask &= ~GPIO_bit(gpio);
495354bf801SLinus Walleij
496fc0589caSRobert Jarzmik grer = readl_relaxed(base + GRER_OFFSET) & ~GPIO_bit(gpio);
497fc0589caSRobert Jarzmik gfer = readl_relaxed(base + GFER_OFFSET) & ~GPIO_bit(gpio);
498fc0589caSRobert Jarzmik writel_relaxed(grer, base + GRER_OFFSET);
499fc0589caSRobert Jarzmik writel_relaxed(gfer, base + GFER_OFFSET);
500354bf801SLinus Walleij }
501354bf801SLinus Walleij
pxa_gpio_set_wake(struct irq_data * d,unsigned int on)502b95ace54SRobert Jarzmik static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
503b95ace54SRobert Jarzmik {
504384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
505384ca3c6SRobert Jarzmik unsigned int gpio = irqd_to_hwirq(d);
506b95ace54SRobert Jarzmik
507fc0589caSRobert Jarzmik if (pchip->set_wake)
508fc0589caSRobert Jarzmik return pchip->set_wake(gpio, on);
509b95ace54SRobert Jarzmik else
510b95ace54SRobert Jarzmik return 0;
511b95ace54SRobert Jarzmik }
512b95ace54SRobert Jarzmik
pxa_unmask_muxed_gpio(struct irq_data * d)513354bf801SLinus Walleij static void pxa_unmask_muxed_gpio(struct irq_data *d)
514354bf801SLinus Walleij {
515384ca3c6SRobert Jarzmik struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
516384ca3c6SRobert Jarzmik unsigned int gpio = irqd_to_hwirq(d);
517fc0589caSRobert Jarzmik struct pxa_gpio_bank *c = gpio_to_pxabank(&pchip->chip, gpio);
518354bf801SLinus Walleij
519354bf801SLinus Walleij c->irq_mask |= GPIO_bit(gpio);
520354bf801SLinus Walleij update_edge_detect(c);
521354bf801SLinus Walleij }
522354bf801SLinus Walleij
523354bf801SLinus Walleij static struct irq_chip pxa_muxed_gpio_chip = {
524354bf801SLinus Walleij .name = "GPIO",
525354bf801SLinus Walleij .irq_ack = pxa_ack_muxed_gpio,
526354bf801SLinus Walleij .irq_mask = pxa_mask_muxed_gpio,
527354bf801SLinus Walleij .irq_unmask = pxa_unmask_muxed_gpio,
528354bf801SLinus Walleij .irq_set_type = pxa_gpio_irq_type,
529b95ace54SRobert Jarzmik .irq_set_wake = pxa_gpio_set_wake,
530354bf801SLinus Walleij };
531354bf801SLinus Walleij
pxa_gpio_nums(struct platform_device * pdev)5322cab0292SHaojian Zhuang static int pxa_gpio_nums(struct platform_device *pdev)
533478e223cSHaojian Zhuang {
5342cab0292SHaojian Zhuang const struct platform_device_id *id = platform_get_device_id(pdev);
5352cab0292SHaojian Zhuang struct pxa_gpio_id *pxa_id = (struct pxa_gpio_id *)id->driver_data;
536478e223cSHaojian Zhuang int count = 0;
537478e223cSHaojian Zhuang
5382cab0292SHaojian Zhuang switch (pxa_id->type) {
5392cab0292SHaojian Zhuang case PXA25X_GPIO:
5402cab0292SHaojian Zhuang case PXA26X_GPIO:
5412cab0292SHaojian Zhuang case PXA27X_GPIO:
5422cab0292SHaojian Zhuang case PXA3XX_GPIO:
5432cab0292SHaojian Zhuang case PXA93X_GPIO:
5442cab0292SHaojian Zhuang case MMP_GPIO:
5452cab0292SHaojian Zhuang case MMP2_GPIO:
546684bba2fSRob Herring case PXA1928_GPIO:
5472cab0292SHaojian Zhuang gpio_type = pxa_id->type;
5482cab0292SHaojian Zhuang count = pxa_id->gpio_nums - 1;
5492cab0292SHaojian Zhuang break;
5502cab0292SHaojian Zhuang default:
5512cab0292SHaojian Zhuang count = -EINVAL;
5522cab0292SHaojian Zhuang break;
553478e223cSHaojian Zhuang }
554478e223cSHaojian Zhuang return count;
555478e223cSHaojian Zhuang }
556478e223cSHaojian Zhuang
pxa_irq_domain_map(struct irq_domain * d,unsigned int irq,irq_hw_number_t hw)5577a4d5079SHaojian Zhuang static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
5587a4d5079SHaojian Zhuang irq_hw_number_t hw)
5597a4d5079SHaojian Zhuang {
5607a4d5079SHaojian Zhuang irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
5617a4d5079SHaojian Zhuang handle_edge_irq);
562384ca3c6SRobert Jarzmik irq_set_chip_data(irq, d->host_data);
56323393d49SRob Herring irq_set_noprobe(irq);
5647a4d5079SHaojian Zhuang return 0;
5657a4d5079SHaojian Zhuang }
5667a4d5079SHaojian Zhuang
5671e9aa2a8SYueHaibing static const struct irq_domain_ops pxa_irq_domain_ops = {
5687a4d5079SHaojian Zhuang .map = pxa_irq_domain_map,
56972121572SDaniel Mack .xlate = irq_domain_xlate_twocell,
5707a4d5079SHaojian Zhuang };
5717a4d5079SHaojian Zhuang
5720440091bSRobert Jarzmik #ifdef CONFIG_OF
5730440091bSRobert Jarzmik static const struct of_device_id pxa_gpio_dt_ids[] = {
5740440091bSRobert Jarzmik { .compatible = "intel,pxa25x-gpio", .data = &pxa25x_id, },
5750440091bSRobert Jarzmik { .compatible = "intel,pxa26x-gpio", .data = &pxa26x_id, },
5760440091bSRobert Jarzmik { .compatible = "intel,pxa27x-gpio", .data = &pxa27x_id, },
5770440091bSRobert Jarzmik { .compatible = "intel,pxa3xx-gpio", .data = &pxa3xx_id, },
5780440091bSRobert Jarzmik { .compatible = "marvell,pxa93x-gpio", .data = &pxa93x_id, },
5790440091bSRobert Jarzmik { .compatible = "marvell,mmp-gpio", .data = &mmp_id, },
5800440091bSRobert Jarzmik { .compatible = "marvell,mmp2-gpio", .data = &mmp2_id, },
5810440091bSRobert Jarzmik { .compatible = "marvell,pxa1928-gpio", .data = &pxa1928_id, },
5820440091bSRobert Jarzmik {}
5830440091bSRobert Jarzmik };
5840440091bSRobert Jarzmik
pxa_gpio_probe_dt(struct platform_device * pdev,struct pxa_gpio_chip * pchip)585fc0589caSRobert Jarzmik static int pxa_gpio_probe_dt(struct platform_device *pdev,
586fc0589caSRobert Jarzmik struct pxa_gpio_chip *pchip)
5877a4d5079SHaojian Zhuang {
588fc0589caSRobert Jarzmik int nr_gpios;
589f8731174SHaojian Zhuang const struct pxa_gpio_id *gpio_id;
5907a4d5079SHaojian Zhuang
5918357759aSThierry Reding gpio_id = of_device_get_match_data(&pdev->dev);
592f8731174SHaojian Zhuang gpio_type = gpio_id->type;
5937a4d5079SHaojian Zhuang
594f8731174SHaojian Zhuang nr_gpios = gpio_id->gpio_nums;
5957a4d5079SHaojian Zhuang pxa_last_gpio = nr_gpios - 1;
5967a4d5079SHaojian Zhuang
597bda61a19SBartosz Golaszewski irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, nr_gpios, 0);
5987a4d5079SHaojian Zhuang if (irq_base < 0) {
5997a4d5079SHaojian Zhuang dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
600fc0589caSRobert Jarzmik return irq_base;
6017a4d5079SHaojian Zhuang }
602384ca3c6SRobert Jarzmik return irq_base;
6037a4d5079SHaojian Zhuang }
6047a4d5079SHaojian Zhuang #else
605fc0589caSRobert Jarzmik #define pxa_gpio_probe_dt(pdev, pchip) (-1)
6067a4d5079SHaojian Zhuang #endif
6077a4d5079SHaojian Zhuang
pxa_gpio_probe(struct platform_device * pdev)6083836309dSBill Pemberton static int pxa_gpio_probe(struct platform_device *pdev)
609354bf801SLinus Walleij {
610fc0589caSRobert Jarzmik struct pxa_gpio_chip *pchip;
611fc0589caSRobert Jarzmik struct pxa_gpio_bank *c;
612389eda15SHaojian Zhuang struct clk *clk;
613b95ace54SRobert Jarzmik struct pxa_gpio_platform_data *info;
614fc0589caSRobert Jarzmik void __iomem *gpio_reg_base;
615384ca3c6SRobert Jarzmik int gpio, ret;
616ae61bac9SWei Yongjun int irq0 = 0, irq1 = 0, irq_mux;
617354bf801SLinus Walleij
618fc0589caSRobert Jarzmik pchip = devm_kzalloc(&pdev->dev, sizeof(*pchip), GFP_KERNEL);
619fc0589caSRobert Jarzmik if (!pchip)
620fc0589caSRobert Jarzmik return -ENOMEM;
621fc0589caSRobert Jarzmik pchip->dev = &pdev->dev;
622fc0589caSRobert Jarzmik
623b8f649f1SHaojian Zhuang info = dev_get_platdata(&pdev->dev);
624b8f649f1SHaojian Zhuang if (info) {
625b8f649f1SHaojian Zhuang irq_base = info->irq_base;
626b8f649f1SHaojian Zhuang if (irq_base <= 0)
627b8f649f1SHaojian Zhuang return -EINVAL;
6282cab0292SHaojian Zhuang pxa_last_gpio = pxa_gpio_nums(pdev);
629fc0589caSRobert Jarzmik pchip->set_wake = info->gpio_set_wake;
6309450be76SDaniel Mack } else {
631384ca3c6SRobert Jarzmik irq_base = pxa_gpio_probe_dt(pdev, pchip);
632384ca3c6SRobert Jarzmik if (irq_base < 0)
633b8f649f1SHaojian Zhuang return -EINVAL;
6349450be76SDaniel Mack }
6359450be76SDaniel Mack
636478e223cSHaojian Zhuang if (!pxa_last_gpio)
637157d2644SHaojian Zhuang return -EINVAL;
638157d2644SHaojian Zhuang
639384ca3c6SRobert Jarzmik pchip->irqdomain = irq_domain_add_legacy(pdev->dev.of_node,
640384ca3c6SRobert Jarzmik pxa_last_gpio + 1, irq_base,
641384ca3c6SRobert Jarzmik 0, &pxa_irq_domain_ops, pchip);
64241d107adSDan Carpenter if (!pchip->irqdomain)
64341d107adSDan Carpenter return -ENOMEM;
644384ca3c6SRobert Jarzmik
645a630fe34SLubomir Rintel irq0 = platform_get_irq_byname_optional(pdev, "gpio0");
646a630fe34SLubomir Rintel irq1 = platform_get_irq_byname_optional(pdev, "gpio1");
647157d2644SHaojian Zhuang irq_mux = platform_get_irq_byname(pdev, "gpio_mux");
648157d2644SHaojian Zhuang if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0)
649157d2644SHaojian Zhuang || (irq_mux <= 0))
650157d2644SHaojian Zhuang return -EINVAL;
651384ca3c6SRobert Jarzmik
652384ca3c6SRobert Jarzmik pchip->irq0 = irq0;
653384ca3c6SRobert Jarzmik pchip->irq1 = irq1;
654542c25b7SEnrico Weigelt, metux IT consult
655542c25b7SEnrico Weigelt, metux IT consult gpio_reg_base = devm_platform_ioremap_resource(pdev, 0);
656558ab2e8STiezhu Yang if (IS_ERR(gpio_reg_base))
657558ab2e8STiezhu Yang return PTR_ERR(gpio_reg_base);
658157d2644SHaojian Zhuang
6593f4e432fSBartosz Golaszewski clk = devm_clk_get_enabled(&pdev->dev, NULL);
660389eda15SHaojian Zhuang if (IS_ERR(clk)) {
661389eda15SHaojian Zhuang dev_err(&pdev->dev, "Error %ld to get gpio clock\n",
662389eda15SHaojian Zhuang PTR_ERR(clk));
663389eda15SHaojian Zhuang return PTR_ERR(clk);
664389eda15SHaojian Zhuang }
665389eda15SHaojian Zhuang
666354bf801SLinus Walleij /* Initialize GPIO chips */
66745a541a6SAndy Shevchenko ret = pxa_init_gpio_chip(pchip, pxa_last_gpio + 1, gpio_reg_base);
6683f4e432fSBartosz Golaszewski if (ret)
669fc0589caSRobert Jarzmik return ret;
670354bf801SLinus Walleij
671354bf801SLinus Walleij /* clear all GPIO edge detects */
672fc0589caSRobert Jarzmik for_each_gpio_bank(gpio, c, pchip) {
673df664d20SHaojian Zhuang writel_relaxed(0, c->regbase + GFER_OFFSET);
674df664d20SHaojian Zhuang writel_relaxed(0, c->regbase + GRER_OFFSET);
675df664d20SHaojian Zhuang writel_relaxed(~0, c->regbase + GEDR_OFFSET);
676be24168fSHaojian Zhuang /* unmask GPIO edge detect for AP side */
677be24168fSHaojian Zhuang if (gpio_is_mmp_type(gpio_type))
678be24168fSHaojian Zhuang writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
679354bf801SLinus Walleij }
680354bf801SLinus Walleij
681ae4f4cfdSRob Herring if (irq0 > 0) {
682384ca3c6SRobert Jarzmik ret = devm_request_irq(&pdev->dev,
683384ca3c6SRobert Jarzmik irq0, pxa_gpio_direct_handler, 0,
684384ca3c6SRobert Jarzmik "gpio-0", pchip);
685384ca3c6SRobert Jarzmik if (ret)
686384ca3c6SRobert Jarzmik dev_err(&pdev->dev, "request of gpio0 irq failed: %d\n",
687384ca3c6SRobert Jarzmik ret);
688ae4f4cfdSRob Herring }
689ae4f4cfdSRob Herring if (irq1 > 0) {
690384ca3c6SRobert Jarzmik ret = devm_request_irq(&pdev->dev,
691384ca3c6SRobert Jarzmik irq1, pxa_gpio_direct_handler, 0,
692384ca3c6SRobert Jarzmik "gpio-1", pchip);
693384ca3c6SRobert Jarzmik if (ret)
694384ca3c6SRobert Jarzmik dev_err(&pdev->dev, "request of gpio1 irq failed: %d\n",
695384ca3c6SRobert Jarzmik ret);
696ae4f4cfdSRob Herring }
697384ca3c6SRobert Jarzmik ret = devm_request_irq(&pdev->dev,
698384ca3c6SRobert Jarzmik irq_mux, pxa_gpio_demux_handler, 0,
699384ca3c6SRobert Jarzmik "gpio-mux", pchip);
700384ca3c6SRobert Jarzmik if (ret)
701384ca3c6SRobert Jarzmik dev_err(&pdev->dev, "request of gpio-mux irq failed: %d\n",
702384ca3c6SRobert Jarzmik ret);
70387c49e20SHaojian Zhuang
704fc0589caSRobert Jarzmik pxa_gpio_chip = pchip;
705354bf801SLinus Walleij
706157d2644SHaojian Zhuang return 0;
707354bf801SLinus Walleij }
708354bf801SLinus Walleij
7092cab0292SHaojian Zhuang static const struct platform_device_id gpio_id_table[] = {
7102cab0292SHaojian Zhuang { "pxa25x-gpio", (unsigned long)&pxa25x_id },
7112cab0292SHaojian Zhuang { "pxa26x-gpio", (unsigned long)&pxa26x_id },
7122cab0292SHaojian Zhuang { "pxa27x-gpio", (unsigned long)&pxa27x_id },
7132cab0292SHaojian Zhuang { "pxa3xx-gpio", (unsigned long)&pxa3xx_id },
7142cab0292SHaojian Zhuang { "pxa93x-gpio", (unsigned long)&pxa93x_id },
7152cab0292SHaojian Zhuang { "mmp-gpio", (unsigned long)&mmp_id },
7162cab0292SHaojian Zhuang { "mmp2-gpio", (unsigned long)&mmp2_id },
717684bba2fSRob Herring { "pxa1928-gpio", (unsigned long)&pxa1928_id },
7182cab0292SHaojian Zhuang { },
7192cab0292SHaojian Zhuang };
7202cab0292SHaojian Zhuang
721157d2644SHaojian Zhuang static struct platform_driver pxa_gpio_driver = {
722157d2644SHaojian Zhuang .probe = pxa_gpio_probe,
723157d2644SHaojian Zhuang .driver = {
724157d2644SHaojian Zhuang .name = "pxa-gpio",
725f43e04ecSArnd Bergmann .of_match_table = of_match_ptr(pxa_gpio_dt_ids),
726157d2644SHaojian Zhuang },
7272cab0292SHaojian Zhuang .id_table = gpio_id_table,
728157d2644SHaojian Zhuang };
729cf3fa17cSLinus Walleij
pxa_gpio_legacy_init(void)730eae122b8SRobert Jarzmik static int __init pxa_gpio_legacy_init(void)
731cf3fa17cSLinus Walleij {
732eae122b8SRobert Jarzmik if (of_have_populated_dt())
733eae122b8SRobert Jarzmik return 0;
734eae122b8SRobert Jarzmik
735cf3fa17cSLinus Walleij return platform_driver_register(&pxa_gpio_driver);
736cf3fa17cSLinus Walleij }
737eae122b8SRobert Jarzmik postcore_initcall(pxa_gpio_legacy_init);
738eae122b8SRobert Jarzmik
pxa_gpio_dt_init(void)739eae122b8SRobert Jarzmik static int __init pxa_gpio_dt_init(void)
740eae122b8SRobert Jarzmik {
741eae122b8SRobert Jarzmik if (of_have_populated_dt())
742eae122b8SRobert Jarzmik return platform_driver_register(&pxa_gpio_driver);
743eae122b8SRobert Jarzmik
744eae122b8SRobert Jarzmik return 0;
745eae122b8SRobert Jarzmik }
746eae122b8SRobert Jarzmik device_initcall(pxa_gpio_dt_init);
747157d2644SHaojian Zhuang
748354bf801SLinus Walleij #ifdef CONFIG_PM
pxa_gpio_suspend(void)749354bf801SLinus Walleij static int pxa_gpio_suspend(void)
750354bf801SLinus Walleij {
751fc0589caSRobert Jarzmik struct pxa_gpio_chip *pchip = pxa_gpio_chip;
752fc0589caSRobert Jarzmik struct pxa_gpio_bank *c;
753354bf801SLinus Walleij int gpio;
754354bf801SLinus Walleij
7559ce3ebe9SRobert Jarzmik if (!pchip)
7569ce3ebe9SRobert Jarzmik return 0;
7579ce3ebe9SRobert Jarzmik
758fc0589caSRobert Jarzmik for_each_gpio_bank(gpio, c, pchip) {
759df664d20SHaojian Zhuang c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET);
760df664d20SHaojian Zhuang c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
761df664d20SHaojian Zhuang c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET);
762df664d20SHaojian Zhuang c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET);
763354bf801SLinus Walleij
764354bf801SLinus Walleij /* Clear GPIO transition detect bits */
765df664d20SHaojian Zhuang writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET);
766354bf801SLinus Walleij }
767354bf801SLinus Walleij return 0;
768354bf801SLinus Walleij }
769354bf801SLinus Walleij
pxa_gpio_resume(void)770354bf801SLinus Walleij static void pxa_gpio_resume(void)
771354bf801SLinus Walleij {
772fc0589caSRobert Jarzmik struct pxa_gpio_chip *pchip = pxa_gpio_chip;
773fc0589caSRobert Jarzmik struct pxa_gpio_bank *c;
774354bf801SLinus Walleij int gpio;
775354bf801SLinus Walleij
7769ce3ebe9SRobert Jarzmik if (!pchip)
7779ce3ebe9SRobert Jarzmik return;
7789ce3ebe9SRobert Jarzmik
779fc0589caSRobert Jarzmik for_each_gpio_bank(gpio, c, pchip) {
780354bf801SLinus Walleij /* restore level with set/clear */
781df664d20SHaojian Zhuang writel_relaxed(c->saved_gplr, c->regbase + GPSR_OFFSET);
782df664d20SHaojian Zhuang writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET);
783354bf801SLinus Walleij
784df664d20SHaojian Zhuang writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET);
785df664d20SHaojian Zhuang writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET);
786df664d20SHaojian Zhuang writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET);
787354bf801SLinus Walleij }
788354bf801SLinus Walleij }
789354bf801SLinus Walleij #else
790354bf801SLinus Walleij #define pxa_gpio_suspend NULL
791354bf801SLinus Walleij #define pxa_gpio_resume NULL
792354bf801SLinus Walleij #endif
793354bf801SLinus Walleij
7941e9aa2a8SYueHaibing static struct syscore_ops pxa_gpio_syscore_ops = {
795354bf801SLinus Walleij .suspend = pxa_gpio_suspend,
796354bf801SLinus Walleij .resume = pxa_gpio_resume,
797354bf801SLinus Walleij };
798157d2644SHaojian Zhuang
pxa_gpio_sysinit(void)799157d2644SHaojian Zhuang static int __init pxa_gpio_sysinit(void)
800157d2644SHaojian Zhuang {
801157d2644SHaojian Zhuang register_syscore_ops(&pxa_gpio_syscore_ops);
802157d2644SHaojian Zhuang return 0;
803157d2644SHaojian Zhuang }
804157d2644SHaojian Zhuang postcore_initcall(pxa_gpio_sysinit);
805