Commit a3199ad9 authored by Jesper Nilsson's avatar Jesper Nilsson

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: default avatarJesper Nilsson <jesper.nilsson@axis.com>
parent 9f1ad51b
...@@ -26,7 +26,29 @@ static DEFINE_SPINLOCK(pinmux_lock); ...@@ -26,7 +26,29 @@ static DEFINE_SPINLOCK(pinmux_lock);
static void crisv32_pinmux_set(int port); static void crisv32_pinmux_set(int port);
int crisv32_pinmux_init(void) static int __crisv32_pinmux_alloc(int port, int first_pin, int last_pin,
enum pin_mode mode)
{
int i;
for (i = first_pin; i <= last_pin; i++) {
if ((pins[port][i] != pinmux_none)
&& (pins[port][i] != pinmux_gpio)
&& (pins[port][i] != mode)) {
#ifdef DEBUG
panic("Pinmux alloc failed!\n");
#endif
return -EPERM;
}
}
for (i = first_pin; i <= last_pin; i++)
pins[port][i] = mode;
crisv32_pinmux_set(port);
}
static int crisv32_pinmux_init(void)
{ {
static int initialized; static int initialized;
...@@ -37,20 +59,20 @@ int crisv32_pinmux_init(void) ...@@ -37,20 +59,20 @@ int crisv32_pinmux_init(void)
pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 = pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes; pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
REG_WR(pinmux, regi_pinmux, rw_pa, pa); REG_WR(pinmux, regi_pinmux, rw_pa, pa);
crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio); __crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio); __crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio); __crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio); __crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
} }
return 0; return 0;
} }
int int crisv32_pinmux_alloc(int port, int first_pin, int last_pin,
crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode) enum pin_mode mode)
{ {
int i;
unsigned long flags; unsigned long flags;
int ret;
crisv32_pinmux_init(); crisv32_pinmux_init();
...@@ -59,26 +81,11 @@ crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode) ...@@ -59,26 +81,11 @@ crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
spin_lock_irqsave(&pinmux_lock, flags); spin_lock_irqsave(&pinmux_lock, flags);
for (i = first_pin; i <= last_pin; i++) { ret = __crisv32_pinmux_alloc(port, first_pin, last_pin, mode);
if ((pins[port][i] != pinmux_none)
&& (pins[port][i] != pinmux_gpio)
&& (pins[port][i] != mode)) {
spin_unlock_irqrestore(&pinmux_lock, flags);
#ifdef DEBUG
panic("Pinmux alloc failed!\n");
#endif
return -EPERM;
}
}
for (i = first_pin; i <= last_pin; i++)
pins[port][i] = mode;
crisv32_pinmux_set(port);
spin_unlock_irqrestore(&pinmux_lock, flags); spin_unlock_irqrestore(&pinmux_lock, flags);
return 0; return ret;
} }
int crisv32_pinmux_alloc_fixed(enum fixed_function function) int crisv32_pinmux_alloc_fixed(enum fixed_function function)
...@@ -98,58 +105,58 @@ int crisv32_pinmux_alloc_fixed(enum fixed_function function) ...@@ -98,58 +105,58 @@ int crisv32_pinmux_alloc_fixed(enum fixed_function function)
switch (function) { switch (function) {
case pinmux_ser1: case pinmux_ser1:
ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
hwprot.ser1 = regk_pinmux_yes; hwprot.ser1 = regk_pinmux_yes;
break; break;
case pinmux_ser2: case pinmux_ser2:
ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
hwprot.ser2 = regk_pinmux_yes; hwprot.ser2 = regk_pinmux_yes;
break; break;
case pinmux_ser3: case pinmux_ser3:
ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
hwprot.ser3 = regk_pinmux_yes; hwprot.ser3 = regk_pinmux_yes;
break; break;
case pinmux_sser0: case pinmux_sser0:
ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); ret |= __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
hwprot.sser0 = regk_pinmux_yes; hwprot.sser0 = regk_pinmux_yes;
break; break;
case pinmux_sser1: case pinmux_sser1:
ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
hwprot.sser1 = regk_pinmux_yes; hwprot.sser1 = regk_pinmux_yes;
break; break;
case pinmux_ata0: case pinmux_ata0:
ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed); ret |= __crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
hwprot.ata0 = regk_pinmux_yes; hwprot.ata0 = regk_pinmux_yes;
break; break;
case pinmux_ata1: case pinmux_ata1:
ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed); ret |= __crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
hwprot.ata1 = regk_pinmux_yes; hwprot.ata1 = regk_pinmux_yes;
break; break;
case pinmux_ata2: case pinmux_ata2:
ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed); ret |= __crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
hwprot.ata2 = regk_pinmux_yes; hwprot.ata2 = regk_pinmux_yes;
break; break;
case pinmux_ata3: case pinmux_ata3:
ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed); ret |= __crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
hwprot.ata2 = regk_pinmux_yes; hwprot.ata2 = regk_pinmux_yes;
break; break;
case pinmux_ata: case pinmux_ata:
ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed); ret |= __crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
hwprot.ata = regk_pinmux_yes; hwprot.ata = regk_pinmux_yes;
break; break;
case pinmux_eth1: case pinmux_eth1:
ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
hwprot.eth1 = regk_pinmux_yes; hwprot.eth1 = regk_pinmux_yes;
hwprot.eth1_mgm = regk_pinmux_yes; hwprot.eth1_mgm = regk_pinmux_yes;
break; break;
case pinmux_timer: case pinmux_timer:
ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); ret = __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
hwprot.timer = regk_pinmux_yes; hwprot.timer = regk_pinmux_yes;
spin_unlock_irqrestore(&pinmux_lock, flags); spin_unlock_irqrestore(&pinmux_lock, flags);
return ret; return ret;
...@@ -188,9 +195,19 @@ void crisv32_pinmux_set(int port) ...@@ -188,9 +195,19 @@ void crisv32_pinmux_set(int port)
#endif #endif
} }
int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) static int __crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
{ {
int i; int i;
for (i = first_pin; i <= last_pin; i++)
pins[port][i] = pinmux_none;
crisv32_pinmux_set(port);
return 0;
}
int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
{
unsigned long flags; unsigned long flags;
crisv32_pinmux_init(); crisv32_pinmux_init();
...@@ -199,11 +216,7 @@ int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) ...@@ -199,11 +216,7 @@ int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pinmux_lock, flags); spin_lock_irqsave(&pinmux_lock, flags);
__crisv32_pinmux_dealloc(port, first_pin, last_pin);
for (i = first_pin; i <= last_pin; i++)
pins[port][i] = pinmux_none;
crisv32_pinmux_set(port);
spin_unlock_irqrestore(&pinmux_lock, flags); spin_unlock_irqrestore(&pinmux_lock, flags);
return 0; return 0;
...@@ -226,58 +239,58 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function) ...@@ -226,58 +239,58 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
switch (function) { switch (function) {
case pinmux_ser1: case pinmux_ser1:
ret = crisv32_pinmux_dealloc(PORT_C, 4, 7); ret = __crisv32_pinmux_dealloc(PORT_C, 4, 7);
hwprot.ser1 = regk_pinmux_no; hwprot.ser1 = regk_pinmux_no;
break; break;
case pinmux_ser2: case pinmux_ser2:
ret = crisv32_pinmux_dealloc(PORT_C, 8, 11); ret = __crisv32_pinmux_dealloc(PORT_C, 8, 11);
hwprot.ser2 = regk_pinmux_no; hwprot.ser2 = regk_pinmux_no;
break; break;
case pinmux_ser3: case pinmux_ser3:
ret = crisv32_pinmux_dealloc(PORT_C, 12, 15); ret = __crisv32_pinmux_dealloc(PORT_C, 12, 15);
hwprot.ser3 = regk_pinmux_no; hwprot.ser3 = regk_pinmux_no;
break; break;
case pinmux_sser0: case pinmux_sser0:
ret = crisv32_pinmux_dealloc(PORT_C, 0, 3); ret = __crisv32_pinmux_dealloc(PORT_C, 0, 3);
ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16); ret |= __crisv32_pinmux_dealloc(PORT_C, 16, 16);
hwprot.sser0 = regk_pinmux_no; hwprot.sser0 = regk_pinmux_no;
break; break;
case pinmux_sser1: case pinmux_sser1:
ret = crisv32_pinmux_dealloc(PORT_D, 0, 4); ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4);
hwprot.sser1 = regk_pinmux_no; hwprot.sser1 = regk_pinmux_no;
break; break;
case pinmux_ata0: case pinmux_ata0:
ret = crisv32_pinmux_dealloc(PORT_D, 5, 7); ret = __crisv32_pinmux_dealloc(PORT_D, 5, 7);
ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17); ret |= __crisv32_pinmux_dealloc(PORT_D, 15, 17);
hwprot.ata0 = regk_pinmux_no; hwprot.ata0 = regk_pinmux_no;
break; break;
case pinmux_ata1: case pinmux_ata1:
ret = crisv32_pinmux_dealloc(PORT_D, 0, 4); ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4);
ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17); ret |= __crisv32_pinmux_dealloc(PORT_E, 17, 17);
hwprot.ata1 = regk_pinmux_no; hwprot.ata1 = regk_pinmux_no;
break; break;
case pinmux_ata2: case pinmux_ata2:
ret = crisv32_pinmux_dealloc(PORT_C, 11, 15); ret = __crisv32_pinmux_dealloc(PORT_C, 11, 15);
ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3); ret |= __crisv32_pinmux_dealloc(PORT_E, 3, 3);
hwprot.ata2 = regk_pinmux_no; hwprot.ata2 = regk_pinmux_no;
break; break;
case pinmux_ata3: case pinmux_ata3:
ret = crisv32_pinmux_dealloc(PORT_C, 8, 10); ret = __crisv32_pinmux_dealloc(PORT_C, 8, 10);
ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2); ret |= __crisv32_pinmux_dealloc(PORT_C, 0, 2);
hwprot.ata2 = regk_pinmux_no; hwprot.ata2 = regk_pinmux_no;
break; break;
case pinmux_ata: case pinmux_ata:
ret = crisv32_pinmux_dealloc(PORT_B, 0, 15); ret = __crisv32_pinmux_dealloc(PORT_B, 0, 15);
ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15); ret |= __crisv32_pinmux_dealloc(PORT_D, 8, 15);
hwprot.ata = regk_pinmux_no; hwprot.ata = regk_pinmux_no;
break; break;
case pinmux_eth1: case pinmux_eth1:
ret = crisv32_pinmux_dealloc(PORT_E, 0, 17); ret = __crisv32_pinmux_dealloc(PORT_E, 0, 17);
hwprot.eth1 = regk_pinmux_no; hwprot.eth1 = regk_pinmux_no;
hwprot.eth1_mgm = regk_pinmux_no; hwprot.eth1_mgm = regk_pinmux_no;
break; break;
case pinmux_timer: case pinmux_timer:
ret = crisv32_pinmux_dealloc(PORT_C, 16, 16); ret = __crisv32_pinmux_dealloc(PORT_C, 16, 16);
hwprot.timer = regk_pinmux_no; hwprot.timer = regk_pinmux_no;
spin_unlock_irqrestore(&pinmux_lock, flags); spin_unlock_irqrestore(&pinmux_lock, flags);
return ret; return ret;
...@@ -293,7 +306,8 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function) ...@@ -293,7 +306,8 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
return ret; return ret;
} }
void crisv32_pinmux_dump(void) #ifdef DEBUG
static void crisv32_pinmux_dump(void)
{ {
int i, j; int i, j;
...@@ -305,5 +319,5 @@ void crisv32_pinmux_dump(void) ...@@ -305,5 +319,5 @@ void crisv32_pinmux_dump(void)
printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]); printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
} }
} }
#endif
__initcall(crisv32_pinmux_init); __initcall(crisv32_pinmux_init);
...@@ -28,11 +28,9 @@ enum fixed_function { ...@@ -28,11 +28,9 @@ enum fixed_function {
pinmux_timer pinmux_timer
}; };
int crisv32_pinmux_init(void);
int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode); int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode);
int crisv32_pinmux_alloc_fixed(enum fixed_function function); int crisv32_pinmux_alloc_fixed(enum fixed_function function);
int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin); int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin);
int crisv32_pinmux_dealloc_fixed(enum fixed_function function); int crisv32_pinmux_dealloc_fixed(enum fixed_function function);
void crisv32_pinmux_dump(void);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment