Blame view

drivers/gpio/gpio-pxa.c 20.2 KB
1c44f5f16   Philipp Zabel   gpiolib support f...
1
  /*
38f539a60   Eric Miao   [ARM] pxa: move c...
2
   *  linux/arch/arm/plat-pxa/gpio.c
1c44f5f16   Philipp Zabel   gpiolib support f...
3
4
5
6
7
8
9
10
11
12
13
   *
   *  Generic PXA GPIO handling
   *
   *  Author:	Nicolas Pitre
   *  Created:	Jun 15, 2001
   *  Copyright:	MontaVista Software Inc.
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License version 2 as
   *  published by the Free Software Foundation.
   */
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
14
  #include <linux/module.h>
389eda15e   Haojian Zhuang   ARM: pxa: add clk...
15
16
  #include <linux/clk.h>
  #include <linux/err.h>
2f8163baa   Russell King   ARM: gpio: conver...
17
  #include <linux/gpio.h>
157d2644c   Haojian Zhuang   ARM: pxa: change ...
18
  #include <linux/gpio-pxa.h>
1c44f5f16   Philipp Zabel   gpiolib support f...
19
  #include <linux/init.h>
ae4f4cfd8   Rob Herring   gpio: pxa: remove...
20
  #include <linux/interrupt.h>
e3630db1f   eric miao   [ARM] pxa: move G...
21
  #include <linux/irq.h>
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
22
  #include <linux/irqdomain.h>
de88cbb7b   Catalin Marinas   arm: Move chained...
23
  #include <linux/irqchip/chained_irq.h>
fced80c73   Russell King   [ARM] Convert asm...
24
  #include <linux/io.h>
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
25
26
  #include <linux/of.h>
  #include <linux/of_device.h>
a770d9463   Robert Jarzmik   gpio: pxa: add pi...
27
  #include <linux/pinctrl/consumer.h>
157d2644c   Haojian Zhuang   ARM: pxa: change ...
28
  #include <linux/platform_device.h>
2eaa03b5b   Rafael J. Wysocki   ARM / PXA: Use st...
29
  #include <linux/syscore_ops.h>
4aa78264d   Daniel Mack   [ARM] pxa: use kz...
30
  #include <linux/slab.h>
1c44f5f16   Philipp Zabel   gpiolib support f...
31

157d2644c   Haojian Zhuang   ARM: pxa: change ...
32
33
34
35
36
37
38
39
40
41
42
43
44
  /*
   * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
   * one set of registers. The register offsets are organized below:
   *
   *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
   * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
   * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
   * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
   *
   * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
   * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
   * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
   *
684bba2ff   Rob Herring   gpio: pxa: add PX...
45
46
   * BANK 6 - 0x0200  0x020C  0x0218  0x0224  0x0230  0x023C  0x0248
   *
157d2644c   Haojian Zhuang   ARM: pxa: change ...
47
48
   * NOTE:
   *   BANK 3 is only available on PXA27x and later processors.
684bba2ff   Rob Herring   gpio: pxa: add PX...
49
50
   *   BANK 4 and 5 are only available on PXA935, PXA1928
   *   BANK 6 is only available on PXA1928
157d2644c   Haojian Zhuang   ARM: pxa: change ...
51
52
53
54
55
56
57
58
59
60
   */
  
  #define GPLR_OFFSET	0x00
  #define GPDR_OFFSET	0x0C
  #define GPSR_OFFSET	0x18
  #define GPCR_OFFSET	0x24
  #define GRER_OFFSET	0x30
  #define GFER_OFFSET	0x3C
  #define GEDR_OFFSET	0x48
  #define GAFR_OFFSET	0x54
be24168f1   Haojian Zhuang   ARM: mmp: clear g...
61
  #define ED_MASK_OFFSET	0x9C	/* GPIO edge detection for AP side */
157d2644c   Haojian Zhuang   ARM: pxa: change ...
62

1e970b7d6   Rob Herring   gpio: pxa: simpli...
63
  #define BANK_OFF(n)	(((n) / 3) << 8) + (((n) % 3) << 2)
1c44f5f16   Philipp Zabel   gpiolib support f...
64

3b8e285c2   Eric Miao   [ARM] pxa: move d...
65
  int pxa_last_gpio;
9450be76d   Daniel Mack   GPIO: gpio-pxa: s...
66
  static int irq_base;
3b8e285c2   Eric Miao   [ARM] pxa: move d...
67

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
68
  struct pxa_gpio_bank {
0807da593   Eric Miao   [ARM] pxa: access...
69
  	void __iomem	*regbase;
0807da593   Eric Miao   [ARM] pxa: access...
70
71
72
73
74
75
76
77
78
79
  	unsigned long	irq_mask;
  	unsigned long	irq_edge_rise;
  	unsigned long	irq_edge_fall;
  
  #ifdef CONFIG_PM
  	unsigned long	saved_gplr;
  	unsigned long	saved_gpdr;
  	unsigned long	saved_grer;
  	unsigned long	saved_gfer;
  #endif
1c44f5f16   Philipp Zabel   gpiolib support f...
80
  };
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
81
82
83
84
  struct pxa_gpio_chip {
  	struct device *dev;
  	struct gpio_chip chip;
  	struct pxa_gpio_bank *banks;
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
85
  	struct irq_domain *irqdomain;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
86
87
88
89
90
  
  	int irq0;
  	int irq1;
  	int (*set_wake)(unsigned int gpio, unsigned int on);
  };
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
91
  enum pxa_gpio_type {
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
92
93
94
95
96
97
  	PXA25X_GPIO = 0,
  	PXA26X_GPIO,
  	PXA27X_GPIO,
  	PXA3XX_GPIO,
  	PXA93X_GPIO,
  	MMP_GPIO = 0x10,
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
98
  	MMP2_GPIO,
684bba2ff   Rob Herring   gpio: pxa: add PX...
99
  	PXA1928_GPIO,
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
100
101
102
103
104
  };
  
  struct pxa_gpio_id {
  	enum pxa_gpio_type	type;
  	int			gpio_nums;
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
105
  };
