LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/8] 44x: Removing dead CONFIG_PPC47x
From: Tony Breeds @ 2011-12-01  7:39 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322725164-4391-1-git-send-email-tony@bakeyournoodle.com>

From: Christoph Egger <siccegge@cs.fau.de>

CONFIG_PPC47x doesn't exist in Kconfig and no 476 processor calls this
function ppc44x_pin_tlb() as it has it's own ppc47x_pin_tlb().

This code is probably an artifact of the original 476 code that
shouldn't have made it upstream.

Signed-off-by: Christoph Egger <siccegge@cs.fau.de>
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
 arch/powerpc/mm/44x_mmu.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index f60e006..5d4e3ff 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -78,11 +78,7 @@ static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys)
 		"tlbwe	%1,%3,%5\n"
 		"tlbwe	%0,%3,%6\n"
 	:
-#ifdef CONFIG_PPC47x
-	: "r" (PPC47x_TLB2_S_RWX),
-#else
 	: "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
-#endif
 	  "r" (phys),
 	  "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M),
 	  "r" (entry),
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 5/8] powerpc/boot: Add extended precision shifts to the boot wrapper.
From: Tony Breeds @ 2011-12-01  7:39 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322725164-4391-1-git-send-email-tony@bakeyournoodle.com>

The upcomming currituck patches will need to do 64-bit shifts which will
fail with undefined symbol without this patch.

I looked at linking against libgcc but we can't guarantee that libgcc
was compiled with soft-float.  Also Using ../lib/div64.S or
../kernel/misc_32.S, this will break the build as the .o's need to be
built with different flags for the bootwrapper vs the kernel.  So for
now the easyest option is to just copy code from
arch/powerpc/kernel/misc_32.S  I don't think this code changes too often ;P

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
 arch/powerpc/boot/div64.S |   52 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/div64.S b/arch/powerpc/boot/div64.S
index d271ab5..bbcb8a4 100644
--- a/arch/powerpc/boot/div64.S
+++ b/arch/powerpc/boot/div64.S
@@ -57,3 +57,55 @@ __div64_32:
 	stw	r8,4(r3)
 	mr	r3,r6		# return the remainder in r3
 	blr
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5    has shift count
+ * result in R3/R4
+ *
+ *  ashrdi3: arithmetic right shift (sign propagation)	
+ *  lshrdi3: logical right shift
+ *  ashldi3: left shift
+ */
+	.globl __ashrdi3
+__ashrdi3:
+	subfic	r6,r5,32
+	srw	r4,r4,r5	# LSW = count > 31 ? 0 : LSW >> count
+	addi	r7,r5,32	# could be xori, or addi with -32
+	slw	r6,r3,r6	# t1 = count > 31 ? 0 : MSW << (32-count)
+	rlwinm	r8,r7,0,32	# t3 = (count < 32) ? 32 : 0
+	sraw	r7,r3,r7	# t2 = MSW >> (count-32)
+	or	r4,r4,r6	# LSW |= t1
+	slw	r7,r7,r8	# t2 = (count < 32) ? 0 : t2
+	sraw	r3,r3,r5	# MSW = MSW >> count
+	or	r4,r4,r7	# LSW |= t2
+	blr
+
+	.globl __ashldi3
+__ashldi3:
+	subfic	r6,r5,32
+	slw	r3,r3,r5	# MSW = count > 31 ? 0 : MSW << count
+	addi	r7,r5,32	# could be xori, or addi with -32
+	srw	r6,r4,r6	# t1 = count > 31 ? 0 : LSW >> (32-count)
+	slw	r7,r4,r7	# t2 = count < 32 ? 0 : LSW << (count-32)
+	or	r3,r3,r6	# MSW |= t1
+	slw	r4,r4,r5	# LSW = LSW << count
+	or	r3,r3,r7	# MSW |= t2
+	blr
+
+	.globl __lshrdi3
+__lshrdi3:
+	subfic	r6,r5,32
+	srw	r4,r4,r5	# LSW = count > 31 ? 0 : LSW >> count
+	addi	r7,r5,32	# could be xori, or addi with -32
+	slw	r6,r3,r6	# t1 = count > 31 ? 0 : MSW << (32-count)
+	srw	r7,r3,r7	# t2 = count < 32 ? 0 : MSW >> (count-32)
+	or	r4,r4,r6	# LSW |= t1
+	srw	r3,r3,r5	# MSW = MSW >> count
+	or	r4,r4,r7	# LSW |= t2
+	blr
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 6/8] powerpc/boot: Add mfdcrx
From: Tony Breeds @ 2011-12-01  7:39 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322725164-4391-1-git-send-email-tony@bakeyournoodle.com>

Needed for currituck support.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
 arch/powerpc/boot/dcr.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

I chose to use a #define to keep with the style of m[tf]dcr in the same file.

diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
index 645a7c9..cc73f7a 100644
--- a/arch/powerpc/boot/dcr.h
+++ b/arch/powerpc/boot/dcr.h
@@ -9,6 +9,12 @@
 	})
 #define mtdcr(rn, val) \
 	asm volatile("mtdcr %0,%1" : : "i"(rn), "r"(val))
+#define mfdcrx(rn) \
+	({	\
+		unsigned long rval; \
+		asm volatile("mfdcrx %0,%1" : "=r"(rval) : "r"(rn)); \
+		rval; \
+	})
 
 /* 440GP/440GX SDRAM controller DCRs */
 #define DCRN_SDRAM0_CFGADDR				0x010
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 7/8] 44x/476fpe: Add 476fpe SoC code
From: Tony Breeds @ 2011-12-01  7:39 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322725164-4391-1-git-send-email-tony@bakeyournoodle.com>

Based on original work by David 'Shaggy' Kliekamp.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
 arch/powerpc/include/asm/reg.h     |    1 +
 arch/powerpc/kernel/cputable.c     |   14 +++++++++
 arch/powerpc/kernel/head_44x.S     |    2 +
 arch/powerpc/platforms/44x/Kconfig |    4 ++
 arch/powerpc/sysdev/ppc4xx_pci.c   |   57 +++++++++++++++++++++++++++++++++++-
 arch/powerpc/sysdev/ppc4xx_pci.h   |    7 ++++
 6 files changed, 84 insertions(+), 1 deletions(-)

I wimped out on doing the mask and test opperations in head_44x.S for the
generic 476 PVR.

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 559da19..7fdc2c0 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -951,6 +951,7 @@
 #define PVR_403GCX	0x00201400
 #define PVR_405GP	0x40110000
 #define PVR_476		0x11a52000
+#define PVR_476FPE	0x7ff50000
 #define PVR_STB03XXX	0x40310000
 #define PVR_NP405H	0x41410000
 #define PVR_NP405L	0x41610000
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index edae5bb..7797ae2 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1830,6 +1830,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.machine_check		= machine_check_47x,
 		.platform		= "ppc470",
 	},
