Blame view

drivers/gpio/gpio-ep93xx.c 10.7 KB
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
1
  /*
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
2
3
   * Generic EP93xx GPIO handling
   *
1c5454eed   Ryan Mallon   Change Ryan Mallo...
4
   * Copyright (c) 2008 Ryan Mallon
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
5
   * Copyright (c) 2011 H Hartley Sweeten <hsweeten@visionengravers.com>
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
6
7
8
9
10
11
12
13
14
15
   *
   * Based on code originally from:
   *  linux/arch/arm/mach-ep93xx/core.c
   *
   *  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.
   */
  
  #include <linux/init.h>
bb207ef1e   Paul Gortmaker   drivers/gpio: Fix...
16
  #include <linux/module.h>
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
17
  #include <linux/platform_device.h>
fced80c73   Russell King   [ARM] Convert asm...
18
  #include <linux/io.h>
ddf4f3d99   Hartley Sweeten   [ARM] 5574/1: ep9...
19
  #include <linux/gpio.h>
595c050d8   Ryan Mallon   [ARM] 5605/1: Fix...
20
  #include <linux/irq.h>
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
21
22
  #include <linux/slab.h>
  #include <linux/basic_mmio_gpio.h>
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
23

ddf4f3d99   Hartley Sweeten   [ARM] 5574/1: ep9...
24
  #include <mach/hardware.h>
bd5f12a24   Linus Walleij   ARM: 7042/3: mach...
25
26
27
  #include <mach/gpio-ep93xx.h>
  
  #define irq_to_gpio(irq)	((irq) - gpio_to_irq(0))
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
28

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
29
30
31
32
  struct ep93xx_gpio {
  	void __iomem		*mmio_base;
  	struct bgpio_chip	bgc[8];
  };
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
33
  /*************************************************************************
4742723cb   Hartley Sweeten   ARM: 6029/1: ep93...
34
   * Interrupt handling for EP93xx on-chip GPIOs
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
35
36
37
38
39
40
41
42
43
44
45
46
47
   *************************************************************************/
  static unsigned char gpio_int_unmasked[3];
  static unsigned char gpio_int_enabled[3];
  static unsigned char gpio_int_type1[3];
  static unsigned char gpio_int_type2[3];
  static unsigned char gpio_int_debounce[3];
  
  /* Port ordering is: A B F */
  static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c };
  static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 };
  static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 };
  static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x58 };
  static const u8 int_debounce_register_offset[3]	= { 0xa8, 0xc4, 0x64 };
4742723cb   Hartley Sweeten   ARM: 6029/1: ep93...
48
  static void ep93xx_gpio_update_int_params(unsigned port)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  {
  	BUG_ON(port > 2);
  
  	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
  
  	__raw_writeb(gpio_int_type2[port],
  		EP93XX_GPIO_REG(int_type2_register_offset[port]));
  
  	__raw_writeb(gpio_int_type1[port],
  		EP93XX_GPIO_REG(int_type1_register_offset[port]));
  
  	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
  		EP93XX_GPIO_REG(int_en_register_offset[port]));
  }
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
63
  static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