0807da593   Eric Miao   [ARM] pxa: access...
106
  static DEFINE_SPINLOCK(gpio_lock);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
107
  static struct pxa_gpio_chip *pxa_gpio_chip;
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
108
  static enum pxa_gpio_type gpio_type;
0807da593   Eric Miao   [ARM] pxa: access...
109

2cab02922   Haojian Zhuang   ARM: pxa: remove ...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  static struct pxa_gpio_id pxa25x_id = {
  	.type		= PXA25X_GPIO,
  	.gpio_nums	= 85,
  };
  
  static struct pxa_gpio_id pxa26x_id = {
  	.type		= PXA26X_GPIO,
  	.gpio_nums	= 90,
  };
  
  static struct pxa_gpio_id pxa27x_id = {
  	.type		= PXA27X_GPIO,
  	.gpio_nums	= 121,
  };
  
  static struct pxa_gpio_id pxa3xx_id = {
  	.type		= PXA3XX_GPIO,
  	.gpio_nums	= 128,
  };
  
  static struct pxa_gpio_id pxa93x_id = {
  	.type		= PXA93X_GPIO,
  	.gpio_nums	= 192,
  };
  
  static struct pxa_gpio_id mmp_id = {
  	.type		= MMP_GPIO,
  	.gpio_nums	= 128,
  };
  
  static struct pxa_gpio_id mmp2_id = {
  	.type		= MMP2_GPIO,
  	.gpio_nums	= 192,
  };
684bba2ff   Rob Herring   gpio: pxa: add PX...
144
145
146
147
  static struct pxa_gpio_id pxa1928_id = {
  	.type		= PXA1928_GPIO,
  	.gpio_nums	= 224,
  };
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
148
149
  #define for_each_gpio_bank(i, b, pc)					\
  	for (i = 0, b = pc->banks; i <= pxa_last_gpio; i += 32, b++)
0807da593   Eric Miao   [ARM] pxa: access...
150

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
151
  static inline struct pxa_gpio_chip *chip_to_pxachip(struct gpio_chip *c)
0807da593   Eric Miao   [ARM] pxa: access...
152
  {
81d0c31d1   Linus Walleij   gpio: pxa: use gp...
153
  	struct pxa_gpio_chip *pxa_chip = gpiochip_get_data(c);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
154
155
  
  	return pxa_chip;
0807da593   Eric Miao   [ARM] pxa: access...
156
  }
81d0c31d1   Linus Walleij   gpio: pxa: use gp...
157

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
158
159
  static inline void __iomem *gpio_bank_base(struct gpio_chip *c, int gpio)
  {
81d0c31d1   Linus Walleij   gpio: pxa: use gp...
160
161
  	struct pxa_gpio_chip *p = gpiochip_get_data(c);
  	struct pxa_gpio_bank *bank = p->banks + (gpio / 32);
0807da593   Eric Miao   [ARM] pxa: access...
162

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
163
164
165
166
167
  	return bank->regbase;
  }
  
  static inline struct pxa_gpio_bank *gpio_to_pxabank(struct gpio_chip *c,
  						    unsigned gpio)
0807da593   Eric Miao   [ARM] pxa: access...
168
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
169
  	return chip_to_pxachip(c)->banks + gpio / 32;
0807da593   Eric Miao   [ARM] pxa: access...
170
  }
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
171
172
173
174
175
176
177
178
179
  static inline int gpio_is_pxa_type(int type)
  {
  	return (type & MMP_GPIO) == 0;
  }
  
  static inline int gpio_is_mmp_type(int type)
  {
  	return (type & MMP_GPIO) != 0;
  }
157d2644c   Haojian Zhuang   ARM: pxa: change ...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  /* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted,
   * as well as their Alternate Function value being '1' for GPIO in GAFRx.
   */
  static inline int __gpio_is_inverted(int gpio)
  {
  	if ((gpio_type == PXA26X_GPIO) && (gpio > 85))
  		return 1;
  	return 0;
  }
  
  /*
   * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
   * function of a GPIO, and GPDRx cannot be altered once configured. It
   * is attributed as "occupied" here (I know this terminology isn't
   * accurate, you are welcome to propose a better one :-)
   */
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
196
  static inline int __gpio_is_occupied(struct pxa_gpio_chip *pchip, unsigned gpio)
157d2644c   Haojian Zhuang   ARM: pxa: change ...
197
  {
157d2644c   Haojian Zhuang   ARM: pxa: change ...
198
199
200
  	void __iomem *base;
  	unsigned long gafr = 0, gpdr = 0;
  	int ret, af = 0, dir = 0;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
201
  	base = gpio_bank_base(&pchip->chip, gpio);
157d2644c   Haojian Zhuang   ARM: pxa: change ...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  	gpdr = readl_relaxed(base + GPDR_OFFSET);
  
  	switch (gpio_type) {
  	case PXA25X_GPIO:
  	case PXA26X_GPIO:
  	case PXA27X_GPIO:
  		gafr = readl_relaxed(base + GAFR_OFFSET);
  		af = (gafr >> ((gpio & 0xf) * 2)) & 0x3;
  		dir = gpdr & GPIO_bit(gpio);
  
  		if (__gpio_is_inverted(gpio))
  			ret = (af != 1) || (dir == 0);
  		else
  			ret = (af != 0) || (dir != 0);
  		break;
  	default:
  		ret = gpdr & GPIO_bit(gpio);
  		break;
  	}
  	return ret;
  }
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
223
  int pxa_irq_to_gpio(int irq)
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
224
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
225
226
227
228
229
230
231
232
  	struct pxa_gpio_chip *pchip = pxa_gpio_chip;
  	int irq_gpio0;
  
  	irq_gpio0 = irq_find_mapping(pchip->irqdomain, 0);
  	if (irq_gpio0 > 0)
  		return irq - irq_gpio0;
  
  	return irq_gpio0;
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
233
  }
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
234
  static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
235
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
236
237
238
  	struct pxa_gpio_chip *pchip = chip_to_pxachip(chip);
  
  	return irq_find_mapping(pchip->irqdomain, offset);
4929f5a8a   Haojian Zhuang   ARM: pxa: rename ...
239
  }
