Blame view

drivers/gpio/gpio-ep93xx.c 10.5 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>
595c050d8   Ryan Mallon   [ARM] 5605/1: Fix...
19
  #include <linux/irq.h>
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
20
  #include <linux/slab.h>
0f4630f37   Linus Walleij   gpio: generic: fa...
21
22
23
  #include <linux/gpio/driver.h>
  /* FIXME: this is here for gpio_to_irq() - get rid of this! */
  #include <linux/gpio.h>
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
24

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

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
30
31
  struct ep93xx_gpio {
  	void __iomem		*mmio_base;
0f4630f37   Linus Walleij   gpio: generic: fa...
32
  	struct gpio_chip	gc[8];
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
33
  };
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
34
  /*************************************************************************
4742723cb   Hartley Sweeten   ARM: 6029/1: ep93...
35
   * Interrupt handling for EP93xx on-chip GPIOs
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
36
37
38
39
40
41
42
43
44
45
46
47
48
   *************************************************************************/
  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...
49
  static void ep93xx_gpio_update_int_params(unsigned port)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
50
51
  {
  	BUG_ON(port > 2);
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
52
  	writeb_relaxed(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
53

d27e06ac5   Linus Walleij   gpio: ep93xx: get...
54
  	writeb_relaxed(gpio_int_type2[port],
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
55
  		EP93XX_GPIO_REG(int_type2_register_offset[port]));
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
56
  	writeb_relaxed(gpio_int_type1[port],
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
57
  		EP93XX_GPIO_REG(int_type1_register_offset[port]));
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
58
  	writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
59
60
  		EP93XX_GPIO_REG(int_en_register_offset[port]));
  }
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
61
  static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
62
63
64
65
66
67
68
69
70
  {
  	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;
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
71
  	writeb(gpio_int_debounce[port],
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
72
73
  		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
  }
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
74

bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
75
  static void ep93xx_gpio_ab_irq_handler(struct irq_desc *desc)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
76
77
78
  {
  	unsigned char status;
  	int i;
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
79
  	status = readb(EP93XX_GPIO_A_INT_STATUS);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
80
81
82
83
84
85
  	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);
  		}
  	}
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
86
  	status = readb(EP93XX_GPIO_B_INT_STATUS);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
87
88
89
90
91
92
93
  	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);
  		}
  	}
  }
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
94
  static void ep93xx_gpio_f_irq_handler(struct irq_desc *desc)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
95
96
  {
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
97
  	 * map discontiguous hw irq range to continuous sw irq range:
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
98
99
100
  	 *
  	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
  	 */
e43ea7a77   Thomas Gleixner   gpio/ep93xx: Prep...
101
  	unsigned int irq = irq_desc_get_irq(desc);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
102
103
104
105
106
  	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_...
107
  static void ep93xx_gpio_irq_ack(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
108
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
109
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
110
111
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
112
  	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
113
114
115
  		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
  		ep93xx_gpio_update_int_params(port);
  	}
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
116
  	writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
117
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
118
  static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
119
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
120
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
121
122
  	int port = line >> 3;
  	int port_mask = 1 << (line & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
123
  	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
124
125
126
127
  		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
  
  	gpio_int_unmasked[port] &= ~port_mask;
  	ep93xx_gpio_update_int_params(port);
d27e06ac5   Linus Walleij   gpio: ep93xx: get...
128
  	writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
129
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
130
  static void ep93xx_gpio_irq_mask(struct irq_data *d)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
131
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
132
  	int line = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
133
134
135
136
137
  	int port = line >> 3;
  
  	gpio_int_unmasked[port] &= ~(1 << (line & 7));
  	ep93xx_gpio_update_int_params(port);
  }
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
138
  static void ep93xx_gpio_irq_unmask(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
146
147
148
149
150
151
  	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_...
152
  static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
153
  {
c0afc9160   Lennert Buytenhek   ARM: ep93xx: irq_...
154
  	const int gpio = irq_to_gpio(d->irq);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
155
156
  	const int port = gpio >> 3;
  	const int port_mask = 1 << (gpio & 7);
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
157
  	irq_flow_handler_t handler;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
158
159
160
161
162
163
164
  
  	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 ...
165
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
166
167
168
169
  		break;
  	case IRQ_TYPE_EDGE_FALLING:
  		gpio_int_type1[port] |= port_mask;
  		gpio_int_type2[port] &= ~port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
170
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
171
172
173
174
  		break;
  	case IRQ_TYPE_LEVEL_HIGH:
  		gpio_int_type1[port] &= ~port_mask;
  		gpio_int_type2[port] |= port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
175
  		handler = handle_level_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
176
177
178
179
  		break;
  	case IRQ_TYPE_LEVEL_LOW:
  		gpio_int_type1[port] &= ~port_mask;
  		gpio_int_type2[port] &= ~port_mask;
d1735a2eb   Thomas Gleixner   arm: ep93xx: Use ...
180
  		handler = handle_level_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
181
182
183
184
185
186
187
188
  		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 ...
189
  		handler = handle_edge_irq;
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
190
191
  		break;
  	default:
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
192
193
  		return -EINVAL;
  	}
72b2a9ef9   Thomas Gleixner   gpio/ep93xx: Use ...
194
  	irq_set_handler_locked(d, handler);
d056ab785   Hartley Sweeten   ARM: 5954/1: ep93...
195

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

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
261
262
263
264
265
266
267
268
269
270
  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),
  };