+	{ /* 476fpe */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x7ff50000,
+		.cpu_name		= "476fpe",
+		.cpu_features		= CPU_FTRS_47X | CPU_FTR_476_DD2,
+		.cpu_user_features	= COMMON_USER_BOOKE |
+			PPC_FEATURE_HAS_FPU,
+		.mmu_features		= MMU_FTR_TYPE_47x |
+			MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 128,
+		.machine_check		= machine_check_47x,
+		.platform		= "ppc470",
+	},
 	{ /* 476 iss */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00050000,
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index b725dab..bb7a9c7 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -732,6 +732,8 @@ _GLOBAL(init_cpu_state)
 	/* We use the PVR to differenciate 44x cores from 476 */
 	mfspr	r3,SPRN_PVR
 	srwi	r3,r3,16
+	cmplwi	cr0,r3,PVR_476FPE@h
+	beq	head_start_47x
 	cmplwi	cr0,r3,PVR_476@h
 	beq	head_start_47x
 	cmplwi	cr0,r3,PVR_476_ISS@h
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 762322c..f0be6e0 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -308,6 +308,10 @@ config 460SX
 	select IBM_EMAC_ZMII
 	select IBM_EMAC_TAH
 
+config 476FPE
+	bool
+	select PPC_FPU
+
 config APM821xx
 	bool
 	select PPC_FPU
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 45148ef..ae15e6f 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1296,6 +1296,52 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
 
 #endif /* CONFIG_40x */
 
+#ifdef CONFIG_476FPE
+static int __init ppc_476fpe_pciex_core_init(struct device_node *np)
+{
+	return 4;
+}
+
+static void __init ppc_476fpe_pciex_check_link(struct ppc4xx_pciex_port *port)
+{
+	u32 timeout_ms = 20;
+	u32 val = 0, mask = (PECFG_TLDLP_LNKUP|PECFG_TLDLP_PRESENT);
+	void __iomem *mbase = ioremap(port->cfg_space.start + 0x10000000,
+	                              0x1000);
+
+	printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
+
+	if (mbase == NULL) {
+		printk(KERN_WARNING "PCIE%d: failed to get cfg space\n",
+		                    port->index);
+		return;
+	}
+		
+	while (timeout_ms--) {
+		val = in_le32(mbase + PECFG_TLDLP);
+
+		if ((val & mask) == mask)
+			break;
+		msleep(10);
+	}
+
+	if (val & PECFG_TLDLP_PRESENT) {
+		printk(KERN_INFO "PCIE%d: link is up !\n", port->index);
+		port->link = 1;
+	} else
+		printk(KERN_WARNING "PCIE%d: Link up failed\n", port->index);
+
+	iounmap(mbase);
+	return;
+}
+
+static struct ppc4xx_pciex_hwops ppc_476fpe_pcie_hwops __initdata =
+{
+	.core_init	= ppc_476fpe_pciex_core_init,
+	.check_link	= ppc_476fpe_pciex_check_link,
+};
+#endif /* CONFIG_476FPE */
+
 /* Check that the core has been initied and if not, do it */
 static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
 {
@@ -1321,6 +1367,10 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
 	if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
 		ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
 #endif
+#ifdef CONFIG_476FPE
+	if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe"))
+		ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops;
+#endif
 	if (ppc4xx_pciex_hwops == NULL) {
 		printk(KERN_WARNING "PCIE: unknown host type %s\n",
 		       np->full_name);
@@ -1629,6 +1679,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port	*port,
 			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
 				sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
 					| DCRO_PEGPL_OMRxMSKL_VAL);
+		else if (of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+				sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT
+					| DCRO_PEGPL_OMRxMSKL_VAL);
 		else
 			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
 				sa | DCRO_PEGPL_OMR1MSKL_UOT
@@ -1753,7 +1807,8 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
 		if (res->flags & IORESOURCE_PREFETCH)
 			sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
 
-		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
+		    of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
 			sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
 
 		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
index 32ce763..bb48219 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.h
+++ b/arch/powerpc/sysdev/ppc4xx_pci.h
@@ -476,6 +476,13 @@
 #define DCRO_PEGPL_OMR1MSKL_UOT	 0x00000002
 #define DCRO_PEGPL_OMR3MSKL_IO	 0x00000002
 
+/* 476FPE */
+#define PCCFG_LCPA			0x270
+#define PECFG_TLDLP			0x3F8
+#define PECFG_TLDLP_LNKUP		0x00000008
+#define PECFG_TLDLP_PRESENT		0x00000010
+#define DCRO_PEGPL_476FPE_OMR1MSKL_UOT	 0x00000004
+
 /* SDR Bit Mappings */
 #define PESDRx_RCSSET_HLDPLB	0x10000000
 #define PESDRx_RCSSET_RSTGU	0x01000000
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 8/8] 44x/currituck: Add support for the new IBM currituck platform
From: Tony Breeds @ 2011-12-01  7:39 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322725164-4391-1-git-send-email-tony@bakeyournoodle.com>

Based on original work by David 'Shaggy' Kliekamp.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
 arch/powerpc/boot/Makefile                   |    5 +-
 arch/powerpc/boot/dts/currituck.dts          |  237 ++++++++++++++++++++++++++
 arch/powerpc/boot/treeboot-currituck.c       |  119 +++++++++++++
 arch/powerpc/boot/wrapper                    |    3 +
 arch/powerpc/configs/44x/currituck_defconfig |  110 ++++++++++++
 arch/powerpc/platforms/44x/Kconfig           |   10 +
 arch/powerpc/platforms/44x/Makefile          |    1 +
 arch/powerpc/platforms/44x/currituck.c       |  204 ++++++++++++++++++++++
 8 files changed, 688 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/currituck.dts
 create mode 100644 arch/powerpc/boot/treeboot-currituck.c
 create mode 100644 arch/powerpc/configs/44x/currituck_defconfig
 create mode 100644 arch/powerpc/platforms/44x/currituck.c

Much of the currituck.c code could go into ppc44x_simple.c but that makes
finding a home for the quirk code harder.  We can always move it there later.

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 72ee8c1..ff0057f 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -45,6 +45,7 @@ $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
 $(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
 $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
 $(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
+$(obj)/treeboot-currituck.o: BOOTCFLAGS += -mcpu=405
 $(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
 
 
@@ -79,7 +80,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
 		cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
 		virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
 		cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
-		gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c
+		gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c \
+		treeboot-currituck.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -212,6 +214,7 @@ image-$(CONFIG_WARP)			+= cuImage.warp
 image-$(CONFIG_YOSEMITE)		+= cuImage.yosemite
 image-$(CONFIG_ISS4xx)			+= treeImage.iss4xx \
 					   treeImage.iss4xx-mpic
+image-$(CONFIG_CURRITUCK)			+= treeImage.currituck
 
 # Board ports in arch/powerpc/platform/8xx/Kconfig
 image-$(CONFIG_MPC86XADS)		+= cuImage.mpc866ads
diff --git a/arch/powerpc/boot/dts/currituck.dts b/arch/powerpc/boot/dts/currituck.dts
new file mode 100644
index 0000000..b801dd0
--- /dev/null
+++ b/arch/powerpc/boot/dts/currituck.dts
@@ -0,0 +1,237 @@
+/*
+ * Device Tree Source for IBM Embedded PPC 476 Platform
+ *
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x01f00000 0x00100000;	// spin table
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+	model = "ibm,currituck";
+	compatible = "ibm,currituck";
+	dcr-parent = <&{/cpus/cpu@0}>;
+
+	aliases {
+		serial0 = &UART0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,476";
+			reg = <0>;
+			clock-frequency = <1600000000>; // 1.6 GHz
+			timebase-frequency = <100000000>; // 100Mhz
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+			status = "ok";
+		};
+		cpu@1 {
+			device_type = "cpu";
+			model = "PowerPC,476";
+			reg = <1>;
+			clock-frequency = <1600000000>; // 1.6 GHz
+			timebase-frequency = <100000000>; // 100Mhz
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+			status = "disabled";
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x01f00000>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x0>; // filled in by zImage
+	};
+
+	MPIC: interrupt-controller {
+		compatible = "chrp,open-pic";
+		interrupt-controller;
+		dcr-reg = <0xffc00000 0x00040000>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+
+	};
+
+	plb {
+		compatible = "ibm,plb6";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		clock-frequency = <200000000>; // 200Mhz
+
+		POB0: opb {
+			compatible = "ibm,opb-4xx", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/* Wish there was a nicer way of specifying a full
+			 * 32-bit range
+			 */
+			ranges = <0x00000000 0x00000200 0x00000000 0x80000000
+				  0x80000000 0x00000200 0x80000000 0x80000000>;
+			clock-frequency = <100000000>;
+
+			UART0: serial@10000000 {
+				device_type = "serial";
+				compatible = "ns16750", "ns16550";
+				reg = <0x10000000 0x00000008>;
+				virtual-reg = <0xe1000000>;
+				clock-frequency = <1851851>; // PCIe refclk/MCGC0_CTL[UART]
+				current-speed = <115200>;
+				interrupt-parent = <&MPIC>;
+				interrupts = <34 2>;
+			};
+
+			IIC0: i2c@00000000 {
+				compatible = "ibm,iic-currituck", "ibm,iic";
+				reg = <0x0 0x00000014>;
+				interrupt-parent = <&MPIC>;
+				interrupts = <79 2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+                                rtc@68 {
+                                        compatible = "stm,m41t80", "m41st85";
+                                        reg = <0x68>;
+                                };
+			};
+		};
+
+		PCIE0: pciex@10100000000 {		// 4xGBIF1
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+			primary;
+			port = <0x0>; /* port number */
+			reg = <0x00000101 0x00000000 0x0 0x10000000		/* Config space access */
+			       0x00000100 0x00000000 0x0 0x00001000>;	/* UTL Registers space access */
+			dcr-reg = <0x80 0x20>;
+
+//                                pci_space  < pci_addr          > < cpu_addr          > < size       >
+			ranges = <0x02000000 0x00000000 0x80000000 0x00000110 0x80000000 0x0 0x80000000
+			          0x01000000 0x0        0x0        0x00000140 0x0        0x0 0x00010000>;
+
+			/* Inbound starting at 0 to memsize filled in by zImage */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+			/* This drives busses 0 to 0xf */
+			bus-range = <0x0 0xf>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &MPIC 46 0x2 /* int A */
+				0x0 0x0 0x0 0x2 &MPIC 47 0x2 /* int B */
+				0x0 0x0 0x0 0x3 &MPIC 48 0x2 /* int C */
+				0x0 0x0 0x0 0x4 &MPIC 49 0x2 /* int D */>;
+		};
+
+		PCIE1: pciex@30100000000 {		// 4xGBIF0
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+			primary;
+			port = <0x1>; /* port number */
+			reg = <0x00000301 0x00000000 0x0 0x10000000		/* Config space access */
+			       0x00000300 0x00000000 0x0 0x00001000>;	/* UTL Registers space access */
+			dcr-reg = <0x60 0x20>;
+
+			ranges = <0x02000000 0x00000000 0x80000000 0x00000310 0x80000000 0x0 0x80000000
+			          0x01000000 0x0        0x0        0x00000340 0x0        0x0 0x00010000>;
+
+			/* Inbound starting at 0 to memsize filled in by zImage */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+			/* This drives busses 0 to 0xf */
+			bus-range = <0x0 0xf>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &MPIC 38 0x2 /* int A */
+				0x0 0x0 0x0 0x2 &MPIC 39 0x2 /* int B */
+				0x0 0x0 0x0 0x3 &MPIC 40 0x2 /* int C */
+				0x0 0x0 0x0 0x4 &MPIC 41 0x2 /* int D */>;
+		};
+
+		PCIE2: pciex@38100000000 {		// 2xGBIF0
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex";
+			primary;
+			port = <0x2>; /* port number */
+			reg = <0x00000381 0x00000000 0x0 0x10000000		/* Config space access */
+			       0x00000380 0x00000000 0x0 0x00001000>;	/* UTL Registers space access */
+			dcr-reg = <0xA0 0x20>;
+
+			ranges = <0x02000000 0x00000000 0x80000000 0x00000390 0x80000000 0x0 0x80000000
+			          0x01000000 0x0        0x0        0x000003C0 0x0        0x0 0x00010000>;
+
+			/* Inbound starting at 0 to memsize filled in by zImage */
+			dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+			/* This drives busses 0 to 0xf */
+			bus-range = <0x0 0xf>;
+
+			/* Legacy interrupts (note the weird polarity, the bridge seems
+			 * to invert PCIe legacy interrupts).
+			 * We are de-swizzling here because the numbers are actually for
+			 * port of the root complex virtual P2P bridge. But I want
+			 * to avoid putting a node for it in the tree, so the numbers
+			 * below are basically de-swizzled numbers.
+			 * The real slot is on idsel 0, so the swizzling is 1:1
+			 */
+			interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+			interrupt-map = <
+				0x0 0x0 0x0 0x1 &MPIC 54 0x2 /* int A */
+				0x0 0x0 0x0 0x2 &MPIC 55 0x2 /* int B */
+				0x0 0x0 0x0 0x3 &MPIC 56 0x2 /* int C */
+				0x0 0x0 0x0 0x4 &MPIC 57 0x2 /* int D */>;
+		};
+
+	};
+
+	chosen {
+		linux,stdout-path = &UART0;
+	};
+};
diff --git a/arch/powerpc/boot/treeboot-currituck.c b/arch/powerpc/boot/treeboot-currituck.c
new file mode 100644
index 0000000..925ae43
--- /dev/null
+++ b/arch/powerpc/boot/treeboot-currituck.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * Based on earlier code:
+ *   Copyright (C) Paul Mackerras 1997.
+ *
+ *   Matt Porter <mporter@kernel.crashing.org>
+ *   Copyright 2002-2005 MontaVista Software Inc.
+ *
+ *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *   Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ *    Copyright 2007 David Gibson, IBM Corporation.
+ *    Copyright 2010 Ben. Herrenschmidt, IBM Corporation.
+ *    Copyright © 2011 David Kleikamp IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+#include "reg.h"
+#include "io.h"
+#include "dcr.h"
+#include "4xx.h"
+#include "44x.h"
+#include "libfdt.h"
+
+BSS_STACK(4096);
+
+#define MAX_RANKS	0x4
+#define DDR3_MR0CF	0x80010011U
+
+static unsigned long long ibm_currituck_memsize;
+static unsigned long long ibm_currituck_detect_memsize(void)
+{
+	u32 reg;
+	unsigned i;
+	unsigned long long memsize = 0;
+
+	for(i = 0; i < MAX_RANKS; i++){
+		reg = mfdcrx(DDR3_MR0CF + i);
+
+		if (!(reg & 1))
+			continue;
+
+		reg &= 0x0000f000;
+		reg >>= 12;
+		memsize += (0x800000ULL << reg);
+	}
+
+	return memsize;
+}
+
+static void ibm_currituck_fixups(void)
+{
+	void *devp = finddevice("/");
+	u32 dma_ranges[7];
+
+	dt_fixup_memory(0x0ULL,  ibm_currituck_memsize);
+
+	while ((devp = find_node_by_devtype(devp, "pci"))) {
+		if (getprop(devp, "dma-ranges", dma_ranges, sizeof(dma_ranges)) < 0) {
+			printf("%s: Failed to get dma-ranges\r\n", __func__);
+			continue;
+		}
+
+		dma_ranges[5] = ibm_currituck_memsize >> 32;
+		dma_ranges[6] = ibm_currituck_memsize & 0xffffffffUL;
+
+		setprop(devp, "dma-ranges", dma_ranges, sizeof(dma_ranges));
+	}
+}
+
+#define SPRN_PIR	0x11E	/* Processor Indentification Register */
+void platform_init(void)
+{
+	unsigned long end_of_ram, avail_ram;
+	u32 pir_reg;
+	int node, size;
+	const u32 *timebase;
+
+	ibm_currituck_memsize = ibm_currituck_detect_memsize();
+	if (ibm_currituck_memsize >> 32)
+		end_of_ram = ~0UL;
+	else
+		end_of_ram = ibm_currituck_memsize;
+	avail_ram = end_of_ram - (unsigned long)_end;
+
+	simple_alloc_init(_end, avail_ram, 128, 64);
+	platform_ops.fixups = ibm_currituck_fixups;
+	platform_ops.exit = ibm44x_dbcr_reset;
+	pir_reg = mfspr(SPRN_PIR);
+
+	/* Make sure FDT blob is sane */
+	if (fdt_check_header(_dtb_start) != 0)
+		fatal("Invalid device tree blob\n");
+
+	node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
+	                                     "cpu", sizeof("cpu"));
+	if (!node)
+		fatal("Cannot find cpu node\n");
+	timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
+	if (timebase && (size == 4))
+		timebase_period_ns = 1000000000 / *timebase;
+
+	fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
+	fdt_init(_dtb_start);
+
+	serial_console_init();
+}
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index c74531a..87f4950 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -244,6 +244,9 @@ gamecube|wii)
     link_address='0x600000'
     platformo="$object/$platform-head.o $object/$platform.o"
     ;;
+treeboot-currituck)
+    link_address='0x1000000'
+    ;;
 treeboot-iss4xx-mpic)
     platformo="$object/treeboot-iss4xx.o"
     ;;
diff --git a/arch/powerpc/configs/44x/currituck_defconfig b/arch/powerpc/configs/44x/currituck_defconfig
new file mode 100644
index 0000000..4192322
--- /dev/null
+++ b/arch/powerpc/configs/44x/currituck_defconfig
@@ -0,0 +1,110 @@
+CONFIG_44x=y
+CONFIG_SMP=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PPC_47x=y
+# CONFIG_EBONY is not set
+CONFIG_CURRITUCK=y
+CONFIG_HIGHMEM=y
+CONFIG_HZ_100=y
+CONFIG_MATH_EMULATION=y
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=35000
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_SATA_PMP is not set
+CONFIG_SATA_SIL24=y
+# CONFIG_ATA_SFF is not set
+CONFIG_NETDEVICES=y
+CONFIG_E1000E=y
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_IBM_IIC=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NLS_DEFAULT="n"
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_PPC_EARLY_DEBUG=y
+CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0x10000000
+CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x200
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index f0be6e0..5d5aaf6 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -186,6 +186,16 @@ config ISS4xx
 	help
 	  This option enables support for the IBM ISS simulation environment
 