1c44f5f16   Philipp Zabel   gpiolib support f...
240
241
  static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
242
243
  	void __iomem *base = gpio_bank_base(chip, offset);
  	uint32_t value, mask = GPIO_bit(offset);
0807da593   Eric Miao   [ARM] pxa: access...
244
  	unsigned long flags;
a770d9463   Robert Jarzmik   gpio: pxa: add pi...
245
246
247
248
249
  	int ret;
  
  	ret = pinctrl_gpio_direction_input(chip->base + offset);
  	if (!ret)
  		return 0;
0807da593   Eric Miao   [ARM] pxa: access...
250
251
  
  	spin_lock_irqsave(&gpio_lock, flags);
df664d208   Haojian Zhuang   ARM: pxa: use lit...
252
  	value = readl_relaxed(base + GPDR_OFFSET);
067455aa5   Eric Miao   [ARM] pxa: add su...
253
254
255
256
  	if (__gpio_is_inverted(chip->base + offset))
  		value |= mask;
  	else
  		value &= ~mask;
df664d208   Haojian Zhuang   ARM: pxa: use lit...
257
  	writel_relaxed(value, base + GPDR_OFFSET);
1c44f5f16   Philipp Zabel   gpiolib support f...
258

0807da593   Eric Miao   [ARM] pxa: access...
259
  	spin_unlock_irqrestore(&gpio_lock, flags);
1c44f5f16   Philipp Zabel   gpiolib support f...
260
261
262
263
  	return 0;
  }
  
  static int pxa_gpio_direction_output(struct gpio_chip *chip,
0807da593   Eric Miao   [ARM] pxa: access...
264
  				     unsigned offset, int value)
1c44f5f16   Philipp Zabel   gpiolib support f...
265
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
266
267
  	void __iomem *base = gpio_bank_base(chip, offset);
  	uint32_t tmp, mask = GPIO_bit(offset);
0807da593   Eric Miao   [ARM] pxa: access...
268
  	unsigned long flags;
a770d9463   Robert Jarzmik   gpio: pxa: add pi...
269
  	int ret;
0807da593   Eric Miao   [ARM] pxa: access...
270

df664d208   Haojian Zhuang   ARM: pxa: use lit...
271
  	writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
0807da593   Eric Miao   [ARM] pxa: access...
272

a770d9463   Robert Jarzmik   gpio: pxa: add pi...
273
  	ret = pinctrl_gpio_direction_output(chip->base + offset);
c4e5ffb6f   Robert Jarzmik   gpio: pxa: fix le...
274
275
  	if (ret)
  		return ret;
a770d9463   Robert Jarzmik   gpio: pxa: add pi...
276

0807da593   Eric Miao   [ARM] pxa: access...
277
  	spin_lock_irqsave(&gpio_lock, flags);
df664d208   Haojian Zhuang   ARM: pxa: use lit...
278
  	tmp = readl_relaxed(base + GPDR_OFFSET);
067455aa5   Eric Miao   [ARM] pxa: add su...
279
280
281
282
  	if (__gpio_is_inverted(chip->base + offset))
  		tmp &= ~mask;
  	else
  		tmp |= mask;
df664d208   Haojian Zhuang   ARM: pxa: use lit...
283
  	writel_relaxed(tmp, base + GPDR_OFFSET);
1c44f5f16   Philipp Zabel   gpiolib support f...
284

0807da593   Eric Miao   [ARM] pxa: access...
285
  	spin_unlock_irqrestore(&gpio_lock, flags);
1c44f5f16   Philipp Zabel   gpiolib support f...
286
287
  	return 0;
  }
1c44f5f16   Philipp Zabel   gpiolib support f...
288
289
  static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
290
291
292
293
  	void __iomem *base = gpio_bank_base(chip, offset);
  	u32 gplr = readl_relaxed(base + GPLR_OFFSET);
  
  	return !!(gplr & GPIO_bit(offset));
1c44f5f16   Philipp Zabel   gpiolib support f...
294
  }
1c44f5f16   Philipp Zabel   gpiolib support f...
295
296
  static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
297
298
299
300
  	void __iomem *base = gpio_bank_base(chip, offset);
  
  	writel_relaxed(GPIO_bit(offset),
  		       base + (value ? GPSR_OFFSET : GPCR_OFFSET));
1c44f5f16   Philipp Zabel   gpiolib support f...
301
  }
721215726   Daniel Mack   GPIO: gpio-pxa: f...
302
303
304
305
306
307
308
  #ifdef CONFIG_OF_GPIO
  static int pxa_gpio_of_xlate(struct gpio_chip *gc,
  			     const struct of_phandle_args *gpiospec,
  			     u32 *flags)
  {
  	if (gpiospec->args[0] > pxa_last_gpio)
  		return -EINVAL;
721215726   Daniel Mack   GPIO: gpio-pxa: f...
309
310
  	if (flags)
  		*flags = gpiospec->args[1];
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
311
  	return gpiospec->args[0];
721215726   Daniel Mack   GPIO: gpio-pxa: f...
312
313
  }
  #endif
a770d9463   Robert Jarzmik   gpio: pxa: add pi...
314
315
316
317
318
319
320
321
322
  static int pxa_gpio_request(struct gpio_chip *chip, unsigned int offset)
  {
  	return pinctrl_request_gpio(chip->base + offset);
  }
  
  static void pxa_gpio_free(struct gpio_chip *chip, unsigned int offset)
  {
  	pinctrl_free_gpio(chip->base + offset);
  }
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
323
  static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
324
  			      struct device_node *np, void __iomem *regbase)
a58fbcd8a   Eric Miao   [ARM] pxa: move I...
325
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
326
327
  	int i, gpio, nbanks = DIV_ROUND_UP(ngpio, 32);
  	struct pxa_gpio_bank *bank;
a58fbcd8a   Eric Miao   [ARM] pxa: move I...
328

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
329
330
331
  	pchip->banks = devm_kcalloc(pchip->dev, nbanks, sizeof(*pchip->banks),
  				    GFP_KERNEL);
  	if (!pchip->banks)
