Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-msm/gpio.c
10817 views
1
/* linux/arch/arm/mach-msm/gpio.c
2
*
3
* Copyright (C) 2007 Google, Inc.
4
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
5
*
6
* This software is licensed under the terms of the GNU General Public
7
* License version 2, as published by the Free Software Foundation, and
8
* may be copied, distributed, and modified under those terms.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
*/
16
17
#include <linux/bitops.h>
18
#include <linux/gpio.h>
19
#include <linux/interrupt.h>
20
#include <linux/io.h>
21
#include <linux/irq.h>
22
#include <linux/module.h>
23
#include "gpio_hw.h"
24
#include "gpiomux.h"
25
26
#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
27
28
#define MSM_GPIO_BANK(bank, first, last) \
29
{ \
30
.regs = { \
31
.out = MSM_GPIO_OUT_##bank, \
32
.in = MSM_GPIO_IN_##bank, \
33
.int_status = MSM_GPIO_INT_STATUS_##bank, \
34
.int_clear = MSM_GPIO_INT_CLEAR_##bank, \
35
.int_en = MSM_GPIO_INT_EN_##bank, \
36
.int_edge = MSM_GPIO_INT_EDGE_##bank, \
37
.int_pos = MSM_GPIO_INT_POS_##bank, \
38
.oe = MSM_GPIO_OE_##bank, \
39
}, \
40
.chip = { \
41
.base = (first), \
42
.ngpio = (last) - (first) + 1, \
43
.get = msm_gpio_get, \
44
.set = msm_gpio_set, \
45
.direction_input = msm_gpio_direction_input, \
46
.direction_output = msm_gpio_direction_output, \
47
.to_irq = msm_gpio_to_irq, \
48
.request = msm_gpio_request, \
49
.free = msm_gpio_free, \
50
} \
51
}
52
53
#define MSM_GPIO_BROKEN_INT_CLEAR 1
54
55
struct msm_gpio_regs {
56
void __iomem *out;
57
void __iomem *in;
58
void __iomem *int_status;
59
void __iomem *int_clear;
60
void __iomem *int_en;
61
void __iomem *int_edge;
62
void __iomem *int_pos;
63
void __iomem *oe;
64
};
65
66
struct msm_gpio_chip {
67
spinlock_t lock;
68
struct gpio_chip chip;
69
struct msm_gpio_regs regs;
70
#if MSM_GPIO_BROKEN_INT_CLEAR
71
unsigned int_status_copy;
72
#endif
73
unsigned int both_edge_detect;
74
unsigned int int_enable[2]; /* 0: awake, 1: sleep */
75
};
76
77
static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
78
unsigned offset, unsigned on)
79
{
80
unsigned mask = BIT(offset);
81
unsigned val;
82
83
val = readl(msm_chip->regs.out);
84
if (on)
85
writel(val | mask, msm_chip->regs.out);
86
else
87
writel(val & ~mask, msm_chip->regs.out);
88
return 0;
89
}
90
91
static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
92
{
93
int loop_limit = 100;
94
unsigned pol, val, val2, intstat;
95
do {
96
val = readl(msm_chip->regs.in);
97
pol = readl(msm_chip->regs.int_pos);
98
pol = (pol & ~msm_chip->both_edge_detect) |
99
(~val & msm_chip->both_edge_detect);
100
writel(pol, msm_chip->regs.int_pos);
101
intstat = readl(msm_chip->regs.int_status);
102
val2 = readl(msm_chip->regs.in);
103
if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
104
return;
105
} while (loop_limit-- > 0);
106
printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
107
"failed to reach stable state %x != %x\n", val, val2);
108
}
109
110
static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
111
unsigned offset)
112
{
113
unsigned bit = BIT(offset);
114
115
#if MSM_GPIO_BROKEN_INT_CLEAR
116
/* Save interrupts that already triggered before we loose them. */
117
/* Any interrupt that triggers between the read of int_status */
118
/* and the write to int_clear will still be lost though. */
119
msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
120
msm_chip->int_status_copy &= ~bit;
121
#endif
122
writel(bit, msm_chip->regs.int_clear);
123
msm_gpio_update_both_edge_detect(msm_chip);
124
return 0;
125
}
126
127
static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
128
{
129
struct msm_gpio_chip *msm_chip;
130
unsigned long irq_flags;
131
132
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
133
spin_lock_irqsave(&msm_chip->lock, irq_flags);
134
writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
135
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
136
return 0;
137
}
138
139
static int
140
msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
141
{
142
struct msm_gpio_chip *msm_chip;
143
unsigned long irq_flags;
144
145
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
146
spin_lock_irqsave(&msm_chip->lock, irq_flags);
147
msm_gpio_write(msm_chip, offset, value);
148
writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
149
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
150
return 0;
151
}
152
153
static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
154
{
155
struct msm_gpio_chip *msm_chip;
156
157
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
158
return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
159
}
160
161
static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
162
{
163
struct msm_gpio_chip *msm_chip;
164
unsigned long irq_flags;
165
166
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
167
spin_lock_irqsave(&msm_chip->lock, irq_flags);
168
msm_gpio_write(msm_chip, offset, value);
169
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
170
}
171
172
static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
173
{
174
return MSM_GPIO_TO_INT(chip->base + offset);
175
}
176
177
#ifdef CONFIG_MSM_GPIOMUX
178
static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
179
{
180
return msm_gpiomux_get(chip->base + offset);
181
}
182
183
static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
184
{
185
msm_gpiomux_put(chip->base + offset);
186
}
187
#else
188
#define msm_gpio_request NULL
189
#define msm_gpio_free NULL
190
#endif
191
192
struct msm_gpio_chip msm_gpio_chips[] = {
193
#if defined(CONFIG_ARCH_MSM7X00A)
194
MSM_GPIO_BANK(0, 0, 15),
195
MSM_GPIO_BANK(1, 16, 42),
196
MSM_GPIO_BANK(2, 43, 67),
197
MSM_GPIO_BANK(3, 68, 94),
198
MSM_GPIO_BANK(4, 95, 106),
199
MSM_GPIO_BANK(5, 107, 121),
200
#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
201
MSM_GPIO_BANK(0, 0, 15),
202
MSM_GPIO_BANK(1, 16, 42),
203
MSM_GPIO_BANK(2, 43, 67),
204
MSM_GPIO_BANK(3, 68, 94),
205
MSM_GPIO_BANK(4, 95, 106),
206
MSM_GPIO_BANK(5, 107, 132),
207
#elif defined(CONFIG_ARCH_MSM7X30)
208
MSM_GPIO_BANK(0, 0, 15),
209
MSM_GPIO_BANK(1, 16, 43),
210
MSM_GPIO_BANK(2, 44, 67),
211
MSM_GPIO_BANK(3, 68, 94),
212
MSM_GPIO_BANK(4, 95, 106),
213
MSM_GPIO_BANK(5, 107, 133),
214
MSM_GPIO_BANK(6, 134, 150),
215
MSM_GPIO_BANK(7, 151, 181),
216
#elif defined(CONFIG_ARCH_QSD8X50)
217
MSM_GPIO_BANK(0, 0, 15),
218
MSM_GPIO_BANK(1, 16, 42),
219
MSM_GPIO_BANK(2, 43, 67),
220
MSM_GPIO_BANK(3, 68, 94),
221
MSM_GPIO_BANK(4, 95, 103),
222
MSM_GPIO_BANK(5, 104, 121),
223
MSM_GPIO_BANK(6, 122, 152),
224
MSM_GPIO_BANK(7, 153, 164),
225
#endif
226
};
227
228
static void msm_gpio_irq_ack(struct irq_data *d)
229
{
230
unsigned long irq_flags;
231
struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
232
spin_lock_irqsave(&msm_chip->lock, irq_flags);
233
msm_gpio_clear_detect_status(msm_chip,
234
d->irq - gpio_to_irq(msm_chip->chip.base));
235
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
236
}
237
238
static void msm_gpio_irq_mask(struct irq_data *d)
239
{
240
unsigned long irq_flags;
241
struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
242
unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
243
244
spin_lock_irqsave(&msm_chip->lock, irq_flags);
245
/* level triggered interrupts are also latched */
246
if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
247
msm_gpio_clear_detect_status(msm_chip, offset);
248
msm_chip->int_enable[0] &= ~BIT(offset);
249
writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
250
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
251
}
252
253
static void msm_gpio_irq_unmask(struct irq_data *d)
254
{
255
unsigned long irq_flags;
256
struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
257
unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
258
259
spin_lock_irqsave(&msm_chip->lock, irq_flags);
260
/* level triggered interrupts are also latched */
261
if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
262
msm_gpio_clear_detect_status(msm_chip, offset);
263
msm_chip->int_enable[0] |= BIT(offset);
264
writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
265
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
266
}
267
268
static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
269
{
270
unsigned long irq_flags;
271
struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
272
unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
273
274
spin_lock_irqsave(&msm_chip->lock, irq_flags);
275
276
if (on)
277
msm_chip->int_enable[1] |= BIT(offset);
278
else
279
msm_chip->int_enable[1] &= ~BIT(offset);
280
281
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
282
return 0;
283
}
284
285
static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
286
{
287
unsigned long irq_flags;
288
struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
289
unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
290
unsigned val, mask = BIT(offset);
291
292
spin_lock_irqsave(&msm_chip->lock, irq_flags);
293
val = readl(msm_chip->regs.int_edge);
294
if (flow_type & IRQ_TYPE_EDGE_BOTH) {
295
writel(val | mask, msm_chip->regs.int_edge);
296
__irq_set_handler_locked(d->irq, handle_edge_irq);
297
} else {
298
writel(val & ~mask, msm_chip->regs.int_edge);
299
__irq_set_handler_locked(d->irq, handle_level_irq);
300
}
301
if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
302
msm_chip->both_edge_detect |= mask;
303
msm_gpio_update_both_edge_detect(msm_chip);
304
} else {
305
msm_chip->both_edge_detect &= ~mask;
306
val = readl(msm_chip->regs.int_pos);
307
if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
308
writel(val | mask, msm_chip->regs.int_pos);
309
else
310
writel(val & ~mask, msm_chip->regs.int_pos);
311
}
312
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
313
return 0;
314
}
315
316
static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
317
{
318
int i, j, mask;
319
unsigned val;
320
321
for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
322
struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
323
val = readl(msm_chip->regs.int_status);
324
val &= msm_chip->int_enable[0];
325
while (val) {
326
mask = val & -val;
327
j = fls(mask) - 1;
328
/* printk("%s %08x %08x bit %d gpio %d irq %d\n",
329
__func__, v, m, j, msm_chip->chip.start + j,
330
FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
331
val &= ~mask;
332
generic_handle_irq(FIRST_GPIO_IRQ +
333
msm_chip->chip.base + j);
334
}
335
}
336
desc->irq_data.chip->irq_ack(&desc->irq_data);
337
}
338
339
static struct irq_chip msm_gpio_irq_chip = {
340
.name = "msmgpio",
341
.irq_ack = msm_gpio_irq_ack,
342
.irq_mask = msm_gpio_irq_mask,
343
.irq_unmask = msm_gpio_irq_unmask,
344
.irq_set_wake = msm_gpio_irq_set_wake,
345
.irq_set_type = msm_gpio_irq_set_type,
346
};
347
348
static int __init msm_init_gpio(void)
349
{
350
int i, j = 0;
351
352
for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
353
if (i - FIRST_GPIO_IRQ >=
354
msm_gpio_chips[j].chip.base +
355
msm_gpio_chips[j].chip.ngpio)
356
j++;
357
irq_set_chip_data(i, &msm_gpio_chips[j]);
358
irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
359
handle_edge_irq);
360
set_irq_flags(i, IRQF_VALID);
361
}
362
363
for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
364
spin_lock_init(&msm_gpio_chips[i].lock);
365
writel(0, msm_gpio_chips[i].regs.int_en);
366
gpiochip_add(&msm_gpio_chips[i].chip);
367
}
368
369
irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
370
irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
371
irq_set_irq_wake(INT_GPIO_GROUP1, 1);
372
irq_set_irq_wake(INT_GPIO_GROUP2, 2);
373
return 0;
374
}
375
376
postcore_initcall(msm_init_gpio);
377
378