+config CURRITUCK
+	bool "IBM Currituck (476fpe) Support"
+	depends on PPC_47x
+	default n
+	select SWIOTLB
+	select 476FPE
+	select PPC4xx_PCI_EXPRESS
+	help
+	  This option enables support for the IBM Currituck (476fpe) evaluation board
+
 config ICON
 	bool "Icon"
 	depends on 44x
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 553db60..d03833a 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
 obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
 obj-$(CONFIG_ISS4xx)	+= iss4xx.o
 obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
+obj-$(CONFIG_CURRITUCK)	+= currituck.o
diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c
new file mode 100644
index 0000000..1fdf569
--- /dev/null
+++ b/arch/powerpc/platforms/44x/currituck.c
@@ -0,0 +1,204 @@
+/*
+ * Currituck board specific routines
+ *
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * Based on earlier code:
+ *    Matt Porter <mporter@kernel.crashing.org>
+ *    Copyright 2002-2005 MontaVista Software Inc.
+ *
+ *    Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *    Copyright (c) 2003-2005 Zultys Technologies
+ *
+ *    Rewritten and ported to the merged powerpc tree:
+ *    Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ *    Copyright © 2011 David Kliekamp IBM Corporation
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/rtc.h>
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/time.h>
+#include <asm/uic.h>
+#include <asm/ppc4xx.h>
+#include <asm/mpic.h>
+#include <asm/mmu.h>
+
+#include <linux/pci.h>
+
+static __initdata struct of_device_id ppc47x_of_bus[] = {
+	{ .compatible = "ibm,plb4", },
+	{ .compatible = "ibm,plb6", },
+	{ .compatible = "ibm,opb", },
+	{ .compatible = "ibm,ebc", },
+	{},
+};
+
+/* The EEPROM is missing and the default values are bogus.  This forces USB in
+ * to EHCI mode */
+static void __devinit quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
+{
+	if (of_machine_is_compatible("ibm,currituck")) {
+		pci_write_config_dword(dev, 0xe0, 0x0114231f);
+		pci_write_config_dword(dev, 0xe4, 0x00006c40);
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
+
+static int __init ppc47x_device_probe(void)
+{
+	of_platform_bus_probe(NULL, ppc47x_of_bus, NULL);
+
+	return 0;
+}
+machine_device_initcall(ppc47x, ppc47x_device_probe);
+
+/* We can have either UICs or MPICs */
+static void __init ppc47x_init_irq(void)
+{
+	struct device_node *np;
+
+	/* Find top level interrupt controller */
+	for_each_node_with_property(np, "interrupt-controller") {
+		if (of_get_property(np, "interrupts", NULL) == NULL)
+			break;
+	}
+	if (np == NULL)
+		panic("Can't find top level interrupt controller");
+
+	/* Check type and do appropriate initialization */
+	if (of_device_is_compatible(np, "chrp,open-pic")) {
+		/* The MPIC driver will get everything it needs from the
+		 * device-tree, just pass 0 to all arguments
+		 */
+		struct mpic *mpic =
+			mpic_alloc(np, 0, MPIC_PRIMARY, 0, 0, " MPIC     ");
+		BUG_ON(mpic == NULL);
+		mpic_init(mpic);
+		ppc_md.get_irq = mpic_get_irq;
+	} else
+		panic("Unrecognized top level interrupt controller");
+}
+
+#ifdef CONFIG_SMP
+static void __cpuinit smp_ppc47x_setup_cpu(int cpu)
+{
+	mpic_setup_this_cpu();
+}
+
+static int __cpuinit smp_ppc47x_kick_cpu(int cpu)
+{
+	struct device_node *cpunode = of_get_cpu_node(cpu, NULL);
+	const u64 *spin_table_addr_prop;
+	u32 *spin_table;
+	extern void start_secondary_47x(void);
+
+	BUG_ON(cpunode == NULL);
+
+	/* Assume spin table. We could test for the enable-method in
+	 * the device-tree but currently there's little point as it's
+	 * our only supported method
+	 */
+	spin_table_addr_prop =
+		of_get_property(cpunode, "cpu-release-addr", NULL);
+
+	if (spin_table_addr_prop == NULL) {
+		pr_err("CPU%d: Can't start, missing cpu-release-addr !\n",
+		       cpu);
+		return 1;
+	}
+
+	/* Assume it's mapped as part of the linear mapping. This is a bit
+	 * fishy but will work fine for now
+	 *
+	 * XXX: Is there any reason to assume differently?
+	 */
+	spin_table = (u32 *)__va(*spin_table_addr_prop);
+	pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table);
+
+	spin_table[3] = cpu;
+	smp_wmb();
+	spin_table[1] = __pa(start_secondary_47x);
+	mb();
+
+	return 0;
+}
+
+static struct smp_ops_t ppc47x_smp_ops = {
+	.probe		= smp_mpic_probe,
+	.message_pass	= smp_mpic_message_pass,
+	.setup_cpu	= smp_ppc47x_setup_cpu,
+	.kick_cpu	= smp_ppc47x_kick_cpu,
+	.give_timebase	= smp_generic_give_timebase,
+	.take_timebase	= smp_generic_take_timebase,
+};
+
+static void __init ppc47x_smp_init(void)
+{
+	if (mmu_has_feature(MMU_FTR_TYPE_47x))
+		smp_ops = &ppc47x_smp_ops;
+}
+
+#else /* CONFIG_SMP */
+static void __init ppc47x_smp_init(void) { }
+#endif /* CONFIG_SMP */
+
+static void __init ppc47x_setup_arch(void)
+{
+
+	/* No need to check the DMA config as we /know/ our windows are all of
+ 	 * RAM.  Lets hope that doesn't change */
+#ifdef CONFIG_SWIOTLB
+	if (memblock_end_of_DRAM() > 0xffffffff) {
+		ppc_swiotlb_enable = 1;
+		set_pci_dma_ops(&swiotlb_dma_ops);
+		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+	}
+#endif
+	ppc47x_smp_init();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init ppc47x_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "ibm,currituck"))
+		return 0;
+
+	return 1;
+}
+
+/* Use USB controller should have been hardware swizzled but it wasn't :( */
+static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
+{
+	if (dev->vendor == 0x1033 && (dev->device == 0x0035 ||
+	                              dev->device == 0x00e0)) {
+		dev->irq = irq_create_mapping(NULL, 47);
+		pr_info("%s: Mapping irq 47 %d\n", __func__, dev->irq);
+	}
+}
+
+define_machine(ppc47x) {
+	.name			= "PowerPC 47x",
+	.probe			= ppc47x_probe,
+	.progress		= udbg_progress,
+	.init_IRQ		= ppc47x_init_irq,
+	.setup_arch		= ppc47x_setup_arch,
+	.pci_irq_fixup		= ppc47x_pci_irq_fixup,
+	.restart		= ppc4xx_reset_system,
+	.calibrate_decr		= generic_calibrate_decr,
+};
-- 
1.7.6.4

^ permalink raw reply related

* Re: Add support for the currituck 476 platform from IBM (v2)
From: Tony Breeds @ 2011-12-01  7:43 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322725164-4391-1-git-send-email-tony@bakeyournoodle.com>

[-- Attachment #1: Type: text/plain, Size: 1462 bytes --]

On Thu, Dec 01, 2011 at 06:39:16PM +1100, Tony Breeds wrote:
> Patches 1 to 3
>         Modify the 44x PCI code to work with 476fpe/currituck.
> Patch 4
>        	Is an old patch by Christoph Egger that fell through the cracks somehow.
> Patches 5 and 6
>         Modify the bootwrapper to handle 476fpe/currituck
> Patch 7
>        	The SoC support.
> Patch 8
>        	The currituck board support.

Sorry I forgot the diffstat

 arch/powerpc/boot/Makefile                   |    5 +-
 arch/powerpc/boot/dcr.h                      |    6 +
 arch/powerpc/boot/div64.S                    |   52 ++++++
 arch/powerpc/boot/dts/currituck.dts          |  237 ++++++++++++++++++++++++++
 arch/powerpc/boot/treeboot-currituck.c       |  119 +++++++++++++
 arch/powerpc/boot/wrapper                    |    3 +
 arch/powerpc/configs/44x/currituck_defconfig |  110 ++++++++++++
 arch/powerpc/include/asm/reg.h               |    1 +
 arch/powerpc/kernel/cputable.c               |   14 ++
 arch/powerpc/kernel/head_44x.S               |    2 +
 arch/powerpc/mm/44x_mmu.c                    |    4 -
 arch/powerpc/platforms/44x/Kconfig           |   14 ++
 arch/powerpc/platforms/44x/Makefile          |    1 +
 arch/powerpc/platforms/44x/currituck.c       |  204 ++++++++++++++++++++++
 arch/powerpc/sysdev/ppc4xx_pci.c             |   85 +++++++++-
 arch/powerpc/sysdev/ppc4xx_pci.h             |    7 +
 16 files changed, 851 insertions(+), 13 deletions(-)

Yours Tony

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* [PATCH net-next v6 4/4] powerpc: tqm8548/tqm8xx: add and update CAN device nodes
From: Wolfgang Grandegger @ 2011-12-01  9:41 UTC (permalink / raw)
  To: netdev; +Cc: devicetree-discuss, linux-can, linuxppc-dev, socketcan-users
In-Reply-To: <1322732481-2255-1-git-send-email-wg@grandegger.com>

This patch enables or updates support for the CC770 and AN82527
CAN controller on the TQM8548 and TQM8xx boards.

CC: devicetree-discuss@lists.ozlabs.org
CC: linuxppc-dev@ozlabs.org
CC: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
 arch/powerpc/boot/dts/tqm8548-bigflash.dts |   19 ++++++++++++++-----
 arch/powerpc/boot/dts/tqm8548.dts          |   19 ++++++++++++++-----
 arch/powerpc/boot/dts/tqm8xx.dts           |   25 +++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 9452c3c..d918752 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -352,7 +352,7 @@
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
 			1 0x0 0xf8000000 0x08000000	// NOR FLASH bank 0
-			2 0x0 0xa3000000 0x00008000	// CAN (2 x i82527)
+			2 0x0 0xa3000000 0x00008000	// CAN (2 x CC770)
 			3 0x0 0xa3010000 0x00008000	// NAND FLASH
 
 		>;
@@ -393,18 +393,27 @@
 		};
 
 		/* Note: CAN support needs be enabled in U-Boot */
-		can0@2,0 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,0 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x0 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+			bosch,clock-out-frequency = <16000000>;
 		};
 
-		can1@2,100 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,100 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x100 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
 		};
 
 		/* Note: NAND support needs to be enabled in U-Boot */
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index 619776f..988d887 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -352,7 +352,7 @@
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
 			1 0x0 0xf8000000 0x08000000	// NOR FLASH bank 0
-			2 0x0 0xe3000000 0x00008000	// CAN (2 x i82527)
+			2 0x0 0xe3000000 0x00008000	// CAN (2 x CC770)
 			3 0x0 0xe3010000 0x00008000	// NAND FLASH
 
 		>;
@@ -393,18 +393,27 @@
 		};
 
 		/* Note: CAN support needs be enabled in U-Boot */
-		can0@2,0 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,0 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x0 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+			bosch,clock-out-frequency = <16000000>;
 		};
 
-		can1@2,100 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,100 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x100 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
 		};
 
 		/* Note: NAND support needs to be enabled in U-Boot */
diff --git a/arch/powerpc/boot/dts/tqm8xx.dts b/arch/powerpc/boot/dts/tqm8xx.dts
index f6da7ec..c3dba25 100644
--- a/arch/powerpc/boot/dts/tqm8xx.dts
+++ b/arch/powerpc/boot/dts/tqm8xx.dts
@@ -57,6 +57,7 @@
 
 		ranges = <
 			0x0 0x0 0x40000000 0x800000
+			0x3 0x0 0xc0000000 0x200
 		>;
 
 		flash@0,0 {
@@ -67,6 +68,30 @@
 			bank-width = <4>;
 			device-width = <2>;
 		};
+
+		/* Note: CAN support needs be enabled in U-Boot */
+		can@3,0 {
+			compatible = "intc,82527";
+			reg = <3 0x0 0x80>;
+			interrupts = <8 1>;
+			interrupt-parent = <&PIC>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+			bosch,clock-out-frequency = <16000000>;
+		};
+
+		can@3,100 {
+			compatible = "intc,82527";
+			reg = <3 0x100 0x80>;
+			interrupts = <8 1>;
+			interrupt-parent = <&PIC>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+		};
 	};
 
 	soc@fff00000 {
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH net-next v6 3/4] can: cc770: add platform bus driver for the CC770 and AN82527
From: Wolfgang Grandegger @ 2011-12-01  9:41 UTC (permalink / raw)
  To: netdev; +Cc: Devicetree-discuss, linux-can, linuxppc-dev, socketcan-users