0807da593   Eric Miao   [ARM] pxa: access...
332
  		return -ENOMEM;
a58fbcd8a   Eric Miao   [ARM] pxa: move I...
333

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
334
335
336
337
338
339
340
  	pchip->chip.label = "gpio-pxa";
  	pchip->chip.direction_input  = pxa_gpio_direction_input;
  	pchip->chip.direction_output = pxa_gpio_direction_output;
  	pchip->chip.get = pxa_gpio_get;
  	pchip->chip.set = pxa_gpio_set;
  	pchip->chip.to_irq = pxa_gpio_to_irq;
  	pchip->chip.ngpio = ngpio;
a770d9463   Robert Jarzmik   gpio: pxa: add pi...
341
342
  	pchip->chip.request = pxa_gpio_request;
  	pchip->chip.free = pxa_gpio_free;
721215726   Daniel Mack   GPIO: gpio-pxa: f...
343
  #ifdef CONFIG_OF_GPIO
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
344
  	pchip->chip.of_node = np;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
345
346
  	pchip->chip.of_xlate = pxa_gpio_of_xlate;
  	pchip->chip.of_gpio_n_cells = 2;
721215726   Daniel Mack   GPIO: gpio-pxa: f...
347
  #endif
0807da593   Eric Miao   [ARM] pxa: access...
348

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
349
350
351
  	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
  		bank = pchip->banks + i;
  		bank->regbase = regbase + BANK_OFF(i);
0807da593   Eric Miao   [ARM] pxa: access...
352
  	}
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
353

81d0c31d1   Linus Walleij   gpio: pxa: use gp...
354
  	return gpiochip_add_data(&pchip->chip, pchip);
0807da593   Eric Miao   [ARM] pxa: access...
355
  }
e3630db1f   eric miao   [ARM] pxa: move G...
356

a8f6faeba   Eric Miao   [ARM] pxa: fix is...
357
358
359
  /* Update only those GRERx and GFERx edge detection register bits if those
   * bits are set in c->irq_mask
   */
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
360
  static inline void update_edge_detect(struct pxa_gpio_bank *c)
a8f6faeba   Eric Miao   [ARM] pxa: fix is...
361
362
  {
  	uint32_t grer, gfer;
df664d208   Haojian Zhuang   ARM: pxa: use lit...
363
364
  	grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask;
  	gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask;
a8f6faeba   Eric Miao   [ARM] pxa: fix is...
365
366
  	grer |= c->irq_edge_rise & c->irq_mask;
  	gfer |= c->irq_edge_fall & c->irq_mask;
df664d208   Haojian Zhuang   ARM: pxa: use lit...
367
368
  	writel_relaxed(grer, c->regbase + GRER_OFFSET);
  	writel_relaxed(gfer, c->regbase + GFER_OFFSET);
a8f6faeba   Eric Miao   [ARM] pxa: fix is...
369
  }
a3f4c927d   Lennert Buytenhek   ARM: PXA SoCs: ir...
370
  static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
e3630db1f   eric miao   [ARM] pxa: move G...
371
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
372
373
  	struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
  	unsigned int gpio = irqd_to_hwirq(d);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
374
  	struct pxa_gpio_bank *c = gpio_to_pxabank(&pchip->chip, gpio);
0807da593   Eric Miao   [ARM] pxa: access...
375
  	unsigned long gpdr, mask = GPIO_bit(gpio);
e3630db1f   eric miao   [ARM] pxa: move G...
376

e3630db1f   eric miao   [ARM] pxa: move G...
377
378
379
380
  	if (type == IRQ_TYPE_PROBE) {
  		/* Don't mess with enabled GPIOs using preconfigured edges or
  		 * GPIOs set to alternate function or to output during probe
  		 */
0807da593   Eric Miao   [ARM] pxa: access...
381
  		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
e3630db1f   eric miao   [ARM] pxa: move G...
382
  			return 0;
689c04a39   eric miao   [ARM] pxa: make p...
383

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
384
  		if (__gpio_is_occupied(pchip, gpio))
e3630db1f   eric miao   [ARM] pxa: move G...
385
  			return 0;
689c04a39   eric miao   [ARM] pxa: make p...
386

e3630db1f   eric miao   [ARM] pxa: move G...
387
388
  		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
  	}
df664d208   Haojian Zhuang   ARM: pxa: use lit...
389
  	gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
0807da593   Eric Miao   [ARM] pxa: access...
390

067455aa5   Eric Miao   [ARM] pxa: add su...
391
  	if (__gpio_is_inverted(gpio))
df664d208   Haojian Zhuang   ARM: pxa: use lit...
392
  		writel_relaxed(gpdr | mask,  c->regbase + GPDR_OFFSET);
067455aa5   Eric Miao   [ARM] pxa: add su...
393
  	else
df664d208   Haojian Zhuang   ARM: pxa: use lit...
394
  		writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET);
e3630db1f   eric miao   [ARM] pxa: move G...
395
396
  
  	if (type & IRQ_TYPE_EDGE_RISING)
0807da593   Eric Miao   [ARM] pxa: access...
397
  		c->irq_edge_rise |= mask;
e3630db1f   eric miao   [ARM] pxa: move G...
398
  	else
0807da593   Eric Miao   [ARM] pxa: access...
399
  		c->irq_edge_rise &= ~mask;
e3630db1f   eric miao   [ARM] pxa: move G...
400
401
  
  	if (type & IRQ_TYPE_EDGE_FALLING)
0807da593   Eric Miao   [ARM] pxa: access...
402
  		c->irq_edge_fall |= mask;
e3630db1f   eric miao   [ARM] pxa: move G...
403
  	else
0807da593   Eric Miao   [ARM] pxa: access...
404
  		c->irq_edge_fall &= ~mask;
e3630db1f   eric miao   [ARM] pxa: move G...
405

a8f6faeba   Eric Miao   [ARM] pxa: fix is...
406
  	update_edge_detect(c);
e3630db1f   eric miao   [ARM] pxa: move G...
407

a3f4c927d   Lennert Buytenhek   ARM: PXA SoCs: ir...
408
409
  	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s
  ", __func__, d->irq, gpio,
