Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/cris/arch-v32/mach-a3/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) 2005-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
#include <hwregs/clkgen_defs.h>
19
20
#undef DEBUG
21
22
#define PINS 80
23
#define PORT_PINS 32
24
#define PORTS 3
25
26
static char pins[PINS];
27
static DEFINE_SPINLOCK(pinmux_lock);
28
29
static void crisv32_pinmux_set(int port);
30
31
int
32
crisv32_pinmux_init(void)
33
{
34
static int initialized;
35
36
if (!initialized) {
37
initialized = 1;
38
REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
39
crisv32_pinmux_alloc(PORT_A, 0, 31, pinmux_gpio);
40
crisv32_pinmux_alloc(PORT_B, 0, 31, pinmux_gpio);
41
crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_gpio);
42
}
43
44
return 0;
45
}
46
47
int
48
crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
49
{
50
int i;
51
unsigned long flags;
52
53
crisv32_pinmux_init();
54
55
if (port >= PORTS)
56
return -EINVAL;
57
58
spin_lock_irqsave(&pinmux_lock, flags);
59
60
for (i = first_pin; i <= last_pin; i++) {
61
if ((pins[port * PORT_PINS + i] != pinmux_none) &&
62
(pins[port * PORT_PINS + i] != pinmux_gpio) &&
63
(pins[port * PORT_PINS + i] != mode)) {
64
spin_unlock_irqrestore(&pinmux_lock, flags);
65
#ifdef DEBUG
66
panic("Pinmux alloc failed!\n");
67
#endif
68
return -EPERM;
69
}
70
}
71
72
for (i = first_pin; i <= last_pin; i++)
73
pins[port * PORT_PINS + i] = mode;
74
75
crisv32_pinmux_set(port);
76
77
spin_unlock_irqrestore(&pinmux_lock, flags);
78
79
return 0;
80
}
81
82
int
83
crisv32_pinmux_alloc_fixed(enum fixed_function function)
84
{
85
int ret = -EINVAL;
86
char saved[sizeof pins];
87
unsigned long flags;
88
89
spin_lock_irqsave(&pinmux_lock, flags);
90
91
/* Save internal data for recovery */
92
memcpy(saved, pins, sizeof pins);
93
94
crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
95
96
reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
97
reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
98
rw_clk_ctrl);
99
100
switch (function) {
101
case pinmux_eth:
102
clk_ctrl.eth = regk_clkgen_yes;
103
clk_ctrl.dma0_1_eth = regk_clkgen_yes;
104
ret = crisv32_pinmux_alloc(PORT_B, 8, 23, pinmux_fixed);
105
ret |= crisv32_pinmux_alloc(PORT_B, 24, 25, pinmux_fixed);
106
hwprot.eth = hwprot.eth_mdio = regk_pinmux_yes;
107
break;
108
case pinmux_geth:
109
ret = crisv32_pinmux_alloc(PORT_B, 0, 7, pinmux_fixed);
110
hwprot.geth = regk_pinmux_yes;
111
break;
112
case pinmux_tg_cmos:
113
clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
114
ret = crisv32_pinmux_alloc(PORT_B, 27, 29, pinmux_fixed);
115
hwprot.tg_clk = regk_pinmux_yes;
116
break;
117
case pinmux_tg_ccd:
118
clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
119
ret = crisv32_pinmux_alloc(PORT_B, 27, 31, pinmux_fixed);
120
ret |= crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_fixed);
121
hwprot.tg = hwprot.tg_clk = regk_pinmux_yes;
122
break;
123
case pinmux_vout:
124
clk_ctrl.strdma0_2_video = regk_clkgen_yes;
125
ret = crisv32_pinmux_alloc(PORT_A, 8, 18, pinmux_fixed);
126
hwprot.vout = hwprot.vout_sync = regk_pinmux_yes;
127
break;
128
case pinmux_ser1:
129
clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
130
ret = crisv32_pinmux_alloc(PORT_A, 24, 25, pinmux_fixed);
131
hwprot.ser1 = regk_pinmux_yes;
132
break;
133
case pinmux_ser2:
134
clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
135
ret = crisv32_pinmux_alloc(PORT_A, 26, 27, pinmux_fixed);
136
hwprot.ser2 = regk_pinmux_yes;
137
break;
138
case pinmux_ser3:
139
clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
140
ret = crisv32_pinmux_alloc(PORT_A, 28, 29, pinmux_fixed);
141
hwprot.ser3 = regk_pinmux_yes;
142
break;
143
case pinmux_ser4:
144
clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
145
ret = crisv32_pinmux_alloc(PORT_A, 30, 31, pinmux_fixed);
146
hwprot.ser4 = regk_pinmux_yes;
147
break;
148
case pinmux_sser:
149
clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
150
ret = crisv32_pinmux_alloc(PORT_A, 19, 23, pinmux_fixed);
151
hwprot.sser = regk_pinmux_yes;
152
break;
153
case pinmux_pio:
154
hwprot.pio = regk_pinmux_yes;
155
ret = 0;
156
break;
157
case pinmux_pwm0:
158
ret = crisv32_pinmux_alloc(PORT_A, 30, 30, pinmux_fixed);
159
hwprot.pwm0 = regk_pinmux_yes;
160
break;
161
case pinmux_pwm1:
162
ret = crisv32_pinmux_alloc(PORT_A, 31, 31, pinmux_fixed);
163
hwprot.pwm1 = regk_pinmux_yes;
164
break;
165
case pinmux_pwm2:
166
ret = crisv32_pinmux_alloc(PORT_B, 26, 26, pinmux_fixed);
167
hwprot.pwm2 = regk_pinmux_yes;
168
break;
169
case pinmux_i2c0:
170
ret = crisv32_pinmux_alloc(PORT_A, 0, 1, pinmux_fixed);
171
hwprot.i2c0 = regk_pinmux_yes;
172
break;
173
case pinmux_i2c1:
174
ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
175
hwprot.i2c1 = regk_pinmux_yes;
176
break;
177
case pinmux_i2c1_3wire:
178
ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
179
ret |= crisv32_pinmux_alloc(PORT_A, 7, 7, pinmux_fixed);
180
hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_yes;
181
break;
182
case pinmux_i2c1_sda1:
183
ret = crisv32_pinmux_alloc(PORT_A, 2, 4, pinmux_fixed);
184
hwprot.i2c1 = hwprot.i2c1_sda1 = regk_pinmux_yes;
185
break;
186
case pinmux_i2c1_sda2:
187
ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
188
ret |= crisv32_pinmux_alloc(PORT_A, 5, 5, pinmux_fixed);
189
hwprot.i2c1 = hwprot.i2c1_sda2 = regk_pinmux_yes;
190
break;
191
case pinmux_i2c1_sda3:
192
ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
193
ret |= crisv32_pinmux_alloc(PORT_A, 6, 6, pinmux_fixed);
194
hwprot.i2c1 = hwprot.i2c1_sda3 = regk_pinmux_yes;
195
break;
196
default:
197
ret = -EINVAL;
198
break;
199
}
200
201
if (!ret) {
202
REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
203
REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
204
} else
205
memcpy(pins, saved, sizeof pins);
206
207
spin_unlock_irqrestore(&pinmux_lock, flags);
208
209
return ret;
210
}
211
212
void
213
crisv32_pinmux_set(int port)
214
{
215
int i;
216
int gpio_val = 0;
217
int iop_val = 0;
218
int pin = port * PORT_PINS;
219
220
for (i = 0; (i < PORT_PINS) && (pin < PINS); i++, pin++) {
221
if (pins[pin] == pinmux_gpio)
222
gpio_val |= (1 << i);
223
else if (pins[pin] == pinmux_iop)
224
iop_val |= (1 << i);
225
}
226
227
REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_gio_pa + 4 * port,
228
gpio_val);
229
REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_iop_pa + 4 * port,
230
iop_val);
231
232
#ifdef DEBUG
233
crisv32_pinmux_dump();
234
#endif
235
}
236
237
int
238
crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
239
{
240
int i;
241
unsigned long flags;
242
243
crisv32_pinmux_init();
244
245
if (port > PORTS || port < 0)
246
return -EINVAL;
247
248
spin_lock_irqsave(&pinmux_lock, flags);
249
250
for (i = first_pin; i <= last_pin; i++)
251
pins[port * PORT_PINS + i] = pinmux_none;
252
253
crisv32_pinmux_set(port);
254
spin_unlock_irqrestore(&pinmux_lock, flags);
255
256
return 0;
257
}
258
259
int
260
crisv32_pinmux_dealloc_fixed(enum fixed_function function)
261
{
262
int ret = -EINVAL;
263
char saved[sizeof pins];
264
unsigned long flags;
265
266
spin_lock_irqsave(&pinmux_lock, flags);
267
268
/* Save internal data for recovery */
269
memcpy(saved, pins, sizeof pins);
270
271
crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
272
273
reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
274
275
switch (function) {
276
case pinmux_eth:
277
ret = crisv32_pinmux_dealloc(PORT_B, 8, 23);
278
ret |= crisv32_pinmux_dealloc(PORT_B, 24, 25);
279
ret |= crisv32_pinmux_dealloc(PORT_B, 0, 7);
280
hwprot.eth = hwprot.eth_mdio = hwprot.geth = regk_pinmux_no;
281
break;
282
case pinmux_tg_cmos:
283
ret = crisv32_pinmux_dealloc(PORT_B, 27, 29);
284
hwprot.tg_clk = regk_pinmux_no;
285
break;
286
case pinmux_tg_ccd:
287
ret = crisv32_pinmux_dealloc(PORT_B, 27, 31);
288
ret |= crisv32_pinmux_dealloc(PORT_C, 0, 15);
289
hwprot.tg = hwprot.tg_clk = regk_pinmux_no;
290
break;
291
case pinmux_vout:
292
ret = crisv32_pinmux_dealloc(PORT_A, 8, 18);
293
hwprot.vout = hwprot.vout_sync = regk_pinmux_no;
294
break;
295
case pinmux_ser1:
296
ret = crisv32_pinmux_dealloc(PORT_A, 24, 25);
297
hwprot.ser1 = regk_pinmux_no;
298
break;
299
case pinmux_ser2:
300
ret = crisv32_pinmux_dealloc(PORT_A, 26, 27);
301
hwprot.ser2 = regk_pinmux_no;
302
break;
303
case pinmux_ser3:
304
ret = crisv32_pinmux_dealloc(PORT_A, 28, 29);
305
hwprot.ser3 = regk_pinmux_no;
306
break;
307
case pinmux_ser4:
308
ret = crisv32_pinmux_dealloc(PORT_A, 30, 31);
309
hwprot.ser4 = regk_pinmux_no;
310
break;
311
case pinmux_sser:
312
ret = crisv32_pinmux_dealloc(PORT_A, 19, 23);
313
hwprot.sser = regk_pinmux_no;
314
break;
315
case pinmux_pwm0:
316
ret = crisv32_pinmux_dealloc(PORT_A, 30, 30);
317
hwprot.pwm0 = regk_pinmux_no;
318
break;
319
case pinmux_pwm1:
320
ret = crisv32_pinmux_dealloc(PORT_A, 31, 31);
321
hwprot.pwm1 = regk_pinmux_no;
322
break;
323
case pinmux_pwm2:
324
ret = crisv32_pinmux_dealloc(PORT_B, 26, 26);
325
hwprot.pwm2 = regk_pinmux_no;
326
break;
327
case pinmux_i2c0:
328
ret = crisv32_pinmux_dealloc(PORT_A, 0, 1);
329
hwprot.i2c0 = regk_pinmux_no;
330
break;
331
case pinmux_i2c1:
332
ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
333
hwprot.i2c1 = regk_pinmux_no;
334
break;
335
case pinmux_i2c1_3wire:
336
ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
337
ret |= crisv32_pinmux_dealloc(PORT_A, 7, 7);
338
hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_no;
339
break;
340
case pinmux_i2c1_sda1:
341
ret = crisv32_pinmux_dealloc(PORT_A, 2, 4);
342
hwprot.i2c1_sda1 = regk_pinmux_no;
343
break;
344
case pinmux_i2c1_sda2:
345
ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
346
ret |= crisv32_pinmux_dealloc(PORT_A, 5, 5);
347
hwprot.i2c1_sda2 = regk_pinmux_no;
348
break;
349
case pinmux_i2c1_sda3:
350
ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
351
ret |= crisv32_pinmux_dealloc(PORT_A, 6, 6);
352
hwprot.i2c1_sda3 = regk_pinmux_no;
353
break;
354
default:
355
ret = -EINVAL;
356
break;
357
}
358
359
if (!ret)
360
REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
361
else
362
memcpy(pins, saved, sizeof pins);
363
364
spin_unlock_irqrestore(&pinmux_lock, flags);
365
366
return ret;
367
}
368
369
void
370
crisv32_pinmux_dump(void)
371
{
372
int i, j;
373
int pin = 0;
374
375
crisv32_pinmux_init();
376
377
for (i = 0; i < PORTS; i++) {
378
pin++;
379
printk(KERN_DEBUG "Port %c\n", 'A'+i);
380
for (j = 0; (j < PORT_PINS) && (pin < PINS); j++, pin++)
381
printk(KERN_DEBUG
382
" Pin %d = %d\n", j, pins[i * PORT_PINS + j]);
383
}
384
}
385
386
__initcall(crisv32_pinmux_init);
387
388