In-Reply-To: <1322732481-2255-1-git-send-email-wg@grandegger.com>

This driver works with both, static platform data and device tree
bindings. It has been tested on a TQM855L board with two AN82527
CAN controllers on the local bus.

CC: Devicetree-discuss@lists.ozlabs.org
CC: linuxppc-dev@ozlabs.org
CC: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../devicetree/bindings/net/can/cc770.txt          |   53 ++++
 drivers/net/can/cc770/Kconfig                      |    7 +
 drivers/net/can/cc770/Makefile                     |    1 +
 drivers/net/can/cc770/cc770_platform.c             |  272 ++++++++++++++++++++
 4 files changed, 333 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/can/cc770.txt
 create mode 100644 drivers/net/can/cc770/cc770_platform.c

diff --git a/Documentation/devicetree/bindings/net/can/cc770.txt b/Documentation/devicetree/bindings/net/can/cc770.txt
new file mode 100644
index 0000000..77027bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/cc770.txt
@@ -0,0 +1,53 @@
+Memory mapped Bosch CC770 and Intel AN82527 CAN controller
+
+Note: The CC770 is a CAN controller from Bosch, which is 100%
+compatible with the old AN82527 from Intel, but with "bugs" being fixed.
+
+Required properties:
+
+- compatible : should be "bosch,cc770" for the CC770 and "intc,82527"
+	for the AN82527.
+
+- reg : should specify the chip select, address offset and size required
+	to map the registers of the controller. The size is usually 0x80.
+
+- interrupts : property with a value describing the interrupt source
+	(number and sensitivity) required for the controller.
+
+Optional properties:
+
+- bosch,external-clock-frequency : frequency of the external oscillator
+	clock in Hz. Note that the internal clock frequency used by the
+	controller is half of that value. If not specified, a default
+	value of 16000000 (16 MHz) is used.
+
+- bosch,clock-out-frequency : slock frequency in Hz on the CLKOUT pin.
+	If not specified or if the specified value is 0, the CLKOUT pin
+	will be disabled.
+
+- bosch,slew-rate : slew rate of the CLKOUT signal. If not specified,
+	a resonable value will be calculated.
+
+- bosch,disconnect-rx0-input : see data sheet.
+
+- bosch,disconnect-rx1-input : see data sheet.
+
+- bosch,disconnect-tx1-output : see data sheet.
+
+- bosch,polarity-dominant : see data sheet.
+
+- bosch,divide-memory-clock : see data sheet.
+
+- bosch,iso-low-speed-mux : see data sheet.
+
+For further information, please have a look to the CC770 or AN82527.
+
+Examples:
+
+can@3,100 {
+	compatible = "bosch,cc770";
+	reg = <3 0x100 0x80>;
+	interrupts = <2 0>;
+	interrupt-parent = <&mpic>;
+	bosch,external-clock-frequency = <16000000>;
+};
diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig
index 28e4d48..22c07a8 100644
--- a/drivers/net/can/cc770/Kconfig
+++ b/drivers/net/can/cc770/Kconfig
@@ -11,4 +11,11 @@ config CAN_CC770_ISA
 	  connected to the ISA bus using I/O port, memory mapped or
 	  indirect access.
 
+config CAN_CC770_PLATFORM
+	tristate "Generic Platform Bus based CC770 driver"
+	---help---
+	  This driver adds support for the CC770 and AN82527 chips
+	  connected to the "platform bus" (Linux abstraction for directly
+	  to the processor attached devices).
+
 endif
diff --git a/drivers/net/can/cc770/Makefile b/drivers/net/can/cc770/Makefile
index 872ecff..9fb8321 100644
--- a/drivers/net/can/cc770/Makefile
+++ b/drivers/net/can/cc770/Makefile
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_CAN_CC770) += cc770.o
 obj-$(CONFIG_CAN_CC770_ISA) += cc770_isa.o
+obj-$(CONFIG_CAN_CC770_PLATFORM) += cc770_platform.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
new file mode 100644
index 0000000..53115ee
--- /dev/null
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -0,0 +1,272 @@
+/*
+ * Driver for CC770 and AN82527 CAN controllers on the platform bus
+ *
+ * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * If platform data are used you should have similar definitions
+ * in your board-specific code:
+ *
+ *   static struct cc770_platform_data myboard_cc770_pdata = {
+ *           .osc_freq = 16000000,
+ *           .cir = 0x41,
+ *           .cor = 0x20,
+ *           .bcr = 0x40,
+ *   };
+ *
+ * Please see include/linux/can/platform/cc770.h for description of
+ * above fields.
+ *
+ * If the device tree is used, you need a CAN node definition in your
+ * DTS file similar to:
+ *
+ *   can@3,100 {
+ *           compatible = "bosch,cc770";
+ *           reg = <3 0x100 0x80>;
+ *           interrupts = <2 0>;
+ *           interrupt-parent = <&mpic>;
+ *           bosch,external-clock-frequency = <16000000>;
+ *   };
+ *
+ * See "Documentation/devicetree/bindings/net/can/cc770.txt" for further
+ * information.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/platform/cc770.h>
+
+#include "cc770.h"
+
+#define DRV_NAME "cc770_platform"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the platform bus");
+MODULE_LICENSE("GPL v2");
+
+#define CC770_PLATFORM_CAN_CLOCK  16000000
+
+static u8 cc770_platform_read_reg(const struct cc770_priv *priv, int reg)
+{
+	return ioread8(priv->reg_base + reg);
+}
+
+static void cc770_platform_write_reg(const struct cc770_priv *priv, int reg,
+				     u8 val)
+{
+	iowrite8(val, priv->reg_base + reg);
+}
+
+static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
+					    struct cc770_priv *priv)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const u32 *prop;
+	int prop_size;
+	u32 clkext;
+
+	prop = of_get_property(np, "bosch,external-clock-frequency",
+			       &prop_size);
+	if (prop && (prop_size ==  sizeof(u32)))
+		clkext = *prop;
+	else
+		clkext = CC770_PLATFORM_CAN_CLOCK; /* default */
+	priv->can.clock.freq = clkext;
+
+	/* The system clock may not exceed 10 MHz */
+	if (priv->can.clock.freq > 10000000) {
+		priv->cpu_interface |= CPUIF_DSC;
+		priv->can.clock.freq /= 2;
+	}
+
+	/* The memory clock may not exceed 8 MHz */
+	if (priv->can.clock.freq > 8000000)
+		priv->cpu_interface |= CPUIF_DMC;
+
+	if (of_get_property(np, "bosch,divide-memory-clock", NULL))
+		priv->cpu_interface |= CPUIF_DMC;
+	if (of_get_property(np, "bosch,iso-low-speed-mux", NULL))
+		priv->cpu_interface |= CPUIF_MUX;
+
+	if (!of_get_property(np, "bosch,no-comperator-bypass", NULL))
+		priv->bus_config |= BUSCFG_CBY;
+	if (of_get_property(np, "bosch,disconnect-rx0-input", NULL))
+		priv->bus_config |= BUSCFG_DR0;
+	if (of_get_property(np, "bosch,disconnect-rx1-input", NULL))
+		priv->bus_config |= BUSCFG_DR1;
+	if (of_get_property(np, "bosch,disconnect-tx1-output", NULL))
+		priv->bus_config |= BUSCFG_DT1;
+	if (of_get_property(np, "bosch,polarity-dominant", NULL))
+		priv->bus_config |= BUSCFG_POL;
+
+	prop = of_get_property(np, "bosch,clock-out-frequency", &prop_size);
+	if (prop && (prop_size == sizeof(u32)) && *prop > 0) {
+		u32 cdv = clkext / *prop;
+		int slew;
+
+		if (cdv > 0 && cdv < 16) {
+			priv->cpu_interface |= CPUIF_CEN;
+			priv->clkout |= (cdv - 1) & CLKOUT_CD_MASK;
+
+			prop = of_get_property(np, "bosch,slew-rate",
+					       &prop_size);
+			if (prop && (prop_size == sizeof(u32))) {
+				slew = *prop;
+			} else {
+				/* Determine default slew rate */
+				slew = (CLKOUT_SL_MASK >>
+					CLKOUT_SL_SHIFT) -
+					((cdv * clkext - 1) / 8000000);
+				if (slew < 0)
+					slew = 0;
+			}
+			priv->clkout |= (slew << CLKOUT_SL_SHIFT) &
+				CLKOUT_SL_MASK;
+		} else {
+			dev_dbg(&pdev->dev, "invalid clock-out-frequency\n");
+		}
+	}
+
+	return 0;
+}
+
+static int __devinit cc770_get_platform_data(struct platform_device *pdev,
+					     struct cc770_priv *priv)
+{
+
+	struct cc770_platform_data *pdata = pdev->dev.platform_data;
+
+	priv->can.clock.freq = pdata->osc_freq;
+	if (priv->cpu_interface | CPUIF_DSC)
+		priv->can.clock.freq /= 2;
+	priv->clkout = pdata->cor;
+	priv->bus_config = pdata->bcr;
+	priv->cpu_interface = pdata->cir;
+
+	return 0;
+}
+
+static int __devinit cc770_platform_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct cc770_priv *priv;
+	struct resource *mem;
+	resource_size_t mem_size;
+	void __iomem *base;
+	int err, irq;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(pdev, 0);
+	if (!mem || irq <= 0)
+		return -ENODEV;
+
+	mem_size = resource_size(mem);
+	if (!request_mem_region(mem->start, mem_size, pdev->name))
+		return -EBUSY;
+
+	base = ioremap(mem->start, mem_size);
+	if (!base) {
+		err = -ENOMEM;
+		goto exit_release_mem;
+	}
+
+	dev = alloc_cc770dev(0);
+	if (!dev) {
+		err = -ENOMEM;
+		goto exit_unmap_mem;
+	}
+
+	dev->irq = irq;
+	priv = netdev_priv(dev);
+	priv->read_reg = cc770_platform_read_reg;
+	priv->write_reg = cc770_platform_write_reg;
+	priv->irq_flags = IRQF_SHARED;
+	priv->reg_base = base;
+
+	if (pdev->dev.of_node)
+		err = cc770_get_of_node_data(pdev, priv);
+	else if (pdev->dev.platform_data)
+		err = cc770_get_platform_data(pdev, priv);
+	else
+		err = -ENODEV;
+	if (err)
+		goto exit_free_cc770;
+
+	dev_dbg(&pdev->dev,
+		 "reg_base=0x%p irq=%d clock=%d cpu_interface=0x%02x "
+		 "bus_config=0x%02x clkout=0x%02x\n",
+		 priv->reg_base, dev->irq, priv->can.clock.freq,
+		 priv->cpu_interface, priv->bus_config, priv->clkout);
+
+	dev_set_drvdata(&pdev->dev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = register_cc770dev(dev);
+	if (err) {
+		dev_err(&pdev->dev,
+			"couldn't register CC700 device (err=%d)\n", err);
+		goto exit_free_cc770;
+	}
+
+	return 0;
+
+exit_free_cc770:
+	free_cc770dev(dev);
+exit_unmap_mem:
+	iounmap(base);
+exit_release_mem:
+	release_mem_region(mem->start, mem_size);
+
+	return err;
+}
+
+static int __devexit cc770_platform_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct resource *mem;
+
+	unregister_cc770dev(dev);
+	iounmap(priv->reg_base);
+	free_cc770dev(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	return 0;
+}
+
+static struct of_device_id __devinitdata cc770_platform_table[] = {
+	{.compatible = "bosch,cc770"}, /* CC770 from Bosch */
+	{.compatible = "intc,82527"},  /* AN82527 from Intel CP */
+	{},
+};
+
+static struct platform_driver cc770_platform_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = cc770_platform_table,
+	},
+	.probe = cc770_platform_probe,
+	.remove = __devexit_p(cc770_platform_remove),
+};
+
+module_platform_driver(cc770_platform_driver);
-- 
1.7.4.1

^ permalink raw reply related

* Different behaviour when using "nosmp" parameter on SMP and UP
From: Jean-Michel Hautbois @ 2011-12-01  9:57 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev

Hi,

I have a P2020 CPU (powerpc) and I compiled it with two different defconfigs.
The first one is a SMP, 2 cores, launched with the "nosmp" kernel
parameter, the other one is an UP kernel.

My driver behaviour is not the same whether launching one or the
other. It is hard to explain more precisely, as it deals only with
ioctl which only does ioread32/iowrite32 on a PCIe device.
But I can tell that it never works the same way when UP (not working
correctly), or SMP "nosmp" (working) or even SMP (not working).