e3630db1f   eric miao   [ARM] pxa: move G...
410
411
412
413
  		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
  		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
  	return 0;
  }
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
414
  static irqreturn_t pxa_gpio_demux_handler(int in_irq, void *d)
e3630db1f   eric miao   [ARM] pxa: move G...
415
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
416
  	int loop, gpio, n, handled = 0;
0807da593   Eric Miao   [ARM] pxa: access...
417
  	unsigned long gedr;
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
418
  	struct pxa_gpio_chip *pchip = d;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
419
  	struct pxa_gpio_bank *c;
0d2ee5d77   Chao Xie   gpio: pxa: add ch...
420

e3630db1f   eric miao   [ARM] pxa: move G...
421
  	do {
e3630db1f   eric miao   [ARM] pxa: move G...
422
  		loop = 0;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
423
  		for_each_gpio_bank(gpio, c, pchip) {
df664d208   Haojian Zhuang   ARM: pxa: use lit...
424
  			gedr = readl_relaxed(c->regbase + GEDR_OFFSET);
0807da593   Eric Miao   [ARM] pxa: access...
425
  			gedr = gedr & c->irq_mask;
df664d208   Haojian Zhuang   ARM: pxa: use lit...
426
  			writel_relaxed(gedr, c->regbase + GEDR_OFFSET);
e3630db1f   eric miao   [ARM] pxa: move G...
427

d724f1c9c   Wei Yongjun   gpio: pxa: using ...
428
  			for_each_set_bit(n, &gedr, BITS_PER_LONG) {
0807da593   Eric Miao   [ARM] pxa: access...
429
  				loop = 1;
e3630db1f   eric miao   [ARM] pxa: move G...
430

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
431
  				generic_handle_irq(gpio_to_irq(gpio + n));
0807da593   Eric Miao   [ARM] pxa: access...
432
  			}
e3630db1f   eric miao   [ARM] pxa: move G...
433
  		}
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
434
  		handled += loop;
e3630db1f   eric miao   [ARM] pxa: move G...
435
  	} while (loop);
0d2ee5d77   Chao Xie   gpio: pxa: add ch...
436

384ca3c6a   Robert Jarzmik   gpio: pxa: change...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  	return handled ? IRQ_HANDLED : IRQ_NONE;
  }
  
  static irqreturn_t pxa_gpio_direct_handler(int in_irq, void *d)
  {
  	struct pxa_gpio_chip *pchip = d;
  
  	if (in_irq == pchip->irq0) {
  		generic_handle_irq(gpio_to_irq(0));
  	} else if (in_irq == pchip->irq1) {
  		generic_handle_irq(gpio_to_irq(1));
  	} else {
  		pr_err("%s() unknown irq %d
  ", __func__, in_irq);
  		return IRQ_NONE;
  	}
  	return IRQ_HANDLED;
e3630db1f   eric miao   [ARM] pxa: move G...
454
  }
a3f4c927d   Lennert Buytenhek   ARM: PXA SoCs: ir...
455
  static void pxa_ack_muxed_gpio(struct irq_data *d)
e3630db1f   eric miao   [ARM] pxa: move G...
456
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
457
458
  	struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
  	unsigned int gpio = irqd_to_hwirq(d);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
459
  	void __iomem *base = gpio_bank_base(&pchip->chip, gpio);
0807da593   Eric Miao   [ARM] pxa: access...
460

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
461
  	writel_relaxed(GPIO_bit(gpio), base + GEDR_OFFSET);
e3630db1f   eric miao   [ARM] pxa: move G...
462
  }
a3f4c927d   Lennert Buytenhek   ARM: PXA SoCs: ir...
463
  static void pxa_mask_muxed_gpio(struct irq_data *d)
e3630db1f   eric miao   [ARM] pxa: move G...
464
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
465
466
  	struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
  	unsigned int gpio = irqd_to_hwirq(d);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
467
468
  	struct pxa_gpio_bank *b = gpio_to_pxabank(&pchip->chip, gpio);
  	void __iomem *base = gpio_bank_base(&pchip->chip, gpio);
0807da593   Eric Miao   [ARM] pxa: access...
469
  	uint32_t grer, gfer;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
470
  	b->irq_mask &= ~GPIO_bit(gpio);
0807da593   Eric Miao   [ARM] pxa: access...
471

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
472
473
474
475
  	grer = readl_relaxed(base + GRER_OFFSET) & ~GPIO_bit(gpio);
  	gfer = readl_relaxed(base + GFER_OFFSET) & ~GPIO_bit(gpio);
  	writel_relaxed(grer, base + GRER_OFFSET);
  	writel_relaxed(gfer, base + GFER_OFFSET);
e3630db1f   eric miao   [ARM] pxa: move G...
476
  }
b95ace54a   Robert Jarzmik   ARM: pxa: fix gpi...
477
478
  static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
479
480
  	struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
  	unsigned int gpio = irqd_to_hwirq(d);
b95ace54a   Robert Jarzmik   ARM: pxa: fix gpi...
481

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
482
483
  	if (pchip->set_wake)
  		return pchip->set_wake(gpio, on);
b95ace54a   Robert Jarzmik   ARM: pxa: fix gpi...
484
485
486
  	else
  		return 0;
  }
a3f4c927d   Lennert Buytenhek   ARM: PXA SoCs: ir...
487
  static void pxa_unmask_muxed_gpio(struct irq_data *d)
