Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/cris/arch-v32/mach-fs/pinmux.c
15125 views
1
/*
2
* Allocator for I/O pins. All pins are allocated to GPIO at bootup.
3
* Unassigned pins and GPIO pins can be allocated to a fixed interface
4
* or the I/O processor instead.
5
*
6
* Copyright (c) 2004-2007 Axis Communications AB.
7
*/
8
9
#include <linux/init.h>
10
#include <linux/errno.h>
11
#include <linux/kernel.h>
12
#include <linux/string.h>
13
#include <linux/spinlock.h>
14
#include <hwregs/reg_map.h>
15
#include <hwregs/reg_rdwr.h>
16
#include <pinmux.h>
17
#include <hwregs/pinmux_defs.h>
18
19
#undef DEBUG
20
21
#define PORT_PINS 18
22
#define PORTS 4
23
24
static char pins[PORTS][PORT_PINS];
25
static DEFINE_SPINLOCK(pinmux_lock);
26
27
static void crisv32_pinmux_set(int port);
28
29
int crisv32_pinmux_init(void)
30
{
31
static int initialized;
32
33
if (!initialized) {
34
reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa);
35
initialized = 1;
36
REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
37
pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
38
pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
39
REG_WR(pinmux, regi_pinmux, rw_pa, pa);
40
crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
41
crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
42
crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
43
crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
44
}
45
46
return 0;
47
}
48
49
int
50
crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
51
{
52
int i;
53
unsigned long flags;
54
55
crisv32_pinmux_init();
56
57
if (port > PORTS || port < 0)
58
return -EINVAL;
59
60
spin_lock_irqsave(&pinmux_lock, flags);
61
62
for (i = first_pin; i <= last_pin; i++) {
63
if ((pins[port][i] != pinmux_none)
64
&& (pins[port][i] != pinmux_gpio)
65
&& (pins[port][i] != mode)) {
66
spin_unlock_irqrestore(&pinmux_lock, flags);
67
#ifdef DEBUG
68
panic("Pinmux alloc failed!\n");
69
#endif
70
return -EPERM;
71
}
72
}
73
74
for (i = first_pin; i <= last_pin; i++)
75
pins[port][i] = mode;
76
77
crisv32_pinmux_set(port);
78
79
spin_unlock_irqrestore(&pinmux_lock, flags);
80
81
return 0;
82
}
83
84
int crisv32_pinmux_alloc_fixed(enum fixed_function function)
85
{
86
int ret = -EINVAL;
87
char saved[sizeof pins];
88
unsigned long flags;
89
90
spin_lock_irqsave(&pinmux_lock, flags);
91
92
/* Save internal data for recovery */
93
memcpy(saved, pins, sizeof pins);
94
95
crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
96
97
reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
98
99
switch (function) {
100
case pinmux_ser1:
101
ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
102
hwprot.ser1 = regk_pinmux_yes;
103
break;
104
case pinmux_ser2:
105
ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
106
hwprot.ser2 = regk_pinmux_yes;
107
break;
108
case pinmux_ser3:
109
ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
110
hwprot.ser3 = regk_pinmux_yes;
111
break;
112
case pinmux_sser0:
113
ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
114
ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
115
hwprot.sser0 = regk_pinmux_yes;
116
break;
117
case pinmux_sser1:
118
ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
119
hwprot.sser1 = regk_pinmux_yes;
120
break;
121
case pinmux_ata0:
122
ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
123
ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
124
hwprot.ata0 = regk_pinmux_yes;
125
break;
126
case pinmux_ata1:
127
ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
128
ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
129
hwprot.ata1 = regk_pinmux_yes;
130
break;
131
case pinmux_ata2:
132
ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
133
ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
134
hwprot.ata2 = regk_pinmux_yes;
135
break;
136
case pinmux_ata3:
137
ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
138
ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
139
hwprot.ata2 = regk_pinmux_yes;
140
break;
141
case pinmux_ata:
142
ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
143
ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
144
hwprot.ata = regk_pinmux_yes;
145
break;
146
case pinmux_eth1:
147
ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
148
hwprot.eth1 = regk_pinmux_yes;
149
hwprot.eth1_mgm = regk_pinmux_yes;
150
break;
151
case pinmux_timer:
152
ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
153
hwprot.timer = regk_pinmux_yes;
154
spin_unlock_irqrestore(&pinmux_lock, flags);
155
return ret;
156
}
157
158
if (!ret)
159
REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
160
else
161
memcpy(pins, saved, sizeof pins);
162
163
spin_unlock_irqrestore(&pinmux_lock, flags);
164
165
return ret;
166
}
167
168
void crisv32_pinmux_set(int port)
169
{
170
int i;
171
int gpio_val = 0;
172
int iop_val = 0;
173
174
for (i = 0; i < PORT_PINS; i++) {
175
if (pins[port][i] == pinmux_gpio)
176
gpio_val |= (1 << i);
177
else if (pins[port][i] == pinmux_iop)
178
iop_val |= (1 << i);
179
}
180
181
REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8 * port,
182
gpio_val);
183
REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8 * port,
184
iop_val);
185
186
#ifdef DEBUG
187
crisv32_pinmux_dump();
188
#endif
189
}
190
191
int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
192
{
193
int i;
194
unsigned long flags;
195
196
crisv32_pinmux_init();
197
198
if (port > PORTS || port < 0)
199
return -EINVAL;
200
201
spin_lock_irqsave(&pinmux_lock, flags);
202
203
for (i = first_pin; i <= last_pin; i++)
204
pins[port][i] = pinmux_none;
205
206
crisv32_pinmux_set(port);
207
spin_unlock_irqrestore(&pinmux_lock, flags);
208
209
return 0;
210
}
211
212
int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
213
{
214
int ret = -EINVAL;
215
char saved[sizeof pins];
216
unsigned long flags;
217
218
spin_lock_irqsave(&pinmux_lock, flags);
219
220
/* Save internal data for recovery */
221
memcpy(saved, pins, sizeof pins);
222
223
crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
224
225
reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
226
227
switch (function) {
228
case pinmux_ser1:
229
ret = crisv32_pinmux_dealloc(PORT_C, 4, 7);
230
hwprot.ser1 = regk_pinmux_no;
231
break;
232
case pinmux_ser2:
233
ret = crisv32_pinmux_dealloc(PORT_C, 8, 11);
234
hwprot.ser2 = regk_pinmux_no;
235
break;
236
case pinmux_ser3:
237
ret = crisv32_pinmux_dealloc(PORT_C, 12, 15);
238
hwprot.ser3 = regk_pinmux_no;
239
break;
240
case pinmux_sser0:
241
ret = crisv32_pinmux_dealloc(PORT_C, 0, 3);
242
ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16);
243
hwprot.sser0 = regk_pinmux_no;
244
break;
245
case pinmux_sser1:
246
ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
247
hwprot.sser1 = regk_pinmux_no;
248
break;
249
case pinmux_ata0:
250
ret = crisv32_pinmux_dealloc(PORT_D, 5, 7);
251
ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17);
252
hwprot.ata0 = regk_pinmux_no;
253
break;
254
case pinmux_ata1:
255
ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
256
ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17);
257
hwprot.ata1 = regk_pinmux_no;
258
break;
259
case pinmux_ata2:
260
ret = crisv32_pinmux_dealloc(PORT_C, 11, 15);
261
ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3);
262
hwprot.ata2 = regk_pinmux_no;
263
break;
264
case pinmux_ata3:
265
ret = crisv32_pinmux_dealloc(PORT_C, 8, 10);
266
ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2);
267
hwprot.ata2 = regk_pinmux_no;
268
break;
269
case pinmux_ata:
270
ret = crisv32_pinmux_dealloc(PORT_B, 0, 15);
271
ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15);
272
hwprot.ata = regk_pinmux_no;
273
break;
274
case pinmux_eth1:
275
ret = crisv32_pinmux_dealloc(PORT_E, 0, 17);
276
hwprot.eth1 = regk_pinmux_no;
277
hwprot.eth1_mgm = regk_pinmux_no;
278
break;
279
case pinmux_timer:
280
ret = crisv32_pinmux_dealloc(PORT_C, 16, 16);
281
hwprot.timer = regk_pinmux_no;
282
spin_unlock_irqrestore(&pinmux_lock, flags);
283
return ret;
284
}
285
286
if (!ret)
287
REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
288
else
289
memcpy(pins, saved, sizeof pins);
290
291
spin_unlock_irqrestore(&pinmux_lock, flags);
292
293
return ret;
294
}
295
296
void crisv32_pinmux_dump(void)
297
{
298
int i, j;
299
300
crisv32_pinmux_init();
301
302
for (i = 0; i < PORTS; i++) {
303
printk(KERN_DEBUG "Port %c\n", 'B' + i);
304
for (j = 0; j < PORT_PINS; j++)
305
printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
306
}
307
}
308
309
__initcall(crisv32_pinmux_init);
310
311