AFAIK, the "nosmp" parameter should tell the kernel to act the same is
if it is an UP kernel, and it disables IO APIC, which is not an issue
in my case.

Can you think about anything that would explain it, or would help me
debugging it ?

Thanks in advance for your help.
Regards,
JM

^ permalink raw reply

* Re: [PATCH 1/2] [hw-breakpoint] Use generic hw-breakpoint interfaces for new PPC ptrace flags
From: K.Prasad @ 2011-12-01 10:20 UTC (permalink / raw)
  To: linuxppc-dev, David Gibson
  Cc: linuxppc-dev, Thiago Jung Bauermann, Edjunior Barbosa Machado
In-Reply-To: <20111128031111.GC3508@truffala.fritz.box>

On Mon, Nov 28, 2011 at 02:11:11PM +1100, David Gibson wrote:
> [snip]
> On Wed, Oct 12, 2011 at 11:09:48PM +0530, K.Prasad wrote:
> > > > +	if (bp) {
> > > > +		attr = bp->attr;
> > > > +		attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN;
> > > > +		arch_bp_generic_fields(dabr &
> > > > +					(DABR_DATA_WRITE | DABR_DATA_READ),
> > > > +							&attr.bp_type);
> > > > +		attr.bp_len = len;
> > > 
> > > If gdb is using the new breakpoint interface, surely it should just
> > > use it, rather than doing this bit frobbing as in the old SET_DABR
> > > call.
> > > 
> > 
> > I understand that you wanted to avoid this duplication of effort in terms
> > of encoding and decoding the breakpoint type from
> > PPC_BREAKPOINT_TRIGGER_READ to DABR_DATA_READ to HW_BREAKPOINT_R.
> > 
> > However HW_BREAKPOINT_R is a generic definition used across
> > architectures, DABR_DATA_READ is used in the !CONFIG_HAVE_HW_BREAKPOINT
> > case while PPC_BREAKPOINT_TRIGGER_READ is used in
> > CONFIG_PPC_ADV_DEBUG_REGS case.
> > 
> > While we could define PPC_BREAKPOINT_TRIGGER_READ and DABR_DATA_READ to
> > the same value it may not result in any code savings (since the bit
> > translation is done for !CONFIG_HAVE_HW_BREAKPOINT case anyway). So, I
> > think it is best left the way it is.
> 
> That's not what I'm suggesting.  What I'm saying is that ig userspace
> is using the new generic interface, then it should just set the
> bp_type field, and it should not use the DABR_DATA_{READ,WRITE} bits.
> The DABR_DATA bits should *only* be processed in the legacy interface,
> never in the generic interface.
> 

The DABR_DATA_{READ,WRITE} bits are neither set by the user, nor
expected by the hw-breakpoint interface. It is an intermediate code used
to re-use the arch_bp_generic_fields function. We could convert directly
from PPC_BREAKPOINT_TRIGGER_READ to HW_BREAKPOINT_R (using a switch-case)
but that may not result in any code savings.

DABR_DATA_{READ,WRITE} is indeed legacy and cannot be set by user-space
for a PPC_PTRACE_SETHWDEBUG + CONFIG_HAVE_HW_BREAKPOINT combination.

[snipped]

> > diff --git a/Documentation/powerpc/ptrace.txt b/Documentation/powerpc/ptrace.txt
> > index f4a5499..f2a7a39 100644
> > --- a/Documentation/powerpc/ptrace.txt
> > +++ b/Documentation/powerpc/ptrace.txt
> > @@ -127,6 +127,22 @@ Some examples of using the structure to:
> >    p.addr2           = (uint64_t) end_range;
> >    p.condition_value = 0;
> >  
> > +- set a watchpoint in server processors (BookS)
> > +
> > +  p.version         = 1;
> > +  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_RW;
> > +  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
> > +  or
> > +  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
> > +
> > +  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
> > +  p.addr            = (uint64_t) begin_range;
> 
> You should probably document the alignment constraint on the address
> here, too.
> 

Alignment constraints will be learnt by the user-space during runtime.
We provide that as part of 'struct ppc_debug_info' in
'data_bp_alignment' field.

While the alignment is always 8-bytes for BookS, I think userspace
should be left to learn it through PTRACE_PPC_GETHWDEBUGINFO.

> > +  /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
> > +   * addr2 - addr <= 8 Bytes.
> > +   */
> > +  p.addr2           = (uint64_t) end_range;
> > +  p.condition_value = 0;
> > +
> >  3. PTRACE_DELHWDEBUG
> >  
> >  Takes an integer which identifies an existing breakpoint or watchpoint
> > diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> > index 05b7dd2..be5dc57 100644
> > --- a/arch/powerpc/kernel/ptrace.c
> > +++ b/arch/powerpc/kernel/ptrace.c
> > @@ -1339,6 +1339,12 @@ static int set_dac_range(struct task_struct *child,
> >  static long ppc_set_hwdebug(struct task_struct *child,
> >  		     struct ppc_hw_breakpoint *bp_info)
> >  {
> > +#ifdef CONFIG_HAVE_HW_BREAKPOINT
> > +	int ret, len = 0;
> > +	struct thread_struct *thread = &(child->thread);
> > +	struct perf_event *bp;
> > +	struct perf_event_attr attr;
> > +#endif /* CONFIG_HAVE_HW_BREAKPOINT */
> >  #ifndef CONFIG_PPC_ADV_DEBUG_REGS
> >  	unsigned long dabr;
> >  #endif
> > @@ -1382,13 +1388,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
> >  	 */
> >  	if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 ||
> >  	    (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 ||
> > -	    bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT ||
> >  	    bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
> >  		return -EINVAL;
> >  
> > -	if (child->thread.dabr)
> > -		return -ENOSPC;
> > -
> >  	if ((unsigned long)bp_info->addr >= TASK_SIZE)
> >  		return -EIO;
> >  
> > @@ -1398,15 +1400,75 @@ static long ppc_set_hwdebug(struct task_struct *child,
> >  		dabr |= DABR_DATA_READ;
> >  	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
> >  		dabr |= DABR_DATA_WRITE;
> > +#ifdef CONFIG_HAVE_HW_BREAKPOINT
> > +	if (ptrace_get_breakpoints(child) < 0)
> > +		return -ESRCH;
> >  
> > -	child->thread.dabr = dabr;
> > +	/*
> > +	 * Check if the request is for 'range' breakpoints. We can
> > +	 * support it if range < 8 bytes.
> > +	 */
> > +	if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) {
> > +		len = bp_info->addr2 - bp_info->addr;
> > +	} else if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
> > +			ptrace_put_breakpoints(child);
> > +			return -EINVAL;
> 
> You are overindented here.

I must have been confused!...Even scripts/checkpath.pl didn't throw an error
at this line. Will correct it.

> > +	}
> > +	bp = thread->ptrace_bps[0];
> > +	if (bp) {
> > +		attr = bp->attr;
> > +		attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN;
> > +		arch_bp_generic_fields(dabr &
> > +					(DABR_DATA_WRITE | DABR_DATA_READ),
> > +							&attr.bp_type);
> 
> You still have this code which has no business in the generic
> interface path.


Same explanation as above. If I have to avoid the call to
arch_bp_generic_fields() then, it should be replaced with

switch(bp_info->trigger_type) {

case PPC_BREAKPOINT_TRIGGER_READ:
	attr.bp_type = HW_BREAKPOINT_R;

case PPC_BREAKPOINT_TRIGGER_WRITE:
	attr.bp_type = HW_BREAKPOINT_W;

case PPC_BREAKPOINT_TRIGGER_RW:
	attr.bp_type = (HW_BREAKPOINT_W | HW_BREAKPOINT_R);
}

All these additional lines for no extra benefit (or I haven't
still understood your comments fully).

> > +		attr.bp_len = len;
> > +		ret =  modify_user_hw_breakpoint(bp, &attr);
> > +		if (ret) {
> > +			ptrace_put_breakpoints(child);
> > +			return ret;
> > +		}
> 
> If a bp already exists, you're modifying it.  I thought the semantics
> of the new interface meant that you shoul return ENOSPC in this case,
> and a DEL would be necessary before adding another breakpoint.
> 

I'm not too sure what would be the desired behaviour for this interface,
either way is fine with me. I'd like to hear from the GDB folks (copied
in this email) to know what would please them.
 
> > +		thread->ptrace_bps[0] = bp;
> > +		ptrace_put_breakpoints(child);
> > +		thread->dabr = dabr;
> > +		return 0;
> > +	}
> > +
> > +	/* Create a new breakpoint request if one doesn't exist already */
> > +	hw_breakpoint_init(&attr);
> > +	attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN;
> > +	attr.bp_len = len;
> > +	arch_bp_generic_fields(dabr & (DABR_DATA_WRITE | DABR_DATA_READ),
> > +								&attr.bp_type);
> > +
> > +	thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
> > +					       ptrace_triggered, NULL, child);
> > +	if (IS_ERR(bp)) {
> > +		thread->ptrace_bps[0] = NULL;
> > +		ptrace_put_breakpoints(child);
> > +		return PTR_ERR(bp);
> > +	}
> >  
> > +	ptrace_put_breakpoints(child);
> > +	return 1;
> > +#endif /* CONFIG_HAVE_HW_BREAKPOINT */
> > +
> > +	if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT)
> > +		return -EINVAL;
> > +
> > +	if (child->thread.dabr)
> > +		return -ENOSPC;
> > +
> > +	child->thread.dabr = dabr;
> >  	return 1;
> >  #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
> >  }
> >  
> >  static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
> >  {
> > +#ifdef CONFIG_HAVE_HW_BREAKPOINT
> > +	struct thread_struct *thread = &(child->thread);
> > +	struct perf_event *bp;
> > +#endif /* CONFIG_HAVE_HW_BREAKPOINT */
> >  #ifdef CONFIG_PPC_ADV_DEBUG_REGS
> >  	int rc;
> >  
> > @@ -1426,10 +1488,24 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
> >  #else
> >  	if (data != 1)
> >  		return -EINVAL;
> > +
> > +#ifdef CONFIG_HAVE_HW_BREAKPOINT
> > +	if (ptrace_get_breakpoints(child) < 0)
> > +		return -ESRCH;
> > +
> > +	bp = thread->ptrace_bps[0];
> > +	if (bp) {
> > +		unregister_hw_breakpoint(bp);
> > +		thread->ptrace_bps[0] = NULL;
> > +	}
> > +	ptrace_put_breakpoints(child);
> > +	return 0;
> 
> Shouldn't DEL return an error if there is no existing bp.
>

Same comment as above. We'd like to know what behaviour would help the
GDB use this interface better as there's no right or wrong way here.

Thanks again for your patient review. I will post the modified patch
after hearing comments from all.

Thanks.
K.Prasad

^ permalink raw reply

* Re: [BUG?]3.0-rc4+ftrace+kprobe: set kprobe at instruction 'stwu' lead to system crash/freeze
From: tiejun.chen @ 2011-12-01 10:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Jim Keniston, Anton Blanchard, linux-kernel, Steven Rostedt,
	Yong Zhang, paulus, yrl.pp-manager.tt, Masami Hiramatsu,
	linuxppc-dev
In-Reply-To: <1322686809.29041.10.camel@pasglop>

Benjamin Herrenschmidt wrote:
> On Wed, 2011-11-30 at 19:06 +0800, tiejun.chen wrote:
> 
>>>  - Copy the exception frame we're about to unwind to just -below- the
>>> new r1 value we want to write to. Then perform the write, and change
>>> r1 to point to that copy of the frame.
>>>
>>>  - Branch to restore: which will unwind everything from that copy of
>>> the frame, and eventually set r1 to GPR(1) in the copy which contains
>>> the new value of r1.
>> We still can't restore this there.
> 
> Yes, we can since we have copied the pt_regs down to -below- where we
> are going to write to. That's the whole trick. We copy the pt_regs
> somewhere "safe" and restore from there.
> 
>> I mean we have to do that real restore here. So I'm really not sure if its a
>> good way to add such a codes including check TIF/copy-get new r1/restore
>> operation here since this is so deep for the exception return code.
> 
> No. Re-read my explanation.
> 
> In the do_work case (so when things are still easy), we copy the pt_regs
> of the return frame to a safe place (right below where we want to write
> to typically), and change r1 to point to this "new" frame which we use
> to restore from. Then we do the store which is now safe and go to an
> unmodified "restore" exit path.

Do you mean we should push the original pt_regs (or that whole exception stack)
downwards the location the new r1 point? Then its safe to perform this real
emulated stw instruction. At last we will reroute r1 to that copied exception
frame to restore as normal. Right?

Here I suppose so, I implement this for PPC32 based on the above understanding.
I take a validation for kprobing do_fork()/show_interrupts(), now looks fine.
Tomorrow I will go PPC64, and hope its fine as well.

If everything is good I'll send these patches to linuxppc-dev next week.

Cheers
Tiejun

> 
>>> This is the less intrusive approach and should work just fine, it's also
>>> more robust than anything I've been able to think of and the approach
>>> would work for 32 and 64-bit similarily.
>>>
>>> (***) Above comment about a bug: If you look at entry_64.S version of
>>> ret_from_except_lite you'll notice that in the !preempt case, after
>>> we've checked MSR_PR we test for any TIF flag in _TIF_USER_WORK_MASK to
>>> decide whether to go to do_work or not. However, in the preempt case, we
>>> do a convoluted trick to test SIGPENDING only if PR was set and always
>>> test NEED_RESCHED ... but we forget to test any other bit of
>>> _TIF_USER_WORK_MASK !!! So that means that with preempt, we completely
>>> fail to test for things like single step, syscall tracing, etc...
>>>
>> This is another problem we should address.
>>
>>> I think this should be fixed at the same time, by simplifying the code
>>> by doing:
>>>
>>>  - Test PR. If set, go to test_work_user, else continue (or the other
>>> way around and call it test_work_kernel)
>>>
>>>  - In test_work_user, always test for _TIF_USER_WORK_MASK to decide to
>>> go to do_work, maybe call it do_user_work
>>>
>>>  - In test_work_kernel, test for _TIF_KERNEL_WORK_MASK which is set to
>>> our new flag along with NEED_RESCHED if preempt is enabled and branch to
>>> do_kernel_work.
>>>
>>> do_user_work is basically the same as today's user_work
>>>
>>> do_kernel_work is basically the same as today preempt block with added
>>> code to handle the new flag as described above.
>>>
>>> Is anybody volunteering for fixing that ? I don't have the bandwidth
>> I always use one specific kprobe stack to fix this for BOOKE and work well in my
>> local tree :) Do you remember my v3 patch? I think its possible to extend this
>> for all PPC variants.
>>
>> Anyway, I'd like to be this volunteer with our last solution.
> 
> So the second problem I exposed, for which you just volunteered
> (hint :-) is an orthogonal issue not related to kprobe or stacks which
> happen to be something I discovered yesterday while looking at the code.
> 
> As for the solution to the emulation problem, re-read my explanation.
> The whole trick is that we can avoid a separate stack (which I really
> want to avoid) and we can avoid touching the low level restore code
> path.
> 
> Cheers,
> Ben.