e3630db1f   eric miao   [ARM] pxa: move G...
488
  {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
489
490
  	struct pxa_gpio_chip *pchip = irq_data_get_irq_chip_data(d);
  	unsigned int gpio = irqd_to_hwirq(d);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
491
  	struct pxa_gpio_bank *c = gpio_to_pxabank(&pchip->chip, gpio);
0807da593   Eric Miao   [ARM] pxa: access...
492
493
  
  	c->irq_mask |= GPIO_bit(gpio);
a8f6faeba   Eric Miao   [ARM] pxa: fix is...
494
  	update_edge_detect(c);
e3630db1f   eric miao   [ARM] pxa: move G...
495
496
497
498
  }
  
  static struct irq_chip pxa_muxed_gpio_chip = {
  	.name		= "GPIO",
a3f4c927d   Lennert Buytenhek   ARM: PXA SoCs: ir...
499
500
501
502
  	.irq_ack	= pxa_ack_muxed_gpio,
  	.irq_mask	= pxa_mask_muxed_gpio,
  	.irq_unmask	= pxa_unmask_muxed_gpio,
  	.irq_set_type	= pxa_gpio_irq_type,
b95ace54a   Robert Jarzmik   ARM: pxa: fix gpi...
503
  	.irq_set_wake	= pxa_gpio_set_wake,
e3630db1f   eric miao   [ARM] pxa: move G...
504
  };
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
505
  static int pxa_gpio_nums(struct platform_device *pdev)
478e223cc   Haojian Zhuang   ARM: pxa: recogni...
506
  {
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
507
508
  	const struct platform_device_id *id = platform_get_device_id(pdev);
  	struct pxa_gpio_id *pxa_id = (struct pxa_gpio_id *)id->driver_data;
478e223cc   Haojian Zhuang   ARM: pxa: recogni...
509
  	int count = 0;
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
510
511
512
513
514
515
516
517
  	switch (pxa_id->type) {
  	case PXA25X_GPIO:
  	case PXA26X_GPIO:
  	case PXA27X_GPIO:
  	case PXA3XX_GPIO:
  	case PXA93X_GPIO:
  	case MMP_GPIO:
  	case MMP2_GPIO:
684bba2ff   Rob Herring   gpio: pxa: add PX...
518
  	case PXA1928_GPIO:
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
519
520
521
522
523
524
  		gpio_type = pxa_id->type;
  		count = pxa_id->gpio_nums - 1;
  		break;
  	default:
  		count = -EINVAL;
  		break;
478e223cc   Haojian Zhuang   ARM: pxa: recogni...
525
  	}
478e223cc   Haojian Zhuang   ARM: pxa: recogni...
526
527
  	return count;
  }
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
528
529
530
531
532
  static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
  			      irq_hw_number_t hw)
  {
  	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
  				 handle_edge_irq);
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
533
  	irq_set_chip_data(irq, d->host_data);
23393d49f   Rob Herring   gpio: kill off se...
534
  	irq_set_noprobe(irq);
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
535
536
537
538
539
  	return 0;
  }
  
  const struct irq_domain_ops pxa_irq_domain_ops = {
  	.map	= pxa_irq_domain_map,
721215726   Daniel Mack   GPIO: gpio-pxa: f...
540
  	.xlate	= irq_domain_xlate_twocell,
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
541
  };
0440091be   Robert Jarzmik   gpio: pxa: fixes ...
542
543
544
545
546
547
548
549
550
551
552
553
  #ifdef CONFIG_OF
  static const struct of_device_id pxa_gpio_dt_ids[] = {
  	{ .compatible = "intel,pxa25x-gpio",	.data = &pxa25x_id, },
  	{ .compatible = "intel,pxa26x-gpio",	.data = &pxa26x_id, },
  	{ .compatible = "intel,pxa27x-gpio",	.data = &pxa27x_id, },
  	{ .compatible = "intel,pxa3xx-gpio",	.data = &pxa3xx_id, },
  	{ .compatible = "marvell,pxa93x-gpio",	.data = &pxa93x_id, },
  	{ .compatible = "marvell,mmp-gpio",	.data = &mmp_id, },
  	{ .compatible = "marvell,mmp2-gpio",	.data = &mmp2_id, },
  	{ .compatible = "marvell,pxa1928-gpio",	.data = &pxa1928_id, },
  	{}
  };
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
554
555
  static int pxa_gpio_probe_dt(struct platform_device *pdev,
  			     struct pxa_gpio_chip *pchip)
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
556
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
557
  	int nr_gpios;
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
558
559
  	const struct of_device_id *of_id =
  				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
f87311743   Haojian Zhuang   ARM: mmp: add mor...
560
  	const struct pxa_gpio_id *gpio_id;
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
561

