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 
crisv32_pinmux_init(void)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
crisv32_pinmux_alloc(int port,int first_pin,int last_pin,enum pin_mode mode)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 
crisv32_pinmux_alloc_fixed(enum fixed_function function)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 
crisv32_pinmux_set(int port)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 
crisv32_pinmux_dealloc(int port,int first_pin,int last_pin)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 
crisv32_pinmux_dealloc_fixed(enum fixed_function function)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 
crisv32_pinmux_dump(void)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