64
65
66
67
68
69
70
71
72
73
74
75
76
  {
  	int line = irq_to_gpio(irq);
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
  
  	if (enable)
  		gpio_int_debounce[port] |= port_mask;
  	else
  		gpio_int_debounce[port] &= ~port_mask;
  
  	__raw_writeb(gpio_int_debounce[port],
  		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
  }
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  
  static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
  {
  	unsigned char status;
  	int i;
  
  	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
  	for (i = 0; i < 8; i++) {
  		if (status & (1 << i)) {
  			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
  			generic_handle_irq(gpio_irq);
  		}
  	}
  
  	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
  	for (i = 0; i < 8; i++) {
  		if (status & (1 << i)) {
  			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
  			generic_handle_irq(gpio_irq);
  		}
  	}
  }
  
  static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
  {
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
103
  	 * map discontiguous hw irq range to continuous sw irq range:
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
104
105
106
107
108
109
110
111
  	 *
  	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
  	 */
  	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
  	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
  
  	generic_handle_irq(gpio_irq);
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
112
  static void ep93xx_gpio_irq_ack(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
113
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
114
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
115
116
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
117
  	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
118
119
120
121
122
123
  		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
  		ep93xx_gpio_update_int_params(port);
  	}
  
  	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
124
  static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
125
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
126
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
127
128
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
129
  	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
130
131
132
133
134
135
136
  		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
  
  	gpio_int_unmasked[port] &= ~port_mask;
  	ep93xx_gpio_update_int_params(port);
  
  	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
137
  static void ep93xx_gpio_irq_mask(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
138
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
139
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
140
141
142
143
144
  	int port = line >> 3;
  
  	gpio_int_unmasked[port] &= ~(1 << (line & 7));
  	ep93xx_gpio_update_int_params(port);
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
145
  static void ep93xx_gpio_irq_unmask(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
146
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
147
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
148
149
150
151
152
153
154
155
156
157
158
  	int port = line >> 3;
  
  	gpio_int_unmasked[port] |= 1 << (line & 7);
  	ep93xx_gpio_update_int_params(port);
  }
  
  /*
   * gpio_int_type1 controls whether the interrupt is level (0) or
   * edge (1) triggered, while gpio_int_type2 controls whether it
   * triggers on low/falling (0) or high/rising (1).
   */
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
159
  static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
160
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
161
  	const int gpio = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
162
163
  	const int port = gpio >> 3;
  	const int port_mask = 1 << (gpio & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
164
  	irq_flow_handler_t handler;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
165
166
167
168
169
170
171
  
  	gpio_direction_input(gpio);
  
  	switch (type) {
  	case IRQ_TYPE_EDGE_RISING:
  		gpio_int_type1[port] |= port_mask;
  		gpio_int_type2[port] |= port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
172
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
173
174
175
176
  		break;
  	case IRQ_TYPE_EDGE_FALLING:
  		gpio_int_type1[port] |= port_mask;
  		gpio_int_type2[port] &= ~port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
177
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
178
179
180
181
  		break;
  	case IRQ_TYPE_LEVEL_HIGH:
  		gpio_int_type1[port] &= ~port_mask;
  		gpio_int_type2[port] |= port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
182
  		handler = handle_level_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
183
184
185
186
  		break;
  	case IRQ_TYPE_LEVEL_LOW:
  		gpio_int_type1[port] &= ~port_mask;
  		gpio_int_type2[port] &= ~port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
187
  		handler = handle_level_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
188
189
190
191
192
193
194
195
  		break;
  	case IRQ_TYPE_EDGE_BOTH:
  		gpio_int_type1[port] |= port_mask;
  		/* set initial polarity based on current input level */
  		if (gpio_get_value(gpio))
  			gpio_int_type2[port] &= ~port_mask; /* falling */
  		else
  			gpio_int_type2[port] |= port_mask; /* rising */
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
196
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
197
198
  		break;
  	default:
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
199
200
  		return -EINVAL;
  	}
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
201
  	__irq_set_handler_locked(d->irq, handler);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
202

d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
203
  	gpio_int_enabled[port] |= port_mask;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
204
205
206
207
208
209
210
211
  
  	ep93xx_gpio_update_int_params(port);
  
  	return 0;
  }
  
  static struct irq_chip ep93xx_gpio_irq_chip = {
  	.name		= "GPIO",
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
212
213
214
215
216
  	.irq_ack	= ep93xx_gpio_irq_ack,
  	.irq_mask_ack	= ep93xx_gpio_irq_mask_ack,
  	.irq_mask	= ep93xx_gpio_irq_mask,
  	.irq_unmask	= ep93xx_gpio_irq_unmask,
  	.irq_set_type	= ep93xx_gpio_irq_type,
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
217
  };
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
218
  static void ep93xx_gpio_init_irq(void)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
219
220
221
222
223
  {
  	int gpio_irq;
  
  	for (gpio_irq = gpio_to_irq(0);
  	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
f38c02f3b   Thomas Gleixner   arm: Fold irq_set...
224
225
  		irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
  					 handle_level_irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
226
227
  		set_irq_flags(gpio_irq, IRQF_VALID);
  	}
6845664a6   Thomas Gleixner   arm: Cleanup the ...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  	irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
  				ep93xx_gpio_ab_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
  				ep93xx_gpio_f_irq_handler);
  	irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
  				ep93xx_gpio_f_irq_handler);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
246
247
248
249
250
251
  }
  
  
  /*************************************************************************
   * gpiolib interface for EP93xx on-chip GPIOs
   *************************************************************************/
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
252
253
254
255
256
257
  struct ep93xx_gpio_bank {
  	const char	*label;
  	int		data;
  	int		dir;
  	int		base;
  	bool		has_debounce;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
258
  };
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
259
260
261
262
263
264
265
266
  #define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce)	\
  	{							\
  		.label		= _label,			\
  		.data		= _data,			\
  		.dir		= _dir,				\
  		.base		= _base,			\
  		.has_debounce	= _debounce,			\
  	}
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
267

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
268
269
270
271
272
273
274
275
276
277
278
279
280
  static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
  	EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true),
  	EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true),
  	EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false),
  	EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false),
  	EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false),
  	EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true),
  	EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false),
  	EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
  };
  
  static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
  				    unsigned offset, unsigned debounce)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
