Blame view

drivers/gpio/gpio-mxs.c 9.84 KB
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  /*
   * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
   * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
   *
   * Based on code from Freescale,
   * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   * MA  02110-1301, USA.
   */
641d03422   Thierry Reding   gpio: Convert to ...
22
  #include <linux/err.h>
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
23
24
25
26
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/irq.h>
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
27
  #include <linux/irqdomain.h>
4052d45e8   Shawn Guo   gpio/mxs: add dev...
28
29
30
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_device.h>
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
31
32
  #include <linux/platform_device.h>
  #include <linux/slab.h>
0f4630f37   Linus Walleij   gpio: generic: fa...
33
34
35
  #include <linux/gpio/driver.h>
  /* FIXME: for gpio_get_value(), replace this by direct register read */
  #include <linux/gpio.h>
bb207ef1e   Paul Gortmaker   drivers/gpio: Fix...
36
  #include <linux/module.h>
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
37

8d7cf8370   Shawn Guo   gpio/mxs: Change ...
38
39
  #define MXS_SET		0x4
  #define MXS_CLR		0x8
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
40

164387d2b   Shawn Guo   gpio/mxs: get rid...
41
42
43
44
45
46
47
48
  #define PINCTRL_DOUT(p)		((is_imx23_gpio(p) ? 0x0500 : 0x0700) + (p->id) * 0x10)
  #define PINCTRL_DIN(p)		((is_imx23_gpio(p) ? 0x0600 : 0x0900) + (p->id) * 0x10)
  #define PINCTRL_DOE(p)		((is_imx23_gpio(p) ? 0x0700 : 0x0b00) + (p->id) * 0x10)
  #define PINCTRL_PIN2IRQ(p)	((is_imx23_gpio(p) ? 0x0800 : 0x1000) + (p->id) * 0x10)
  #define PINCTRL_IRQEN(p)	((is_imx23_gpio(p) ? 0x0900 : 0x1100) + (p->id) * 0x10)
  #define PINCTRL_IRQLEV(p)	((is_imx23_gpio(p) ? 0x0a00 : 0x1200) + (p->id) * 0x10)
  #define PINCTRL_IRQPOL(p)	((is_imx23_gpio(p) ? 0x0b00 : 0x1300) + (p->id) * 0x10)
  #define PINCTRL_IRQSTAT(p)	((is_imx23_gpio(p) ? 0x0c00 : 0x1400) + (p->id) * 0x10)
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
49
50
51
52
53
54
55
  
  #define GPIO_INT_FALL_EDGE	0x0
  #define GPIO_INT_LOW_LEV	0x1
  #define GPIO_INT_RISE_EDGE	0x2
  #define GPIO_INT_HIGH_LEV	0x3
  #define GPIO_INT_LEV_MASK	(1 << 0)
  #define GPIO_INT_POL_MASK	(1 << 1)
164387d2b   Shawn Guo   gpio/mxs: get rid...
56
57
58
59
  enum mxs_gpio_id {
  	IMX23_GPIO,
  	IMX28_GPIO,
  };
7b2fa5702   Grant Likely   gpio/mxs: Move Fr...
60
61
62
63
  struct mxs_gpio_port {
  	void __iomem *base;
  	int id;
  	int irq;
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
64
  	struct irq_domain *domain;
0f4630f37   Linus Walleij   gpio: generic: fa...
65
  	struct gpio_chip gc;
164387d2b   Shawn Guo   gpio/mxs: get rid...
66
  	enum mxs_gpio_id devid;
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
67
  	u32 both_edges;
7b2fa5702   Grant Likely   gpio/mxs: Move Fr...
68
  };
164387d2b   Shawn Guo   gpio/mxs: get rid...
69
70
71
72
73
74
75
76
77
  static inline int is_imx23_gpio(struct mxs_gpio_port *port)
  {
  	return port->devid == IMX23_GPIO;
  }
  
  static inline int is_imx28_gpio(struct mxs_gpio_port *port)
  {
  	return port->devid == IMX28_GPIO;
  }
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
78
  /* Note: This driver assumes 32 GPIOs are handled in one register */
