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
   *
   * 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.
   */
47732cb4f   H Hartley Sweeten   gpio/ep93xx: fix ...
14
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
15

b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
16
  #include <linux/init.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>
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
25

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
26
27
28
29
  struct ep93xx_gpio {
  	void __iomem		*mmio_base;
  	struct bgpio_chip	bgc[8];
  };
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
30
  /*************************************************************************
4742723cb   Hartley Sweeten   ARM: 6029/1: ep93...
31
   * Interrupt handling for EP93xx on-chip GPIOs
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
32
33
34
35
36
37
38
39
40
41
42
43
44
   *************************************************************************/
  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...
45
  static void ep93xx_gpio_update_int_params(unsigned port)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  {
  	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]));
  }
4742723cb   Hartley Sweeten   ARM: 6029/1: ep93...
60
  static inline void ep93xx_gpio_int_mask(unsigned line)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
61
62
63
  {
  	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
  }
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
64
  static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
65
66
67
68
69
70
71
72
73
74
75
76
77
  {
  	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...
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
103
  
  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...
104
  	 * map discontiguous hw irq range to continuous sw irq range:
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
105
106
107
108
109
110
111
112
  	 *
  	 *  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_...
113
  static void ep93xx_gpio_irq_ack(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
114
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
115
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
116
117
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
118
  	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
119
120
121
122
123
124
  		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_...
125
  static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
126
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
127
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
128
129
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
130
  	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
131
132
133
134
135
136
137
  		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_...
138
  static void ep93xx_gpio_irq_mask(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
139
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
140
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
141
142
143
144
145
  	int port = line >> 3;
  
  	gpio_int_unmasked[port] &= ~(1 << (line & 7));
  	ep93xx_gpio_update_int_params(port);
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
146
  static void ep93xx_gpio_irq_unmask(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
147
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
148
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
149
150
151
152
153
154
155
156
157
158
159
  	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_...
160
  static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
161
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
162
  	const int gpio = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
163
164
  	const int port = gpio >> 3;
  	const int port_mask = 1 << (gpio & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
165
  	irq_flow_handler_t handler;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
166
167
168
169
170
171
172
  
  	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 ...
173
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
174
175
176
177
  		break;
  	case IRQ_TYPE_EDGE_FALLING:
  		gpio_int_type1[port] |= port_mask;
  		gpio_int_type2[port] &= ~port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
178
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
179
180
181
182
  		break;
  	case IRQ_TYPE_LEVEL_HIGH:
  		gpio_int_type1[port] &= ~port_mask;
  		gpio_int_type2[port] |= port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
183
  		handler = handle_level_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
184
185
186
187
  		break;
  	case IRQ_TYPE_LEVEL_LOW:
  		gpio_int_type1[port] &= ~port_mask;
  		gpio_int_type2[port] &= ~port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
188
  		handler = handle_level_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
189
190
191
192
193
194
195
196
  		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 ...
197
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
198
199
200
201
202
203
  		break;
  	default:
  		pr_err("failed to set irq type %d for gpio %d
  ", type, gpio);
  		return -EINVAL;
  	}
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
204
  	__irq_set_handler_locked(d->irq, handler);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
205

d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
206
  	gpio_int_enabled[port] |= port_mask;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
207
208
209
210
211
212
213
214
  
  	ep93xx_gpio_update_int_params(port);
  
  	return 0;
  }
  
  static struct irq_chip ep93xx_gpio_irq_chip = {
  	.name		= "GPIO",
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
215
216
217
218
219
  	.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...
220
  };
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
221
  static void ep93xx_gpio_init_irq(void)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
222
223
224
225
226
  {
  	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...
227
228
  		irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
  					 handle_level_irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
229
230
  		set_irq_flags(gpio_irq, IRQF_VALID);
  	}
6845664a6   Thomas Gleixner   arm: Cleanup the ...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  	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...
249
250
251
252
253
254
  }
  
  
  /*************************************************************************
   * gpiolib interface for EP93xx on-chip GPIOs
   *************************************************************************/
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
255
256
257
258
259
260
  struct ep93xx_gpio_bank {
  	const char	*label;
  	int		data;
  	int		dir;
  	int		base;
  	bool		has_debounce;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
261
  };
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
262
263
264
265
266
267
268
269
  #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...
270

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
271
272
273
274
275
276
277
278
279
280
281
282
283
  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...
284
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
285
286
  	int gpio = chip->base + offset;
  	int irq = gpio_to_irq(gpio);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
287

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
288
289
290
291
  	if (irq < 0)
  		return -EINVAL;
  
  	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
292
293
294
  
  	return 0;
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
295
296
  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...
297
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
298
299
300
  	void __iomem *data = mmio_base + bank->data;
  	void __iomem *dir =  mmio_base + bank->dir;
  	int err;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
301

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
302
303
304
  	err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false);
  	if (err)
  		return err;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
305

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

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
309
310
  	if (bank->has_debounce)
  		bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
311

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
312
  	return gpiochip_add(&bgc->gc);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
313
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
314
  static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
315
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
316
317
318
319
320
  	struct ep93xx_gpio *ep93xx_gpio;
  	struct resource *res;
  	void __iomem *mmio;
  	int i;
  	int ret;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
321

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

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
326
327
328
329
330
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!res) {
  		ret = -ENXIO;
  		goto exit_free;
  	}
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
331

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
332
333
334
335
  	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
  		ret = -EBUSY;
  		goto exit_free;
  	}
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
336

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
337
338
339
340
341
342
  	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...
343

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
344
345
346
347
348
349
  	/* Default all ports to GPIO */
  	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
  			       EP93XX_SYSCON_DEVCFG_GONK |
  			       EP93XX_SYSCON_DEVCFG_EONIDE |
  			       EP93XX_SYSCON_DEVCFG_GONIDE |
  			       EP93XX_SYSCON_DEVCFG_HONIDE);
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
350

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
351
352
353
  	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...
354

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
355
356
357
358
  		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...
359
  	}
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
360
  	ep93xx_gpio_init_irq();
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
361

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

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
364
365
366
367
368
369
370
371
  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...
372

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
373
374
375
376
377
378
379
380
381
382
  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...
383
  	return platform_driver_register(&ep93xx_gpio_driver);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
384
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
385
386
387
388
389
390
  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");