2956b5d94   Mika Westerberg   pinctrl / gpio: I...
271
272
  static int ep93xx_gpio_set_config(struct gpio_chip *chip, unsigned offset,
  				  unsigned long config)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
273
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
274
275
  	int gpio = chip->base + offset;
  	int irq = gpio_to_irq(gpio);
2956b5d94   Mika Westerberg   pinctrl / gpio: I...
276
277
278
279
  	u32 debounce;
  
  	if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
  		return -ENOTSUPP;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
280

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
281
282
  	if (irq < 0)
  		return -EINVAL;
2956b5d94   Mika Westerberg   pinctrl / gpio: I...
283
  	debounce = pinconf_to_config_argument(config);
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
284
  	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
285
286
287
  
  	return 0;
  }
257af9f97   Linus Walleij   ARM: 7041/1: gpio...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
  /*
   * 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;
  }
0f4630f37   Linus Walleij   gpio: generic: fa...
302
  static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
303
  	void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
304
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
305
306
307
  	void __iomem *data = mmio_base + bank->data;
  	void __iomem *dir =  mmio_base + bank->dir;
  	int err;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
308

0f4630f37   Linus Walleij   gpio: generic: fa...
309
  	err = bgpio_init(gc, dev, 1, data, NULL, NULL, dir, NULL, 0);
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
310
311
  	if (err)
  		return err;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
312

0f4630f37   Linus Walleij   gpio: generic: fa...
313
314
  	gc->label = bank->label;
  	gc->base = bank->base;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
315

257af9f97   Linus Walleij   ARM: 7041/1: gpio...
316
  	if (bank->has_debounce) {
2956b5d94   Mika Westerberg   pinctrl / gpio: I...
317
  		gc->set_config = ep93xx_gpio_set_config;
0f4630f37   Linus Walleij   gpio: generic: fa...
318
  		gc->to_irq = ep93xx_gpio_to_irq;
257af9f97   Linus Walleij   ARM: 7041/1: gpio...
319
  	}
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
320

4cb220e27   Laxman Dewangan   gpio: ep93xx: Use...
321
  	return devm_gpiochip_add_data(dev, gc, NULL);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
322
  }
3836309d9   Bill Pemberton   gpio: remove use ...
323
  static int ep93xx_gpio_probe(struct platform_device *pdev)
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
324
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
325
326
  	struct ep93xx_gpio *ep93xx_gpio;
  	struct resource *res;
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
327
  	int i;
1aeede0b3   abdoulaye berthe   gpio: gpioep93xx:...
328
  	struct device *dev = &pdev->dev;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
329

1aeede0b3   abdoulaye berthe   gpio: gpioep93xx:...
330
  	ep93xx_gpio = devm_kzalloc(dev, sizeof(struct ep93xx_gpio), GFP_KERNEL);
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
331
332
  	if (!ep93xx_gpio)
  		return -ENOMEM;
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
333

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
334
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
c829f956f   Jingoo Han   gpio: ep93xx: Use...
335
  	ep93xx_gpio->mmio_base = devm_ioremap_resource(dev, res);
1aeede0b3   abdoulaye berthe   gpio: gpioep93xx:...
336
337
  	if (IS_ERR(ep93xx_gpio->mmio_base))
  		return PTR_ERR(ep93xx_gpio->mmio_base);
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
338

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
339
  	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
0f4630f37   Linus Walleij   gpio: generic: fa...
340
  		struct gpio_chip *gc = &ep93xx_gpio->gc[i];
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
341
  		struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
5d046af0e   Hartley Sweeten   ARM: 6641/1: ep93...
342

0f4630f37   Linus Walleij   gpio: generic: fa...
343
  		if (ep93xx_gpio_add_bank(gc, &pdev->dev,
1aeede0b3   abdoulaye berthe   gpio: gpioep93xx:...
344
  					 ep93xx_gpio->mmio_base, bank))
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
345
346
347
  			dev_warn(&pdev->dev, "Unable to add gpio bank %s
  ",
  				bank->label);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
348
  	}
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
349
  	ep93xx_gpio_init_irq();
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
350

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
351
  	return 0;
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
352
  }
fd015480c   Hartley Sweeten   ARM: 6636/1: ep93...
353

1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
354
355
356
  static struct platform_driver ep93xx_gpio_driver = {
  	.driver		= {
  		.name	= "gpio-ep93xx",
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
357
358
359
360
361
362
  	},
  	.probe		= ep93xx_gpio_probe,
  };
  
  static int __init ep93xx_gpio_init(void)
  {
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
363
  	return platform_driver_register(&ep93xx_gpio_driver);
b685004f8   Ryan Mallon   [ARM] 4988/1: Add...
364
  }
1e4c88420   H Hartley Sweeten   gpio/ep93xx: conv...
365
366
367
368
369
370
  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");