^ permalink raw reply

* Re: ppc4xx simple vs SoC's
From: Josh Boyer @ 2011-12-01 11:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1322717953.3729.18.camel@pasglop>

On Thu, Dec 1, 2011 at 12:39 AM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> Hi Josh !
>
> I was helping Tony with some of the Currituck stuff when I noticed an
> oddity...
>
> So we have various "SoC" config symbols such as 440EP, 460SX, etc...
> that in turn select various bits & pieces that enable support for that
> SoC (such as EMAC4 support or FPU support). Those only act as "enables"
> for compiling of the code, there is still going to be a runtime check of
> course.
>
> Those SoC config symbols are not user selectable, they are meant to be
> themselves select'ed by the board Kconfig entries.

Yep, and they are.

> However, the entry for ppc44x_simple doesn't select any of these,
> meaning for example, AFAIK, that you don't get EMAC4 etc... I'm
> surprised things work at all !
>
> What am I missing ?

CONFIG_PPC44x_SIMPLE is selected by the board Kconfig values, which
also select all of the SoC Kconfig options they need as well.
ppc44x_simple started as a way to basically avoid duplicating a bunch
of board.c files, but it's still "driven" from the board options.

So hopefully that explains how things are working today.  The question
now is whether you would like something different?

josh

^ permalink raw reply

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Kumar Gala @ 2011-12-01 14:03 UTC (permalink / raw)
  To: Jean-Michel Hautbois; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <CAL8zT=juU_PC92R4za31R8Lmur0PrFwog1m1fk+PEarW_0C6ng@mail.gmail.com>


On Dec 1, 2011, at 3:57 AM, Jean-Michel Hautbois wrote:

> Hi,
>=20
> I have a P2020 CPU (powerpc) and I compiled it with two different =
defconfigs.
> The first one is a SMP, 2 cores, launched with the "nosmp" kernel
> parameter, the other one is an UP kernel.
>=20
> My driver behaviour is not the same whether launching one or the
> other. It is hard to explain more precisely, as it deals only with
> ioctl which only does ioread32/iowrite32 on a PCIe device.
> But I can tell that it never works the same way when UP (not working
> correctly), or SMP "nosmp" (working) or even SMP (not working).
>=20
> AFAIK, the "nosmp" parameter should tell the kernel to act the same is
> if it is an UP kernel, and it disables IO APIC, which is not an issue
> in my case.
>=20
> Can you think about anything that would explain it, or would help me
> debugging it ?

This is a bit odd, hard to say w/o more details on what exactly your =
code is trying to do and wait the failure is.

The larger differences between SMP & UP build would be setting of memory =
attribute for cache coherency.  In UP case we don't set it.

Between SMP 'nosmp' and SMP 'on' cases you seem like you're hitting some =
locking condition.

Guessing your running into a timing & locking issue that you're getting =
lucky on the SMP 'nosmp' case such that it just happens to work.

- k=

^ permalink raw reply

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Jean-Michel Hautbois @ 2011-12-01 15:04 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <D70E8CC4-9FA3-4DC9-B623-02F32EFBFE0F@kernel.crashing.org>

2011/12/1 Kumar Gala <galak@kernel.crashing.org>:
>
> On Dec 1, 2011, at 3:57 AM, Jean-Michel Hautbois wrote:
>
>> Hi,
>>
>> I have a P2020 CPU (powerpc) and I compiled it with two different defcon=
figs.
>> The first one is a SMP, 2 cores, launched with the "nosmp" kernel
>> parameter, the other one is an UP kernel.
>>
>> My driver behaviour is not the same whether launching one or the
>> other. It is hard to explain more precisely, as it deals only with
>> ioctl which only does ioread32/iowrite32 on a PCIe device.
>> But I can tell that it never works the same way when UP (not working
>> correctly), or SMP "nosmp" (working) or even SMP (not working).
>>
>> AFAIK, the "nosmp" parameter should tell the kernel to act the same is
>> if it is an UP kernel, and it disables IO APIC, which is not an issue
>> in my case.
>>
>> Can you think about anything that would explain it, or would help me
>> debugging it ?
>
> This is a bit odd, hard to say w/o more details on what exactly your code=
 is trying to do and wait the failure is.

I understand that it is difficult to give more details, but the driver
is not mine, and I can't give all the code associated.

> The larger differences between SMP & UP build would be setting of memory =
attribute for cache coherency. =C2=A0In UP case we don't set it.
>
> Between SMP 'nosmp' and SMP 'on' cases you seem like you're hitting some =
locking condition.
>
> Guessing your running into a timing & locking issue that you're getting l=
ucky on the SMP 'nosmp' case such that it just happens to work.

Any idea on how to debug this ? I am using a 2.6.35 kernel.

Thanks,
JM

^ permalink raw reply

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Tabi Timur-B04825 @ 2011-12-01 15:56 UTC (permalink / raw)
  To: Jean-Michel Hautbois; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <CAL8zT=gGfBYsLcsKobJPhfhEhNeLcrYMoWh2kv0odT0n0wnZgQ@mail.gmail.com>

On Thu, Dec 1, 2011 at 9:04 AM, Jean-Michel Hautbois
<jhautbois@gmail.com> wrote:
>
> Any idea on how to debug this ? I am using a 2.6.35 kernel.

There are a ton of Kconfig options for debugging various locking bugs.
 Try turning them on.

--=20
Timur Tabi
Linux kernel developer at Freescale=

^ permalink raw reply

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Jean-Michel Hautbois @ 2011-12-01 16:14 UTC (permalink / raw)
  To: Tabi Timur-B04825; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <CAOZdJXVq_g=GAJLRsHZ+290cAJfpOx0LX3sBL3T5i0CaG+xh9Q@mail.gmail.com>

2011/12/1 Tabi Timur-B04825 <B04825@freescale.com>:
> On Thu, Dec 1, 2011 at 9:04 AM, Jean-Michel Hautbois
> <jhautbois@gmail.com> wrote:
>>
>> Any idea on how to debug this ? I am using a 2.6.35 kernel.
>
> There are a ton of Kconfig options for debugging various locking bugs.
> =C2=A0Try turning them on.
>

And when I do that, it works, even in SMP... :).

JM

^ permalink raw reply

* [PATCH] i2c-mpc: use the cell-index property to enumerate the I2C adapters
From: Timur Tabi @ 2011-12-01 17:33 UTC (permalink / raw)
  To: kumar.gala, grant.likely, linuxppc-dev

An I2C device tree node can contain a 'cell-index' property that can be
used to enumerate the I2C devices.  If such a property exists, use it
to specify the I2C adapter number.

This feature is necessary for the Freescale PowerPC audio drivers (e.g.
on the P1022DS).  The "machine driver" needs to know the adapter number
for each I2C adapter, but it only has access to the device tree.
Previously, the I2C nodes always appeared in cell-index order, so the
dynamic numbering coincided with the cell-index property.  With commit
ab827d97 ("powerpc/85xx: Rework P1022DS device tree"), the I2C nodes are
unintentionally reversed in the device tree, and so the machine driver
guesses the wrong I2C adapter number.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 drivers/i2c/busses/i2c-mpc.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 107397a..8551c34 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -632,7 +632,19 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)
 	i2c->adap.dev.parent = &op->dev;
 	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
 