f87311743   Haojian Zhuang   ARM: mmp: add mor...
562
  	if (!of_id || !of_id->data) {
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
563
564
565
566
  		dev_err(&pdev->dev, "Failed to find gpio controller
  ");
  		return -EFAULT;
  	}
f87311743   Haojian Zhuang   ARM: mmp: add mor...
567
568
  	gpio_id = of_id->data;
  	gpio_type = gpio_id->type;
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
569

f87311743   Haojian Zhuang   ARM: mmp: add mor...
570
  	nr_gpios = gpio_id->gpio_nums;
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
571
572
573
574
575
576
  	pxa_last_gpio = nr_gpios - 1;
  
  	irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
  	if (irq_base < 0) {
  		dev_err(&pdev->dev, "Failed to allocate IRQ numbers
  ");
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
577
  		return irq_base;
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
578
  	}
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
579
  	return irq_base;
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
580
581
  }
  #else
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
582
  #define pxa_gpio_probe_dt(pdev, pchip)		(-1)
7a4d5079b   Haojian Zhuang   gpio: pxa: parse ...
583
  #endif
3836309d9   Bill Pemberton   gpio: remove use ...
584
  static int pxa_gpio_probe(struct platform_device *pdev)
e3630db1f   eric miao   [ARM] pxa: move G...
585
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
586
587
  	struct pxa_gpio_chip *pchip;
  	struct pxa_gpio_bank *c;
157d2644c   Haojian Zhuang   ARM: pxa: change ...
588
  	struct resource *res;
389eda15e   Haojian Zhuang   ARM: pxa: add clk...
589
  	struct clk *clk;
b95ace54a   Robert Jarzmik   ARM: pxa: fix gpi...
590
  	struct pxa_gpio_platform_data *info;
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
591
  	void __iomem *gpio_reg_base;
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
592
  	int gpio, ret;
157d2644c   Haojian Zhuang   ARM: pxa: change ...
593
  	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
e3630db1f   eric miao   [ARM] pxa: move G...
594

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
595
596
597
598
  	pchip = devm_kzalloc(&pdev->dev, sizeof(*pchip), GFP_KERNEL);
  	if (!pchip)
  		return -ENOMEM;
  	pchip->dev = &pdev->dev;
b8f649f1f   Haojian Zhuang   ARM: pxa: move PX...
599
600
601
602
603
  	info = dev_get_platdata(&pdev->dev);
  	if (info) {
  		irq_base = info->irq_base;
  		if (irq_base <= 0)
  			return -EINVAL;
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
604
  		pxa_last_gpio = pxa_gpio_nums(pdev);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
605
  		pchip->set_wake = info->gpio_set_wake;
9450be76d   Daniel Mack   GPIO: gpio-pxa: s...
606
  	} else {
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
607
608
  		irq_base = pxa_gpio_probe_dt(pdev, pchip);
  		if (irq_base < 0)
b8f649f1f   Haojian Zhuang   ARM: pxa: move PX...
609
  			return -EINVAL;
9450be76d   Daniel Mack   GPIO: gpio-pxa: s...
610
  	}
478e223cc   Haojian Zhuang   ARM: pxa: recogni...
611
  	if (!pxa_last_gpio)
157d2644c   Haojian Zhuang   ARM: pxa: change ...
612
  		return -EINVAL;
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
613
614
615
  	pchip->irqdomain = irq_domain_add_legacy(pdev->dev.of_node,
  						 pxa_last_gpio + 1, irq_base,
  						 0, &pxa_irq_domain_ops, pchip);
41d107ad9   Dan Carpenter   gpio: pxa: checki...
616
617
  	if (!pchip->irqdomain)
  		return -ENOMEM;
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
618

157d2644c   Haojian Zhuang   ARM: pxa: change ...
619
620
621
622
623
624
  	irq0 = platform_get_irq_byname(pdev, "gpio0");
  	irq1 = platform_get_irq_byname(pdev, "gpio1");
  	irq_mux = platform_get_irq_byname(pdev, "gpio_mux");
  	if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0)
  		|| (irq_mux <= 0))
  		return -EINVAL;
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
625
626
627
  
  	pchip->irq0 = irq0;
  	pchip->irq1 = irq1;
157d2644c   Haojian Zhuang   ARM: pxa: change ...
628
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8852b2f7d   Robert Jarzmik   gpio: pxa: conver...
629
630
  	gpio_reg_base = devm_ioremap(&pdev->dev, res->start,
  				     resource_size(res));
157d2644c   Haojian Zhuang   ARM: pxa: change ...
631
632
633
634
635
  	if (!gpio_reg_base)
  		return -EINVAL;
  
  	if (irq0 > 0)
  		gpio_offset = 2;
e3630db1f   eric miao   [ARM] pxa: move G...
636

389eda15e   Haojian Zhuang   ARM: pxa: add clk...
637
638
639
640
641
  	clk = clk_get(&pdev->dev, NULL);
  	if (IS_ERR(clk)) {
  		dev_err(&pdev->dev, "Error %ld to get gpio clock
  ",
  			PTR_ERR(clk));
389eda15e   Haojian Zhuang   ARM: pxa: add clk...
642
643
  		return PTR_ERR(clk);
  	}
6ab49f420   Julia Lawall   drivers/gpio/gpio...
644
  	ret = clk_prepare_enable(clk);
389eda15e   Haojian Zhuang   ARM: pxa: add clk...
645
646
  	if (ret) {
  		clk_put(clk);
389eda15e   Haojian Zhuang   ARM: pxa: add clk...
647
648
  		return ret;
  	}
389eda15e   Haojian Zhuang   ARM: pxa: add clk...
649

0807da593   Eric Miao   [ARM] pxa: access...
650
  	/* Initialize GPIO chips */
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
651
652
  	ret = pxa_init_gpio_chip(pchip, pxa_last_gpio + 1, pdev->dev.of_node,
  				 gpio_reg_base);
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
653
654
655
656
  	if (ret) {
  		clk_put(clk);
  		return ret;
  	}
0807da593   Eric Miao   [ARM] pxa: access...
657

e3630db1f   eric miao   [ARM] pxa: move G...
658
  	/* clear all GPIO edge detects */
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
659
  	for_each_gpio_bank(gpio, c, pchip) {
df664d208   Haojian Zhuang   ARM: pxa: use lit...
660
661
  		writel_relaxed(0, c->regbase + GFER_OFFSET);
  		writel_relaxed(0, c->regbase + GRER_OFFSET);
e37f4af76   Laurent Navet   gpio: gpio-pxa.c:...
662
  		writel_relaxed(~0, c->regbase + GEDR_OFFSET);
be24168f1   Haojian Zhuang   ARM: mmp: clear g...
663
664
665
  		/* unmask GPIO edge detect for AP side */
  		if (gpio_is_mmp_type(gpio_type))
  			writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
e3630db1f   eric miao   [ARM] pxa: move G...
666
  	}
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
667
668
669
670
671
672
673
674
  	if (irq0 > 0) {
  		ret = devm_request_irq(&pdev->dev,
  				       irq0, pxa_gpio_direct_handler, 0,
  				       "gpio-0", pchip);
  		if (ret)
  			dev_err(&pdev->dev, "request of gpio0 irq failed: %d
  ",
  				ret);
e3630db1f   eric miao   [ARM] pxa: move G...
675
  	}
384ca3c6a   Robert Jarzmik   gpio: pxa: change...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  	if (irq1 > 0) {
  		ret = devm_request_irq(&pdev->dev,
  				       irq1, pxa_gpio_direct_handler, 0,
  				       "gpio-1", pchip);
  		if (ret)
  			dev_err(&pdev->dev, "request of gpio1 irq failed: %d
  ",
  				ret);
  	}
  	ret = devm_request_irq(&pdev->dev,
  			       irq_mux, pxa_gpio_demux_handler, 0,
  				       "gpio-mux", pchip);
  	if (ret)
  		dev_err(&pdev->dev, "request of gpio-mux irq failed: %d
  ",
  				ret);
e3630db1f   eric miao   [ARM] pxa: move G...
692

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
693
  	pxa_gpio_chip = pchip;
