Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-ks8695/gpio.c
10817 views
1
/*
2
* arch/arm/mach-ks8695/gpio.c
3
*
4
* Copyright (C) 2006 Andrew Victor
5
* Updated to GPIOLIB, Copyright 2008 Simtec Electronics
6
* Daniel Silverstone <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
22
#include <linux/kernel.h>
23
#include <linux/mm.h>
24
#include <linux/init.h>
25
#include <linux/debugfs.h>
26
#include <linux/seq_file.h>
27
#include <linux/module.h>
28
#include <linux/io.h>
29
30
#include <mach/hardware.h>
31
#include <asm/mach/irq.h>
32
33
#include <mach/regs-gpio.h>
34
#include <mach/gpio.h>
35
36
/*
37
* Configure a GPIO line for either GPIO function, or its internal
38
* function (Interrupt, Timer, etc).
39
*/
40
static void ks8695_gpio_mode(unsigned int pin, short gpio)
41
{
42
unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
43
unsigned long x, flags;
44
45
if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */
46
return;
47
48
local_irq_save(flags);
49
50
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
51
if (gpio) /* GPIO: set bit to 0 */
52
x &= ~enable[pin];
53
else /* Internal function: set bit to 1 */
54
x |= enable[pin];
55
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
56
57
local_irq_restore(flags);
58
}
59
60
61
static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
62
63
/*
64
* Configure GPIO pin as external interrupt source.
65
*/
66
int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
67
{
68
unsigned long x, flags;
69
70
if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
71
return -EINVAL;
72
73
local_irq_save(flags);
74
75
/* set pin as input */
76
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
77
x &= ~IOPM(pin);
78
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
79
80
local_irq_restore(flags);
81
82
/* Set IRQ triggering type */
83
irq_set_irq_type(gpio_irq[pin], type);
84
85
/* enable interrupt mode */
86
ks8695_gpio_mode(pin, 0);
87
88
return 0;
89
}
90
EXPORT_SYMBOL(ks8695_gpio_interrupt);
91
92
93
94
/* .... Generic GPIO interface .............................................. */
95
96
/*
97
* Configure the GPIO line as an input.
98
*/
99
static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
100
{
101
unsigned long x, flags;
102
103
if (pin > KS8695_GPIO_15)
104
return -EINVAL;
105
106
/* set pin to GPIO mode */
107
ks8695_gpio_mode(pin, 1);
108
109
local_irq_save(flags);
110
111
/* set pin as input */
112
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
113
x &= ~IOPM(pin);
114
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
115
116
local_irq_restore(flags);
117
118
return 0;
119
}
120
121
122
/*
123
* Configure the GPIO line as an output, with default state.
124
*/
125
static int ks8695_gpio_direction_output(struct gpio_chip *gc,
126
unsigned int pin, int state)
127
{
128
unsigned long x, flags;
129
130
if (pin > KS8695_GPIO_15)
131
return -EINVAL;
132
133
/* set pin to GPIO mode */
134
ks8695_gpio_mode(pin, 1);
135
136
local_irq_save(flags);
137
138
/* set line state */
139
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
140
if (state)
141
x |= IOPD(pin);
142
else
143
x &= ~IOPD(pin);
144
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
145
146
/* set pin as output */
147
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
148
x |= IOPM(pin);
149
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
150
151
local_irq_restore(flags);
152
153
return 0;
154
}
155
156
157
/*
158
* Set the state of an output GPIO line.
159
*/
160
static void ks8695_gpio_set_value(struct gpio_chip *gc,
161
unsigned int pin, int state)
162
{
163
unsigned long x, flags;
164
165
if (pin > KS8695_GPIO_15)
166
return;
167
168
local_irq_save(flags);
169
170
/* set output line state */
171
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
172
if (state)
173
x |= IOPD(pin);
174
else
175
x &= ~IOPD(pin);
176
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
177
178
local_irq_restore(flags);
179
}
180
181
182
/*
183
* Read the state of a GPIO line.
184
*/
185
static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
186
{
187
unsigned long x;
188
189
if (pin > KS8695_GPIO_15)
190
return -EINVAL;
191
192
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
193
return (x & IOPD(pin)) != 0;
194
}
195
196
197
/*
198
* Map GPIO line to IRQ number.
199
*/
200
static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
201
{
202
if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
203
return -EINVAL;
204
205
return gpio_irq[pin];
206
}
207
208
/*
209
* Map IRQ number to GPIO line.
210
*/
211
int irq_to_gpio(unsigned int irq)
212
{
213
if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
214
return -EINVAL;
215
216
return (irq - KS8695_IRQ_EXTERN0);
217
}
218
EXPORT_SYMBOL(irq_to_gpio);
219
220
/* GPIOLIB interface */
221
222
static struct gpio_chip ks8695_gpio_chip = {
223
.label = "KS8695",
224
.direction_input = ks8695_gpio_direction_input,
225
.direction_output = ks8695_gpio_direction_output,
226
.get = ks8695_gpio_get_value,
227
.set = ks8695_gpio_set_value,
228
.to_irq = ks8695_gpio_to_irq,
229
.base = 0,
230
.ngpio = 16,
231
.can_sleep = 0,
232
};
233
234
/* Register the GPIOs */
235
void ks8695_register_gpios(void)
236
{
237
if (gpiochip_add(&ks8695_gpio_chip))
238
printk(KERN_ERR "Unable to register core GPIOs\n");
239
}
240
241
/* .... Debug interface ..................................................... */
242
243
#ifdef CONFIG_DEBUG_FS
244
245
static int ks8695_gpio_show(struct seq_file *s, void *unused)
246
{
247
unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
248
unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
249
unsigned long mode, ctrl, data;
250
int i;
251
252
mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
253
ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
254
data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
255
256
seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
257
258
for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
259
seq_printf(s, "%i:\t", i);
260
261
seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
262
263
if (i <= KS8695_GPIO_3) {
264
if (ctrl & enable[i]) {
265
seq_printf(s, "EXT%i ", i);
266
267
switch ((ctrl & intmask[i]) >> (4 * i)) {
268
case IOPC_TM_LOW:
269
seq_printf(s, "(Low)"); break;
270
case IOPC_TM_HIGH:
271
seq_printf(s, "(High)"); break;
272
case IOPC_TM_RISING:
273
seq_printf(s, "(Rising)"); break;
274
case IOPC_TM_FALLING:
275
seq_printf(s, "(Falling)"); break;
276
case IOPC_TM_EDGE:
277
seq_printf(s, "(Edges)"); break;
278
}
279
}
280
else
281
seq_printf(s, "GPIO\t");
282
}
283
else if (i <= KS8695_GPIO_5) {
284
if (ctrl & enable[i])
285
seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
286
else
287
seq_printf(s, "GPIO\t");
288
}
289
else
290
seq_printf(s, "GPIO\t");
291
292
seq_printf(s, "\t");
293
294
seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
295
}
296
return 0;
297
}
298
299
static int ks8695_gpio_open(struct inode *inode, struct file *file)
300
{
301
return single_open(file, ks8695_gpio_show, NULL);
302
}
303
304
static const struct file_operations ks8695_gpio_operations = {
305
.open = ks8695_gpio_open,
306
.read = seq_read,
307
.llseek = seq_lseek,
308
.release = single_release,
309
};
310
311
static int __init ks8695_gpio_debugfs_init(void)
312
{
313
/* /sys/kernel/debug/ks8695_gpio */
314
(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
315
return 0;
316
}
317
postcore_initcall(ks8695_gpio_debugfs_init);
318
319
#endif
320
321