aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris
diff options
context:
space:
mode:
authorJesper Nilsson <jespern@axis.com>2014-10-27 04:11:31 -0400
committerJesper Nilsson <jespern@axis.com>2014-12-19 18:06:04 -0500
commita3199ad90ac33c1afae0fa3dbf2e0fe4ee827fa7 (patch)
treee3f1feb76da1db3d59351ed2c19707bed2855882 /arch/cris
parent9f1ad51b32173a2da3c4fab58bc4f87d6094868f (diff)
CRISv32: ETRAXFS: Fix recursive spinlock
Move pinmux alloc/dealloc code into functions that don't take the spinlock so we can use from code that has the spinlock already. CRISv32 has no working SMP, so spinlocks becomes a NOP, so deadlock was never seen. Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
Diffstat (limited to 'arch/cris')
-rw-r--r--arch/cris/arch-v32/mach-fs/pinmux.c152
-rw-r--r--arch/cris/include/arch-v32/mach-fs/mach/pinmux.h2
2 files changed, 83 insertions, 71 deletions
diff --git a/arch/cris/arch-v32/mach-fs/pinmux.c b/arch/cris/arch-v32/mach-fs/pinmux.c
index 38f29eec14a6..05a04708b8eb 100644
--- a/arch/cris/arch-v32/mach-fs/pinmux.c
+++ b/arch/cris/arch-v32/mach-fs/pinmux.c
@@ -26,7 +26,29 @@ static DEFINE_SPINLOCK(pinmux_lock);
26 26
27static void crisv32_pinmux_set(int port); 27static void crisv32_pinmux_set(int port);
28 28
29int crisv32_pinmux_init(void) 29static int __crisv32_pinmux_alloc(int port, int first_pin, int last_pin,
30 enum pin_mode mode)
31{
32 int i;
33
34 for (i = first_pin; i <= last_pin; i++) {
35 if ((pins[port][i] != pinmux_none)
36 && (pins[port][i] != pinmux_gpio)
37 && (pins[port][i] != mode)) {
38#ifdef DEBUG
39 panic("Pinmux alloc failed!\n");
40#endif
41 return -EPERM;
42 }
43 }
44
45 for (i = first_pin; i <= last_pin; i++)
46 pins[port][i] = mode;
47
48 crisv32_pinmux_set(port);
49}
50
51static int crisv32_pinmux_init(void)
30{ 52{
31 static int initialized; 53 static int initialized;
32 54
@@ -37,20 +59,20 @@ int crisv32_pinmux_init(void)
37 pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 = 59 pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
38 pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes; 60 pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
39 REG_WR(pinmux, regi_pinmux, rw_pa, pa); 61 REG_WR(pinmux, regi_pinmux, rw_pa, pa);
40 crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio); 62 __crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
41 crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio); 63 __crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
42 crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio); 64 __crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
43 crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio); 65 __crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
44 } 66 }
45 67
46 return 0; 68 return 0;
47} 69}
48 70
49int 71int crisv32_pinmux_alloc(int port, int first_pin, int last_pin,
50crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode) 72 enum pin_mode mode)
51{ 73{
52 int i;
53 unsigned long flags; 74 unsigned long flags;
75 int ret;
54 76
55 crisv32_pinmux_init(); 77 crisv32_pinmux_init();
56 78
@@ -59,26 +81,11 @@ crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
59 81
60 spin_lock_irqsave(&pinmux_lock, flags); 82 spin_lock_irqsave(&pinmux_lock, flags);
61 83
62 for (i = first_pin; i <= last_pin; i++) { 84 ret = __crisv32_pinmux_alloc(port, first_pin, last_pin, mode);
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 85
79 spin_unlock_irqrestore(&pinmux_lock, flags); 86 spin_unlock_irqrestore(&pinmux_lock, flags);
80 87
81 return 0; 88 return ret;
82} 89}
83 90
84int crisv32_pinmux_alloc_fixed(enum fixed_function function) 91int crisv32_pinmux_alloc_fixed(enum fixed_function function)
@@ -98,58 +105,58 @@ int crisv32_pinmux_alloc_fixed(enum fixed_function function)
98 105
99 switch (function) { 106 switch (function) {
100 case pinmux_ser1: 107 case pinmux_ser1:
101 ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed); 108 ret = __crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
102 hwprot.ser1 = regk_pinmux_yes; 109 hwprot.ser1 = regk_pinmux_yes;
103 break; 110 break;
104 case pinmux_ser2: 111 case pinmux_ser2:
105 ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed); 112 ret = __crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
106 hwprot.ser2 = regk_pinmux_yes; 113 hwprot.ser2 = regk_pinmux_yes;
107 break; 114 break;
108 case pinmux_ser3: 115 case pinmux_ser3:
109 ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed); 116 ret = __crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
110 hwprot.ser3 = regk_pinmux_yes; 117 hwprot.ser3 = regk_pinmux_yes;
111 break; 118 break;
112 case pinmux_sser0: 119 case pinmux_sser0:
113 ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed); 120 ret = __crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
114 ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); 121 ret |= __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
115 hwprot.sser0 = regk_pinmux_yes; 122 hwprot.sser0 = regk_pinmux_yes;
116 break; 123 break;
117 case pinmux_sser1: 124 case pinmux_sser1:
118 ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); 125 ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
119 hwprot.sser1 = regk_pinmux_yes; 126 hwprot.sser1 = regk_pinmux_yes;
120 break; 127 break;
121 case pinmux_ata0: 128 case pinmux_ata0:
122 ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed); 129 ret = __crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
123 ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed); 130 ret |= __crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
124 hwprot.ata0 = regk_pinmux_yes; 131 hwprot.ata0 = regk_pinmux_yes;
125 break; 132 break;
126 case pinmux_ata1: 133 case pinmux_ata1:
127 ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); 134 ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
128 ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed); 135 ret |= __crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
129 hwprot.ata1 = regk_pinmux_yes; 136 hwprot.ata1 = regk_pinmux_yes;
130 break; 137 break;
131 case pinmux_ata2: 138 case pinmux_ata2:
132 ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed); 139 ret = __crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
133 ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed); 140 ret |= __crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
134 hwprot.ata2 = regk_pinmux_yes; 141 hwprot.ata2 = regk_pinmux_yes;
135 break; 142 break;
136 case pinmux_ata3: 143 case pinmux_ata3:
137 ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed); 144 ret = __crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
138 ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed); 145 ret |= __crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
139 hwprot.ata2 = regk_pinmux_yes; 146 hwprot.ata2 = regk_pinmux_yes;
140 break; 147 break;
141 case pinmux_ata: 148 case pinmux_ata:
142 ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed); 149 ret = __crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
143 ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed); 150 ret |= __crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
144 hwprot.ata = regk_pinmux_yes; 151 hwprot.ata = regk_pinmux_yes;
145 break; 152 break;
146 case pinmux_eth1: 153 case pinmux_eth1:
147 ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed); 154 ret = __crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
148 hwprot.eth1 = regk_pinmux_yes; 155 hwprot.eth1 = regk_pinmux_yes;
149 hwprot.eth1_mgm = regk_pinmux_yes; 156 hwprot.eth1_mgm = regk_pinmux_yes;
150 break; 157 break;
151 case pinmux_timer: 158 case pinmux_timer:
152 ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); 159 ret = __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
153 hwprot.timer = regk_pinmux_yes; 160 hwprot.timer = regk_pinmux_yes;
154 spin_unlock_irqrestore(&pinmux_lock, flags); 161 spin_unlock_irqrestore(&pinmux_lock, flags);
155 return ret; 162 return ret;
@@ -188,9 +195,19 @@ void crisv32_pinmux_set(int port)
188#endif 195#endif
189} 196}
190 197
191int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) 198static int __crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
192{ 199{
193 int i; 200 int i;
201
202 for (i = first_pin; i <= last_pin; i++)
203 pins[port][i] = pinmux_none;
204
205 crisv32_pinmux_set(port);
206 return 0;
207}
208
209int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
210{
194 unsigned long flags; 211 unsigned long flags;
195 212
196 crisv32_pinmux_init(); 213 crisv32_pinmux_init();
@@ -199,11 +216,7 @@ int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
199 return -EINVAL; 216 return -EINVAL;
200 217
201 spin_lock_irqsave(&pinmux_lock, flags); 218 spin_lock_irqsave(&pinmux_lock, flags);
202 219 __crisv32_pinmux_dealloc(port, first_pin, last_pin);
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); 220 spin_unlock_irqrestore(&pinmux_lock, flags);
208 221
209 return 0; 222 return 0;
@@ -226,58 +239,58 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
226 239
227 switch (function) { 240 switch (function) {
228 case pinmux_ser1: 241 case pinmux_ser1:
229 ret = crisv32_pinmux_dealloc(PORT_C, 4, 7); 242 ret = __crisv32_pinmux_dealloc(PORT_C, 4, 7);
230 hwprot.ser1 = regk_pinmux_no; 243 hwprot.ser1 = regk_pinmux_no;
231 break; 244 break;
232 case pinmux_ser2: 245 case pinmux_ser2:
233 ret = crisv32_pinmux_dealloc(PORT_C, 8, 11); 246 ret = __crisv32_pinmux_dealloc(PORT_C, 8, 11);
234 hwprot.ser2 = regk_pinmux_no; 247 hwprot.ser2 = regk_pinmux_no;
235 break; 248 break;
236 case pinmux_ser3: 249 case pinmux_ser3:
237 ret = crisv32_pinmux_dealloc(PORT_C, 12, 15); 250 ret = __crisv32_pinmux_dealloc(PORT_C, 12, 15);
238 hwprot.ser3 = regk_pinmux_no; 251 hwprot.ser3 = regk_pinmux_no;
239 break; 252 break;
240 case pinmux_sser0: 253 case pinmux_sser0:
241 ret = crisv32_pinmux_dealloc(PORT_C, 0, 3); 254 ret = __crisv32_pinmux_dealloc(PORT_C, 0, 3);
242 ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16); 255 ret |= __crisv32_pinmux_dealloc(PORT_C, 16, 16);
243 hwprot.sser0 = regk_pinmux_no; 256 hwprot.sser0 = regk_pinmux_no;
244 break; 257 break;
245 case pinmux_sser1: 258 case pinmux_sser1:
246 ret = crisv32_pinmux_dealloc(PORT_D, 0, 4); 259 ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4);
247 hwprot.sser1 = regk_pinmux_no; 260 hwprot.sser1 = regk_pinmux_no;
248 break; 261 break;
249 case pinmux_ata0: 262 case pinmux_ata0:
250 ret = crisv32_pinmux_dealloc(PORT_D, 5, 7); 263 ret = __crisv32_pinmux_dealloc(PORT_D, 5, 7);
251 ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17); 264 ret |= __crisv32_pinmux_dealloc(PORT_D, 15, 17);
252 hwprot.ata0 = regk_pinmux_no; 265 hwprot.ata0 = regk_pinmux_no;
253 break; 266 break;
254 case pinmux_ata1: 267 case pinmux_ata1:
255 ret = crisv32_pinmux_dealloc(PORT_D, 0, 4); 268 ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4);
256 ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17); 269 ret |= __crisv32_pinmux_dealloc(PORT_E, 17, 17);
257 hwprot.ata1 = regk_pinmux_no; 270 hwprot.ata1 = regk_pinmux_no;
258 break; 271 break;
259 case pinmux_ata2: 272 case pinmux_ata2:
260 ret = crisv32_pinmux_dealloc(PORT_C, 11, 15); 273 ret = __crisv32_pinmux_dealloc(PORT_C, 11, 15);
261 ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3); 274 ret |= __crisv32_pinmux_dealloc(PORT_E, 3, 3);
262 hwprot.ata2 = regk_pinmux_no; 275 hwprot.ata2 = regk_pinmux_no;
263 break; 276 break;
264 case pinmux_ata3: 277 case pinmux_ata3:
265 ret = crisv32_pinmux_dealloc(PORT_C, 8, 10); 278 ret = __crisv32_pinmux_dealloc(PORT_C, 8, 10);
266 ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2); 279 ret |= __crisv32_pinmux_dealloc(PORT_C, 0, 2);
267 hwprot.ata2 = regk_pinmux_no; 280 hwprot.ata2 = regk_pinmux_no;
268 break; 281 break;
269 case pinmux_ata: 282 case pinmux_ata:
270 ret = crisv32_pinmux_dealloc(PORT_B, 0, 15); 283 ret = __crisv32_pinmux_dealloc(PORT_B, 0, 15);
271 ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15); 284 ret |= __crisv32_pinmux_dealloc(PORT_D, 8, 15);
272 hwprot.ata = regk_pinmux_no; 285 hwprot.ata = regk_pinmux_no;
273 break; 286 break;
274 case pinmux_eth1: 287 case pinmux_eth1:
275 ret = crisv32_pinmux_dealloc(PORT_E, 0, 17); 288 ret = __crisv32_pinmux_dealloc(PORT_E, 0, 17);
276 hwprot.eth1 = regk_pinmux_no; 289 hwprot.eth1 = regk_pinmux_no;
277 hwprot.eth1_mgm = regk_pinmux_no; 290 hwprot.eth1_mgm = regk_pinmux_no;
278 break; 291 break;
279 case pinmux_timer: 292 case pinmux_timer:
280 ret = crisv32_pinmux_dealloc(PORT_C, 16, 16); 293 ret = __crisv32_pinmux_dealloc(PORT_C, 16, 16);
281 hwprot.timer = regk_pinmux_no; 294 hwprot.timer = regk_pinmux_no;
282 spin_unlock_irqrestore(&pinmux_lock, flags); 295 spin_unlock_irqrestore(&pinmux_lock, flags);
283 return ret; 296 return ret;
@@ -293,7 +306,8 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
293 return ret; 306 return ret;
294} 307}
295 308
296void crisv32_pinmux_dump(void) 309#ifdef DEBUG
310static void crisv32_pinmux_dump(void)
297{ 311{
298 int i, j; 312 int i, j;
299 313
@@ -305,5 +319,5 @@ void crisv32_pinmux_dump(void)
305 printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]); 319 printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
306 } 320 }
307} 321}
308 322#endif
309__initcall(crisv32_pinmux_init); 323__initcall(crisv32_pinmux_init);
diff --git a/arch/cris/include/arch-v32/mach-fs/mach/pinmux.h b/arch/cris/include/arch-v32/mach-fs/mach/pinmux.h
index c2b3036779df..09bf0c90d2d3 100644
--- a/arch/cris/include/arch-v32/mach-fs/mach/pinmux.h
+++ b/arch/cris/include/arch-v32/mach-fs/mach/pinmux.h
@@ -28,11 +28,9 @@ enum fixed_function {
28 pinmux_timer 28 pinmux_timer
29}; 29};
30 30
31int crisv32_pinmux_init(void);
32int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode); 31int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode);
33int crisv32_pinmux_alloc_fixed(enum fixed_function function); 32int crisv32_pinmux_alloc_fixed(enum fixed_function function);
34int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin); 33int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin);
35int crisv32_pinmux_dealloc_fixed(enum fixed_function function); 34int crisv32_pinmux_dealloc_fixed(enum fixed_function function);
36void crisv32_pinmux_dump(void);
37 35
38#endif 36#endif