Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-ep93xx/gpio.c
10817 views
1
/*
2
* linux/arch/arm/mach-ep93xx/gpio.c
3
*
4
* Generic EP93xx GPIO handling
5
*
6
* Copyright (c) 2008 Ryan Mallon <[email protected]>
7
*
8
* Based on code originally from:
9
* linux/arch/arm/mach-ep93xx/core.c
10
*
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License version 2 as
13
* published by the Free Software Foundation.
14
*/
15
16
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
17
18
#include <linux/init.h>
19
#include <linux/module.h>
20
#include <linux/seq_file.h>
21
#include <linux/io.h>
22
#include <linux/gpio.h>
23
#include <linux/irq.h>
24
25
#include <mach/hardware.h>
26
27
/*************************************************************************
28
* Interrupt handling for EP93xx on-chip GPIOs
29
*************************************************************************/
30
static unsigned char gpio_int_unmasked[3];
31
static unsigned char gpio_int_enabled[3];
32
static unsigned char gpio_int_type1[3];
33
static unsigned char gpio_int_type2[3];
34
static unsigned char gpio_int_debounce[3];
35
36
/* Port ordering is: A B F */
37
static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
38
static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
39
static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
40
static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
41
static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
42
43
static void ep93xx_gpio_update_int_params(unsigned port)
44
{
45
BUG_ON(port > 2);
46
47
__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
48
49
__raw_writeb(gpio_int_type2[port],
50
EP93XX_GPIO_REG(int_type2_register_offset[port]));
51
52
__raw_writeb(gpio_int_type1[port],
53
EP93XX_GPIO_REG(int_type1_register_offset[port]));
54
55
__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
56
EP93XX_GPIO_REG(int_en_register_offset[port]));
57
}
58
59
static inline void ep93xx_gpio_int_mask(unsigned line)
60
{
61
gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
62
}
63
64
static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
65
{
66
int line = irq_to_gpio(irq);
67
int port = line >> 3;
68
int port_mask = 1 << (line & 7);
69
70
if (enable)
71
gpio_int_debounce[port] |= port_mask;
72
else
73
gpio_int_debounce[port] &= ~port_mask;
74
75
__raw_writeb(gpio_int_debounce[port],
76
EP93XX_GPIO_REG(int_debounce_register_offset[port]));
77
}
78
79
static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
80
{
81
unsigned char status;
82
int i;
83
84
status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
85
for (i = 0; i < 8; i++) {
86
if (status & (1 << i)) {
87
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
88
generic_handle_irq(gpio_irq);
89
}
90
}
91
92
status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
93
for (i = 0; i < 8; i++) {
94
if (status & (1 << i)) {
95
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
96
generic_handle_irq(gpio_irq);
97
}
98
}
99
}
100
101
static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
102
{
103
/*
104
* map discontiguous hw irq range to continuous sw irq range:
105
*
106
* IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
107
*/
108
int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
109
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
110
111
generic_handle_irq(gpio_irq);
112
}
113
114
static void ep93xx_gpio_irq_ack(struct irq_data *d)
115
{
116
int line = irq_to_gpio(d->irq);
117
int port = line >> 3;
118
int port_mask = 1 << (line & 7);
119
120
if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
121
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
122
ep93xx_gpio_update_int_params(port);
123
}
124
125
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
126
}
127
128
static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
129
{
130
int line = irq_to_gpio(d->irq);
131
int port = line >> 3;
132
int port_mask = 1 << (line & 7);
133
134
if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
135
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
136
137
gpio_int_unmasked[port] &= ~port_mask;
138
ep93xx_gpio_update_int_params(port);
139
140
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
141
}
142
143
static void ep93xx_gpio_irq_mask(struct irq_data *d)
144
{
145
int line = irq_to_gpio(d->irq);
146
int port = line >> 3;
147
148
gpio_int_unmasked[port] &= ~(1 << (line & 7));
149
ep93xx_gpio_update_int_params(port);
150
}
151
152
static void ep93xx_gpio_irq_unmask(struct irq_data *d)
153
{
154
int line = irq_to_gpio(d->irq);
155
int port = line >> 3;
156
157
gpio_int_unmasked[port] |= 1 << (line & 7);
158
ep93xx_gpio_update_int_params(port);
159
}
160
161
/*
162
* gpio_int_type1 controls whether the interrupt is level (0) or
163
* edge (1) triggered, while gpio_int_type2 controls whether it
164
* triggers on low/falling (0) or high/rising (1).
165
*/
166
static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
167
{
168
const int gpio = irq_to_gpio(d->irq);
169
const int port = gpio >> 3;
170
const int port_mask = 1 << (gpio & 7);
171
irq_flow_handler_t handler;
172
173
gpio_direction_input(gpio);
174
175
switch (type) {
176
case IRQ_TYPE_EDGE_RISING:
177
gpio_int_type1[port] |= port_mask;
178
gpio_int_type2[port] |= port_mask;
179
handler = handle_edge_irq;
180
break;
181
case IRQ_TYPE_EDGE_FALLING:
182
gpio_int_type1[port] |= port_mask;
183
gpio_int_type2[port] &= ~port_mask;
184
handler = handle_edge_irq;
185
break;
186
case IRQ_TYPE_LEVEL_HIGH:
187
gpio_int_type1[port] &= ~port_mask;
188
gpio_int_type2[port] |= port_mask;
189
handler = handle_level_irq;
190
break;
191
case IRQ_TYPE_LEVEL_LOW:
192
gpio_int_type1[port] &= ~port_mask;
193
gpio_int_type2[port] &= ~port_mask;
194
handler = handle_level_irq;
195
break;
196
case IRQ_TYPE_EDGE_BOTH:
197
gpio_int_type1[port] |= port_mask;
198
/* set initial polarity based on current input level */
199
if (gpio_get_value(gpio))
200
gpio_int_type2[port] &= ~port_mask; /* falling */
201
else
202
gpio_int_type2[port] |= port_mask; /* rising */
203
handler = handle_edge_irq;
204
break;
205
default:
206
pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
207
return -EINVAL;
208
}
209
210
__irq_set_handler_locked(d->irq, handler);
211
212
gpio_int_enabled[port] |= port_mask;
213
214
ep93xx_gpio_update_int_params(port);
215
216
return 0;
217
}
218
219
static struct irq_chip ep93xx_gpio_irq_chip = {
220
.name = "GPIO",
221
.irq_ack = ep93xx_gpio_irq_ack,
222
.irq_mask_ack = ep93xx_gpio_irq_mask_ack,
223
.irq_mask = ep93xx_gpio_irq_mask,
224
.irq_unmask = ep93xx_gpio_irq_unmask,
225
.irq_set_type = ep93xx_gpio_irq_type,
226
};
227
228
void __init ep93xx_gpio_init_irq(void)
229
{
230
int gpio_irq;
231
232
for (gpio_irq = gpio_to_irq(0);
233
gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
234
irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
235
handle_level_irq);
236
set_irq_flags(gpio_irq, IRQF_VALID);
237
}
238
239
irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
240
ep93xx_gpio_ab_irq_handler);
241
irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
242
ep93xx_gpio_f_irq_handler);
243
irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
244
ep93xx_gpio_f_irq_handler);
245
irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
246
ep93xx_gpio_f_irq_handler);
247
irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
248
ep93xx_gpio_f_irq_handler);
249
irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
250
ep93xx_gpio_f_irq_handler);
251
irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
252
ep93xx_gpio_f_irq_handler);
253
irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
254
ep93xx_gpio_f_irq_handler);
255
irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
256
ep93xx_gpio_f_irq_handler);
257
}
258
259
260
/*************************************************************************
261
* gpiolib interface for EP93xx on-chip GPIOs
262
*************************************************************************/
263
struct ep93xx_gpio_chip {
264
struct gpio_chip chip;
265
266
void __iomem *data_reg;
267
void __iomem *data_dir_reg;
268
};
269
270
#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
271
272
static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
273
{
274
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
275
unsigned long flags;
276
u8 v;
277
278
local_irq_save(flags);
279
v = __raw_readb(ep93xx_chip->data_dir_reg);
280
v &= ~(1 << offset);
281
__raw_writeb(v, ep93xx_chip->data_dir_reg);
282
local_irq_restore(flags);
283
284
return 0;
285
}
286
287
static int ep93xx_gpio_direction_output(struct gpio_chip *chip,
288
unsigned offset, int val)
289
{
290
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
291
unsigned long flags;
292
int line;
293
u8 v;
294
295
local_irq_save(flags);
296
297
/* Set the value */
298
v = __raw_readb(ep93xx_chip->data_reg);
299
if (val)
300
v |= (1 << offset);
301
else
302
v &= ~(1 << offset);
303
__raw_writeb(v, ep93xx_chip->data_reg);
304
305
/* Drive as an output */
306
line = chip->base + offset;
307
if (line <= EP93XX_GPIO_LINE_MAX_IRQ) {
308
/* Ports A/B/F */
309
ep93xx_gpio_int_mask(line);
310
ep93xx_gpio_update_int_params(line >> 3);
311
}
312
313
v = __raw_readb(ep93xx_chip->data_dir_reg);
314
v |= (1 << offset);
315
__raw_writeb(v, ep93xx_chip->data_dir_reg);
316
317
local_irq_restore(flags);
318
319
return 0;
320
}
321
322
static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset)
323
{
324
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
325
326
return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset));
327
}
328
329
static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
330
{
331
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
332
unsigned long flags;
333
u8 v;
334
335
local_irq_save(flags);
336
v = __raw_readb(ep93xx_chip->data_reg);
337
if (val)
338
v |= (1 << offset);
339
else
340
v &= ~(1 << offset);
341
__raw_writeb(v, ep93xx_chip->data_reg);
342
local_irq_restore(flags);
343
}
344
345
static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
346
unsigned offset, unsigned debounce)
347
{
348
int gpio = chip->base + offset;
349
int irq = gpio_to_irq(gpio);
350
351
if (irq < 0)
352
return -EINVAL;
353
354
ep93xx_gpio_int_debounce(irq, debounce ? true : false);
355
356
return 0;
357
}
358
359
#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \
360
{ \
361
.chip = { \
362
.label = name, \
363
.direction_input = ep93xx_gpio_direction_input, \
364
.direction_output = ep93xx_gpio_direction_output, \
365
.get = ep93xx_gpio_get, \
366
.set = ep93xx_gpio_set, \
367
.base = base_gpio, \
368
.ngpio = 8, \
369
}, \
370
.data_reg = EP93XX_GPIO_REG(dr), \
371
.data_dir_reg = EP93XX_GPIO_REG(ddr), \
372
}
373
374
static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = {
375
EP93XX_GPIO_BANK("A", 0x00, 0x10, 0),
376
EP93XX_GPIO_BANK("B", 0x04, 0x14, 8),
377
EP93XX_GPIO_BANK("C", 0x08, 0x18, 40),
378
EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24),
379
EP93XX_GPIO_BANK("E", 0x20, 0x24, 32),
380
EP93XX_GPIO_BANK("F", 0x30, 0x34, 16),
381
EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48),
382
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56),
383
};
384
385
void __init ep93xx_gpio_init(void)
386
{
387
int i;
388
389
/* Set Ports C, D, E, G, and H for GPIO use */
390
ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
391
EP93XX_SYSCON_DEVCFG_GONK |
392
EP93XX_SYSCON_DEVCFG_EONIDE |
393
EP93XX_SYSCON_DEVCFG_GONIDE |
394
EP93XX_SYSCON_DEVCFG_HONIDE);
395
396
for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
397
struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip;
398
399
/*
400
* Ports A, B, and F support input debouncing when
401
* used as interrupts.
402
*/
403
if (!strcmp(chip->label, "A") ||
404
!strcmp(chip->label, "B") ||
405
!strcmp(chip->label, "F"))
406
chip->set_debounce = ep93xx_gpio_set_debounce;
407
408
gpiochip_add(chip);
409
}
410
}
411
412