281
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
282
283
  	int gpio = chip->base + offset;
  	int irq = gpio_to_irq(gpio);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
284

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
285
286
287
288
  	if (irq < 0)
  		return -EINVAL;
  
  	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
289
290
291
  
  	return 0;
  }
257af9f97   Linus Walleij   ARM: 7041/1: gpio...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  /*
   * Map GPIO A0..A7  (0..7)  to irq 64..71,
   *          B0..B7  (7..15) to irq 72..79, and
   *          F0..F7 (16..24) to irq 80..87.
   */
  static int ep93xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  {
  	int gpio = chip->base + offset;
  
  	if (gpio > EP93XX_GPIO_LINE_MAX_IRQ)
  		return -EINVAL;
  
  	return 64 + gpio;
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
306
307
  static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
  	void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
308
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
309
310
311
  	void __iomem *data = mmio_base + bank->data;
  	void __iomem *dir =  mmio_base + bank->dir;
  	int err;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
312

3e11f7b84   Shawn Guo   gpio/generic: ini...
313
  	err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, 0);
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
314
315
  	if (err)
  		return err;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
316

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
317
318
  	bgc->gc.label = bank->label;
  	bgc->gc.base = bank->base;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
319

257af9f97   Linus Walleij   ARM: 7041/1: gpio...
320
  	if (bank->has_debounce) {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
321
  		bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
257af9f97   Linus Walleij   ARM: 7041/1: gpio...
322
323
  		bgc->gc.to_irq = ep93xx_gpio_to_irq;
  	}
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
324

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
325
  	return gpiochip_add(&bgc->gc);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
326
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
327
  static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
328
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
329
330
331
332
333
  	struct ep93xx_gpio *ep93xx_gpio;
  	struct resource *res;
  	void __iomem *mmio;
  	int i;
  	int ret;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
334

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
335
336
337
  	ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
  	if (!ep93xx_gpio)
  		return -ENOMEM;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
338

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
339
340
341
342
343
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!res) {
  		ret = -ENXIO;
  		goto exit_free;
  	}
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
344

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
345
346
347
348
  	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
  		ret = -EBUSY;
  		goto exit_free;
  	}
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
349

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
350
351
352
353
354
355
  	mmio = ioremap(res->start, resource_size(res));
  	if (!mmio) {
  		ret = -ENXIO;
  		goto exit_release;
  	}
  	ep93xx_gpio->mmio_base = mmio;
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
356

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
357
358
359
  	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
  		struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
  		struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
360

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
361
362
363
364
  		if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
  			dev_warn(&pdev->dev, "Unable to add gpio bank %s
  ",
  				bank->label);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
365
  	}
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
366
  	ep93xx_gpio_init_irq();
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
367

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
368
  	return 0;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
369

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
370
371
372
373
374
375
376
377
  exit_release:
  	release_mem_region(res->start, resource_size(res));
  exit_free:
  	kfree(ep93xx_gpio);
  	dev_info(&pdev->dev, "%s failed with errno %d
  ", __func__, ret);
  	return ret;
  }
fd015480c   Hartley Sweeten   ARM: 6636/1: ep93...
378

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
379
380
381
382
383
384
385
386
387
388
  static struct platform_driver ep93xx_gpio_driver = {
  	.driver		= {
  		.name	= "gpio-ep93xx",
  		.owner	= THIS_MODULE,
  	},
  	.probe		= ep93xx_gpio_probe,
  };
  
  static int __init ep93xx_gpio_init(void)
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
389
  	return platform_driver_register(&ep93xx_gpio_driver);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
390
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
391
392
393
394
395
396
  postcore_initcall(ep93xx_gpio_init);
  
  MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com> "
  		"H Hartley Sweeten <hsweeten@visionengravers.com>");
  MODULE_DESCRIPTION("EP93XX GPIO driver");
  MODULE_LICENSE("GPL");