bf0c11183   Uwe Kleine-König   ARM: 6744/1: mxs:...
79
  static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
80
  {
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
81
  	u32 val;
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
82
  	u32 pin_mask = 1 << d->hwirq;
498c17cf6   Shawn Guo   gpio/mxs: convert...
83
84
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  	struct mxs_gpio_port *port = gc->private;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
85
86
  	void __iomem *pin_addr;
  	int edge;
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
87
  	port->both_edges &= ~pin_mask;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
88
  	switch (type) {
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
89
  	case IRQ_TYPE_EDGE_BOTH:
0f4630f37   Linus Walleij   gpio: generic: fa...
90
  		val = gpio_get_value(port->gc.base + d->hwirq);
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
91
92
93
94
95
96
  		if (val)
  			edge = GPIO_INT_FALL_EDGE;
  		else
  			edge = GPIO_INT_RISE_EDGE;
  		port->both_edges |= pin_mask;
  		break;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  	case IRQ_TYPE_EDGE_RISING:
  		edge = GPIO_INT_RISE_EDGE;
  		break;
  	case IRQ_TYPE_EDGE_FALLING:
  		edge = GPIO_INT_FALL_EDGE;
  		break;
  	case IRQ_TYPE_LEVEL_LOW:
  		edge = GPIO_INT_LOW_LEV;
  		break;
  	case IRQ_TYPE_LEVEL_HIGH:
  		edge = GPIO_INT_HIGH_LEV;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	/* set level or edge */
164387d2b   Shawn Guo   gpio/mxs: get rid...
114
  	pin_addr = port->base + PINCTRL_IRQLEV(port);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
115
  	if (edge & GPIO_INT_LEV_MASK)
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
116
  		writel(pin_mask, pin_addr + MXS_SET);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
117
  	else
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
118
  		writel(pin_mask, pin_addr + MXS_CLR);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
119
120
  
  	/* set polarity */
164387d2b   Shawn Guo   gpio/mxs: get rid...
121
  	pin_addr = port->base + PINCTRL_IRQPOL(port);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
122
  	if (edge & GPIO_INT_POL_MASK)
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
123
  		writel(pin_mask, pin_addr + MXS_SET);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
124
  	else
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
125
  		writel(pin_mask, pin_addr + MXS_CLR);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
126

0b76c5412   Shawn Guo   gpio/mxs: adopt i...
127
  	writel(pin_mask,
164387d2b   Shawn Guo   gpio/mxs: get rid...
128
  	       port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
129
130
131
  
  	return 0;
  }
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
  {
  	u32 bit, val, edge;
  	void __iomem *pin_addr;
  
  	bit = 1 << gpio;
  
  	pin_addr = port->base + PINCTRL_IRQPOL(port);
  	val = readl(pin_addr);
  	edge = val & bit;
  
  	if (edge)
  		writel(bit, pin_addr + MXS_CLR);
  	else
  		writel(bit, pin_addr + MXS_SET);
  }
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
148
  /* MXS has one interrupt *per* gpio port */
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
149
  static void mxs_gpio_irq_handler(struct irq_desc *desc)
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
150
151
  {
  	u32 irq_stat;
476f8b4c9   Jiang Liu   gpio: Use irq_des...
152
  	struct mxs_gpio_port *port = irq_desc_get_handler_data(desc);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
153

1f6b5dd41   Uwe Kleine-König   ARM: mxs: acknowl...
154
  	desc->irq_data.chip->irq_ack(&desc->irq_data);
164387d2b   Shawn Guo   gpio/mxs: get rid...
155
156
  	irq_stat = readl(port->base + PINCTRL_IRQSTAT(port)) &
  			readl(port->base + PINCTRL_IRQEN(port));
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
157
158
159
  
  	while (irq_stat != 0) {
  		int irqoffset = fls(irq_stat) - 1;
66d7990e2   Gwenhael Goavec-Merou   gpio: mxs: Add IR...
160
161
  		if (port->both_edges & (1 << irqoffset))
  			mxs_flip_edge(port, irqoffset);
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
162
  		generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
163
164
165
166
167
168
169
170
171
172
173
174
175
  		irq_stat &= ~(1 << irqoffset);
  	}
  }
  
  /*
   * Set interrupt number "irq" in the GPIO as a wake-up source.
   * While system is running, all registered GPIO interrupts need to have
   * wake-up enabled. When system is suspended, only selected GPIO interrupts
   * need to have wake-up enabled.
   * @param  irq          interrupt source number
   * @param  enable       enable as wake-up if equal to non-zero
   * @return       This function returns 0 on success.
   */
bf0c11183   Uwe Kleine-König   ARM: 6744/1: mxs:...
176
  static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
177
  {
498c17cf6   Shawn Guo   gpio/mxs: convert...
178
179
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  	struct mxs_gpio_port *port = gc->private;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
180

6161715e3   Shawn Guo   gpio/mxs: remove ...
181
182
183
184
  	if (enable)
  		enable_irq_wake(port->irq);
  	else
  		disable_irq_wake(port->irq);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
185
186
187
  
  	return 0;
  }
1bbc557d9   Peng Fan   gpio: mxs: need t...
188
  static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
498c17cf6   Shawn Guo   gpio/mxs: convert...
189
190
191
  {
  	struct irq_chip_generic *gc;
  	struct irq_chip_type *ct;
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
192
  	gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
498c17cf6   Shawn Guo   gpio/mxs: convert...
193
  				    port->base, handle_level_irq);
1bbc557d9   Peng Fan   gpio: mxs: need t...
194
195
  	if (!gc)
  		return -ENOMEM;
498c17cf6   Shawn Guo   gpio/mxs: convert...
196
197
198
  	gc->private = port;
  
  	ct = gc->chip_types;
591567a5e   Shawn Guo   gpio/mxc/mxs: fix...
199
  	ct->chip.irq_ack = irq_gc_ack_set_bit;
498c17cf6   Shawn Guo   gpio/mxs: convert...
200
201
202
  	ct->chip.irq_mask = irq_gc_mask_clr_bit;
  	ct->chip.irq_unmask = irq_gc_mask_set_bit;
  	ct->chip.irq_set_type = mxs_gpio_set_irq_type;
591567a5e   Shawn Guo   gpio/mxc/mxs: fix...
203
  	ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
164387d2b   Shawn Guo   gpio/mxs: get rid...
204
205
  	ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
  	ct->regs.mask = PINCTRL_IRQEN(port);
498c17cf6   Shawn Guo   gpio/mxs: convert...
206

a585f87c8   Marek Vasut   gpio: mxs: Allow ...
207
208
  	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
  			       IRQ_NOREQUEST, 0);
1bbc557d9   Peng Fan   gpio: mxs: need t...
209
210
  
  	return 0;
498c17cf6   Shawn Guo   gpio/mxs: convert...
211
  }
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
212

