Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-pnx4008/gpio.c
10817 views
1
/*
2
* arch/arm/mach-pnx4008/gpio.c
3
*
4
* PNX4008 GPIO driver
5
*
6
* Author: Dmitry Chigirev <[email protected]>
7
*
8
* Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
9
* Copyright (c) 2005 Koninklijke Philips Electronics N.V.
10
*
11
* 2005 (c) MontaVista Software, Inc. This file is licensed under
12
* the terms of the GNU General Public License version 2. This program
13
* is licensed "as is" without any warranty of any kind, whether express
14
* or implied.
15
*/
16
17
#include <linux/types.h>
18
#include <linux/kernel.h>
19
#include <linux/module.h>
20
#include <linux/io.h>
21
#include <mach/hardware.h>
22
#include <mach/platform.h>
23
#include <mach/gpio.h>
24
25
/* register definitions */
26
#define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE)
27
28
#define PIO_INP_STATE (0x00U)
29
#define PIO_OUTP_SET (0x04U)
30
#define PIO_OUTP_CLR (0x08U)
31
#define PIO_OUTP_STATE (0x0CU)
32
#define PIO_DRV_SET (0x10U)
33
#define PIO_DRV_CLR (0x14U)
34
#define PIO_DRV_STATE (0x18U)
35
#define PIO_SDINP_STATE (0x1CU)
36
#define PIO_SDOUTP_SET (0x20U)
37
#define PIO_SDOUTP_CLR (0x24U)
38
#define PIO_MUX_SET (0x28U)
39
#define PIO_MUX_CLR (0x2CU)
40
#define PIO_MUX_STATE (0x30U)
41
42
static inline void gpio_lock(void)
43
{
44
local_irq_disable();
45
}
46
47
static inline void gpio_unlock(void)
48
{
49
local_irq_enable();
50
}
51
52
/* Inline functions */
53
static inline int gpio_read_bit(u32 reg, int gpio)
54
{
55
u32 bit, val;
56
int ret = -EFAULT;
57
58
if (gpio < 0)
59
goto out;
60
61
bit = GPIO_BIT(gpio);
62
if (bit) {
63
val = __raw_readl(PIO_VA_BASE + reg);
64
ret = (val & bit) ? 1 : 0;
65
}
66
out:
67
return ret;
68
}
69
70
static inline int gpio_set_bit(u32 reg, int gpio)
71
{
72
u32 bit, val;
73
int ret = -EFAULT;
74
75
if (gpio < 0)
76
goto out;
77
78
bit = GPIO_BIT(gpio);
79
if (bit) {
80
val = __raw_readl(PIO_VA_BASE + reg);
81
val |= bit;
82
__raw_writel(val, PIO_VA_BASE + reg);
83
ret = 0;
84
}
85
out:
86
return ret;
87
}
88
89
/* Very simple access control, bitmap for allocated/free */
90
static unsigned long access_map[4];
91
#define INP_INDEX 0
92
#define OUTP_INDEX 1
93
#define GPIO_INDEX 2
94
#define MUX_INDEX 3
95
96
/*GPIO to Input Mapping */
97
static short gpio_to_inp_map[32] = {
98
-1, -1, -1, -1, -1, -1, -1, -1,
99
-1, -1, -1, -1, -1, -1, -1, -1,
100
-1, -1, -1, -1, -1, -1, -1, -1,
101
-1, 10, 11, 12, 13, 14, 24, -1
102
};
103
104
/*GPIO to Mux Mapping */
105
static short gpio_to_mux_map[32] = {
106
-1, -1, -1, -1, -1, -1, -1, -1,
107
-1, -1, -1, -1, -1, -1, -1, -1,
108
-1, -1, -1, -1, -1, -1, -1, -1,
109
-1, -1, -1, 0, 1, 4, 5, -1
110
};
111
112
/*Output to Mux Mapping */
113
static short outp_to_mux_map[32] = {
114
-1, -1, -1, 6, -1, -1, -1, -1,
115
-1, -1, -1, -1, -1, -1, -1, -1,
116
-1, -1, -1, -1, -1, 2, -1, -1,
117
-1, -1, -1, -1, -1, -1, -1, -1
118
};
119
120
int pnx4008_gpio_register_pin(unsigned short pin)
121
{
122
unsigned long bit = GPIO_BIT(pin);
123
int ret = -EBUSY; /* Already in use */
124
125
gpio_lock();
126
127
if (GPIO_ISBID(pin)) {
128
if (access_map[GPIO_INDEX] & bit)
129
goto out;
130
access_map[GPIO_INDEX] |= bit;
131
132
} else if (GPIO_ISRAM(pin)) {
133
if (access_map[GPIO_INDEX] & bit)
134
goto out;
135
access_map[GPIO_INDEX] |= bit;
136
137
} else if (GPIO_ISMUX(pin)) {
138
if (access_map[MUX_INDEX] & bit)
139
goto out;
140
access_map[MUX_INDEX] |= bit;
141
142
} else if (GPIO_ISOUT(pin)) {
143
if (access_map[OUTP_INDEX] & bit)
144
goto out;
145
access_map[OUTP_INDEX] |= bit;
146
147
} else if (GPIO_ISIN(pin)) {
148
if (access_map[INP_INDEX] & bit)
149
goto out;
150
access_map[INP_INDEX] |= bit;
151
} else
152
goto out;
153
ret = 0;
154
155
out:
156
gpio_unlock();
157
return ret;
158
}
159
160
EXPORT_SYMBOL(pnx4008_gpio_register_pin);
161
162
int pnx4008_gpio_unregister_pin(unsigned short pin)
163
{
164
unsigned long bit = GPIO_BIT(pin);
165
int ret = -EFAULT; /* Not registered */
166
167
gpio_lock();
168
169
if (GPIO_ISBID(pin)) {
170
if (~access_map[GPIO_INDEX] & bit)
171
goto out;
172
access_map[GPIO_INDEX] &= ~bit;
173
} else if (GPIO_ISRAM(pin)) {
174
if (~access_map[GPIO_INDEX] & bit)
175
goto out;
176
access_map[GPIO_INDEX] &= ~bit;
177
} else if (GPIO_ISMUX(pin)) {
178
if (~access_map[MUX_INDEX] & bit)
179
goto out;
180
access_map[MUX_INDEX] &= ~bit;
181
} else if (GPIO_ISOUT(pin)) {
182
if (~access_map[OUTP_INDEX] & bit)
183
goto out;
184
access_map[OUTP_INDEX] &= ~bit;
185
} else if (GPIO_ISIN(pin)) {
186
if (~access_map[INP_INDEX] & bit)
187
goto out;
188
access_map[INP_INDEX] &= ~bit;
189
} else
190
goto out;
191
ret = 0;
192
193
out:
194
gpio_unlock();
195
return ret;
196
}
197
198
EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
199
200
unsigned long pnx4008_gpio_read_pin(unsigned short pin)
201
{
202
unsigned long ret = -EFAULT;
203
int gpio = GPIO_BIT_MASK(pin);
204
gpio_lock();
205
if (GPIO_ISOUT(pin)) {
206
ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
207
} else if (GPIO_ISRAM(pin)) {
208
if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
209
ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
210
}
211
} else if (GPIO_ISBID(pin)) {
212
ret = gpio_read_bit(PIO_DRV_STATE, gpio);
213
if (ret > 0)
214
ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
215
else if (ret == 0)
216
ret =
217
gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
218
} else if (GPIO_ISIN(pin)) {
219
ret = gpio_read_bit(PIO_INP_STATE, gpio);
220
}
221
gpio_unlock();
222
return ret;
223
}
224
225
EXPORT_SYMBOL(pnx4008_gpio_read_pin);
226
227
/* Write Value to output */
228
int pnx4008_gpio_write_pin(unsigned short pin, int output)
229
{
230
int gpio = GPIO_BIT_MASK(pin);
231
int ret = -EFAULT;
232
233
gpio_lock();
234
if (GPIO_ISOUT(pin)) {
235
printk( "writing '%x' to '%x'\n",
236
gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
237
ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
238
} else if (GPIO_ISRAM(pin)) {
239
if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
240
ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
241
PIO_SDOUTP_CLR, gpio);
242
} else if (GPIO_ISBID(pin)) {
243
if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
244
ret = gpio_set_bit(output ? PIO_OUTP_SET :
245
PIO_OUTP_CLR, gpio);
246
}
247
gpio_unlock();
248
return ret;
249
}
250
251
EXPORT_SYMBOL(pnx4008_gpio_write_pin);
252
253
/* Value = 1 : Set GPIO pin as output */
254
/* Value = 0 : Set GPIO pin as input */
255
int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
256
{
257
int gpio = GPIO_BIT_MASK(pin);
258
int ret = -EFAULT;
259
260
gpio_lock();
261
if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
262
ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
263
}
264
gpio_unlock();
265
return ret;
266
}
267
268
EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
269
270
/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
271
int pnx4008_gpio_read_pin_direction(unsigned short pin)
272
{
273
int gpio = GPIO_BIT_MASK(pin);
274
int ret = -EFAULT;
275
276
gpio_lock();
277
if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
278
ret = gpio_read_bit(PIO_DRV_STATE, gpio);
279
}
280
gpio_unlock();
281
return ret;
282
}
283
284
EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
285
286
/* Value = 1 : Set pin to muxed function */
287
/* Value = 0 : Set pin as GPIO */
288
int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
289
{
290
int gpio = GPIO_BIT_MASK(pin);
291
int ret = -EFAULT;
292
293
gpio_lock();
294
if (GPIO_ISBID(pin)) {
295
ret =
296
gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
297
gpio_to_mux_map[gpio]);
298
} else if (GPIO_ISOUT(pin)) {
299
ret =
300
gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
301
outp_to_mux_map[gpio]);
302
} else if (GPIO_ISMUX(pin)) {
303
ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
304
}
305
gpio_unlock();
306
return ret;
307
}
308
309
EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
310
311
/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
312
int pnx4008_gpio_read_pin_mux(unsigned short pin)
313
{
314
int gpio = GPIO_BIT_MASK(pin);
315
int ret = -EFAULT;
316
317
gpio_lock();
318
if (GPIO_ISBID(pin)) {
319
ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
320
} else if (GPIO_ISOUT(pin)) {
321
ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
322
} else if (GPIO_ISMUX(pin)) {
323
ret = gpio_read_bit(PIO_MUX_STATE, gpio);
324
}
325
gpio_unlock();
326
return ret;
327
}
328
329
EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
330
331