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