06f88a8ae   Shawn Guo   gpio/mxs: convert...
213
  static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
214
  {
0f4630f37   Linus Walleij   gpio: generic: fa...
215
  	struct mxs_gpio_port *port = gpiochip_get_data(gc);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
216

0b76c5412   Shawn Guo   gpio/mxs: adopt i...
217
  	return irq_find_mapping(port->domain, offset);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
218
  }
c8aaa1bf0   Janusz Uzycki   gpio: mxs: implem...
219
220
  static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
  {
0f4630f37   Linus Walleij   gpio: generic: fa...
221
  	struct mxs_gpio_port *port = gpiochip_get_data(gc);
c8aaa1bf0   Janusz Uzycki   gpio: mxs: implem...
222
223
224
225
226
227
  	u32 mask = 1 << offset;
  	u32 dir;
  
  	dir = readl(port->base + PINCTRL_DOE(port));
  	return !(dir & mask);
  }
f4f79d406   Krzysztof Kozlowski   gpio: Constify pl...
228
  static const struct platform_device_id mxs_gpio_ids[] = {
164387d2b   Shawn Guo   gpio/mxs: get rid...
229
230
231
232
233
234
235
236
237
238
239
  	{
  		.name = "imx23-gpio",
  		.driver_data = IMX23_GPIO,
  	}, {
  		.name = "imx28-gpio",
  		.driver_data = IMX28_GPIO,
  	}, {
  		/* sentinel */
  	}
  };
  MODULE_DEVICE_TABLE(platform, mxs_gpio_ids);