ae4f4cfd8   Rob Herring   gpio: pxa: remove...
694

157d2644c   Haojian Zhuang   ARM: pxa: change ...
695
696
  	return 0;
  }
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
697
698
699
700
701
702
703
704
  static const struct platform_device_id gpio_id_table[] = {
  	{ "pxa25x-gpio",	(unsigned long)&pxa25x_id },
  	{ "pxa26x-gpio",	(unsigned long)&pxa26x_id },
  	{ "pxa27x-gpio",	(unsigned long)&pxa27x_id },
  	{ "pxa3xx-gpio",	(unsigned long)&pxa3xx_id },
  	{ "pxa93x-gpio",	(unsigned long)&pxa93x_id },
  	{ "mmp-gpio",		(unsigned long)&mmp_id },
  	{ "mmp2-gpio",		(unsigned long)&mmp2_id },
684bba2ff   Rob Herring   gpio: pxa: add PX...
705
  	{ "pxa1928-gpio",	(unsigned long)&pxa1928_id },
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
706
707
  	{ },
  };
157d2644c   Haojian Zhuang   ARM: pxa: change ...
708
709
710
711
  static struct platform_driver pxa_gpio_driver = {
  	.probe		= pxa_gpio_probe,
  	.driver		= {
  		.name	= "pxa-gpio",
f43e04ec4   Arnd Bergmann   GPIO: gpio-pxa: f...
712
  		.of_match_table = of_match_ptr(pxa_gpio_dt_ids),
157d2644c   Haojian Zhuang   ARM: pxa: change ...
713
  	},
2cab02922   Haojian Zhuang   ARM: pxa: remove ...
714
  	.id_table	= gpio_id_table,
157d2644c   Haojian Zhuang   ARM: pxa: change ...
715
  };
cf3fa17c2   Linus Walleij   Revert "gpio: pxa...
716

eae122b82   Robert Jarzmik   gpio: pxa: change...
717
  static int __init pxa_gpio_legacy_init(void)
cf3fa17c2   Linus Walleij   Revert "gpio: pxa...
718
  {
eae122b82   Robert Jarzmik   gpio: pxa: change...
719
720
  	if (of_have_populated_dt())
  		return 0;
cf3fa17c2   Linus Walleij   Revert "gpio: pxa...
721
722
  	return platform_driver_register(&pxa_gpio_driver);
  }
eae122b82   Robert Jarzmik   gpio: pxa: change...
723
724
725
726
727
728
729
730
731
732
  postcore_initcall(pxa_gpio_legacy_init);
  
  static int __init pxa_gpio_dt_init(void)
  {
  	if (of_have_populated_dt())
  		return platform_driver_register(&pxa_gpio_driver);
  
  	return 0;
  }
  device_initcall(pxa_gpio_dt_init);
663707c1a   eric miao   [ARM] pxa: move G...
733
734
  
  #ifdef CONFIG_PM
2eaa03b5b   Rafael J. Wysocki   ARM / PXA: Use st...
735
  static int pxa_gpio_suspend(void)
663707c1a   eric miao   [ARM] pxa: move G...
736
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
737
738
  	struct pxa_gpio_chip *pchip = pxa_gpio_chip;
  	struct pxa_gpio_bank *c;
0807da593   Eric Miao   [ARM] pxa: access...
739
  	int gpio;
663707c1a   eric miao   [ARM] pxa: move G...
740

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
741
  	for_each_gpio_bank(gpio, c, pchip) {
df664d208   Haojian Zhuang   ARM: pxa: use lit...
742
743
744
745
  		c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET);
  		c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
  		c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET);
  		c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET);
663707c1a   eric miao   [ARM] pxa: move G...
746
747
  
  		/* Clear GPIO transition detect bits */
df664d208   Haojian Zhuang   ARM: pxa: use lit...
748
  		writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET);
663707c1a   eric miao   [ARM] pxa: move G...
749
750
751
  	}
  	return 0;
  }
2eaa03b5b   Rafael J. Wysocki   ARM / PXA: Use st...
752
  static void pxa_gpio_resume(void)
663707c1a   eric miao   [ARM] pxa: move G...
753
  {
fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
754
755
  	struct pxa_gpio_chip *pchip = pxa_gpio_chip;
  	struct pxa_gpio_bank *c;
0807da593   Eric Miao   [ARM] pxa: access...
756
  	int gpio;
663707c1a   eric miao   [ARM] pxa: move G...
757

fc0589ca6   Robert Jarzmik   gpio: pxa: conver...
758
  	for_each_gpio_bank(gpio, c, pchip) {
663707c1a   eric miao   [ARM] pxa: move G...
759
  		/* restore level with set/clear */
e37f4af76   Laurent Navet   gpio: gpio-pxa.c:...
760
  		writel_relaxed(c->saved_gplr, c->regbase + GPSR_OFFSET);
df664d208   Haojian Zhuang   ARM: pxa: use lit...
761
  		writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET);
663707c1a   eric miao   [ARM] pxa: move G...
762

df664d208   Haojian Zhuang   ARM: pxa: use lit...
763
764
765
  		writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET);
  		writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET);
  		writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET);
663707c1a   eric miao   [ARM] pxa: move G...
766
  	}
663707c1a   eric miao   [ARM] pxa: move G...
767
768
769
770
771
  }
  #else
  #define pxa_gpio_suspend	NULL
  #define pxa_gpio_resume		NULL
  #endif
2eaa03b5b   Rafael J. Wysocki   ARM / PXA: Use st...
772
  struct syscore_ops pxa_gpio_syscore_ops = {
663707c1a   eric miao   [ARM] pxa: move G...
773
774
775
  	.suspend	= pxa_gpio_suspend,
  	.resume		= pxa_gpio_resume,
  };
157d2644c   Haojian Zhuang   ARM: pxa: change ...
776
777
778
779
780
781
782
  
  static int __init pxa_gpio_sysinit(void)
  {
  	register_syscore_ops(&pxa_gpio_syscore_ops);
  	return 0;
  }
  postcore_initcall(pxa_gpio_sysinit);