-	result = i2c_add_adapter(&i2c->adap);
+	/*
+	 * If the I2C node has a "cell-index" property, use it to enumerate
+	 * the I2C adapter.
+	 */
+	prop = of_get_property(i2c->adap.dev.of_node, "cell-index", &plen);
+	if (prop && plen == sizeof(u32)) {
+		dev_dbg(i2c->dev, "using cell-index property %u", *prop);
+		i2c->adap.nr = *prop;
+		result = i2c_add_numbered_adapter(&i2c->adap);
+	} else {
+		result = i2c_add_adapter(&i2c->adap);
+	}
+
 	if (result < 0) {
 		dev_err(i2c->dev, "failed to add adapter\n");
 		goto fail_add;
-- 
1.7.3.4

^ permalink raw reply related

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Jean-Michel Hautbois @ 2011-12-01 17:52 UTC (permalink / raw)
  To: Tabi Timur-B04825; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <CAL8zT=hK2rDDC7s+SkvCA=C5LjVX+5oRQmP+KQet2mkFEnaKKw@mail.gmail.com>

2011/12/1 Jean-Michel Hautbois <jhautbois@gmail.com>:
> 2011/12/1 Tabi Timur-B04825 <B04825@freescale.com>:
>> On Thu, Dec 1, 2011 at 9:04 AM, Jean-Michel Hautbois
>> <jhautbois@gmail.com> wrote:
>>>
>>> Any idea on how to debug this ? I am using a 2.6.35 kernel.
>>
>> There are a ton of Kconfig options for debugging various locking bugs.
>> =C2=A0Try turning them on.
>>

All Kconfig options do not help me with cache coherency problems, though.
Or, I didn't find any option related.
Any idea ?

JM

^ permalink raw reply

* Re: [PATCH] i2c-mpc: use the cell-index property to enumerate the I2C adapters
From: Scott Wood @ 2011-12-01 18:41 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev, kumar.gala
In-Reply-To: <1322760781-31226-1-git-send-email-timur@freescale.com>

On 12/01/2011 11:33 AM, Timur Tabi wrote:
> An I2C device tree node can contain a 'cell-index' property that can be
> used to enumerate the I2C devices.  If such a property exists, use it
> to specify the I2C adapter number.

Didn't we decide a long time ago that this was a bad idea?

> This feature is necessary for the Freescale PowerPC audio drivers (e.g.
> on the P1022DS).  The "machine driver" needs to know the adapter number
> for each I2C adapter, but it only has access to the device tree.
> Previously, the I2C nodes always appeared in cell-index order, so the
> dynamic numbering coincided with the cell-index property.  With commit
> ab827d97 ("powerpc/85xx: Rework P1022DS device tree"), the I2C nodes are
> unintentionally reversed in the device tree, and so the machine driver
> guesses the wrong I2C adapter number.

What specifically do you need this number for?  What does it represent?

-Scott

^ permalink raw reply

* [PATCH 6/8 v2] powerpc/ps3: Fix PS3 repository build warnings
From: Geoff Levand @ 2011-12-01 18:58 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: cbe-oss-dev, linuxppc-dev, Geert Uytterhoeven
In-Reply-To: <CAMuHMdUjOXLskrRXYYO1Esd75W4Z=WS3srT0+qFF66DfLeQQmA@mail.gmail.com>

Fix some PS3 repository.c build warnings when DEBUG is
defined. Also change most pr_debug calls to pr_devel calls.

Fixes warnings like these:

  format '%lx' expects type 'long unsigned int', but argument 7 has type 'u64'

Signed-off-by: Geoff Levand <geoff@infradead.org>
---

Hi Ben,

I rebased my for-powerpc branch to include this update.

-Geoff

v2: - Format u64 is using the "ll" length modifier (thanks Geert).
    - Convert pr_debug to pr_devel.

 arch/powerpc/platforms/ps3/repository.c |  135 ++++++++++++++++---------------
 1 files changed, 68 insertions(+), 67 deletions(-)

diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index cb68729..7bdfea3 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -44,7 +44,7 @@ static void _dump_field(const char *hdr, u64 n, const char *func, int line)
 		s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
 	s[i] = 0;
 
-	pr_debug("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
+	pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
 #endif
 }
 
@@ -53,7 +53,7 @@ static void _dump_field(const char *hdr, u64 n, const char *func, int line)
 static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
 	u64 n4, const char *func, int line)
 {
-	pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
+	pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
 	_dump_field("n1: ", n1, func, line);
 	_dump_field("n2: ", n2, func, line);
 	_dump_field("n3: ", n3, func, line);
@@ -65,13 +65,13 @@ static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
 	u64 v1, u64 v2, const char *func, int line)
 {
-	pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
+	pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
 	_dump_field("n1: ", n1, func, line);
 	_dump_field("n2: ", n2, func, line);
 	_dump_field("n3: ", n3, func, line);
 	_dump_field("n4: ", n4, func, line);
-	pr_debug("%s:%d: v1: %016llx\n", func, line, v1);
-	pr_debug("%s:%d: v2: %016llx\n", func, line, v2);
+	pr_devel("%s:%d: v1: %016llx\n", func, line, v1);
+	pr_devel("%s:%d: v2: %016llx\n", func, line, v2);
 }
 
 /**
@@ -135,7 +135,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
 		&v2);
 
 	if (result) {
-		pr_debug("%s:%d: lv1_read_repository_node failed: %s\n",
+		pr_warn("%s:%d: lv1_read_repository_node failed: %s\n",
 			__func__, __LINE__, ps3_result(result));
 		dump_node_name(lpar_id, n1, n2, n3, n4);
 		return -ENOENT;
@@ -149,10 +149,10 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
 		*_v2 = v2;
 
 	if (v1 && !_v1)
-		pr_debug("%s:%d: warning: discarding non-zero v1: %016llx\n",
+		pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n",
 			__func__, __LINE__, v1);
 	if (v2 && !_v2)
-		pr_debug("%s:%d: warning: discarding non-zero v2: %016llx\n",
+		pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n",
 			__func__, __LINE__, v2);
 
 	return 0;
@@ -323,16 +323,16 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
 	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 
 	if (result) {
-		pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
+		pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
 		return result;
 	}
 
-	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
+	pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
 		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
 		num_dev);
 
 	if (tmp.dev_index >= num_dev) {
-		pr_debug("%s:%d: no device found\n", __func__, __LINE__);
+		pr_devel("%s:%d: no device found\n", __func__, __LINE__);
 		return -ENODEV;
 	}
 
@@ -340,7 +340,7 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
 		&tmp.dev_type);
 
 	if (result) {
-		pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);
+		pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__);
 		return result;
 	}
 
@@ -348,12 +348,12 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
 		&tmp.dev_id);
 
 	if (result) {
-		pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
+		pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__,
 		__LINE__);
 		return result;
 	}
 
-	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
+	pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
 		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
 
 	*repo = tmp;
@@ -367,14 +367,14 @@ int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
 	struct ps3_repository_device tmp;
 	unsigned int num_dev;
 
-	pr_debug(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
+	pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
 		 bus_id, dev_id);
 
 	for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
 		result = ps3_repository_read_bus_id(tmp.bus_index,
 						    &tmp.bus_id);
 		if (result) {
-			pr_debug("%s:%u read_bus_id(%u) failed\n", __func__,
+			pr_devel("%s:%u read_bus_id(%u) failed\n", __func__,
 				 __LINE__, tmp.bus_index);
 			return result;
 		}
@@ -382,23 +382,23 @@ int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
 		if (tmp.bus_id == bus_id)
 			goto found_bus;
 
-		pr_debug("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
+		pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
 			 tmp.bus_id);
 	}
-	pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
+	pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
 	return result;
 
 found_bus:
 	result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
 	if (result) {
-		pr_debug("%s:%u read_bus_type(%u) failed\n", __func__,
+		pr_devel("%s:%u read_bus_type(%u) failed\n", __func__,
 			 __LINE__, tmp.bus_index);
 		return result;
 	}
 
 	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 	if (result) {
-		pr_debug("%s:%u read_bus_num_dev failed\n", __func__,
+		pr_devel("%s:%u read_bus_num_dev failed\n", __func__,
 			 __LINE__);
 		return result;
 	}
@@ -408,7 +408,7 @@ found_bus:
 						    tmp.dev_index,
 						    &tmp.dev_id);
 		if (result) {
-			pr_debug("%s:%u read_dev_id(%u:%u) failed\n", __func__,
+			pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__,
 				 __LINE__, tmp.bus_index, tmp.dev_index);
 			return result;
 		}
@@ -416,21 +416,21 @@ found_bus:
 		if (tmp.dev_id == dev_id)
 			goto found_dev;
 
-		pr_debug("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
+		pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
 			 tmp.dev_id);
 	}
-	pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__);
+	pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__);
 	return result;
 
 found_dev:
 	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
 					      &tmp.dev_type);
 	if (result) {
-		pr_debug("%s:%u read_dev_type failed\n", __func__, __LINE__);
+		pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__);
 		return result;
 	}
 
-	pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
+	pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
 		 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
 		 tmp.dev_index, tmp.bus_id, tmp.dev_id);
 	*repo = tmp;
@@ -443,18 +443,18 @@ int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
 	int result = 0;
 	struct ps3_repository_device repo;
 
-	pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
+	pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 
 	repo.bus_type = bus_type;
 	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
 	if (result) {
-		pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
+		pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
 		return result;
 	}
 
 	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
 	if (result) {
-		pr_debug("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
+		pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
 			 repo.bus_index);
 		return result;
 	}
@@ -469,13 +469,13 @@ int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
 
 		result = callback(&repo);
 		if (result) {
-			pr_debug("%s:%d: abort at callback\n", __func__,
+			pr_devel("%s:%d: abort at callback\n", __func__,
 				__LINE__);
 			break;
 		}
 	}
 
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	pr_devel(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
@@ -489,7 +489,7 @@ int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
 	for (i = from; i < 10; i++) {
 		error = ps3_repository_read_bus_type(i, &type);
 		if (error) {
-			pr_debug("%s:%d read_bus_type failed\n",
+			pr_devel("%s:%d read_bus_type failed\n",
 				__func__, __LINE__);
 			*bus_index = UINT_MAX;
 			return error;
@@ -509,7 +509,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	int result = 0;
 	unsigned int res_index;
 
-	pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
+	pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
 
 	*interrupt_id = UINT_MAX;
 
@@ -521,7 +521,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 			repo->dev_index, res_index, &t, &id);
 
 		if (result) {
-			pr_debug("%s:%d read_dev_intr failed\n",
+			pr_devel("%s:%d read_dev_intr failed\n",
 				__func__, __LINE__);
 			return result;
 		}
@@ -535,7 +535,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
 	if (res_index == 10)
 		return -ENODEV;
 
-	pr_debug("%s:%d: found intr_type %u at res_index %u\n",
+	pr_devel("%s:%d: found intr_type %u at res_index %u\n",
 		__func__, __LINE__, intr_type, res_index);
 
 	return result;
@@ -547,7 +547,7 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	int result = 0;
 	unsigned int res_index;
 
-	pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
+	pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
 
 	*bus_addr = *len = 0;
 
@@ -560,7 +560,7 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 			repo->dev_index, res_index, &t, &a, &l);
 
 		if (result) {
-			pr_debug("%s:%d read_dev_reg failed\n",
+			pr_devel("%s:%d read_dev_reg failed\n",
 				__func__, __LINE__);
 			return result;
 		}
@@ -575,7 +575,7 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo,
 	if (res_index == 10)
 		return -ENODEV;
 
-	pr_debug("%s:%d: found reg_type %u at res_index %u\n",
+	pr_devel("%s:%d: found reg_type %u at res_index %u\n",
 		__func__, __LINE__, reg_type, res_index);
 
 	return result;
@@ -1009,7 +1009,7 @@ int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
 	int result = 0;
 	unsigned int res_index;
 
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+	pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
 		repo->bus_index, repo->dev_index);
 
 	for (res_index = 0; res_index < 10; res_index++) {
@@ -1021,13 +1021,13 @@ int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
 
 		if (result) {
 			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_intr"
+				pr_devel("%s:%d ps3_repository_read_dev_intr"
 					" (%u:%u) failed\n", __func__, __LINE__,
 					repo->bus_index, repo->dev_index);
 			break;
 		}
 
-		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
+		pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
 			__func__, __LINE__, repo->bus_index, repo->dev_index,
 			intr_type, interrupt_id);
 	}
@@ -1042,18 +1042,18 @@ int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
 
 		if (result) {
 			if (result !=  LV1_NO_ENTRY)
-				pr_debug("%s:%d ps3_repository_read_dev_reg"
+				pr_devel("%s:%d ps3_repository_read_dev_reg"
 					" (%u:%u) failed\n", __func__, __LINE__,
 					repo->bus_index, repo->dev_index);
 			break;
 		}
 
-		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
+		pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n",
 			__func__, __LINE__, repo->bus_index, repo->dev_index,
 			reg_type, bus_addr, len);
 	}
 
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	pr_devel(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
@@ -1063,22 +1063,22 @@ static int dump_stor_dev_info(struct ps3_repository_device *repo)
 	unsigned int num_regions, region_index;
 	u64 port, blk_size, num_blocks;
 
-	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+	pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
 		repo->bus_index, repo->dev_index);
 
 	result = ps3_repository_read_stor_dev_info(repo->bus_index,
 		repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
 	if (result) {
-		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+		pr_devel("%s:%d ps3_repository_read_stor_dev_info"
 			" (%u:%u) failed\n", __func__, __LINE__,
 			repo->bus_index, repo->dev_index);
 		goto out;
 	}
 
-	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
-		 "%lu, num_regions %u\n",
-		 __func__, __LINE__, repo->bus_index, repo->dev_index, port,
-		 blk_size, num_blocks, num_regions);
+	pr_devel("%s:%d  (%u:%u): port %llu, blk_size %llu, num_blocks "
+		 "%llu, num_regions %u\n",
+		 __func__, __LINE__, repo->bus_index, repo->dev_index,
+		port, blk_size, num_blocks, num_regions);
 
 	for (region_index = 0; region_index < num_regions; region_index++) {
 		unsigned int region_id;
@@ -1088,19 +1088,20 @@ static int dump_stor_dev_info(struct ps3_repository_device *repo)
 			repo->dev_index, region_index, &region_id,
 			&region_start, &region_size);
 		if (result) {
-			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+			 pr_devel("%s:%d ps3_repository_read_stor_dev_region"
 				  " (%u:%u) failed\n", __func__, __LINE__,
 				  repo->bus_index, repo->dev_index);
 			break;
 		}
 
-		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+		pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
 			__func__, __LINE__, repo->bus_index, repo->dev_index,
-			region_id, region_start, region_size);
+			region_id, (unsigned long)region_start,
+			(unsigned long)region_size);
 	}
 
 out:
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	pr_devel(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
@@ -1109,7 +1110,7 @@ static int dump_device_info(struct ps3_repository_device *repo,
 {
 	int result = 0;
 
-	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
+	pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
 
 	for (repo->dev_index = 0; repo->dev_index < num_dev;
 		repo->dev_index++) {
@@ -1118,7 +1119,7 @@ static int dump_device_info(struct ps3_repository_device *repo,
 			repo->dev_index, &repo->dev_type);
 
 		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_type"
+			pr_devel("%s:%d ps3_repository_read_dev_type"
 				" (%u:%u) failed\n", __func__, __LINE__,
 				repo->bus_index, repo->dev_index);
 			break;
@@ -1128,15 +1129,15 @@ static int dump_device_info(struct ps3_repository_device *repo,
 			repo->dev_index, &repo->dev_id);
 
 		if (result) {
-			pr_debug("%s:%d ps3_repository_read_dev_id"
+			pr_devel("%s:%d ps3_repository_read_dev_id"
 				" (%u:%u) failed\n", __func__, __LINE__,
 				repo->bus_index, repo->dev_index);
 			continue;
 		}
 
-		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %lu\n", __func__,
+		pr_devel("%s:%d  (%u:%u): dev_type %u, dev_id %lu\n", __func__,
 			__LINE__, repo->bus_index, repo->dev_index,
-			repo->dev_type, repo->dev_id);
+			repo->dev_type, (unsigned long)repo->dev_id);
 
 		ps3_repository_dump_resource_info(repo);
 
@@ -1144,7 +1145,7 @@ static int dump_device_info(struct ps3_repository_device *repo,
 			dump_stor_dev_info(repo);
 	}
 
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	pr_devel(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
@@ -1153,7 +1154,7 @@ int ps3_repository_dump_bus_info(void)
 	int result = 0;
 	struct ps3_repository_device repo;
 
-	pr_debug(" -> %s:%d\n", __func__, __LINE__);
+	pr_devel(" -> %s:%d\n", __func__, __LINE__);
 
 	memset(&repo, 0, sizeof(repo));
 
@@ -1164,7 +1165,7 @@ int ps3_repository_dump_bus_info(void)
 			&repo.bus_type);
 
 		if (result) {
-			pr_debug("%s:%d read_bus_type(%u) failed\n",
+			pr_devel("%s:%d read_bus_type(%u) failed\n",
 				__func__, __LINE__, repo.bus_index);
 			break;
 		}
@@ -1173,32 +1174,32 @@ int ps3_repository_dump_bus_info(void)
 			&repo.bus_id);
 
 		if (result) {
-			pr_debug("%s:%d read_bus_id(%u) failed\n",
+			pr_devel("%s:%d read_bus_id(%u) failed\n",
 				__func__, __LINE__, repo.bus_index);
 			continue;
 		}
 
 		if (repo.bus_index != repo.bus_id)
-			pr_debug("%s:%d bus_index != bus_id\n",
+			pr_devel("%s:%d bus_index != bus_id\n",
 				__func__, __LINE__);
 
 		result = ps3_repository_read_bus_num_dev(repo.bus_index,
 			&num_dev);
 
 		if (result) {
-			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
+			pr_devel("%s:%d read_bus_num_dev(%u) failed\n",
 				__func__, __LINE__, repo.bus_index);
 			continue;
 		}
 
-		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
+		pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
 			__func__, __LINE__, repo.bus_index, repo.bus_type,
-			repo.bus_id, num_dev);
+			(unsigned long)repo.bus_id, num_dev);
 
 		dump_device_info(&repo, num_dev);
 	}
 
-	pr_debug(" <- %s:%d\n", __func__, __LINE__);
+	pr_devel(" <- %s:%d\n", __func__, __LINE__);
 	return result;
 }
 
-- 
1.7.0.4

^ permalink raw reply related

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Kumar Gala @ 2011-12-01 19:35 UTC (permalink / raw)
  To: Jean-Michel Hautbois; +Cc: linuxppc-dev, Tabi Timur-B04825, linux-kernel
In-Reply-To: <CAL8zT=jgZS2=t0SadUXXshabKPsxHJe_frkfOw5XyF88k3jR=g@mail.gmail.com>


On Dec 1, 2011, at 11:52 AM, Jean-Michel Hautbois wrote:

> 2011/12/1 Jean-Michel Hautbois <jhautbois@gmail.com>:
>> 2011/12/1 Tabi Timur-B04825 <B04825@freescale.com>:
>>> On Thu, Dec 1, 2011 at 9:04 AM, Jean-Michel Hautbois
>>> <jhautbois@gmail.com> wrote:
>>>> 
>>>> Any idea on how to debug this ? I am using a 2.6.35 kernel.
>>> 
>>> There are a ton of Kconfig options for debugging various locking bugs.
>>>  Try turning them on.
>>> 
> 
> All Kconfig options do not help me with cache coherency problems, though.
> Or, I didn't find any option related.
> Any idea ?
> 
> JM

Nope, if you can't describe the code in any more detail we can't help.

- k

^ permalink raw reply

* Re: Different behaviour when using "nosmp" parameter on SMP and UP
From: Jean-Michel Hautbois @ 2011-12-01 20:09 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Tabi Timur-B04825, linux-kernel
In-Reply-To: <40F38A2B-48A0-4A8C-B45D-579865F135CC@kernel.crashing.org>

2011/12/1 Kumar Gala <galak@kernel.crashing.org>:
>
> On Dec 1, 2011, at 11:52 AM, Jean-Michel Hautbois wrote:
>
>> 2011/12/1 Jean-Michel Hautbois <jhautbois@gmail.com>:
>>> 2011/12/1 Tabi Timur-B04825 <B04825@freescale.com>:
>>>> On Thu, Dec 1, 2011 at 9:04 AM, Jean-Michel Hautbois
>>>> <jhautbois@gmail.com> wrote:
>>>>>
>>>>> Any idea on how to debug this ? I am using a 2.6.35 kernel.
>>>>
>>>> There are a ton of Kconfig options for debugging various locking bugs.
>>>> =C2=A0Try turning them on.
>>>>
>>
>> All Kconfig options do not help me with cache coherency problems, though=
.
>> Or, I didn't find any option related.
>> Any idea ?
>>
>> JM
>
> Nope, if you can't describe the code in any more detail we can't help.
>

Here is what I can tell, I hope this will help you.

I have a userland process, which reads and writes data to a character
device thanks to ioctl.
Reads and Writes are performed with this scheme :
Lock Access -> ioctl -> down_interruptible(semaphore)
Read (or Write) -> ioctl -> ioread32
Unlock Access -> ioctl -> up(semaphore)

It reads (or writes) 4 bytes by 4 bytes, in a loop in the process
which will eventually get several bytes from the PCIe device.
The read (write) ioctl is really simple (and in fact, may be rewritten) :
- kmalloc a structure, then copy_from_user
- ioread32 using adress and offset from the structure copied previously
- copy_to_user and free the structure.

The userland process is currently doing a loop in order to read or
writes with a 4bytes step.
I am neither the writer of the driver nor the userland process, this
is why I can't give you the code.

Here is what I would do, at least :
1/ rewrite the read/write part of the ioctl in order to user a per_cpu
structure and not a "dynamically allocated at each call" structure
2/ rewrite the userland part in order to ask the driver for n bytes,
leaving the loop on ioread32/iowrite32 inside the ioctl

Thanks for your help.
JM

^ permalink raw reply

* Re: [PATCH] i2c-mpc: use the cell-index property to enumerate the I2C adapters
From: Timur Tabi @ 2011-12-01 20:54 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, kumar.gala
In-Reply-To: <4ED7CA64.2080503@freescale.com>

Scott Wood wrote:
> On 12/01/2011 11:33 AM, Timur Tabi wrote:
>> An I2C device tree node can contain a 'cell-index' property that can be
>> used to enumerate the I2C devices.  If such a property exists, use it
>> to specify the I2C adapter number.
> 
> Didn't we decide a long time ago that this was a bad idea?

I don't see what's wrong with it.

>> This feature is necessary for the Freescale PowerPC audio drivers (e.g.
>> on the P1022DS).  The "machine driver" needs to know the adapter number
>> for each I2C adapter, but it only has access to the device tree.
>> Previously, the I2C nodes always appeared in cell-index order, so the
>> dynamic numbering coincided with the cell-index property.  With commit
>> ab827d97 ("powerpc/85xx: Rework P1022DS device tree"), the I2C nodes are
>> unintentionally reversed in the device tree, and so the machine driver
>> guesses the wrong I2C adapter number.
> 
> What specifically do you need this number for?  What does it represent?

Well, I thought the above paragraph explained it pretty well.

Audio drivers come in sets of four -- machine, ssi, dma, and codec.  The machine driver needs to know which ssi is connected to which codec and which DMA channel(s) it needs to use.  So I extract all this information from the device tree.  

The individual drivers, however, register only with their own subsystem.  So the codec driver, for example, doesn't know anything about device trees -- it just registers as an i2c driver.  That means that the machine driver has to guess what name the codec driver will use when it registers.  In this case, that's the i2c device name, which include the I2C adapter number (adap->nr).  That means that given a device tree node, I need to know what the actual bus number is.

An alternative approach is to create a function like this:

	struct i2c_adapter *i2c_adapter_from_node(struct device_node *np);

I could then just use adap->nr directly.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: [PATCH] i2c-mpc: use the cell-index property to enumerate the I2C adapters
From: Scott Wood @ 2011-12-01 21:29 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev, kumar.gala
In-Reply-To: <4ED7E975.6090704@freescale.com>

On 12/01/2011 02:54 PM, Timur Tabi wrote:
> Scott Wood wrote:
>> On 12/01/2011 11:33 AM, Timur Tabi wrote:
>>> An I2C device tree node can contain a 'cell-index' property that can be
>>> used to enumerate the I2C devices.  If such a property exists, use it
>>> to specify the I2C adapter number.
>>
>> Didn't we decide a long time ago that this was a bad idea?
> 
> I don't see what's wrong with it.

Obviously, since you're suggesting doing it. :-P

Did you search for the old discussions?

How is this going to interact with other i2c buses (e.g. on a board
FPGA) that might have a conflicting static numbering scheme?  Have you
ensured that no dynamic bus registrations (e.g. an i2c bus on a PCI
device) can happen before the static SoC i2c buses are added?

Global numberspaces of this sort are usually the wrong answer.  Look at
the mess it made with IRQ numbers, and the gymnastics we go through to
virtualize it.

>>> This feature is necessary for the Freescale PowerPC audio drivers (e.g.
>>> on the P1022DS).  The "machine driver" needs to know the adapter number
>>> for each I2C adapter, but it only has access to the device tree.
>>> Previously, the I2C nodes always appeared in cell-index order, so the
>>> dynamic numbering coincided with the cell-index property.  With commit
>>> ab827d97 ("powerpc/85xx: Rework P1022DS device tree"), the I2C nodes are
>>> unintentionally reversed in the device tree, and so the machine driver
>>> guesses the wrong I2C adapter number.
>>
>> What specifically do you need this number for?  What does it represent?
> 
> Well, I thought the above paragraph explained it pretty well.

All you said was "needs to know the adapter number", nothing about why.

> Audio drivers come in sets of four -- machine, ssi, dma, and codec.
> The machine driver needs to know which ssi is connected to which
> codec and which DMA channel(s) it needs to use.  So I extract all
> this information from the device tree.
>
> The individual drivers, however, register only with their own
> subsystem.  So the codec driver, for example, doesn't know anything
> about device trees -- it just registers as an i2c driver.  That means
> that the machine driver has to guess what name the codec driver will
> use when it registers.  In this case, that's the i2c device name,
> which include the I2C adapter number (adap->nr).  That means that
> given a device tree node, I need to know what the actual bus number
> is.
> 
> An alternative approach is to create a function like this:
> 
> 	struct i2c_adapter *i2c_adapter_from_node(struct device_node *np);
> 
> I could then just use adap->nr directly.

If there isn't a way to get a "struct device" from "struct device_node",
we should add it.  From that you should be able to look up the sysfs
name -- no need to mess around with adap->nr as an intermediary.

-Scott

^ permalink raw reply

* Re: [BUG?]3.0-rc4+ftrace+kprobe: set kprobe at instruction 'stwu' lead to system crash/freeze
From: Benjamin Herrenschmidt @ 2011-12-01 21:37 UTC (permalink / raw)
  To: tiejun.chen
  Cc: Jim Keniston, Anton Blanchard, linux-kernel, Steven Rostedt,
	Yong Zhang, paulus, yrl.pp-manager.tt, Masami Hiramatsu,
	linuxppc-dev
In-Reply-To: <4ED75A9A.1030100@windriver.com>

On Thu, 2011-12-01 at 18:44 +0800, tiejun.chen wrote:

> Do you mean we should push the original pt_regs (or that whole exception stack)
> downwards the location the new r1 point? Then its safe to perform this real
> emulated stw instruction. At last we will reroute r1 to that copied exception
> frame to restore as normal. Right?

Right. That way we don't have to modify the (sensitive) restore path, we
only hook around the do_work branch which is a lot easier and less
risky.

> Here I suppose so, I implement this for PPC32 based on the above understanding.
> I take a validation for kprobing do_fork()/show_interrupts(), now looks fine.
> Tomorrow I will go PPC64, and hope its fine as well.
> 
> If everything is good I'll send these patches to linuxppc-dev next week.

Excellent, thanks !

Cheers,
Ben.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox