Title: [9143] trunk/arch/blackfin/kernel/bfin_gpio.c: [#5155] bfin gpio: add peripheral group check
Revision
9143
Author
steven.miao
Date
2010-09-16 23:03:17 -0400 (Thu, 16 Sep 2010)

Log Message

[#5155] bfin gpio: add peripheral group check

detect periphreral function group conflict for bf51x,bf52x and bf537,
add peripheral pin mux group check function, change port_mux offset look up
table and mux setup method for bf537.

Modified Paths

Diff

Modified: trunk/arch/blackfin/kernel/bfin_gpio.c (9142 => 9143)


--- trunk/arch/blackfin/kernel/bfin_gpio.c	2010-09-16 08:37:37 UTC (rev 9142)
+++ trunk/arch/blackfin/kernel/bfin_gpio.c	2010-09-17 03:03:17 UTC (rev 9143)
@@ -215,75 +215,107 @@
 }
 
 #ifdef BF537_FAMILY
-static struct {
-	unsigned short res;
-	unsigned short offset;
-} port_mux_lut[] = {
-	{.res = P_PPI0_D13, .offset = 11},
-	{.res = P_PPI0_D14, .offset = 11},
-	{.res = P_PPI0_D15, .offset = 11},
-	{.res = P_SPORT1_TFS, .offset = 11},
-	{.res = P_SPORT1_TSCLK, .offset = 11},
-	{.res = P_SPORT1_DTPRI, .offset = 11},
-	{.res = P_PPI0_D10, .offset = 10},
-	{.res = P_PPI0_D11, .offset = 10},
-	{.res = P_PPI0_D12, .offset = 10},
-	{.res = P_SPORT1_RSCLK, .offset = 10},
-	{.res = P_SPORT1_RFS, .offset = 10},
-	{.res = P_SPORT1_DRPRI, .offset = 10},
-	{.res = P_PPI0_D8, .offset = 9},
-	{.res = P_PPI0_D9, .offset = 9},
-	{.res = P_SPORT1_DRSEC, .offset = 9},
-	{.res = P_SPORT1_DTSEC, .offset = 9},
-	{.res = P_TMR2, .offset = 8},
-	{.res = P_PPI0_FS3, .offset = 8},
-	{.res = P_TMR3, .offset = 7},
-	{.res = P_SPI0_SSEL4, .offset = 7},
-	{.res = P_TMR4, .offset = 6},
-	{.res = P_SPI0_SSEL5, .offset = 6},
-	{.res = P_TMR5, .offset = 5},
-	{.res = P_SPI0_SSEL6, .offset = 5},
-	{.res = P_UART1_RX, .offset = 4},
-	{.res = P_UART1_TX, .offset = 4},
-	{.res = P_TMR6, .offset = 4},
-	{.res = P_TMR7, .offset = 4},
-	{.res = P_UART0_RX, .offset = 3},
-	{.res = P_UART0_TX, .offset = 3},
-	{.res = P_DMAR0, .offset = 3},
-	{.res = P_DMAR1, .offset = 3},
-	{.res = P_SPORT0_DTSEC, .offset = 1},
-	{.res = P_SPORT0_DRSEC, .offset = 1},
-	{.res = P_CAN0_RX, .offset = 1},
-	{.res = P_CAN0_TX, .offset = 1},
-	{.res = P_SPI0_SSEL7, .offset = 1},
-	{.res = P_SPORT0_TFS, .offset = 0},
-	{.res = P_SPORT0_DTPRI, .offset = 0},
-	{.res = P_SPI0_SSEL2, .offset = 0},
-	{.res = P_SPI0_SSEL3, .offset = 0},
+s8 port_mux[] = {
+	[GPIO_PF0] = 3,
+	[GPIO_PF1] = 3,
+	[GPIO_PF2] = 4,
+	[GPIO_PF3] = 4,
+	[GPIO_PF4] = 5,
+	[GPIO_PF5] = 6,
+	[GPIO_PF6] = 7,
+	[GPIO_PF7] = 8,
+	[GPIO_PF8] = -1,
+	[GPIO_PF9] = -1,
+	[GPIO_PF10] = -1,
+	[GPIO_PF11] = -1,
+	[GPIO_PF12] = -1,
+	[GPIO_PF13] = -1,
+	[GPIO_PF14] = -1,
+	[GPIO_PF15] = -1,
+	[GPIO_PG0] = -1,
+	[GPIO_PG1] = -1,
+	[GPIO_PG2] = -1,
+	[GPIO_PG3] = -1,
+	[GPIO_PG4] = -1,
+	[GPIO_PG5] = -1,
+	[GPIO_PG6] = -1,
+	[GPIO_PG7] = -1,
+	[GPIO_PG8] = 9,
+	[GPIO_PG9] = 9,
+	[GPIO_PG10] = 10,
+	[GPIO_PG11] = 10,
+	[GPIO_PG12] = 10,
+	[GPIO_PG13] = 11,
+	[GPIO_PG14] = 11,
+	[GPIO_PG15] = 11,
+	[GPIO_PH0 ... GPIO_PH15] = -1,
+	[PORT_PJ0] = -1,
+	[PORT_PJ1] = -1,
+	[PORT_PJ2] = -1,
+	[PORT_PJ3] = -1,
+	[PORT_PJ4] = 1,
+	[PORT_PJ5] = 1,
+	[PORT_PJ6] = -1,
+	[PORT_PJ7] = -1,
+	[PORT_PJ8] = -1,
+	[PORT_PJ9] = -1,
+	[PORT_PJ10] = 0,
+	[PORT_PJ11] = 0,
 };
 
+int portmuxgroup_check(unsigned short per)
+{
+	u16 m, ident, pfunc;
+	s8 offset;
+	u16 function = P_FUNCT2MUX(per);
+	offset = port_mux[P_IDENT(per)];
+	ident = P_IDENT(per);
+	for (m = 0; m < ARRAY_SIZE(port_mux); m++) {
+		if (m == ident)
+			continue;
+		if (port_mux[m] == offset) {
+			if (is_reserved(peri, m, 1)) {
+				pfunc =  bfin_read_PORT_MUX();
+				if (offset == 1)
+					pfunc = (pfunc >> offset) & 3;
+				else
+					pfunc = (pfunc >> offset) & 1;
+				if (pfunc != function) {
+					printk(KERN_ERR "pin grounp conflict!"
+						"request pin %d func %d"
+						"conflict with pin %d func %d\n"
+						, ident, function,
+						m, pfunc);
+					return -EINVAL;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
 static void portmux_setup(unsigned short per)
 {
-	u16 y, offset, muxreg;
+	u16 ident, muxreg, reg;
+	s8 offset;
 	u16 function = P_FUNCT2MUX(per);
 
-	for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
-		if (port_mux_lut[y].res == per) {
+	/* SET PORTMUX REG */
+	ident = P_IDENT(per);
+	offset = port_mux[ident];
+	if (offset == -1)
+		return;
+	reg = muxreg = bfin_read_PORT_MUX();
 
-			/* SET PORTMUX REG */
+	if (offset != 1)
+		muxreg &= ~(1 << offset);
+	else
+		muxreg &= ~(3 << 1);
 
-			offset = port_mux_lut[y].offset;
-			muxreg = bfin_read_PORT_MUX();
-
-			if (offset != 1)
-				muxreg &= ~(1 << offset);
-			else
-				muxreg &= ~(3 << 1);
-
-			muxreg |= (function << offset);
-			bfin_write_PORT_MUX(muxreg);
-		}
-	}
+	muxreg |= (function << offset);
+	if (muxreg == reg)
+		return;
+	bfin_write_PORT_MUX(muxreg);
 }
 #elif defined(CONFIG_BF54x)
 inline void portmux_setup(unsigned short per)
@@ -310,12 +342,41 @@
 	return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
 }
 #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
+int portmuxgroup_check(unsigned short per)
+{
+	u16 pin, pfunc;
+	u16 ident = P_IDENT(per), function = P_FUNCT2MUX(per);
+	u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+	for (pin = 0; pin < 16; pin++) {
+		if (offset == pmux_offset[gpio_bank(ident)][pin]) {
+			if ((gpio_bank(ident)*16 + pin) == ident)
+				continue;
+			if (is_reserved(peri, gpio_bank(ident)*16 + pin, 1)) {
+				pfunc = *port_mux[gpio_bank(ident)];
+				pfunc = (pfunc >> offset) & 3;
+				if (pfunc != function) {
+					printk(KERN_ERR "pin grounp conflict!"
+						"request pin %d func %d"
+						"conflict with pin %d func %d\n"
+						, ident, function,
+						gpio_bank(ident)*16 + pin,
+						pfunc);
+					return -EINVAL;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
 inline void portmux_setup(unsigned short per)
 {
 	u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
 	u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
 
 	pmux = *port_mux[gpio_bank(ident)];
+	if  (((pmux >> offset) & 3) == function)
+		return;
 	pmux &= ~(3 << offset);
 	pmux |= (function & 3) << offset;
 	*port_mux[gpio_bank(ident)] = pmux;
@@ -735,6 +796,12 @@
 		}
 	}
 
+#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) || defined(BF537_FAMILY)
+	if (unlikely(portmuxgroup_check(per))) {
+		local_irq_restore_hw(flags);
+		return -EBUSY;
+	}
+#endif
  anyway:
 	reserve(peri, ident);
 
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to