4052d45e8   Shawn Guo   gpio/mxs: add dev...
240
241
242
243
244
245
  static const struct of_device_id mxs_gpio_dt_ids[] = {
  	{ .compatible = "fsl,imx23-gpio", .data = (void *) IMX23_GPIO, },
  	{ .compatible = "fsl,imx28-gpio", .data = (void *) IMX28_GPIO, },
  	{ /* sentinel */ }
  };
  MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
3836309d9   Bill Pemberton   gpio: remove use ...
246
  static int mxs_gpio_probe(struct platform_device *pdev)
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
247
  {
4052d45e8   Shawn Guo   gpio/mxs: add dev...
248
249
250
251
  	const struct of_device_id *of_id =
  			of_match_device(mxs_gpio_dt_ids, &pdev->dev);
  	struct device_node *np = pdev->dev.of_node;
  	struct device_node *parent;
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
252
253
  	static void __iomem *base;
  	struct mxs_gpio_port *port;
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
254
  	int irq_base;
498c17cf6   Shawn Guo   gpio/mxs: convert...
255
  	int err;
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
256

940a4f7b5   Shawn Guo   gpio/mxs: use dev...
257
  	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
258
259
  	if (!port)
  		return -ENOMEM;
993571273   Fabio Estevam   gpio: gpio-mxs: R...
260
261
262
263
  	port->id = of_alias_get_id(np, "gpio");
  	if (port->id < 0)
  		return port->id;
  	port->devid = (enum mxs_gpio_id) of_id->data;
940a4f7b5   Shawn Guo   gpio/mxs: use dev...
264
265
266
  	port->irq = platform_get_irq(pdev, 0);
  	if (port->irq < 0)
  		return port->irq;
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
267
268
269
270
271
  	/*
  	 * map memory region only once, as all the gpio ports
  	 * share the same one
  	 */
  	if (!base) {
993571273   Fabio Estevam   gpio: gpio-mxs: R...
272
273
274
275
276
  		parent = of_get_parent(np);
  		base = of_iomap(parent, 0);
  		of_node_put(parent);
  		if (!base)
  			return -EADDRNOTAVAIL;
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
277
278
  	}
  	port->base = base;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
279

498c17cf6   Shawn Guo   gpio/mxs: convert...
280
281
282
283
  	/*
  	 * select the pin interrupt functionality but initially
  	 * disable the interrupts
  	 */
164387d2b   Shawn Guo   gpio/mxs: get rid...
284
285
  	writel(~0U, port->base + PINCTRL_PIN2IRQ(port));
  	writel(0, port->base + PINCTRL_IRQEN(port));
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
286

8d7cf8370   Shawn Guo   gpio/mxs: Change ...
287
  	/* clear address has to be used to clear IRQSTAT bits */
164387d2b   Shawn Guo   gpio/mxs: get rid...
288
  	writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
289

0b76c5412   Shawn Guo   gpio/mxs: adopt i...
290
  	irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
44df08198   Arvind Yadav   gpio: mxs: Unmap ...
291
292
293
294
  	if (irq_base < 0) {
  		err = irq_base;
  		goto out_iounmap;
  	}
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
295
296
297
298
299
300
301
  
  	port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
  					     &irq_domain_simple_ops, NULL);
  	if (!port->domain) {
  		err = -ENODEV;
  		goto out_irqdesc_free;
  	}
498c17cf6   Shawn Guo   gpio/mxs: convert...
302
  	/* gpio-mxs can be a generic irq chip */
1bbc557d9   Peng Fan   gpio: mxs: need t...
303
304
305
  	err = mxs_gpio_init_gc(port, irq_base);
  	if (err < 0)
  		goto out_irqdomain_remove;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
306

8d7cf8370   Shawn Guo   gpio/mxs: Change ...
307
  	/* setup one handler for each entry */
a44735f42   Russell King   gpio: gpio-mxs: F...
308
309
  	irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
  					 port);
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
310

0f4630f37   Linus Walleij   gpio: generic: fa...
311
  	err = bgpio_init(&port->gc, &pdev->dev, 4,
164387d2b   Shawn Guo   gpio/mxs: get rid...
312
  			 port->base + PINCTRL_DIN(port),
90dae4ebf   Maxime Ripard   gpio: mxs: Use se...
313
314
  			 port->base + PINCTRL_DOUT(port) + MXS_SET,
  			 port->base + PINCTRL_DOUT(port) + MXS_CLR,
84a442b9a   Linus Torvalds   Merge tag 'dt2' o...
315
  			 port->base + PINCTRL_DOE(port), NULL, 0);
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
316
  	if (err)
0f4630f37   Linus Walleij   gpio: generic: fa...
317
  		goto out_irqdomain_remove;
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
318

0f4630f37   Linus Walleij   gpio: generic: fa...
319
320
321
  	port->gc.to_irq = mxs_gpio_to_irq;
  	port->gc.get_direction = mxs_gpio_get_direction;
  	port->gc.base = port->id * 32;
06f88a8ae   Shawn Guo   gpio/mxs: convert...
322

0f4630f37   Linus Walleij   gpio: generic: fa...
323
  	err = gpiochip_add_data(&port->gc, port);
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
324
  	if (err)
0f4630f37   Linus Walleij   gpio: generic: fa...
325
  		goto out_irqdomain_remove;
06f88a8ae   Shawn Guo   gpio/mxs: convert...
326

8d7cf8370   Shawn Guo   gpio/mxs: Change ...
327
  	return 0;
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
328

1bbc557d9   Peng Fan   gpio: mxs: need t...
329
330
  out_irqdomain_remove:
  	irq_domain_remove(port->domain);
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
331
332
  out_irqdesc_free:
  	irq_free_descs(irq_base, 32);
44df08198   Arvind Yadav   gpio: mxs: Unmap ...
333
334
  out_iounmap:
  	iounmap(port->base);
0b76c5412   Shawn Guo   gpio/mxs: adopt i...
335
  	return err;
ef19660b0   Sascha Hauer   ARM i.MX23/28: de...
336
  }
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
337
338
339
340
  
  static struct platform_driver mxs_gpio_driver = {
  	.driver		= {
  		.name	= "gpio-mxs",
4052d45e8   Shawn Guo   gpio/mxs: add dev...
341
  		.of_match_table = mxs_gpio_dt_ids,
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
342
343
  	},
  	.probe		= mxs_gpio_probe,
164387d2b   Shawn Guo   gpio/mxs: get rid...
344
  	.id_table	= mxs_gpio_ids,
fba311fcf   Shawn Guo   ARM: mxs: Add gpi...
345
  };
ef19660b0   Sascha Hauer   ARM i.MX23/28: de...
346

8d7cf8370   Shawn Guo   gpio/mxs: Change ...
347
  static int __init mxs_gpio_init(void)
ef19660b0   Sascha Hauer   ARM i.MX23/28: de...
348
  {
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
349
  	return platform_driver_register(&mxs_gpio_driver);
ef19660b0   Sascha Hauer   ARM i.MX23/28: de...
350
  }
8d7cf8370   Shawn Guo   gpio/mxs: Change ...
351
352
353
354
355
356
357
  postcore_initcall(mxs_gpio_init);
  
  MODULE_AUTHOR("Freescale Semiconductor, "
  	      "Daniel Mack <danielncaiaq.de>, "
  	      "Juergen Beisert <kernel@pengutronix.de>");
  MODULE_DESCRIPTION("Freescale MXS GPIO");
  MODULE_LICENSE("GPL");