All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
@ 2013-04-19 10:47 ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

These cache operations support Freescale SoCs based on BOOK3E.
Move L1 cache operations to fsl_booke_cache.S in order to maintain
easily. And, add cache operations for backside L2 cache and platform cache.

The backside L2 cache appears on e500mc and e5500 core. The platform cache
supported by this patch is L2 Look-Aside Cache, which appears on SoCs
with e500v1/e500v2 core, such as MPC8572, P1020, etc.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/include/asm/cacheflush.h |    8 ++
 arch/powerpc/kernel/Makefile          |    1 +
 arch/powerpc/kernel/fsl_booke_cache.S |  210 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
 4 files changed, 219 insertions(+), 74 deletions(-)
 create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S

diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index b843e35..bc3f937 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -32,6 +32,14 @@ extern void flush_dcache_page(struct page *page);
 
 extern void __flush_disable_L1(void);
 
+#ifdef CONFIG_FSL_SOC_BOOKE
+void flush_dcache_L1(void);
+void flush_backside_L2_cache(void);
+void disable_backside_L2_cache(void);
+void flush_disable_L2(void);
+void invalidate_enable_L2(void);
+#endif
+
 extern void __flush_icache_range(unsigned long, unsigned long);
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index f960a79..4acf739 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -87,6 +87,7 @@ extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-y				+= vmlinux.lds
 
 obj-$(CONFIG_RELOCATABLE_PPC32)	+= reloc_32.o
+obj-$(CONFIG_FSL_SOC_BOOKE)	+= fsl_booke_cache.o
 
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
 obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
diff --git a/arch/powerpc/kernel/fsl_booke_cache.S b/arch/powerpc/kernel/fsl_booke_cache.S
new file mode 100644
index 0000000..232c47b
--- /dev/null
+++ b/arch/powerpc/kernel/fsl_booke_cache.S
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2009-2013 Freescale Semiconductor, Inc.
+ *	Scott Wood <scottwood@freescale.com>
+ *	Dave Liu <daveliu@freescale.com>
+ *
+ * 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 <asm/reg.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+	.section .text
+
+/********    L1 Cache    ********/
+
+/* flush L1 d-cache */
+_GLOBAL(flush_dcache_L1)
+	mfspr	r3,SPRN_L1CFG0
+
+	rlwinm	r5,r3,9,3	/* Extract cache block size */
+	twlgti	r5,1		/* Only 32 and 64 byte cache blocks
+				 * are currently defined.
+				 */
+	li	r4,32
+	subfic	r6,r5,2		/* r6 = log2(1KiB / cache block size) -
+				 *      log2(number of ways)
+				 */
+	slw	r5,r4,r5	/* r5 = cache block size */
+
+	rlwinm	r7,r3,0,0xff	/* Extract number of KiB in the cache */
+	mulli	r7,r7,13	/* An 8-way cache will require 13
+				 * loads per set.
+				 */
+	slw	r7,r7,r6
+
+	/* save off HID0 and set DCFA */
+	mfspr	r8,SPRN_HID0
+	ori	r9,r8,HID0_DCFA@l
+	mtspr	SPRN_HID0,r9
+	isync
+
+	LOAD_REG_IMMEDIATE(r4, KERNELBASE)
+	mtctr	r7
+
+1:	lwz	r3,0(r4)	/* Load... */
+	add	r4,r4,r5
+	bdnz	1b
+
+	msync
+	LOAD_REG_IMMEDIATE(r4, KERNELBASE)
+	mtctr	r7
+
+1:	dcbf	0,r4		/* ...and flush. */
+	add	r4,r4,r5
+	bdnz	1b
+
+	/* restore HID0 */
+	mtspr	SPRN_HID0,r8
+	isync
+
+	blr
+
+/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
+_GLOBAL(__flush_disable_L1)
+	mflr	r10
+	bl	flush_dcache_L1	/* Flush L1 d-cache */
+	mtlr	r10
+
+	msync
+	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
+	li	r5, 2
+	rlwimi	r4, r5, 0, 3
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r4
+	isync
+
+	msync
+1:	mfspr	r4, SPRN_L1CSR0	/* Wait for the invalidate to finish */
+	andi.	r4, r4, 2
+	bne	1b
+
+	msync
+	mfspr	r4, SPRN_L1CSR1	/* Invalidate and disable i-cache */
+	li	r5, 2
+	rlwimi	r4, r5, 0, 3
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR1, r4
+	isync
+	msync
+
+	blr
+
+/********    Backside L2 Cache    ********/
+
+#define SVR_P2040	0x821000
+
+need_L2_cache:
+	/* skip L2 cache on P2040/P2040E as they have no L2 cache */
+	mfspr	r3, SPRN_SVR
+	/* shift right by 8 bits and clear E bit of SVR */
+	rlwinm	r4, r3, 24, ~0x800
+
+	lis	r3, SVR_P2040@h
+	ori	r3, r3, SVR_P2040@l
+	cmpw	r4, r3
+	beq	1f
+
+	/* If L2 cache is disabled, skip it */
+	mfspr	r3, SPRN_L2CSR0
+	andis.	r3, r3, L2CSR0_L2E@h
+	beq	1f
+
+	li	r3, 0
+	blr
+1:
+	li	r3, 1
+	blr
+
+/* flush backside L2 cache */
+_GLOBAL(flush_backside_L2_cache)
+	mflr	r10
+	bl	need_L2_cache
+	mtlr	r10
+	cmpwi	r3, 0
+	bne	2f
+
+__flush_backside_L2_cache:
+	/* Flush the L2 cache */
+	mfspr	r3, SPRN_L2CSR0
+	ori	r3, r3, L2CSR0_L2FL@l
+	msync
+	isync
+	mtspr	SPRN_L2CSR0,r3
+	isync
+1:
+	mfspr	r3,SPRN_L2CSR0
+	andi.	r3, r3, L2CSR0_L2FL@l
+	bne	1b
+2:
+	blr
+
+/* flush and disable backside L2 cache */
+_GLOBAL(disable_backside_L2_cache)
+	mflr	r10
+	bl	need_L2_cache
+	mtlr	r10
+	cmpwi	r3, 0
+	bne	1f
+
+	mflr	r10
+	bl	__flush_backside_L2_cache
+	mtlr	r10
+
+	/* disable L2 cache */
+	li	r3, 0
+	msync
+	isync
+	mtspr	SPRN_L2CSR0, r3
+	isync
+1:
+	blr
+
+/********    Platform Cache    ********/
+
+#define L2CTL_L2E	0x80000000
+#define L2CTL_L2I	0x40000000
+
+/* r3 = base address of L2 controller registers */
+_GLOBAL(flush_disable_L2)
+	/* It's a write-through cache, so only invalidation is needed. */
+	mbar
+	isync
+	lwz	r4, 0(r3)
+	li	r5, 1
+	rlwimi	r4, r5, 30, L2CTL_L2E | L2CTL_L2I
+	stw	r4, 0(r3)
+
+	/* Wait for the invalidate to finish */
+1:	lwz	r4, 0(r3)
+	andis.	r4, r4, L2CTL_L2I@h
+	bne	1b
+	mbar
+
+	blr
+
+/* r3 = base address of L2 controller registers */
+_GLOBAL(invalidate_enable_L2)
+	mbar
+	isync
+	lwz	r4, 0(r3)
+	li	r5, 3
+	rlwimi	r4, r5, 30, L2CTL_L2E | L2CTL_L2I
+	stw	r4, 0(r3)
+
+	/* Wait for the invalidate to finish */
+1:	lwz	r4, 0(r3)
+	andis.	r4, r4, L2CTL_L2I@h
+	bne	1b
+	mbar
+
+	blr
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 6f62a73..58925b6 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -987,80 +987,6 @@ _GLOBAL(set_context)
 	isync			/* Force context change */
 	blr
 
-_GLOBAL(flush_dcache_L1)
-	mfspr	r3,SPRN_L1CFG0
-
-	rlwinm	r5,r3,9,3	/* Extract cache block size */
-	twlgti	r5,1		/* Only 32 and 64 byte cache blocks
-				 * are currently defined.
-				 */
-	li	r4,32
-	subfic	r6,r5,2		/* r6 = log2(1KiB / cache block size) -
-				 *      log2(number of ways)
-				 */
-	slw	r5,r4,r5	/* r5 = cache block size */
-
-	rlwinm	r7,r3,0,0xff	/* Extract number of KiB in the cache */
-	mulli	r7,r7,13	/* An 8-way cache will require 13
-				 * loads per set.
-				 */
-	slw	r7,r7,r6
-
-	/* save off HID0 and set DCFA */
-	mfspr	r8,SPRN_HID0
-	ori	r9,r8,HID0_DCFA@l
-	mtspr	SPRN_HID0,r9
-	isync
-
-	lis	r4,KERNELBASE@h
-	mtctr	r7
-
-1:	lwz	r3,0(r4)	/* Load... */
-	add	r4,r4,r5
-	bdnz	1b
-
-	msync
-	lis	r4,KERNELBASE@h
-	mtctr	r7
-
-1:	dcbf	0,r4		/* ...and flush. */
-	add	r4,r4,r5
-	bdnz	1b
-	
-	/* restore HID0 */
-	mtspr	SPRN_HID0,r8
-	isync
-
-	blr
-
-/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
-_GLOBAL(__flush_disable_L1)
-	mflr	r10
-	bl	flush_dcache_L1	/* Flush L1 d-cache */
-	mtlr	r10
-
-	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
-	li	r5, 2
-	rlwimi	r4, r5, 0, 3
-
-	msync
-	isync
-	mtspr	SPRN_L1CSR0, r4
-	isync
-
-1:	mfspr	r4, SPRN_L1CSR0	/* Wait for the invalidate to finish */
-	andi.	r4, r4, 2
-	bne	1b
-
-	mfspr	r4, SPRN_L1CSR1	/* Invalidate and disable i-cache */
-	li	r5, 2
-	rlwimi	r4, r5, 0, 3
-
-	mtspr	SPRN_L1CSR1, r4
-	isync
-
-	blr
-
 #ifdef CONFIG_SMP
 /* When we get here, r24 needs to hold the CPU # */
 	.globl __secondary_start
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
@ 2013-04-19 10:47 ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

These cache operations support Freescale SoCs based on BOOK3E.
Move L1 cache operations to fsl_booke_cache.S in order to maintain
easily. And, add cache operations for backside L2 cache and platform cache.

The backside L2 cache appears on e500mc and e5500 core. The platform cache
supported by this patch is L2 Look-Aside Cache, which appears on SoCs
with e500v1/e500v2 core, such as MPC8572, P1020, etc.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/include/asm/cacheflush.h |    8 ++
 arch/powerpc/kernel/Makefile          |    1 +
 arch/powerpc/kernel/fsl_booke_cache.S |  210 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
 4 files changed, 219 insertions(+), 74 deletions(-)
 create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S

diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index b843e35..bc3f937 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -32,6 +32,14 @@ extern void flush_dcache_page(struct page *page);
 
 extern void __flush_disable_L1(void);
 
+#ifdef CONFIG_FSL_SOC_BOOKE
+void flush_dcache_L1(void);
+void flush_backside_L2_cache(void);
+void disable_backside_L2_cache(void);
+void flush_disable_L2(void);
+void invalidate_enable_L2(void);
+#endif
+
 extern void __flush_icache_range(unsigned long, unsigned long);
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index f960a79..4acf739 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -87,6 +87,7 @@ extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-y				+= vmlinux.lds
 
 obj-$(CONFIG_RELOCATABLE_PPC32)	+= reloc_32.o
+obj-$(CONFIG_FSL_SOC_BOOKE)	+= fsl_booke_cache.o
 
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
 obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
diff --git a/arch/powerpc/kernel/fsl_booke_cache.S b/arch/powerpc/kernel/fsl_booke_cache.S
new file mode 100644
index 0000000..232c47b
--- /dev/null
+++ b/arch/powerpc/kernel/fsl_booke_cache.S
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2009-2013 Freescale Semiconductor, Inc.
+ *	Scott Wood <scottwood@freescale.com>
+ *	Dave Liu <daveliu@freescale.com>
+ *
+ * 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 <asm/reg.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+	.section .text
+
+/********    L1 Cache    ********/
+
+/* flush L1 d-cache */
+_GLOBAL(flush_dcache_L1)
+	mfspr	r3,SPRN_L1CFG0
+
+	rlwinm	r5,r3,9,3	/* Extract cache block size */
+	twlgti	r5,1		/* Only 32 and 64 byte cache blocks
+				 * are currently defined.
+				 */
+	li	r4,32
+	subfic	r6,r5,2		/* r6 = log2(1KiB / cache block size) -
+				 *      log2(number of ways)
+				 */
+	slw	r5,r4,r5	/* r5 = cache block size */
+
+	rlwinm	r7,r3,0,0xff	/* Extract number of KiB in the cache */
+	mulli	r7,r7,13	/* An 8-way cache will require 13
+				 * loads per set.
+				 */
+	slw	r7,r7,r6
+
+	/* save off HID0 and set DCFA */
+	mfspr	r8,SPRN_HID0
+	ori	r9,r8,HID0_DCFA@l
+	mtspr	SPRN_HID0,r9
+	isync
+
+	LOAD_REG_IMMEDIATE(r4, KERNELBASE)
+	mtctr	r7
+
+1:	lwz	r3,0(r4)	/* Load... */
+	add	r4,r4,r5
+	bdnz	1b
+
+	msync
+	LOAD_REG_IMMEDIATE(r4, KERNELBASE)
+	mtctr	r7
+
+1:	dcbf	0,r4		/* ...and flush. */
+	add	r4,r4,r5
+	bdnz	1b
+
+	/* restore HID0 */
+	mtspr	SPRN_HID0,r8
+	isync
+
+	blr
+
+/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
+_GLOBAL(__flush_disable_L1)
+	mflr	r10
+	bl	flush_dcache_L1	/* Flush L1 d-cache */
+	mtlr	r10
+
+	msync
+	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
+	li	r5, 2
+	rlwimi	r4, r5, 0, 3
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r4
+	isync
+
+	msync
+1:	mfspr	r4, SPRN_L1CSR0	/* Wait for the invalidate to finish */
+	andi.	r4, r4, 2
+	bne	1b
+
+	msync
+	mfspr	r4, SPRN_L1CSR1	/* Invalidate and disable i-cache */
+	li	r5, 2
+	rlwimi	r4, r5, 0, 3
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR1, r4
+	isync
+	msync
+
+	blr
+
+/********    Backside L2 Cache    ********/
+
+#define SVR_P2040	0x821000
+
+need_L2_cache:
+	/* skip L2 cache on P2040/P2040E as they have no L2 cache */
+	mfspr	r3, SPRN_SVR
+	/* shift right by 8 bits and clear E bit of SVR */
+	rlwinm	r4, r3, 24, ~0x800
+
+	lis	r3, SVR_P2040@h
+	ori	r3, r3, SVR_P2040@l
+	cmpw	r4, r3
+	beq	1f
+
+	/* If L2 cache is disabled, skip it */
+	mfspr	r3, SPRN_L2CSR0
+	andis.	r3, r3, L2CSR0_L2E@h
+	beq	1f
+
+	li	r3, 0
+	blr
+1:
+	li	r3, 1
+	blr
+
+/* flush backside L2 cache */
+_GLOBAL(flush_backside_L2_cache)
+	mflr	r10
+	bl	need_L2_cache
+	mtlr	r10
+	cmpwi	r3, 0
+	bne	2f
+
+__flush_backside_L2_cache:
+	/* Flush the L2 cache */
+	mfspr	r3, SPRN_L2CSR0
+	ori	r3, r3, L2CSR0_L2FL@l
+	msync
+	isync
+	mtspr	SPRN_L2CSR0,r3
+	isync
+1:
+	mfspr	r3,SPRN_L2CSR0
+	andi.	r3, r3, L2CSR0_L2FL@l
+	bne	1b
+2:
+	blr
+
+/* flush and disable backside L2 cache */
+_GLOBAL(disable_backside_L2_cache)
+	mflr	r10
+	bl	need_L2_cache
+	mtlr	r10
+	cmpwi	r3, 0
+	bne	1f
+
+	mflr	r10
+	bl	__flush_backside_L2_cache
+	mtlr	r10
+
+	/* disable L2 cache */
+	li	r3, 0
+	msync
+	isync
+	mtspr	SPRN_L2CSR0, r3
+	isync
+1:
+	blr
+
+/********    Platform Cache    ********/
+
+#define L2CTL_L2E	0x80000000
+#define L2CTL_L2I	0x40000000
+
+/* r3 = base address of L2 controller registers */
+_GLOBAL(flush_disable_L2)
+	/* It's a write-through cache, so only invalidation is needed. */
+	mbar
+	isync
+	lwz	r4, 0(r3)
+	li	r5, 1
+	rlwimi	r4, r5, 30, L2CTL_L2E | L2CTL_L2I
+	stw	r4, 0(r3)
+
+	/* Wait for the invalidate to finish */
+1:	lwz	r4, 0(r3)
+	andis.	r4, r4, L2CTL_L2I@h
+	bne	1b
+	mbar
+
+	blr
+
+/* r3 = base address of L2 controller registers */
+_GLOBAL(invalidate_enable_L2)
+	mbar
+	isync
+	lwz	r4, 0(r3)
+	li	r5, 3
+	rlwimi	r4, r5, 30, L2CTL_L2E | L2CTL_L2I
+	stw	r4, 0(r3)
+
+	/* Wait for the invalidate to finish */
+1:	lwz	r4, 0(r3)
+	andis.	r4, r4, L2CTL_L2I@h
+	bne	1b
+	mbar
+
+	blr
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 6f62a73..58925b6 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -987,80 +987,6 @@ _GLOBAL(set_context)
 	isync			/* Force context change */
 	blr
 
-_GLOBAL(flush_dcache_L1)
-	mfspr	r3,SPRN_L1CFG0
-
-	rlwinm	r5,r3,9,3	/* Extract cache block size */
-	twlgti	r5,1		/* Only 32 and 64 byte cache blocks
-				 * are currently defined.
-				 */
-	li	r4,32
-	subfic	r6,r5,2		/* r6 = log2(1KiB / cache block size) -
-				 *      log2(number of ways)
-				 */
-	slw	r5,r4,r5	/* r5 = cache block size */
-
-	rlwinm	r7,r3,0,0xff	/* Extract number of KiB in the cache */
-	mulli	r7,r7,13	/* An 8-way cache will require 13
-				 * loads per set.
-				 */
-	slw	r7,r7,r6
-
-	/* save off HID0 and set DCFA */
-	mfspr	r8,SPRN_HID0
-	ori	r9,r8,HID0_DCFA@l
-	mtspr	SPRN_HID0,r9
-	isync
-
-	lis	r4,KERNELBASE@h
-	mtctr	r7
-
-1:	lwz	r3,0(r4)	/* Load... */
-	add	r4,r4,r5
-	bdnz	1b
-
-	msync
-	lis	r4,KERNELBASE@h
-	mtctr	r7
-
-1:	dcbf	0,r4		/* ...and flush. */
-	add	r4,r4,r5
-	bdnz	1b
-	
-	/* restore HID0 */
-	mtspr	SPRN_HID0,r8
-	isync
-
-	blr
-
-/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
-_GLOBAL(__flush_disable_L1)
-	mflr	r10
-	bl	flush_dcache_L1	/* Flush L1 d-cache */
-	mtlr	r10
-
-	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
-	li	r5, 2
-	rlwimi	r4, r5, 0, 3
-
-	msync
-	isync
-	mtspr	SPRN_L1CSR0, r4
-	isync
-
-1:	mfspr	r4, SPRN_L1CSR0	/* Wait for the invalidate to finish */
-	andi.	r4, r4, 2
-	bne	1b
-
-	mfspr	r4, SPRN_L1CSR1	/* Invalidate and disable i-cache */
-	li	r5, 2
-	rlwimi	r4, r5, 0, 3
-
-	mtspr	SPRN_L1CSR1, r4
-	isync
-
-	blr
-
 #ifdef CONFIG_SMP
 /* When we get here, r24 needs to hold the CPU # */
 	.globl __secondary_start
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

Some Freescale SoCs like MPC8536 and P1022 has the deep sleep mode
in addtion to the sleep mode.

In sleep PM mode, the clocks of e500 core and unused IP blocks is
turned off. IP blocks which are allowed to wake up the processor
are still running.

While in deep sleep PM mode, additionally, the power supply is
removed from e500 core and most IP blocks. Only the blocks needed
to wake up the chip out of deep sleep are ON.

This patch supports 32-bit and 36-bit address space.

The sleep mode is equal to the Standby state in Linux. The deep sleep
mode is equal to the Suspend-to-RAM state of Linux Power Management.

Command to enter sleep mode.
  echo standby > /sys/power/state
Command to enter deep sleep mode.
  echo mem > /sys/power/state

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/platforms/85xx/Makefile |    1 +
 arch/powerpc/platforms/85xx/sleep.S  |  621 ++++++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/fsl_pmc.c        |   98 +++++-
 arch/powerpc/sysdev/fsl_soc.h        |    5 +
 4 files changed, 707 insertions(+), 18 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/sleep.S

diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 2eab37e..a35bab7 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 85xx linux kernel.
 #
 obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_FSL_PMC)	+= sleep.o
 
 obj-y += common.o
 
diff --git a/arch/powerpc/platforms/85xx/sleep.S b/arch/powerpc/platforms/85xx/sleep.S
new file mode 100644
index 0000000..5a43adb
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/sleep.S
@@ -0,0 +1,621 @@
+/*
+ * Enter and leave deep sleep/sleep state on MPC85xx
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (C) 2006-2013 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+#include <asm/mmu.h>
+
+#define CCSR_ADDR		0xf0000000
+
+#define L2C_OFFSET		0x20000	/* L2 Cache Controller offset */
+
+#define BPTR_OFFSET		0x20 /* Boot Page Translation Register */
+#define BPTR_EN			0x80000000
+
+#define PMRCCR_OFFSET		0xe0084
+#define PMRCCR_VRCNT_PRE_MASK	0x1f000000
+#define PMRCCR_VRCNT_MASK	0x00ff0000
+
+#define POWMGTSCR_OFFSET	0xe0080
+#define POWMGTSCR_DPSLP		0x00100000 /* deep sleep mode */
+
+#define SS_TB		0x00
+#define SS_HID		0x08 /* 2 HIDs */
+#define SS_IAC		0x10 /* 2 IACs */
+#define SS_DAC		0x18 /* 2 DACs */
+#define SS_DBCR		0x20 /* 3 DBCRs */
+#define SS_PID		0x2c /* 3 PIDs */
+#define SS_SPRG		0x38 /* 8 SPRGs */
+#define SS_IVOR		0x58 /* 20 interrupt vectors */
+#define SS_TCR		0xa8
+#define SS_BUCSR	0xac
+#define SS_L1CSR	0xb0 /* 2 L1CSRs */
+#define SS_MSR		0xb8
+#define SS_USPRG	0xbc
+#define SS_GPREG	0xc0 /* r12-r31 */
+#define SS_LR		0x110
+#define SS_CR		0x114
+#define SS_SP		0x118
+#define SS_CURRENT	0x11c
+#define SS_IVPR		0x120
+#define SS_BPTR		0x124
+
+#define STATE_SAVE_SIZE 0x128
+
+	.section .data
+	.align	5
+mpc85xx_sleep_save_area:
+	.space	STATE_SAVE_SIZE
+ccsrbase_low:
+	.long	0
+ccsrbase_high:
+	.long	0
+powmgtreq:
+	.long	0
+
+	.section .text
+	.align	12
+
+	/*
+	 * r3 = high word of physical address of CCSR
+	 * r4 = low word of physical address of CCSR
+	 * r5 = JOG or deep sleep request
+	 *      JOG-0x00200000, deep sleep-0x00100000
+	 */
+_GLOBAL(mpc85xx_enter_deep_sleep)
+	lis	r6, ccsrbase_low@ha
+	stw	r4, ccsrbase_low@l(r6)
+	lis	r6, ccsrbase_high@ha
+	stw	r3, ccsrbase_high@l(r6)
+
+	lis	r6, powmgtreq@ha
+	stw	r5, powmgtreq@l(r6)
+
+	lis	r10, mpc85xx_sleep_save_area@h
+	ori	r10, r10, mpc85xx_sleep_save_area@l
+
+	mfspr	r5, SPRN_HID0
+	mfspr	r6, SPRN_HID1
+
+	stw	r5, SS_HID+0(r10)
+	stw	r6, SS_HID+4(r10)
+
+	mfspr	r4, SPRN_IAC1
+	mfspr	r5, SPRN_IAC2
+	mfspr	r6, SPRN_DAC1
+	mfspr	r7, SPRN_DAC2
+
+	stw	r4, SS_IAC+0(r10)
+	stw	r5, SS_IAC+4(r10)
+	stw	r6, SS_DAC+0(r10)
+	stw	r7, SS_DAC+4(r10)
+
+	mfspr	r4, SPRN_DBCR0
+	mfspr	r5, SPRN_DBCR1
+	mfspr	r6, SPRN_DBCR2
+
+	stw	r4, SS_DBCR+0(r10)
+	stw	r5, SS_DBCR+4(r10)
+	stw	r6, SS_DBCR+8(r10)
+
+	mfspr	r4, SPRN_PID0
+	mfspr	r5, SPRN_PID1
+	mfspr	r6, SPRN_PID2
+
+	stw	r4, SS_PID+0(r10)
+	stw	r5, SS_PID+4(r10)
+	stw	r6, SS_PID+8(r10)
+
+	mfspr	r4, SPRN_SPRG0
+	mfspr	r5, SPRN_SPRG1
+	mfspr	r6, SPRN_SPRG2
+	mfspr	r7, SPRN_SPRG3
+
+	stw	r4, SS_SPRG+0x00(r10)
+	stw	r5, SS_SPRG+0x04(r10)
+	stw	r6, SS_SPRG+0x08(r10)
+	stw	r7, SS_SPRG+0x0c(r10)
+
+	mfspr	r4, SPRN_SPRG4
+	mfspr	r5, SPRN_SPRG5
+	mfspr	r6, SPRN_SPRG6
+	mfspr	r7, SPRN_SPRG7
+
+	stw	r4, SS_SPRG+0x10(r10)
+	stw	r5, SS_SPRG+0x14(r10)
+	stw	r6, SS_SPRG+0x18(r10)
+	stw	r7, SS_SPRG+0x1c(r10)
+
+	mfspr	r4, SPRN_IVPR
+	stw	r4, SS_IVPR(r10)
+
+	mfspr	r4, SPRN_IVOR0
+	mfspr	r5, SPRN_IVOR1
+	mfspr	r6, SPRN_IVOR2
+	mfspr	r7, SPRN_IVOR3
+
+	stw	r4, SS_IVOR+0x00(r10)
+	stw	r5, SS_IVOR+0x04(r10)
+	stw	r6, SS_IVOR+0x08(r10)
+	stw	r7, SS_IVOR+0x0c(r10)
+
+	mfspr	r4, SPRN_IVOR4
+	mfspr	r5, SPRN_IVOR5
+	mfspr	r6, SPRN_IVOR6
+	mfspr	r7, SPRN_IVOR7
+
+	stw	r4, SS_IVOR+0x10(r10)
+	stw	r5, SS_IVOR+0x14(r10)
+	stw	r6, SS_IVOR+0x18(r10)
+	stw	r7, SS_IVOR+0x1c(r10)
+
+	mfspr	r4, SPRN_IVOR8
+	mfspr	r5, SPRN_IVOR9
+	mfspr	r6, SPRN_IVOR10
+	mfspr	r7, SPRN_IVOR11
+
+	stw	r4, SS_IVOR+0x20(r10)
+	stw	r5, SS_IVOR+0x24(r10)
+	stw	r6, SS_IVOR+0x28(r10)
+	stw	r7, SS_IVOR+0x2c(r10)
+
+	mfspr	r4, SPRN_IVOR12
+	mfspr	r5, SPRN_IVOR13
+	mfspr	r6, SPRN_IVOR14
+	mfspr	r7, SPRN_IVOR15
+
+	stw	r4, SS_IVOR+0x30(r10)
+	stw	r5, SS_IVOR+0x34(r10)
+	stw	r6, SS_IVOR+0x38(r10)
+	stw	r7, SS_IVOR+0x3c(r10)
+
+	mfspr	r4, SPRN_IVOR32
+	mfspr	r5, SPRN_IVOR33
+	mfspr	r6, SPRN_IVOR34
+	mfspr	r7, SPRN_IVOR35
+
+	stw	r4, SS_IVOR+0x40(r10)
+	stw	r5, SS_IVOR+0x44(r10)
+	stw	r6, SS_IVOR+0x48(r10)
+	stw	r7, SS_IVOR+0x4c(r10)
+
+	mfspr	r4, SPRN_TCR
+	mfspr	r5, SPRN_BUCSR
+	mfspr	r6, SPRN_L1CSR0
+	mfspr	r7, SPRN_L1CSR1
+	mfspr	r8, SPRN_USPRG0
+
+	stw	r4, SS_TCR(r10)
+	stw	r5, SS_BUCSR(r10)
+	stw	r6, SS_L1CSR+0(r10)
+	stw	r7, SS_L1CSR+4(r10)
+	stw	r8, SS_USPRG+0(r10)
+
+	stmw	r12, SS_GPREG(r10)
+
+	mfmsr	r4
+	mflr	r5
+	mfcr	r6
+
+	stw	r4, SS_MSR(r10)
+	stw	r5, SS_LR(r10)
+	stw	r6, SS_CR(r10)
+	stw	r1, SS_SP(r10)
+	stw	r2, SS_CURRENT(r10)
+
+1:	mftbu	r4
+	mftb	r5
+	mftbu	r6
+	cmpw	r4, r6
+	bne	1b
+
+	stw	r4, SS_TB+0(r10)
+	stw	r5, SS_TB+4(r10)
+
+	lis	r5, ccsrbase_low@ha
+	lwz	r4, ccsrbase_low@l(r5)
+	lis	r5, ccsrbase_high@ha
+	lwz	r3, ccsrbase_high@l(r5)
+
+	/* Disable machine checks and critical exceptions */
+	mfmsr	r5
+	rlwinm	r5, r5, 0, ~MSR_CE
+	rlwinm	r5, r5, 0, ~MSR_ME
+	mtmsr	r5
+	isync
+
+	/* Use TLB1[15] to map the CCSR at 0xf0000000 */
+	LOAD_REG_IMMEDIATE(r5, MAS0_TLBSEL(1) | MAS0_ESEL(15))
+	mtspr	SPRN_MAS0, r5
+	LOAD_REG_IMMEDIATE(r5,
+		MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(BOOK3E_PAGESZ_1M))
+	mtspr	SPRN_MAS1, r5
+	LOAD_REG_IMMEDIATE(r5, CCSR_ADDR | MAS2_I | MAS2_M)
+	mtspr	SPRN_MAS2, r5
+	rlwinm	r5, r4, 0, MAS3_RPN
+	ori	r5, r5, (MAS3_SW | MAS3_SR)
+	mtspr	SPRN_MAS3, r5
+	mtspr	SPRN_MAS7, r3
+	isync
+	tlbwe
+	isync
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + BPTR_OFFSET)
+	lwz	r4, 0(r3)
+	stw	r4, SS_BPTR(r10)
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + L2C_OFFSET)
+	bl	flush_disable_L2
+	bl	__flush_disable_L1
+
+	/* Enable I-cache, so as not to upset the bus
+	 * with our loop.
+	 */
+	mfspr	r4, SPRN_L1CSR1
+	ori	r4, r4, L1CSR1_ICE
+	mtspr	SPRN_L1CSR1, r4
+	isync
+
+	/* Set boot page translation */
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + BPTR_OFFSET)
+	lis	r4, (mpc85xx_deep_resume - PAGE_OFFSET)@h
+	ori	r4, r4, (mpc85xx_deep_resume - PAGE_OFFSET)@l
+	rlwinm	r4, r4, 20, 12, 31
+	oris	r4, r4, BPTR_EN@h
+	stw	r4, 0(r3)
+	lwz	r4, 0(r3) /* read-back to flush write */
+	twi	0, r4, 0
+	isync
+
+	/* Disable the decrementer */
+	mfspr	r4, SPRN_TCR
+	rlwinm	r4, r4, 0, ~TCR_DIE
+	mtspr	SPRN_TCR, r4
+
+	mfspr	r4, SPRN_TSR
+	oris	r4, r4, TSR_DIS@h
+	mtspr	SPRN_TSR, r4
+
+	/* set PMRCCR[VRCNT] to wait power stable for 40ms */
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + PMRCCR_OFFSET)
+	lwz	r4, 0(r3)
+	li	r5, 0x12
+	rlwimi	r4, r5, 0, PMRCCR_VRCNT_PRE_MASK
+	li	r5, 0xa3
+	rlwimi	r4, r5, 0, PMRCCR_VRCNT_MASK
+	stw	r4, 0(r3)
+	lwz	r4, 0(r3)
+
+	/* set deep sleep bit in POWMGTSCR */
+	lis	r3, powmgtreq@ha
+	lwz	r8, powmgtreq@l(r3)
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + POWMGTSCR_OFFSET)
+	lwz	r4, 0(r3)
+	or	r4, r4, r8
+	stw	r4, 0(r3)
+	lwz	r4, 0(r3)		/* read-back to flush write */
+	twi	0, r4, 0
+	isync
+
+	mftb	r5
+1:	/* spin until either we enter deep sleep, or the sleep process is
+	 * aborted due to a pending wakeup event.  Wait some time between
+	 * accesses, so we don't flood the bus and prevent the pmc from
+	 * detecting an idle system.
+	 */
+
+	mftb	r4
+	subf	r7, r5, r4
+	cmpwi	r7, 1000
+	blt	1b
+	mr	r5, r4
+
+	lwz	r6, 0(r3)
+	andis.	r6, r6, POWMGTSCR_DPSLP@h
+	bne	1b
+	b	2f
+
+2:	mfspr	r4, SPRN_PIR
+	andi.	r4, r4, 1
+99:	bne	99b
+
+	/* Establish a temporary 64MB 0->0 mapping in TLB1[1]. */
+	LOAD_REG_IMMEDIATE(r4, MAS0_TLBSEL(1) | MAS0_ESEL(1))
+	mtspr	SPRN_MAS0, r4
+	LOAD_REG_IMMEDIATE(r4,
+		MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(BOOK3E_PAGESZ_64M))
+	mtspr	SPRN_MAS1, r4
+	li	r4, 0
+	mtspr	SPRN_MAS2, r4
+	li	r4, (MAS3_SX | MAS3_SW | MAS3_SR)
+	mtspr	SPRN_MAS3, r4
+	li	r4, 0
+	mtspr	SPRN_MAS7, r4
+	isync
+	tlbwe
+	isync
+
+	lis	r3, (3f - PAGE_OFFSET)@h
+	ori	r3, r3, (3f - PAGE_OFFSET)@l
+	mtctr	r3
+	bctr
+
+	/* Locate the resume vector in the last word of the current page. */
+	. = mpc85xx_enter_deep_sleep + 0xffc
+mpc85xx_deep_resume:
+	b	2b
+
+3:
+	/* Restore the contents of TLB1[0].  It is assumed that it covers
+	 * the currently executing code and the sleep save area, and that
+	 * it does not alias our temporary mapping (which is at virtual zero).
+	 */
+	lis	r3, (TLBCAM - PAGE_OFFSET)@h
+	ori	r3, r3, (TLBCAM - PAGE_OFFSET)@l
+
+	lwz	r4, 0(r3)
+	lwz	r5, 4(r3)
+	lwz	r6, 8(r3)
+	lwz	r7, 12(r3)
+	lwz	r8, 16(r3)
+
+	mtspr	SPRN_MAS0, r4
+	mtspr	SPRN_MAS1, r5
+	mtspr	SPRN_MAS2, r6
+	mtspr	SPRN_MAS3, r7
+	mtspr	SPRN_MAS7, r8
+
+	isync
+	tlbwe
+	isync
+
+	/* Access the ccsrbase address with TLB1[0] */
+	lis	r5, ccsrbase_low@ha
+	lwz	r4, ccsrbase_low@l(r5)
+	lis	r5, ccsrbase_high@ha
+	lwz	r3, ccsrbase_high@l(r5)
+
+	/* Use TLB1[15] to map the CCSR at 0xf0000000 */
+	LOAD_REG_IMMEDIATE(r5, MAS0_TLBSEL(1) | MAS0_ESEL(15))
+	mtspr	SPRN_MAS0, r5
+	LOAD_REG_IMMEDIATE(r5,
+		MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(BOOK3E_PAGESZ_1M))
+	mtspr	SPRN_MAS1, r5
+	LOAD_REG_IMMEDIATE(r5, CCSR_ADDR | MAS2_I | MAS2_M)
+	mtspr	SPRN_MAS2, r5
+	rlwinm	r5, r4, 0, MAS3_RPN
+	ori	r5, r5, (MAS3_SW | MAS3_SR)
+	mtspr	SPRN_MAS3, r5
+	mtspr	SPRN_MAS7, r3
+	isync
+	tlbwe
+	isync
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + L2C_OFFSET)
+	bl	invalidate_enable_L2
+
+	/* Access the MEM(r10) with TLB1[0] */
+	lis	r10, mpc85xx_sleep_save_area@h
+	ori	r10, r10, mpc85xx_sleep_save_area@l
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + BPTR_OFFSET)
+	lwz	r4, SS_BPTR(r10)
+	stw	r4, 0(r3)		/* restore BPTR */
+
+	/* Program shift running space to PAGE_OFFSET */
+	mfmsr	r3
+	lis	r4, 1f@h
+	ori	r4, r4, 1f@l
+
+	mtsrr1	r3
+	mtsrr0	r4
+	rfi
+
+1:	/* Restore the rest of TLB1, in ascending order so that
+	 * the TLB1[1] gets invalidated first.
+	 *
+	 * XXX: It's better to invalidate the temporary mapping
+	 * TLB1[15] for CCSR before restore any TLB1 entry include 0.
+	 */
+	LOAD_REG_IMMEDIATE(r4, MAS0_TLBSEL(1) | MAS0_ESEL(15))
+	mtspr	SPRN_MAS0, r4
+	lis	r4, 0
+	mtspr	SPRN_MAS1, r4
+	isync
+	tlbwe
+	isync
+
+	lis	r3, (TLBCAM + 5*4 - 4)@h
+	ori	r3, r3, (TLBCAM + 5*4 - 4)@l
+	li	r4, 15
+	mtctr	r4
+
+2:
+	lwz	r5, 4(r3)
+	lwz	r6, 8(r3)
+	lwz	r7, 12(r3)
+	lwz	r8, 16(r3)
+	lwzu	r9, 20(r3)
+
+	mtspr	SPRN_MAS0, r5
+	mtspr	SPRN_MAS1, r6
+	mtspr	SPRN_MAS2, r7
+	mtspr	SPRN_MAS3, r8
+	mtspr	SPRN_MAS7, r9
+
+	isync
+	tlbwe
+	isync
+	bdnz	2b
+
+	lis	r10, mpc85xx_sleep_save_area@h
+	ori	r10, r10, mpc85xx_sleep_save_area@l
+
+	lwz	r5, SS_HID+0(r10)
+	lwz	r6, SS_HID+4(r10)
+
+	isync
+	mtspr	SPRN_HID0, r5
+	isync
+
+	msync
+	mtspr	SPRN_HID1, r6
+	isync
+
+	lwz	r4, SS_IAC+0(r10)
+	lwz	r5, SS_IAC+4(r10)
+	lwz	r6, SS_DAC+0(r10)
+	lwz	r7, SS_DAC+4(r10)
+
+	mtspr	SPRN_IAC1, r4
+	mtspr	SPRN_IAC2, r5
+	mtspr	SPRN_DAC1, r6
+	mtspr	SPRN_DAC2, r7
+
+	lwz	r4, SS_DBCR+0(r10)
+	lwz	r5, SS_DBCR+4(r10)
+	lwz	r6, SS_DBCR+8(r10)
+
+	mtspr	SPRN_DBCR0, r4
+	mtspr	SPRN_DBCR1, r5
+	mtspr	SPRN_DBCR2, r6
+
+	lwz	r4, SS_PID+0(r10)
+	lwz	r5, SS_PID+4(r10)
+	lwz	r6, SS_PID+8(r10)
+
+	mtspr	SPRN_PID0, r4
+	mtspr	SPRN_PID1, r5
+	mtspr	SPRN_PID2, r6
+
+	lwz	r4, SS_SPRG+0x00(r10)
+	lwz	r5, SS_SPRG+0x04(r10)
+	lwz	r6, SS_SPRG+0x08(r10)
+	lwz	r7, SS_SPRG+0x0c(r10)
+
+	mtspr	SPRN_SPRG0, r4
+	mtspr	SPRN_SPRG1, r5
+	mtspr	SPRN_SPRG2, r6
+	mtspr	SPRN_SPRG3, r7
+
+	lwz	r4, SS_SPRG+0x10(r10)
+	lwz	r5, SS_SPRG+0x14(r10)
+	lwz	r6, SS_SPRG+0x18(r10)
+	lwz	r7, SS_SPRG+0x1c(r10)
+
+	mtspr	SPRN_SPRG4, r4
+	mtspr	SPRN_SPRG5, r5
+	mtspr	SPRN_SPRG6, r6
+	mtspr	SPRN_SPRG7, r7
+
+	lwz	r4, SS_IVPR(r10)
+	mtspr	SPRN_IVPR, r4
+
+	lwz	r4, SS_IVOR+0x00(r10)
+	lwz	r5, SS_IVOR+0x04(r10)
+	lwz	r6, SS_IVOR+0x08(r10)
+	lwz	r7, SS_IVOR+0x0c(r10)
+
+	mtspr	SPRN_IVOR0, r4
+	mtspr	SPRN_IVOR1, r5
+	mtspr	SPRN_IVOR2, r6
+	mtspr	SPRN_IVOR3, r7
+
+	lwz	r4, SS_IVOR+0x10(r10)
+	lwz	r5, SS_IVOR+0x14(r10)
+	lwz	r6, SS_IVOR+0x18(r10)
+	lwz	r7, SS_IVOR+0x1c(r10)
+
+	mtspr	SPRN_IVOR4, r4
+	mtspr	SPRN_IVOR5, r5
+	mtspr	SPRN_IVOR6, r6
+	mtspr	SPRN_IVOR7, r7
+
+	lwz	r4, SS_IVOR+0x20(r10)
+	lwz	r5, SS_IVOR+0x24(r10)
+	lwz	r6, SS_IVOR+0x28(r10)
+	lwz	r7, SS_IVOR+0x2c(r10)
+
+	mtspr	SPRN_IVOR8, r4
+	mtspr	SPRN_IVOR9, r5
+	mtspr	SPRN_IVOR10, r6
+	mtspr	SPRN_IVOR11, r7
+
+	lwz	r4, SS_IVOR+0x30(r10)
+	lwz	r5, SS_IVOR+0x34(r10)
+	lwz	r6, SS_IVOR+0x38(r10)
+	lwz	r7, SS_IVOR+0x3c(r10)
+
+	mtspr	SPRN_IVOR12, r4
+	mtspr	SPRN_IVOR13, r5
+	mtspr	SPRN_IVOR14, r6
+	mtspr	SPRN_IVOR15, r7
+
+	lwz	r4, SS_IVOR+0x40(r10)
+	lwz	r5, SS_IVOR+0x44(r10)
+	lwz	r6, SS_IVOR+0x48(r10)
+	lwz	r7, SS_IVOR+0x4c(r10)
+
+	mtspr	SPRN_IVOR32, r4
+	mtspr	SPRN_IVOR33, r5
+	mtspr	SPRN_IVOR34, r6
+	mtspr	SPRN_IVOR35, r7
+
+	lwz	r4, SS_TCR(r10)
+	lwz	r5, SS_BUCSR(r10)
+	lwz	r6, SS_L1CSR+0(r10)
+	lwz	r7, SS_L1CSR+4(r10)
+	lwz	r8, SS_USPRG+0(r10)
+
+	mtspr	SPRN_TCR, r4
+	mtspr	SPRN_BUCSR, r5
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r6
+	isync
+
+	mtspr	SPRN_L1CSR1, r7
+	isync
+
+	mtspr	SPRN_USPRG0, r8
+
+	lmw	r12, SS_GPREG(r10)
+
+	lwz	r1, SS_SP(r10)
+	lwz	r2, SS_CURRENT(r10)
+	lwz	r4, SS_MSR(r10)
+	lwz	r5, SS_LR(r10)
+	lwz	r6, SS_CR(r10)
+
+	msync
+	mtmsr	r4
+	isync
+
+	mtlr	r5
+	mtcr	r6
+
+	li	r4, 0
+	mtspr	SPRN_TBWL, r4
+
+	lwz	r4, SS_TB+0(r10)
+	lwz	r5, SS_TB+4(r10)
+
+	mtspr	SPRN_TBWU, r4
+	mtspr	SPRN_TBWL, r5
+
+	lis	r3, 1
+	mtdec	r3
+
+	blr
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 592a0f8..6c2c8b3 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -2,6 +2,7 @@
  * Suspend/resume support
  *
  * Copyright 2009  MontaVista Software, Inc.
+ * Copyright 2010-2013 Freescale Semiconductor Inc.
  *
  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
  *
@@ -19,39 +20,88 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
+#include <asm/cacheflush.h>
+#include <asm/switch_to.h>
+
+#include <sysdev/fsl_soc.h>
 
 struct pmc_regs {
+	/* 0xe0070: Device disable control register */
 	__be32 devdisr;
+	/* 0xe0074: 2nd Device disable control register */
 	__be32 devdisr2;
-	__be32 :32;
-	__be32 :32;
-	__be32 pmcsr;
-#define PMCSR_SLP	(1 << 17)
+	__be32 res1;
+	/* 0xe007c: Power Management Jog Control Register */
+	__be32 pmjcr;
+	/* 0xe0080: Power management control and status register */
+	__be32 powmgtcsr;
+#define POWMGTCSR_SLP		0x00020000
+#define POWMGTCSR_DPSLP		0x00100000
+	__be32 res3[2];
+	/* 0xe008c: Power management clock disable register */
+	__be32 pmcdr;
 };
 
-static struct device *pmc_dev;
 static struct pmc_regs __iomem *pmc_regs;
+static unsigned int pmc_flag;
+
+#define PMC_SLEEP	0x1
+#define PMC_DEEP_SLEEP	0x2
 
 static int pmc_suspend_enter(suspend_state_t state)
 {
-	int ret;
+	int ret = 0;
+
+	switch (state) {
+#ifdef CONFIG_PPC_85xx
+	case PM_SUSPEND_MEM:
+#ifdef CONFIG_SPE
+		enable_kernel_spe();
+#endif
+		enable_kernel_fp();
+
+		pr_debug("%s: Entering deep sleep\n", __func__);
+
+		mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_DPSLP);
+
+		pr_debug("%s: Resumed from deep sleep\n", __func__);
+		break;
+#endif
+
+	case PM_SUSPEND_STANDBY:
+#ifdef CONFIG_FSL_SOC_BOOKE
+		flush_dcache_L1();
+#endif
+		setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);
 
-	setbits32(&pmc_regs->pmcsr, PMCSR_SLP);
-	/* At this point, the CPU is asleep. */
+		/* At this point, the CPU is asleep. */
 
-	/* Upon resume, wait for SLP bit to be clear. */
-	ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0,
-				 10000, 10) ? 0 : -ETIMEDOUT;
-	if (ret)
-		dev_err(pmc_dev, "tired waiting for SLP bit to clear\n");
+		/* Upon resume, wait for SLP bit to be clear. */
+		ret = spin_event_timeout(
+			(in_be32(&pmc_regs->powmgtcsr) & POWMGTCSR_SLP) == 0,
+			10000, 10);
+		if (!ret) {
+			pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+				__func__);
+			ret = -EINVAL;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+
+	}
 	return ret;
 }
 
 static int pmc_suspend_valid(suspend_state_t state)
 {
-	if (state != PM_SUSPEND_STANDBY)
+	if (((pmc_flag & PMC_SLEEP) && (state == PM_SUSPEND_STANDBY)) ||
+	    ((pmc_flag & PMC_DEEP_SLEEP) && (state == PM_SUSPEND_MEM)))
+		return 1;
+	else
 		return 0;
-	return 1;
 }
 
 static const struct platform_suspend_ops pmc_suspend_ops = {
@@ -59,14 +109,26 @@ static const struct platform_suspend_ops pmc_suspend_ops = {
 	.enter = pmc_suspend_enter,
 };
 
-static int pmc_probe(struct platform_device *ofdev)
+static int pmc_probe(struct platform_device *pdev)
 {
-	pmc_regs = of_iomap(ofdev->dev.of_node, 0);
+	struct device_node *np = pdev->dev.of_node;
+
+	pmc_regs = of_iomap(np, 0);
 	if (!pmc_regs)
 		return -ENOMEM;
 
-	pmc_dev = &ofdev->dev;
+	pmc_flag = PMC_SLEEP;
+	if (of_device_is_compatible(np, "fsl,mpc8536-pmc"))
+		pmc_flag |= PMC_DEEP_SLEEP;
+
+	if (of_device_is_compatible(np, "fsl,p1022-pmc"))
+		pmc_flag |= PMC_DEEP_SLEEP;
+
 	suspend_set_ops(&pmc_suspend_ops);
+
+	pr_info("Freescale PMC driver: sleep(standby)%s\n",
+		(pmc_flag & PMC_DEEP_SLEEP) ? ", deep sleep(mem)" : "");
+
 	return 0;
 }
 
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c6d0073..949377d 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -48,5 +48,10 @@ extern struct platform_diu_data_ops diu_ops;
 void fsl_hv_restart(char *cmd);
 void fsl_hv_halt(void);
 
+/*
+ * Cast the ccsrbar to 64-bit parameter so that the assembly
+ * code can be compatible with both 32-bit & 36-bit.
+ */
+extern void mpc85xx_enter_deep_sleep(u64 ccsrbar, u32 powmgtreq);
 #endif
 #endif
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

Some Freescale SoCs like MPC8536 and P1022 has the deep sleep mode
in addtion to the sleep mode.

In sleep PM mode, the clocks of e500 core and unused IP blocks is
turned off. IP blocks which are allowed to wake up the processor
are still running.

While in deep sleep PM mode, additionally, the power supply is
removed from e500 core and most IP blocks. Only the blocks needed
to wake up the chip out of deep sleep are ON.

This patch supports 32-bit and 36-bit address space.

The sleep mode is equal to the Standby state in Linux. The deep sleep
mode is equal to the Suspend-to-RAM state of Linux Power Management.

Command to enter sleep mode.
  echo standby > /sys/power/state
Command to enter deep sleep mode.
  echo mem > /sys/power/state

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/platforms/85xx/Makefile |    1 +
 arch/powerpc/platforms/85xx/sleep.S  |  621 ++++++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/fsl_pmc.c        |   98 +++++-
 arch/powerpc/sysdev/fsl_soc.h        |    5 +
 4 files changed, 707 insertions(+), 18 deletions(-)
 create mode 100644 arch/powerpc/platforms/85xx/sleep.S

diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 2eab37e..a35bab7 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 85xx linux kernel.
 #
 obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_FSL_PMC)	+= sleep.o
 
 obj-y += common.o
 
diff --git a/arch/powerpc/platforms/85xx/sleep.S b/arch/powerpc/platforms/85xx/sleep.S
new file mode 100644
index 0000000..5a43adb
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/sleep.S
@@ -0,0 +1,621 @@
+/*
+ * Enter and leave deep sleep/sleep state on MPC85xx
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (C) 2006-2013 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+#include <asm/mmu.h>
+
+#define CCSR_ADDR		0xf0000000
+
+#define L2C_OFFSET		0x20000	/* L2 Cache Controller offset */
+
+#define BPTR_OFFSET		0x20 /* Boot Page Translation Register */
+#define BPTR_EN			0x80000000
+
+#define PMRCCR_OFFSET		0xe0084
+#define PMRCCR_VRCNT_PRE_MASK	0x1f000000
+#define PMRCCR_VRCNT_MASK	0x00ff0000
+
+#define POWMGTSCR_OFFSET	0xe0080
+#define POWMGTSCR_DPSLP		0x00100000 /* deep sleep mode */
+
+#define SS_TB		0x00
+#define SS_HID		0x08 /* 2 HIDs */
+#define SS_IAC		0x10 /* 2 IACs */
+#define SS_DAC		0x18 /* 2 DACs */
+#define SS_DBCR		0x20 /* 3 DBCRs */
+#define SS_PID		0x2c /* 3 PIDs */
+#define SS_SPRG		0x38 /* 8 SPRGs */
+#define SS_IVOR		0x58 /* 20 interrupt vectors */
+#define SS_TCR		0xa8
+#define SS_BUCSR	0xac
+#define SS_L1CSR	0xb0 /* 2 L1CSRs */
+#define SS_MSR		0xb8
+#define SS_USPRG	0xbc
+#define SS_GPREG	0xc0 /* r12-r31 */
+#define SS_LR		0x110
+#define SS_CR		0x114
+#define SS_SP		0x118
+#define SS_CURRENT	0x11c
+#define SS_IVPR		0x120
+#define SS_BPTR		0x124
+
+#define STATE_SAVE_SIZE 0x128
+
+	.section .data
+	.align	5
+mpc85xx_sleep_save_area:
+	.space	STATE_SAVE_SIZE
+ccsrbase_low:
+	.long	0
+ccsrbase_high:
+	.long	0
+powmgtreq:
+	.long	0
+
+	.section .text
+	.align	12
+
+	/*
+	 * r3 = high word of physical address of CCSR
+	 * r4 = low word of physical address of CCSR
+	 * r5 = JOG or deep sleep request
+	 *      JOG-0x00200000, deep sleep-0x00100000
+	 */
+_GLOBAL(mpc85xx_enter_deep_sleep)
+	lis	r6, ccsrbase_low@ha
+	stw	r4, ccsrbase_low@l(r6)
+	lis	r6, ccsrbase_high@ha
+	stw	r3, ccsrbase_high@l(r6)
+
+	lis	r6, powmgtreq@ha
+	stw	r5, powmgtreq@l(r6)
+
+	lis	r10, mpc85xx_sleep_save_area@h
+	ori	r10, r10, mpc85xx_sleep_save_area@l
+
+	mfspr	r5, SPRN_HID0
+	mfspr	r6, SPRN_HID1
+
+	stw	r5, SS_HID+0(r10)
+	stw	r6, SS_HID+4(r10)
+
+	mfspr	r4, SPRN_IAC1
+	mfspr	r5, SPRN_IAC2
+	mfspr	r6, SPRN_DAC1
+	mfspr	r7, SPRN_DAC2
+
+	stw	r4, SS_IAC+0(r10)
+	stw	r5, SS_IAC+4(r10)
+	stw	r6, SS_DAC+0(r10)
+	stw	r7, SS_DAC+4(r10)
+
+	mfspr	r4, SPRN_DBCR0
+	mfspr	r5, SPRN_DBCR1
+	mfspr	r6, SPRN_DBCR2
+
+	stw	r4, SS_DBCR+0(r10)
+	stw	r5, SS_DBCR+4(r10)
+	stw	r6, SS_DBCR+8(r10)
+
+	mfspr	r4, SPRN_PID0
+	mfspr	r5, SPRN_PID1
+	mfspr	r6, SPRN_PID2
+
+	stw	r4, SS_PID+0(r10)
+	stw	r5, SS_PID+4(r10)
+	stw	r6, SS_PID+8(r10)
+
+	mfspr	r4, SPRN_SPRG0
+	mfspr	r5, SPRN_SPRG1
+	mfspr	r6, SPRN_SPRG2
+	mfspr	r7, SPRN_SPRG3
+
+	stw	r4, SS_SPRG+0x00(r10)
+	stw	r5, SS_SPRG+0x04(r10)
+	stw	r6, SS_SPRG+0x08(r10)
+	stw	r7, SS_SPRG+0x0c(r10)
+
+	mfspr	r4, SPRN_SPRG4
+	mfspr	r5, SPRN_SPRG5
+	mfspr	r6, SPRN_SPRG6
+	mfspr	r7, SPRN_SPRG7
+
+	stw	r4, SS_SPRG+0x10(r10)
+	stw	r5, SS_SPRG+0x14(r10)
+	stw	r6, SS_SPRG+0x18(r10)
+	stw	r7, SS_SPRG+0x1c(r10)
+
+	mfspr	r4, SPRN_IVPR
+	stw	r4, SS_IVPR(r10)
+
+	mfspr	r4, SPRN_IVOR0
+	mfspr	r5, SPRN_IVOR1
+	mfspr	r6, SPRN_IVOR2
+	mfspr	r7, SPRN_IVOR3
+
+	stw	r4, SS_IVOR+0x00(r10)
+	stw	r5, SS_IVOR+0x04(r10)
+	stw	r6, SS_IVOR+0x08(r10)
+	stw	r7, SS_IVOR+0x0c(r10)
+
+	mfspr	r4, SPRN_IVOR4
+	mfspr	r5, SPRN_IVOR5
+	mfspr	r6, SPRN_IVOR6
+	mfspr	r7, SPRN_IVOR7
+
+	stw	r4, SS_IVOR+0x10(r10)
+	stw	r5, SS_IVOR+0x14(r10)
+	stw	r6, SS_IVOR+0x18(r10)
+	stw	r7, SS_IVOR+0x1c(r10)
+
+	mfspr	r4, SPRN_IVOR8
+	mfspr	r5, SPRN_IVOR9
+	mfspr	r6, SPRN_IVOR10
+	mfspr	r7, SPRN_IVOR11
+
+	stw	r4, SS_IVOR+0x20(r10)
+	stw	r5, SS_IVOR+0x24(r10)
+	stw	r6, SS_IVOR+0x28(r10)
+	stw	r7, SS_IVOR+0x2c(r10)
+
+	mfspr	r4, SPRN_IVOR12
+	mfspr	r5, SPRN_IVOR13
+	mfspr	r6, SPRN_IVOR14
+	mfspr	r7, SPRN_IVOR15
+
+	stw	r4, SS_IVOR+0x30(r10)
+	stw	r5, SS_IVOR+0x34(r10)
+	stw	r6, SS_IVOR+0x38(r10)
+	stw	r7, SS_IVOR+0x3c(r10)
+
+	mfspr	r4, SPRN_IVOR32
+	mfspr	r5, SPRN_IVOR33
+	mfspr	r6, SPRN_IVOR34
+	mfspr	r7, SPRN_IVOR35
+
+	stw	r4, SS_IVOR+0x40(r10)
+	stw	r5, SS_IVOR+0x44(r10)
+	stw	r6, SS_IVOR+0x48(r10)
+	stw	r7, SS_IVOR+0x4c(r10)
+
+	mfspr	r4, SPRN_TCR
+	mfspr	r5, SPRN_BUCSR
+	mfspr	r6, SPRN_L1CSR0
+	mfspr	r7, SPRN_L1CSR1
+	mfspr	r8, SPRN_USPRG0
+
+	stw	r4, SS_TCR(r10)
+	stw	r5, SS_BUCSR(r10)
+	stw	r6, SS_L1CSR+0(r10)
+	stw	r7, SS_L1CSR+4(r10)
+	stw	r8, SS_USPRG+0(r10)
+
+	stmw	r12, SS_GPREG(r10)
+
+	mfmsr	r4
+	mflr	r5
+	mfcr	r6
+
+	stw	r4, SS_MSR(r10)
+	stw	r5, SS_LR(r10)
+	stw	r6, SS_CR(r10)
+	stw	r1, SS_SP(r10)
+	stw	r2, SS_CURRENT(r10)
+
+1:	mftbu	r4
+	mftb	r5
+	mftbu	r6
+	cmpw	r4, r6
+	bne	1b
+
+	stw	r4, SS_TB+0(r10)
+	stw	r5, SS_TB+4(r10)
+
+	lis	r5, ccsrbase_low@ha
+	lwz	r4, ccsrbase_low@l(r5)
+	lis	r5, ccsrbase_high@ha
+	lwz	r3, ccsrbase_high@l(r5)
+
+	/* Disable machine checks and critical exceptions */
+	mfmsr	r5
+	rlwinm	r5, r5, 0, ~MSR_CE
+	rlwinm	r5, r5, 0, ~MSR_ME
+	mtmsr	r5
+	isync
+
+	/* Use TLB1[15] to map the CCSR at 0xf0000000 */
+	LOAD_REG_IMMEDIATE(r5, MAS0_TLBSEL(1) | MAS0_ESEL(15))
+	mtspr	SPRN_MAS0, r5
+	LOAD_REG_IMMEDIATE(r5,
+		MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(BOOK3E_PAGESZ_1M))
+	mtspr	SPRN_MAS1, r5
+	LOAD_REG_IMMEDIATE(r5, CCSR_ADDR | MAS2_I | MAS2_M)
+	mtspr	SPRN_MAS2, r5
+	rlwinm	r5, r4, 0, MAS3_RPN
+	ori	r5, r5, (MAS3_SW | MAS3_SR)
+	mtspr	SPRN_MAS3, r5
+	mtspr	SPRN_MAS7, r3
+	isync
+	tlbwe
+	isync
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + BPTR_OFFSET)
+	lwz	r4, 0(r3)
+	stw	r4, SS_BPTR(r10)
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + L2C_OFFSET)
+	bl	flush_disable_L2
+	bl	__flush_disable_L1
+
+	/* Enable I-cache, so as not to upset the bus
+	 * with our loop.
+	 */
+	mfspr	r4, SPRN_L1CSR1
+	ori	r4, r4, L1CSR1_ICE
+	mtspr	SPRN_L1CSR1, r4
+	isync
+
+	/* Set boot page translation */
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + BPTR_OFFSET)
+	lis	r4, (mpc85xx_deep_resume - PAGE_OFFSET)@h
+	ori	r4, r4, (mpc85xx_deep_resume - PAGE_OFFSET)@l
+	rlwinm	r4, r4, 20, 12, 31
+	oris	r4, r4, BPTR_EN@h
+	stw	r4, 0(r3)
+	lwz	r4, 0(r3) /* read-back to flush write */
+	twi	0, r4, 0
+	isync
+
+	/* Disable the decrementer */
+	mfspr	r4, SPRN_TCR
+	rlwinm	r4, r4, 0, ~TCR_DIE
+	mtspr	SPRN_TCR, r4
+
+	mfspr	r4, SPRN_TSR
+	oris	r4, r4, TSR_DIS@h
+	mtspr	SPRN_TSR, r4
+
+	/* set PMRCCR[VRCNT] to wait power stable for 40ms */
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + PMRCCR_OFFSET)
+	lwz	r4, 0(r3)
+	li	r5, 0x12
+	rlwimi	r4, r5, 0, PMRCCR_VRCNT_PRE_MASK
+	li	r5, 0xa3
+	rlwimi	r4, r5, 0, PMRCCR_VRCNT_MASK
+	stw	r4, 0(r3)
+	lwz	r4, 0(r3)
+
+	/* set deep sleep bit in POWMGTSCR */
+	lis	r3, powmgtreq@ha
+	lwz	r8, powmgtreq@l(r3)
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + POWMGTSCR_OFFSET)
+	lwz	r4, 0(r3)
+	or	r4, r4, r8
+	stw	r4, 0(r3)
+	lwz	r4, 0(r3)		/* read-back to flush write */
+	twi	0, r4, 0
+	isync
+
+	mftb	r5
+1:	/* spin until either we enter deep sleep, or the sleep process is
+	 * aborted due to a pending wakeup event.  Wait some time between
+	 * accesses, so we don't flood the bus and prevent the pmc from
+	 * detecting an idle system.
+	 */
+
+	mftb	r4
+	subf	r7, r5, r4
+	cmpwi	r7, 1000
+	blt	1b
+	mr	r5, r4
+
+	lwz	r6, 0(r3)
+	andis.	r6, r6, POWMGTSCR_DPSLP@h
+	bne	1b
+	b	2f
+
+2:	mfspr	r4, SPRN_PIR
+	andi.	r4, r4, 1
+99:	bne	99b
+
+	/* Establish a temporary 64MB 0->0 mapping in TLB1[1]. */
+	LOAD_REG_IMMEDIATE(r4, MAS0_TLBSEL(1) | MAS0_ESEL(1))
+	mtspr	SPRN_MAS0, r4
+	LOAD_REG_IMMEDIATE(r4,
+		MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(BOOK3E_PAGESZ_64M))
+	mtspr	SPRN_MAS1, r4
+	li	r4, 0
+	mtspr	SPRN_MAS2, r4
+	li	r4, (MAS3_SX | MAS3_SW | MAS3_SR)
+	mtspr	SPRN_MAS3, r4
+	li	r4, 0
+	mtspr	SPRN_MAS7, r4
+	isync
+	tlbwe
+	isync
+
+	lis	r3, (3f - PAGE_OFFSET)@h
+	ori	r3, r3, (3f - PAGE_OFFSET)@l
+	mtctr	r3
+	bctr
+
+	/* Locate the resume vector in the last word of the current page. */
+	. = mpc85xx_enter_deep_sleep + 0xffc
+mpc85xx_deep_resume:
+	b	2b
+
+3:
+	/* Restore the contents of TLB1[0].  It is assumed that it covers
+	 * the currently executing code and the sleep save area, and that
+	 * it does not alias our temporary mapping (which is at virtual zero).
+	 */
+	lis	r3, (TLBCAM - PAGE_OFFSET)@h
+	ori	r3, r3, (TLBCAM - PAGE_OFFSET)@l
+
+	lwz	r4, 0(r3)
+	lwz	r5, 4(r3)
+	lwz	r6, 8(r3)
+	lwz	r7, 12(r3)
+	lwz	r8, 16(r3)
+
+	mtspr	SPRN_MAS0, r4
+	mtspr	SPRN_MAS1, r5
+	mtspr	SPRN_MAS2, r6
+	mtspr	SPRN_MAS3, r7
+	mtspr	SPRN_MAS7, r8
+
+	isync
+	tlbwe
+	isync
+
+	/* Access the ccsrbase address with TLB1[0] */
+	lis	r5, ccsrbase_low@ha
+	lwz	r4, ccsrbase_low@l(r5)
+	lis	r5, ccsrbase_high@ha
+	lwz	r3, ccsrbase_high@l(r5)
+
+	/* Use TLB1[15] to map the CCSR at 0xf0000000 */
+	LOAD_REG_IMMEDIATE(r5, MAS0_TLBSEL(1) | MAS0_ESEL(15))
+	mtspr	SPRN_MAS0, r5
+	LOAD_REG_IMMEDIATE(r5,
+		MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(BOOK3E_PAGESZ_1M))
+	mtspr	SPRN_MAS1, r5
+	LOAD_REG_IMMEDIATE(r5, CCSR_ADDR | MAS2_I | MAS2_M)
+	mtspr	SPRN_MAS2, r5
+	rlwinm	r5, r4, 0, MAS3_RPN
+	ori	r5, r5, (MAS3_SW | MAS3_SR)
+	mtspr	SPRN_MAS3, r5
+	mtspr	SPRN_MAS7, r3
+	isync
+	tlbwe
+	isync
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + L2C_OFFSET)
+	bl	invalidate_enable_L2
+
+	/* Access the MEM(r10) with TLB1[0] */
+	lis	r10, mpc85xx_sleep_save_area@h
+	ori	r10, r10, mpc85xx_sleep_save_area@l
+
+	LOAD_REG_IMMEDIATE(r3, CCSR_ADDR + BPTR_OFFSET)
+	lwz	r4, SS_BPTR(r10)
+	stw	r4, 0(r3)		/* restore BPTR */
+
+	/* Program shift running space to PAGE_OFFSET */
+	mfmsr	r3
+	lis	r4, 1f@h
+	ori	r4, r4, 1f@l
+
+	mtsrr1	r3
+	mtsrr0	r4
+	rfi
+
+1:	/* Restore the rest of TLB1, in ascending order so that
+	 * the TLB1[1] gets invalidated first.
+	 *
+	 * XXX: It's better to invalidate the temporary mapping
+	 * TLB1[15] for CCSR before restore any TLB1 entry include 0.
+	 */
+	LOAD_REG_IMMEDIATE(r4, MAS0_TLBSEL(1) | MAS0_ESEL(15))
+	mtspr	SPRN_MAS0, r4
+	lis	r4, 0
+	mtspr	SPRN_MAS1, r4
+	isync
+	tlbwe
+	isync
+
+	lis	r3, (TLBCAM + 5*4 - 4)@h
+	ori	r3, r3, (TLBCAM + 5*4 - 4)@l
+	li	r4, 15
+	mtctr	r4
+
+2:
+	lwz	r5, 4(r3)
+	lwz	r6, 8(r3)
+	lwz	r7, 12(r3)
+	lwz	r8, 16(r3)
+	lwzu	r9, 20(r3)
+
+	mtspr	SPRN_MAS0, r5
+	mtspr	SPRN_MAS1, r6
+	mtspr	SPRN_MAS2, r7
+	mtspr	SPRN_MAS3, r8
+	mtspr	SPRN_MAS7, r9
+
+	isync
+	tlbwe
+	isync
+	bdnz	2b
+
+	lis	r10, mpc85xx_sleep_save_area@h
+	ori	r10, r10, mpc85xx_sleep_save_area@l
+
+	lwz	r5, SS_HID+0(r10)
+	lwz	r6, SS_HID+4(r10)
+
+	isync
+	mtspr	SPRN_HID0, r5
+	isync
+
+	msync
+	mtspr	SPRN_HID1, r6
+	isync
+
+	lwz	r4, SS_IAC+0(r10)
+	lwz	r5, SS_IAC+4(r10)
+	lwz	r6, SS_DAC+0(r10)
+	lwz	r7, SS_DAC+4(r10)
+
+	mtspr	SPRN_IAC1, r4
+	mtspr	SPRN_IAC2, r5
+	mtspr	SPRN_DAC1, r6
+	mtspr	SPRN_DAC2, r7
+
+	lwz	r4, SS_DBCR+0(r10)
+	lwz	r5, SS_DBCR+4(r10)
+	lwz	r6, SS_DBCR+8(r10)
+
+	mtspr	SPRN_DBCR0, r4
+	mtspr	SPRN_DBCR1, r5
+	mtspr	SPRN_DBCR2, r6
+
+	lwz	r4, SS_PID+0(r10)
+	lwz	r5, SS_PID+4(r10)
+	lwz	r6, SS_PID+8(r10)
+
+	mtspr	SPRN_PID0, r4
+	mtspr	SPRN_PID1, r5
+	mtspr	SPRN_PID2, r6
+
+	lwz	r4, SS_SPRG+0x00(r10)
+	lwz	r5, SS_SPRG+0x04(r10)
+	lwz	r6, SS_SPRG+0x08(r10)
+	lwz	r7, SS_SPRG+0x0c(r10)
+
+	mtspr	SPRN_SPRG0, r4
+	mtspr	SPRN_SPRG1, r5
+	mtspr	SPRN_SPRG2, r6
+	mtspr	SPRN_SPRG3, r7
+
+	lwz	r4, SS_SPRG+0x10(r10)
+	lwz	r5, SS_SPRG+0x14(r10)
+	lwz	r6, SS_SPRG+0x18(r10)
+	lwz	r7, SS_SPRG+0x1c(r10)
+
+	mtspr	SPRN_SPRG4, r4
+	mtspr	SPRN_SPRG5, r5
+	mtspr	SPRN_SPRG6, r6
+	mtspr	SPRN_SPRG7, r7
+
+	lwz	r4, SS_IVPR(r10)
+	mtspr	SPRN_IVPR, r4
+
+	lwz	r4, SS_IVOR+0x00(r10)
+	lwz	r5, SS_IVOR+0x04(r10)
+	lwz	r6, SS_IVOR+0x08(r10)
+	lwz	r7, SS_IVOR+0x0c(r10)
+
+	mtspr	SPRN_IVOR0, r4
+	mtspr	SPRN_IVOR1, r5
+	mtspr	SPRN_IVOR2, r6
+	mtspr	SPRN_IVOR3, r7
+
+	lwz	r4, SS_IVOR+0x10(r10)
+	lwz	r5, SS_IVOR+0x14(r10)
+	lwz	r6, SS_IVOR+0x18(r10)
+	lwz	r7, SS_IVOR+0x1c(r10)
+
+	mtspr	SPRN_IVOR4, r4
+	mtspr	SPRN_IVOR5, r5
+	mtspr	SPRN_IVOR6, r6
+	mtspr	SPRN_IVOR7, r7
+
+	lwz	r4, SS_IVOR+0x20(r10)
+	lwz	r5, SS_IVOR+0x24(r10)
+	lwz	r6, SS_IVOR+0x28(r10)
+	lwz	r7, SS_IVOR+0x2c(r10)
+
+	mtspr	SPRN_IVOR8, r4
+	mtspr	SPRN_IVOR9, r5
+	mtspr	SPRN_IVOR10, r6
+	mtspr	SPRN_IVOR11, r7
+
+	lwz	r4, SS_IVOR+0x30(r10)
+	lwz	r5, SS_IVOR+0x34(r10)
+	lwz	r6, SS_IVOR+0x38(r10)
+	lwz	r7, SS_IVOR+0x3c(r10)
+
+	mtspr	SPRN_IVOR12, r4
+	mtspr	SPRN_IVOR13, r5
+	mtspr	SPRN_IVOR14, r6
+	mtspr	SPRN_IVOR15, r7
+
+	lwz	r4, SS_IVOR+0x40(r10)
+	lwz	r5, SS_IVOR+0x44(r10)
+	lwz	r6, SS_IVOR+0x48(r10)
+	lwz	r7, SS_IVOR+0x4c(r10)
+
+	mtspr	SPRN_IVOR32, r4
+	mtspr	SPRN_IVOR33, r5
+	mtspr	SPRN_IVOR34, r6
+	mtspr	SPRN_IVOR35, r7
+
+	lwz	r4, SS_TCR(r10)
+	lwz	r5, SS_BUCSR(r10)
+	lwz	r6, SS_L1CSR+0(r10)
+	lwz	r7, SS_L1CSR+4(r10)
+	lwz	r8, SS_USPRG+0(r10)
+
+	mtspr	SPRN_TCR, r4
+	mtspr	SPRN_BUCSR, r5
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r6
+	isync
+
+	mtspr	SPRN_L1CSR1, r7
+	isync
+
+	mtspr	SPRN_USPRG0, r8
+
+	lmw	r12, SS_GPREG(r10)
+
+	lwz	r1, SS_SP(r10)
+	lwz	r2, SS_CURRENT(r10)
+	lwz	r4, SS_MSR(r10)
+	lwz	r5, SS_LR(r10)
+	lwz	r6, SS_CR(r10)
+
+	msync
+	mtmsr	r4
+	isync
+
+	mtlr	r5
+	mtcr	r6
+
+	li	r4, 0
+	mtspr	SPRN_TBWL, r4
+
+	lwz	r4, SS_TB+0(r10)
+	lwz	r5, SS_TB+4(r10)
+
+	mtspr	SPRN_TBWU, r4
+	mtspr	SPRN_TBWL, r5
+
+	lis	r3, 1
+	mtdec	r3
+
+	blr
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 592a0f8..6c2c8b3 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -2,6 +2,7 @@
  * Suspend/resume support
  *
  * Copyright 2009  MontaVista Software, Inc.
+ * Copyright 2010-2013 Freescale Semiconductor Inc.
  *
  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
  *
@@ -19,39 +20,88 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
+#include <asm/cacheflush.h>
+#include <asm/switch_to.h>
+
+#include <sysdev/fsl_soc.h>
 
 struct pmc_regs {
+	/* 0xe0070: Device disable control register */
 	__be32 devdisr;
+	/* 0xe0074: 2nd Device disable control register */
 	__be32 devdisr2;
-	__be32 :32;
-	__be32 :32;
-	__be32 pmcsr;
-#define PMCSR_SLP	(1 << 17)
+	__be32 res1;
+	/* 0xe007c: Power Management Jog Control Register */
+	__be32 pmjcr;
+	/* 0xe0080: Power management control and status register */
+	__be32 powmgtcsr;
+#define POWMGTCSR_SLP		0x00020000
+#define POWMGTCSR_DPSLP		0x00100000
+	__be32 res3[2];
+	/* 0xe008c: Power management clock disable register */
+	__be32 pmcdr;
 };
 
-static struct device *pmc_dev;
 static struct pmc_regs __iomem *pmc_regs;
+static unsigned int pmc_flag;
+
+#define PMC_SLEEP	0x1
+#define PMC_DEEP_SLEEP	0x2
 
 static int pmc_suspend_enter(suspend_state_t state)
 {
-	int ret;
+	int ret = 0;
+
+	switch (state) {
+#ifdef CONFIG_PPC_85xx
+	case PM_SUSPEND_MEM:
+#ifdef CONFIG_SPE
+		enable_kernel_spe();
+#endif
+		enable_kernel_fp();
+
+		pr_debug("%s: Entering deep sleep\n", __func__);
+
+		mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_DPSLP);
+
+		pr_debug("%s: Resumed from deep sleep\n", __func__);
+		break;
+#endif
+
+	case PM_SUSPEND_STANDBY:
+#ifdef CONFIG_FSL_SOC_BOOKE
+		flush_dcache_L1();
+#endif
+		setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);
 
-	setbits32(&pmc_regs->pmcsr, PMCSR_SLP);
-	/* At this point, the CPU is asleep. */
+		/* At this point, the CPU is asleep. */
 
-	/* Upon resume, wait for SLP bit to be clear. */
-	ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0,
-				 10000, 10) ? 0 : -ETIMEDOUT;
-	if (ret)
-		dev_err(pmc_dev, "tired waiting for SLP bit to clear\n");
+		/* Upon resume, wait for SLP bit to be clear. */
+		ret = spin_event_timeout(
+			(in_be32(&pmc_regs->powmgtcsr) & POWMGTCSR_SLP) == 0,
+			10000, 10);
+		if (!ret) {
+			pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+				__func__);
+			ret = -EINVAL;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+
+	}
 	return ret;
 }
 
 static int pmc_suspend_valid(suspend_state_t state)
 {
-	if (state != PM_SUSPEND_STANDBY)
+	if (((pmc_flag & PMC_SLEEP) && (state == PM_SUSPEND_STANDBY)) ||
+	    ((pmc_flag & PMC_DEEP_SLEEP) && (state == PM_SUSPEND_MEM)))
+		return 1;
+	else
 		return 0;
-	return 1;
 }
 
 static const struct platform_suspend_ops pmc_suspend_ops = {
@@ -59,14 +109,26 @@ static const struct platform_suspend_ops pmc_suspend_ops = {
 	.enter = pmc_suspend_enter,
 };
 
-static int pmc_probe(struct platform_device *ofdev)
+static int pmc_probe(struct platform_device *pdev)
 {
-	pmc_regs = of_iomap(ofdev->dev.of_node, 0);
+	struct device_node *np = pdev->dev.of_node;
+
+	pmc_regs = of_iomap(np, 0);
 	if (!pmc_regs)
 		return -ENOMEM;
 
-	pmc_dev = &ofdev->dev;
+	pmc_flag = PMC_SLEEP;
+	if (of_device_is_compatible(np, "fsl,mpc8536-pmc"))
+		pmc_flag |= PMC_DEEP_SLEEP;
+
+	if (of_device_is_compatible(np, "fsl,p1022-pmc"))
+		pmc_flag |= PMC_DEEP_SLEEP;
+
 	suspend_set_ops(&pmc_suspend_ops);
+
+	pr_info("Freescale PMC driver: sleep(standby)%s\n",
+		(pmc_flag & PMC_DEEP_SLEEP) ? ", deep sleep(mem)" : "");
+
 	return 0;
 }
 
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c6d0073..949377d 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -48,5 +48,10 @@ extern struct platform_diu_data_ops diu_ops;
 void fsl_hv_restart(char *cmd);
 void fsl_hv_halt(void);
 
+/*
+ * Cast the ccsrbar to 64-bit parameter so that the assembly
+ * code can be compatible with both 32-bit & 36-bit.
+ */
+extern void mpc85xx_enter_deep_sleep(u64 ccsrbar, u32 powmgtreq);
 #endif
 #endif
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 03/15] fsl_pmc: Add API to enable device as wakeup event source
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: chenhui zhao <chenhui.zhao@freescale.com>

Add APIs for setting wakeup source and lossless Ethernet in low power modes.
These APIs can be used by wake-on-packet feature.

Change-Id: I1803dcd4571af1eac49b43d99c578e7f99e2c278
Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
 arch/powerpc/sysdev/fsl_pmc.c |   72 ++++++++++++++++++++++++++++++++++++++++-
 arch/powerpc/sysdev/fsl_soc.h |   11 ++++++
 2 files changed, 82 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 6c2c8b3..94ae476 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -38,6 +38,7 @@ struct pmc_regs {
 	__be32 powmgtcsr;
 #define POWMGTCSR_SLP		0x00020000
 #define POWMGTCSR_DPSLP		0x00100000
+#define POWMGTCSR_LOSSLESS	0x00400000
 	__be32 res3[2];
 	/* 0xe008c: Power management clock disable register */
 	__be32 pmcdr;
@@ -48,6 +49,75 @@ static unsigned int pmc_flag;
 
 #define PMC_SLEEP	0x1
 #define PMC_DEEP_SLEEP	0x2
+#define PMC_LOSSLESS	0x4
+
+/**
+ * mpc85xx_pmc_set_wake - enable devices as wakeup event source
+ * @dev: a device affected
+ * @enable: True to enable event generation; false to disable
+ *
+ * This enables the device as a wakeup event source, or disables it.
+ *
+ * RETURN VALUE:
+ * 0 is returned on success.
+ * -EINVAL is returned if device is not supposed to wake up the system.
+ * -ENODEV is returned if PMC is unavailable.
+ * Error code depending on the platform is returned if both the platform and
+ * the native mechanism fail to enable the generation of wake-up events
+ */
+int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
+{
+	int ret = 0;
+	struct device_node *clk_np;
+	const u32 *prop;
+	u32 pmcdr_mask;
+
+	if (!pmc_regs) {
+		dev_err(dev, "%s: PMC is unavailable\n", __func__);
+		return -ENODEV;
+	}
+
+	if (enable && !device_may_wakeup(dev))
+		return -EINVAL;
+
+	clk_np = of_parse_phandle(dev->of_node, "fsl,pmc-handle", 0);
+	if (!clk_np)
+		return -EINVAL;
+
+	prop = of_get_property(clk_np, "fsl,pmcdr-mask", NULL);
+	if (!prop) {
+		ret = -EINVAL;
+		goto out;
+	}
+	pmcdr_mask = be32_to_cpup(prop);
+
+	if (enable)
+		/* clear to enable clock in low power mode */
+		clrbits32(&pmc_regs->pmcdr, pmcdr_mask);
+	else
+		setbits32(&pmc_regs->pmcdr, pmcdr_mask);
+
+out:
+	of_node_put(clk_np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_wake);
+
+/**
+ * mpc85xx_pmc_set_lossless_ethernet - enable lossless ethernet
+ * in (deep) sleep mode
+ * @enable: True to enable event generation; false to disable
+ */
+void mpc85xx_pmc_set_lossless_ethernet(int enable)
+{
+	if (pmc_flag & PMC_LOSSLESS) {
+		if (enable)
+			setbits32(&pmc_regs->powmgtcsr,	POWMGTCSR_LOSSLESS);
+		else
+			clrbits32(&pmc_regs->powmgtcsr, POWMGTCSR_LOSSLESS);
+	}
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_lossless_ethernet);
 
 static int pmc_suspend_enter(suspend_state_t state)
 {
@@ -122,7 +192,7 @@ static int pmc_probe(struct platform_device *pdev)
 		pmc_flag |= PMC_DEEP_SLEEP;
 
 	if (of_device_is_compatible(np, "fsl,p1022-pmc"))
-		pmc_flag |= PMC_DEEP_SLEEP;
+		pmc_flag |= PMC_DEEP_SLEEP | PMC_LOSSLESS;
 
 	suspend_set_ops(&pmc_suspend_ops);
 
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 949377d..e58f4dd 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -21,6 +21,17 @@ struct device_node;
 
 extern void fsl_rstcr_restart(char *cmd);
 
+#ifdef CONFIG_FSL_PMC
+int mpc85xx_pmc_set_wake(struct device *dev, bool enable);
+void mpc85xx_pmc_set_lossless_ethernet(int enable);
+#else
+static inline int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
+{
+	return -ENODEV;
+}
+#define mpc85xx_pmc_set_lossless_ethernet(enable)	do { } while (0)
+#endif
+
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 
 /* The different ports that the DIU can be connected to */
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 03/15] fsl_pmc: Add API to enable device as wakeup event source
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: chenhui zhao <chenhui.zhao@freescale.com>

Add APIs for setting wakeup source and lossless Ethernet in low power modes.
These APIs can be used by wake-on-packet feature.

Change-Id: I1803dcd4571af1eac49b43d99c578e7f99e2c278
Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
 arch/powerpc/sysdev/fsl_pmc.c |   72 ++++++++++++++++++++++++++++++++++++++++-
 arch/powerpc/sysdev/fsl_soc.h |   11 ++++++
 2 files changed, 82 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 6c2c8b3..94ae476 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -38,6 +38,7 @@ struct pmc_regs {
 	__be32 powmgtcsr;
 #define POWMGTCSR_SLP		0x00020000
 #define POWMGTCSR_DPSLP		0x00100000
+#define POWMGTCSR_LOSSLESS	0x00400000
 	__be32 res3[2];
 	/* 0xe008c: Power management clock disable register */
 	__be32 pmcdr;
@@ -48,6 +49,75 @@ static unsigned int pmc_flag;
 
 #define PMC_SLEEP	0x1
 #define PMC_DEEP_SLEEP	0x2
+#define PMC_LOSSLESS	0x4
+
+/**
+ * mpc85xx_pmc_set_wake - enable devices as wakeup event source
+ * @dev: a device affected
+ * @enable: True to enable event generation; false to disable
+ *
+ * This enables the device as a wakeup event source, or disables it.
+ *
+ * RETURN VALUE:
+ * 0 is returned on success.
+ * -EINVAL is returned if device is not supposed to wake up the system.
+ * -ENODEV is returned if PMC is unavailable.
+ * Error code depending on the platform is returned if both the platform and
+ * the native mechanism fail to enable the generation of wake-up events
+ */
+int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
+{
+	int ret = 0;
+	struct device_node *clk_np;
+	const u32 *prop;
+	u32 pmcdr_mask;
+
+	if (!pmc_regs) {
+		dev_err(dev, "%s: PMC is unavailable\n", __func__);
+		return -ENODEV;
+	}
+
+	if (enable && !device_may_wakeup(dev))
+		return -EINVAL;
+
+	clk_np = of_parse_phandle(dev->of_node, "fsl,pmc-handle", 0);
+	if (!clk_np)
+		return -EINVAL;
+
+	prop = of_get_property(clk_np, "fsl,pmcdr-mask", NULL);
+	if (!prop) {
+		ret = -EINVAL;
+		goto out;
+	}
+	pmcdr_mask = be32_to_cpup(prop);
+
+	if (enable)
+		/* clear to enable clock in low power mode */
+		clrbits32(&pmc_regs->pmcdr, pmcdr_mask);
+	else
+		setbits32(&pmc_regs->pmcdr, pmcdr_mask);
+
+out:
+	of_node_put(clk_np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_wake);
+
+/**
+ * mpc85xx_pmc_set_lossless_ethernet - enable lossless ethernet
+ * in (deep) sleep mode
+ * @enable: True to enable event generation; false to disable
+ */
+void mpc85xx_pmc_set_lossless_ethernet(int enable)
+{
+	if (pmc_flag & PMC_LOSSLESS) {
+		if (enable)
+			setbits32(&pmc_regs->powmgtcsr,	POWMGTCSR_LOSSLESS);
+		else
+			clrbits32(&pmc_regs->powmgtcsr, POWMGTCSR_LOSSLESS);
+	}
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_lossless_ethernet);
 
 static int pmc_suspend_enter(suspend_state_t state)
 {
@@ -122,7 +192,7 @@ static int pmc_probe(struct platform_device *pdev)
 		pmc_flag |= PMC_DEEP_SLEEP;
 
 	if (of_device_is_compatible(np, "fsl,p1022-pmc"))
-		pmc_flag |= PMC_DEEP_SLEEP;
+		pmc_flag |= PMC_DEEP_SLEEP | PMC_LOSSLESS;
 
 	suspend_set_ops(&pmc_suspend_ops);
 
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 949377d..e58f4dd 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -21,6 +21,17 @@ struct device_node;
 
 extern void fsl_rstcr_restart(char *cmd);
 
+#ifdef CONFIG_FSL_PMC
+int mpc85xx_pmc_set_wake(struct device *dev, bool enable);
+void mpc85xx_pmc_set_lossless_ethernet(int enable);
+#else
+static inline int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
+{
+	return -ENODEV;
+}
+#define mpc85xx_pmc_set_lossless_ethernet(enable)	do { } while (0)
+#endif
+
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 
 /* The different ports that the DIU can be connected to */
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 04/15] pm: add power node to dts
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

The Power Management device tree stub indicated that the platform
supports Power Management feature.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
 arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi |   14 ++++++-
 arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi |    2 +
 arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi |    2 +
 arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi |    2 +
 arch/powerpc/boot/dts/fsl/p1010si-post.dtsi   |    8 ++++
 arch/powerpc/boot/dts/fsl/p1020si-post.dtsi   |    5 +++
 arch/powerpc/boot/dts/fsl/p1021si-post.dtsi   |    5 +++
 arch/powerpc/boot/dts/fsl/p1022si-post.dtsi   |   11 ++++--
 arch/powerpc/boot/dts/fsl/p2020si-post.dtsi   |   14 +++++++
 arch/powerpc/boot/dts/fsl/pq3-power.dtsi      |   48 +++++++++++++++++++++++++
 10 files changed, 106 insertions(+), 5 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-power.dtsi

diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
index c8b2daa..900f117 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
@@ -199,6 +199,10 @@
 
 /include/ "pq3-dma-0.dtsi"
 /include/ "pq3-etsec1-0.dtsi"
+	enet0: ethernet@24000 {
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec1_clk>;
+	};
 /include/ "pq3-etsec1-timer-0.dtsi"
 
 	usb@22000 {
@@ -222,9 +226,10 @@
 	};
 
 /include/ "pq3-etsec1-2.dtsi"
-
-	ethernet@26000 {
+	enet2: ethernet@26000 {
 		cell-index = <1>;
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec3_clk>;
 	};
 
 	usb@2b000 {
@@ -249,4 +254,9 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
+	power@e0070 {
+		compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
+	};
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
index b68eb11..ea7416a 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
@@ -188,4 +188,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
index 579d76c..dddb737 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
@@ -156,4 +156,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
index d44e25a..7313351 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
@@ -193,4 +193,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
index af12ead..01c8c33 100644
--- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
@@ -171,6 +171,8 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: ethernet@b0000 {
+		fsl,pmc-handle = <&etsec1_clk>;
+
 		queue-group@b0000 {
 			fsl,rx-bit-map = <0xff>;
 			fsl,tx-bit-map = <0xff>;
@@ -179,6 +181,8 @@
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: ethernet@b1000 {
+		fsl,pmc-handle = <&etsec2_clk>;
+
 		queue-group@b1000 {
 			fsl,rx-bit-map = <0xff>;
 			fsl,tx-bit-map = <0xff>;
@@ -187,6 +191,8 @@
 
 /include/ "pq3-etsec2-2.dtsi"
 	enet2: ethernet@b2000 {
+		fsl,pmc-handle = <&etsec3_clk>;
+
 		queue-group@b2000 {
 			fsl,rx-bit-map = <0xff>;
 			fsl,tx-bit-map = <0xff>;
@@ -199,4 +205,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
index 68cc5e7..410e6e5 100644
--- a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
@@ -162,14 +162,17 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: enet0_grp2: ethernet@b0000 {
+		fsl,pmc-handle = <&etsec1_clk>;
 	};
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: enet1_grp2: ethernet@b1000 {
+		fsl,pmc-handle = <&etsec2_clk>;
 	};
 
 /include/ "pq3-etsec2-2.dtsi"
 	enet2: enet2_grp2: ethernet@b2000 {
+		fsl,pmc-handle = <&etsec3_clk>;
 	};
 
 	global-utilities@e0000 {
@@ -177,6 +180,8 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
 
 /include/ "pq3-etsec2-grp2-0.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
index adb82fd..02df574 100644
--- a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
@@ -158,14 +158,17 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: enet0_grp2: ethernet@b0000 {
+		fsl,pmc-handle = <&etsec1_clk>;
 	};
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: enet1_grp2: ethernet@b1000 {
+		fsl,pmc-handle = <&etsec2_clk>;
 	};
 
 /include/ "pq3-etsec2-2.dtsi"
 	enet2: enet2_grp2: ethernet@b2000 {
+		fsl,pmc-handle = <&etsec3_clk>;
 	};
 
 	global-utilities@e0000 {
@@ -173,6 +176,8 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
 
 &qe {
diff --git a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
index e179803..c5343e7 100644
--- a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
@@ -223,10 +223,14 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: enet0_grp2: ethernet@b0000 {
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec1_clk>;
 	};
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: enet1_grp2: ethernet@b1000 {
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec2_clk>;
 	};
 
 	global-utilities@e0000 {
@@ -235,9 +239,10 @@
 		fsl,has-rstcr;
 	};
 
-	power@e0070{
-		compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
-		reg = <0xe0070 0x20>;
+/include/ "pq3-power.dtsi"
+	power@e0070 {
+		compatible = "fsl,p1022-pmc", "fsl,mpc8536-pmc",
+				"fsl,mpc8548-pmc";
 	};
 
 };
diff --git a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
index 884e01b..2c4787c 100644
--- a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
@@ -175,6 +175,10 @@
 		compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
 	};
 /include/ "pq3-etsec1-0.dtsi"
+	enet0: ethernet@24000 {
+		fsl,pmc-handle = <&etsec1_clk>;
+
+	};
 /include/ "pq3-etsec1-timer-0.dtsi"
 
 	ptp_clock@24e00 {
@@ -183,7 +187,15 @@
 
 
 /include/ "pq3-etsec1-1.dtsi"
+	enet1: ethernet@25000 {
+		fsl,pmc-handle = <&etsec2_clk>;
+	};
+
 /include/ "pq3-etsec1-2.dtsi"
+	enet2: ethernet@26000 {
+		fsl,pmc-handle = <&etsec3_clk>;
+	};
+
 /include/ "pq3-esdhc-0.dtsi"
 	sdhc@2e000 {
 		compatible = "fsl,p2020-esdhc", "fsl,esdhc";
@@ -198,4 +210,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/pq3-power.dtsi b/arch/powerpc/boot/dts/fsl/pq3-power.dtsi
new file mode 100644
index 0000000..5a760b3
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-power.dtsi
@@ -0,0 +1,48 @@
+/*
+ * PQ3 Power Management device tree stub
+ *
+ * Copyright 2012-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+power@e0070 {
+	compatible = "fsl,mpc8548-pmc";
+	reg = <0xe0070 0x20>;
+
+	etsec1_clk: soc-clk@24 {
+		fsl,pmcdr-mask = <0x00000080>;
+	};
+	etsec2_clk: soc-clk@25 {
+		fsl,pmcdr-mask = <0x00000040>;
+	};
+	etsec3_clk: soc-clk@26 {
+		fsl,pmcdr-mask = <0x00000020>;
+	};
+};
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 04/15] pm: add power node to dts
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

The Power Management device tree stub indicated that the platform
supports Power Management feature.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
 arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi |   14 ++++++-
 arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi |    2 +
 arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi |    2 +
 arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi |    2 +
 arch/powerpc/boot/dts/fsl/p1010si-post.dtsi   |    8 ++++
 arch/powerpc/boot/dts/fsl/p1020si-post.dtsi   |    5 +++
 arch/powerpc/boot/dts/fsl/p1021si-post.dtsi   |    5 +++
 arch/powerpc/boot/dts/fsl/p1022si-post.dtsi   |   11 ++++--
 arch/powerpc/boot/dts/fsl/p2020si-post.dtsi   |   14 +++++++
 arch/powerpc/boot/dts/fsl/pq3-power.dtsi      |   48 +++++++++++++++++++++++++
 10 files changed, 106 insertions(+), 5 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-power.dtsi

diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
index c8b2daa..900f117 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
@@ -199,6 +199,10 @@
 
 /include/ "pq3-dma-0.dtsi"
 /include/ "pq3-etsec1-0.dtsi"
+	enet0: ethernet@24000 {
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec1_clk>;
+	};
 /include/ "pq3-etsec1-timer-0.dtsi"
 
 	usb@22000 {
@@ -222,9 +226,10 @@
 	};
 
 /include/ "pq3-etsec1-2.dtsi"
-
-	ethernet@26000 {
+	enet2: ethernet@26000 {
 		cell-index = <1>;
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec3_clk>;
 	};
 
 	usb@2b000 {
@@ -249,4 +254,9 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
+	power@e0070 {
+		compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
+	};
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
index b68eb11..ea7416a 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
@@ -188,4 +188,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
index 579d76c..dddb737 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
@@ -156,4 +156,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
index d44e25a..7313351 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
@@ -193,4 +193,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
index af12ead..01c8c33 100644
--- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
@@ -171,6 +171,8 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: ethernet@b0000 {
+		fsl,pmc-handle = <&etsec1_clk>;
+
 		queue-group@b0000 {
 			fsl,rx-bit-map = <0xff>;
 			fsl,tx-bit-map = <0xff>;
@@ -179,6 +181,8 @@
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: ethernet@b1000 {
+		fsl,pmc-handle = <&etsec2_clk>;
+
 		queue-group@b1000 {
 			fsl,rx-bit-map = <0xff>;
 			fsl,tx-bit-map = <0xff>;
@@ -187,6 +191,8 @@
 
 /include/ "pq3-etsec2-2.dtsi"
 	enet2: ethernet@b2000 {
+		fsl,pmc-handle = <&etsec3_clk>;
+
 		queue-group@b2000 {
 			fsl,rx-bit-map = <0xff>;
 			fsl,tx-bit-map = <0xff>;
@@ -199,4 +205,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
index 68cc5e7..410e6e5 100644
--- a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
@@ -162,14 +162,17 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: enet0_grp2: ethernet@b0000 {
+		fsl,pmc-handle = <&etsec1_clk>;
 	};
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: enet1_grp2: ethernet@b1000 {
+		fsl,pmc-handle = <&etsec2_clk>;
 	};
 
 /include/ "pq3-etsec2-2.dtsi"
 	enet2: enet2_grp2: ethernet@b2000 {
+		fsl,pmc-handle = <&etsec3_clk>;
 	};
 
 	global-utilities@e0000 {
@@ -177,6 +180,8 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
 
 /include/ "pq3-etsec2-grp2-0.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
index adb82fd..02df574 100644
--- a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
@@ -158,14 +158,17 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: enet0_grp2: ethernet@b0000 {
+		fsl,pmc-handle = <&etsec1_clk>;
 	};
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: enet1_grp2: ethernet@b1000 {
+		fsl,pmc-handle = <&etsec2_clk>;
 	};
 
 /include/ "pq3-etsec2-2.dtsi"
 	enet2: enet2_grp2: ethernet@b2000 {
+		fsl,pmc-handle = <&etsec3_clk>;
 	};
 
 	global-utilities@e0000 {
@@ -173,6 +176,8 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
 
 &qe {
diff --git a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
index e179803..c5343e7 100644
--- a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
@@ -223,10 +223,14 @@
 
 /include/ "pq3-etsec2-0.dtsi"
 	enet0: enet0_grp2: ethernet@b0000 {
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec1_clk>;
 	};
 
 /include/ "pq3-etsec2-1.dtsi"
 	enet1: enet1_grp2: ethernet@b1000 {
+		fsl,wake-on-filer;
+		fsl,pmc-handle = <&etsec2_clk>;
 	};
 
 	global-utilities@e0000 {
@@ -235,9 +239,10 @@
 		fsl,has-rstcr;
 	};
 
-	power@e0070{
-		compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
-		reg = <0xe0070 0x20>;
+/include/ "pq3-power.dtsi"
+	power@e0070 {
+		compatible = "fsl,p1022-pmc", "fsl,mpc8536-pmc",
+				"fsl,mpc8548-pmc";
 	};
 
 };
diff --git a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
index 884e01b..2c4787c 100644
--- a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
@@ -175,6 +175,10 @@
 		compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
 	};
 /include/ "pq3-etsec1-0.dtsi"
+	enet0: ethernet@24000 {
+		fsl,pmc-handle = <&etsec1_clk>;
+
+	};
 /include/ "pq3-etsec1-timer-0.dtsi"
 
 	ptp_clock@24e00 {
@@ -183,7 +187,15 @@
 
 
 /include/ "pq3-etsec1-1.dtsi"
+	enet1: ethernet@25000 {
+		fsl,pmc-handle = <&etsec2_clk>;
+	};
+
 /include/ "pq3-etsec1-2.dtsi"
+	enet2: ethernet@26000 {
+		fsl,pmc-handle = <&etsec3_clk>;
+	};
+
 /include/ "pq3-esdhc-0.dtsi"
 	sdhc@2e000 {
 		compatible = "fsl,p2020-esdhc", "fsl,esdhc";
@@ -198,4 +210,6 @@
 		reg = <0xe0000 0x1000>;
 		fsl,has-rstcr;
 	};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/pq3-power.dtsi b/arch/powerpc/boot/dts/fsl/pq3-power.dtsi
new file mode 100644
index 0000000..5a760b3
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-power.dtsi
@@ -0,0 +1,48 @@
+/*
+ * PQ3 Power Management device tree stub
+ *
+ * Copyright 2012-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+power@e0070 {
+	compatible = "fsl,mpc8548-pmc";
+	reg = <0xe0070 0x20>;
+
+	etsec1_clk: soc-clk@24 {
+		fsl,pmcdr-mask = <0x00000080>;
+	};
+	etsec2_clk: soc-clk@25 {
+		fsl,pmcdr-mask = <0x00000040>;
+	};
+	etsec3_clk: soc-clk@26 {
+		fsl,pmcdr-mask = <0x00000020>;
+	};
+};
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 05/15] fsl_pmc: update device bindings
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Li Yang <leoli@freescale.com>

Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
 .../devicetree/bindings/powerpc/fsl/pmc.txt        |   59 +++++++++++--------
 1 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
index 07256b7..f1f749f 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
@@ -9,15 +9,20 @@ Properties:
 
   "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
   compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
-  whose PMC is compatible, and implies deep-sleep capability.
+  whose PMC is compatible, and implies deep-sleep capability and
+  wake on user defined packet(wakeup on ARP).
+
+  "fsl,p1022-pmc" should be listed for any chip whose PMC is
+  compatible, and implies lossless Ethernet capability during sleep.
 
   "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
   compatible; all statements below that apply to "fsl,mpc8548-pmc" also
   apply to "fsl,mpc8641d-pmc".
 
   Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
-  bit assignments are indicated via the sleep specifier in each device's
-  sleep property.
+  bit assignments are indicated via the clock nodes.  Device which has a
+  controllable clock source should have a "fsl,pmc-handle" property pointing
+  to the clock node.
 
 - reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
   is the PMC block, and the second resource is the Clock Configuration
@@ -33,31 +38,35 @@ Properties:
   this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
   a wakeup source from deep sleep.
 
-Sleep specifiers:
+Clock nodes:
+The clock nodes are to describe the masks in PM controller registers for each
+soc clock.
+- fsl,pmcdr-mask: For "fsl,mpc8548-pmc"-compatible devices, the mask will be
+  ORed into PMCDR before suspend if the device using this clock is the wake-up
+  source and need to be running during low power mode; clear the mask if
+  otherwise.
 
-  fsl,mpc8349-pmc: Sleep specifiers consist of one cell.  For each bit
-  that is set in the cell, the corresponding bit in SCCR will be saved
-  and cleared on suspend, and restored on resume.  This sleep controller
-  supports disabling and resuming devices at any time.
+- fsl,sccr-mask: For "fsl,mpc8349-pmc"-compatible devices, the corresponding
+  bit specified by the mask in SCCR will be saved and cleared on suspend, and
+  restored on resume.
 
-  fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
-  which will be ORed into PMCDR upon suspend, and cleared from PMCDR
-  upon resume.  The first two cells are as described for fsl,mpc8578-pmc.
-  This sleep controller only supports disabling devices during system
-  sleep, or permanently.
-
-  fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
-  first of which will be ORed into DEVDISR (and the second into
-  DEVDISR2, if present -- this cell should be zero or absent if the
-  hardware does not have DEVDISR2) upon a request for permanent device
-  disabling.  This sleep controller does not support configuring devices
-  to disable during system sleep (unless supported by another compatible
-  match), or dynamically.
+- fsl,devdisr-mask: Contain one or two cells, depending on the availability of
+  DEVDISR2 register.  For compatible devices, the mask will be ORed into DEVDISR
+  or DEVDISR2 when the clock should be permenently disabled.
 
 Example:
 
-	power@b00 {
-		compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
-		reg = <0xb00 0x100 0xa00 0x100>;
-		interrupts = <80 8>;
+	power@e0070 {
+		compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
+		reg = <0xe0070 0x20>;
+
+		etsec1_clk: soc-clk@24 {
+			fsl,pmcdr-mask = <0x00000080>;
+		};
+		etsec2_clk: soc-clk@25 {
+			fsl,pmcdr-mask = <0x00000040>;
+		};
+		etsec3_clk: soc-clk@26 {
+			fsl,pmcdr-mask = <0x00000020>;
+		};
 	};
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 05/15] fsl_pmc: update device bindings
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Li Yang <leoli@freescale.com>

Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
 .../devicetree/bindings/powerpc/fsl/pmc.txt        |   59 +++++++++++--------
 1 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
index 07256b7..f1f749f 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
@@ -9,15 +9,20 @@ Properties:
 
   "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
   compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
-  whose PMC is compatible, and implies deep-sleep capability.
+  whose PMC is compatible, and implies deep-sleep capability and
+  wake on user defined packet(wakeup on ARP).
+
+  "fsl,p1022-pmc" should be listed for any chip whose PMC is
+  compatible, and implies lossless Ethernet capability during sleep.
 
   "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
   compatible; all statements below that apply to "fsl,mpc8548-pmc" also
   apply to "fsl,mpc8641d-pmc".
 
   Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
-  bit assignments are indicated via the sleep specifier in each device's
-  sleep property.
+  bit assignments are indicated via the clock nodes.  Device which has a
+  controllable clock source should have a "fsl,pmc-handle" property pointing
+  to the clock node.
 
 - reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
   is the PMC block, and the second resource is the Clock Configuration
@@ -33,31 +38,35 @@ Properties:
   this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
   a wakeup source from deep sleep.
 
-Sleep specifiers:
+Clock nodes:
+The clock nodes are to describe the masks in PM controller registers for each
+soc clock.
+- fsl,pmcdr-mask: For "fsl,mpc8548-pmc"-compatible devices, the mask will be
+  ORed into PMCDR before suspend if the device using this clock is the wake-up
+  source and need to be running during low power mode; clear the mask if
+  otherwise.
 
-  fsl,mpc8349-pmc: Sleep specifiers consist of one cell.  For each bit
-  that is set in the cell, the corresponding bit in SCCR will be saved
-  and cleared on suspend, and restored on resume.  This sleep controller
-  supports disabling and resuming devices at any time.
+- fsl,sccr-mask: For "fsl,mpc8349-pmc"-compatible devices, the corresponding
+  bit specified by the mask in SCCR will be saved and cleared on suspend, and
+  restored on resume.
 
-  fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
-  which will be ORed into PMCDR upon suspend, and cleared from PMCDR
-  upon resume.  The first two cells are as described for fsl,mpc8578-pmc.
-  This sleep controller only supports disabling devices during system
-  sleep, or permanently.
-
-  fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
-  first of which will be ORed into DEVDISR (and the second into
-  DEVDISR2, if present -- this cell should be zero or absent if the
-  hardware does not have DEVDISR2) upon a request for permanent device
-  disabling.  This sleep controller does not support configuring devices
-  to disable during system sleep (unless supported by another compatible
-  match), or dynamically.
+- fsl,devdisr-mask: Contain one or two cells, depending on the availability of
+  DEVDISR2 register.  For compatible devices, the mask will be ORed into DEVDISR
+  or DEVDISR2 when the clock should be permenently disabled.
 
 Example:
 
-	power@b00 {
-		compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
-		reg = <0xb00 0x100 0xa00 0x100>;
-		interrupts = <80 8>;
+	power@e0070 {
+		compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
+		reg = <0xe0070 0x20>;
+
+		etsec1_clk: soc-clk@24 {
+			fsl,pmcdr-mask = <0x00000080>;
+		};
+		etsec2_clk: soc-clk@25 {
+			fsl,pmcdr-mask = <0x00000040>;
+		};
+		etsec3_clk: soc-clk@26 {
+			fsl,pmcdr-mask = <0x00000020>;
+		};
 	};
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: chenhui zhao <chenhui.zhao@freescale.com>

Some 85xx silicons like MPC8536 and P1022 have a JOG feature, which provides
a dynamic mechanism to lower or raise the CPU core clock at runtime.

This patch adds the support to change CPU frequency using the standard
cpufreq interface. The ratio CORE to CCB can be 1:1(except MPC8536), 3:2,
2:1, 5:2, 3:1, 7:2 and 4:1.

Two CPU cores on P1022 must not in the low power state during the frequency
transition. The driver uses a atomic counter to meet the requirement.

The jog mode frequency transition process on the MPC8536 is similar to
the deep sleep process. The driver need save the CPU state and restore
it after CPU warm reset.

Note:
 * The I/O peripherals such as PCIe and eTSEC may lose packets during
   the jog mode frequency transition.
 * The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
   Subsequent revisions of MPC8536 have corrected the erratum.

Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
CC: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/platforms/85xx/Makefile |    1 +
 drivers/cpufreq/Kconfig.powerpc      |   10 +
 drivers/cpufreq/Makefile             |    1 +
 drivers/cpufreq/mpc85xx-cpufreq.c    |  390 ++++++++++++++++++++++++++++++++++
 4 files changed, 402 insertions(+), 0 deletions(-)
 create mode 100644 drivers/cpufreq/mpc85xx-cpufreq.c

diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index a35bab7..da53bde 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,6 +3,7 @@
 #
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_FSL_PMC)	+= sleep.o
+obj-$(CONFIG_CPU_FREQ_MPC85xx)	+= sleep.o
 
 obj-y += common.o
 
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index e76992f..ba06a00 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -5,3 +5,13 @@ config CPU_FREQ_MAPLE
 	help
 	  This adds support for frequency switching on Maple 970FX
 	  Evaluation Board and compatible boards (IBM JS2x blades).
+
+config CPU_FREQ_MPC85xx
+	bool "Support for Freescale MPC85xx CPU freq"
+	depends on PPC_85xx && PPC32 && !PPC_E500MC
+	select CPU_FREQ_TABLE
+	help
+	  This adds support for dynamic frequency switching on
+	  Freescale MPC85xx by cpufreq interface. MPC8536 and P1022
+	  have a JOG feature, which provides a dynamic mechanism
+	  to lower or raise the CPU core clock at runtime.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 863fd18..e7aecc5 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -61,3 +61,4 @@ obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
 ##################################################################################
 # PowerPC platform drivers
 obj-$(CONFIG_CPU_FREQ_MAPLE)		+= maple-cpufreq.o
+obj-$(CONFIG_CPU_FREQ_MPC85xx)		+= mpc85xx-cpufreq.o
diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c
new file mode 100644
index 0000000..f56c826
--- /dev/null
+++ b/drivers/cpufreq/mpc85xx-cpufreq.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Author: Dave Liu <daveliu@freescale.com>
+ * Modifier: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * The cpufreq driver is for Freescale 85xx processor,
+ * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ *	Christian Krafft <krafft@de.ibm.com>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+#include <linux/suspend.h>
+#include <linux/cpu.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+
+#include <asm/prom.h>
+#include <asm/reg.h>
+#include <asm/machdep.h>
+
+#include <sysdev/fsl_soc.h>
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+
+static u32 sysfreq;
+static unsigned int max_pll[2];
+static atomic_t in_jog_process;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+static int (*set_pll)(unsigned int cpu, unsigned int pll);
+
+static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
+	{3,	0},
+	{4,	0},
+	{5,	0},
+	{6,	0},
+	{7,	0},
+	{8,	0},
+	{0,	CPUFREQ_TABLE_END},
+};
+
+static struct cpufreq_frequency_table p1022_freqs_table[] = {
+	{2,	0},
+	{3,	0},
+	{4,	0},
+	{5,	0},
+	{6,	0},
+	{7,	0},
+	{8,	0},
+	{0,	CPUFREQ_TABLE_END},
+};
+
+#define FREQ_500MHz	500000000
+#define FREQ_800MHz	800000000
+
+#define CORE_RATIO_STRIDE	8
+#define CORE_RATIO_MASK		0x3f
+#define CORE_RATIO_SHIFT	16
+
+#define PORPLLSR	0x0	/* Power-On Reset PLL ratio status register */
+
+#define PMJCR		0x7c	/* Power Management Jog Control Register */
+#define PMJCR_CORE0_SPD	0x00001000
+#define PMJCR_CORE_SPD	0x00002000
+
+#define POWMGTCSR	0x80 /* Power management control and status register */
+#define POWMGTCSR_JOG		0x00200000
+#define POWMGTCSR_INT_MASK	0x00000f00
+
+static void spin_while_jogging(void *dummy)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	atomic_inc(&in_jog_process);
+
+	while (atomic_read(&in_jog_process) != 0)
+		barrier();
+
+	local_irq_restore(flags);
+}
+
+static int get_pll(int hw_cpu)
+{
+	int shift;
+	u32 val = in_be32(guts + PORPLLSR);
+
+	shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+
+	return (val >> shift) & CORE_RATIO_MASK;
+}
+
+static int mpc8536_set_pll(unsigned int cpu, unsigned int pll)
+{
+	u32 corefreq, val, mask;
+	unsigned int cur_pll = get_pll(0);
+	unsigned long flags;
+
+	if (pll == cur_pll)
+		return 0;
+
+	val = (pll & CORE_RATIO_MASK) << CORE_RATIO_SHIFT;
+
+	corefreq = sysfreq * pll / 2;
+	/*
+	 * Set the COREx_SPD bit if the requested core frequency
+	 * is larger than the threshold frequency.
+	 */
+	if (corefreq > FREQ_800MHz)
+			val |= PMJCR_CORE_SPD;
+
+	mask = (CORE_RATIO_MASK << CORE_RATIO_SHIFT) | PMJCR_CORE_SPD;
+	clrsetbits_be32(guts + PMJCR, mask, val);
+
+	/* readback to sync write */
+	in_be32(guts + PMJCR);
+
+	local_irq_save(flags);
+	mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_JOG);
+	local_irq_restore(flags);
+
+	/* verify */
+	cur_pll =  get_pll(0);
+	if (cur_pll != pll) {
+		pr_err("%s: error. The current PLL is %d instead of %d.\n",
+				__func__, cur_pll, pll);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int p1022_set_pll(unsigned int cpu, unsigned int pll)
+{
+	int index, hw_cpu = get_hard_smp_processor_id(cpu);
+	int shift;
+	u32 corefreq, val, mask = 0;
+	unsigned int cur_pll = get_pll(hw_cpu);
+	unsigned long flags;
+	int ret = 0;
+
+	if (pll == cur_pll)
+		return 0;
+
+	shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+	val = (pll & CORE_RATIO_MASK) << shift;
+
+	corefreq = sysfreq * pll / 2;
+	/*
+	 * Set the COREx_SPD bit if the requested core frequency
+	 * is larger than the threshold frequency.
+	 */
+	if (corefreq > FREQ_500MHz)
+		val |= PMJCR_CORE0_SPD << hw_cpu;
+
+	mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD << hw_cpu);
+	clrsetbits_be32(guts + PMJCR, mask, val);
+
+	/* readback to sync write */
+	in_be32(guts + PMJCR);
+
+	get_online_cpus();
+	/*
+	 * A Jog request can not be asserted when any core is in a low
+	 * power state on P1022. Before executing a jog request, any
+	 * core which is in a low power state must be waked by a
+	 * interrupt, and keep waking up until the sequence is
+	 * finished.
+	 */
+	for_each_present_cpu(index) {
+		if (!cpu_online(index)) {
+			put_online_cpus();
+			pr_err("%s: error, core%d is down.\n", __func__, index);
+			return -1;
+		}
+	}
+
+	atomic_set(&in_jog_process, 0);
+	smp_call_function(spin_while_jogging, NULL, 0);
+
+	local_irq_save(flags);
+
+	/* Wait for the other core to wake. */
+	if (!spin_event_timeout(atomic_read(&in_jog_process) == 1, 1000, 100)) {
+		pr_err("%s: timeout, the other core is not at running state.\n",
+					__func__);
+		ret = -1;
+		goto err;
+	}
+
+	out_be32(guts + POWMGTCSR, POWMGTCSR_JOG | POWMGTCSR_INT_MASK);
+
+	if (!spin_event_timeout(
+		(in_be32(guts + POWMGTCSR) & POWMGTCSR_JOG) == 0, 1000, 100)) {
+		pr_err("%s: timeout, fail to switch the core frequency.\n",
+				__func__);
+		ret = -1;
+		goto err;
+	}
+
+	clrbits32(guts + POWMGTCSR, POWMGTCSR_INT_MASK);
+	in_be32(guts + POWMGTCSR);
+
+	atomic_set(&in_jog_process, 0);
+err:
+	local_irq_restore(flags);
+	put_online_cpus();
+
+	/* verify */
+	cur_pll =  get_pll(hw_cpu);
+	if (cur_pll != pll) {
+		pr_err("%s: error, the current PLL of core %d is %d instead of %d.\n",
+				__func__, hw_cpu, cur_pll, pll);
+		return -1;
+	}
+
+	return ret;
+}
+
+/*
+ * cpufreq functions
+ */
+static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	unsigned int i, cur_pll;
+	int hw_cpu = get_hard_smp_processor_id(policy->cpu);
+
+	if (!cpu_present(policy->cpu))
+		return -ENODEV;
+
+	/* the latency of a transition, the unit is ns */
+	policy->cpuinfo.transition_latency = 2000;
+
+	cur_pll = get_pll(hw_cpu);
+
+	/* initialize frequency table */
+	pr_debug("core%d frequency table:\n", hw_cpu);
+	for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
+		if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
+			/* The frequency unit is kHz. */
+			mpc85xx_freqs[i].frequency =
+				(sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
+		} else {
+			mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
+		}
+
+		pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
+
+		if (mpc85xx_freqs[i].index == cur_pll)
+			policy->cur = mpc85xx_freqs[i].frequency;
+	}
+	pr_debug("current pll is at %d, and core freq is%d\n",
+			cur_pll, policy->cur);
+
+	cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
+
+	/*
+	 * This ensures that policy->cpuinfo_min
+	 * and policy->cpuinfo_max are set correctly.
+	 */
+	return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+
+	return 0;
+}
+
+static int mpc85xx_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
+			      unsigned int target_freq,
+			      unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	unsigned int new;
+	int ret = 0;
+
+	if (!set_pll)
+		return -ENODEV;
+
+	cpufreq_frequency_table_target(policy,
+				       mpc85xx_freqs,
+				       target_freq,
+				       relation,
+				       &new);
+
+	freqs.old = policy->cur;
+	freqs.new = mpc85xx_freqs[new].frequency;
+	freqs.cpu = policy->cpu;
+
+	mutex_lock(&mpc85xx_switch_mutex);
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
+	if (!ret) {
+		pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
+			 policy->cpu, mpc85xx_freqs[new].frequency,
+			 mpc85xx_freqs[new].index);
+
+		ppc_proc_freq = freqs.new * 1000ul;
+	}
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	mutex_unlock(&mpc85xx_switch_mutex);
+
+	return ret;
+}
+
+static struct cpufreq_driver mpc85xx_cpufreq_driver = {
+	.verify		= mpc85xx_cpufreq_verify,
+	.target		= mpc85xx_cpufreq_target,
+	.init		= mpc85xx_cpufreq_cpu_init,
+	.exit		= mpc85xx_cpufreq_cpu_exit,
+	.name		= "mpc85xx-JOG",
+	.owner		= THIS_MODULE,
+	.flags		= CPUFREQ_CONST_LOOPS,
+};
+
+static struct of_device_id mpc85xx_jog_ids[] = {
+	{ .compatible = "fsl,mpc8536-guts", },
+	{ .compatible = "fsl,p1022-guts", },
+	{}
+};
+
+static int __init mpc85xx_jog_init(void)
+{
+	struct device_node *np;
+	unsigned int svr;
+
+	np = of_find_matching_node(NULL, mpc85xx_jog_ids);
+	if (!np)
+		return -ENODEV;
+
+	guts = of_iomap(np, 0);
+	if (!guts) {
+		of_node_put(np);
+		return -ENODEV;
+	}
+
+	sysfreq = fsl_get_sys_freq();
+
+	if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
+		svr = mfspr(SPRN_SVR);
+		if ((svr & 0x7fff) == 0x10) {
+			pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
+			of_node_put(np);
+			return -ENODEV;
+		}
+		mpc85xx_freqs = mpc8536_freqs_table;
+		set_pll = mpc8536_set_pll;
+		max_pll[0] = get_pll(0);
+
+	} else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
+		mpc85xx_freqs = p1022_freqs_table;
+		set_pll = p1022_set_pll;
+		max_pll[0] = get_pll(0);
+		max_pll[1] = get_pll(1);
+	}
+
+	pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
+
+	of_node_put(np);
+	return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
+}
+
+device_initcall(mpc85xx_jog_init);
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: chenhui zhao <chenhui.zhao@freescale.com>

Some 85xx silicons like MPC8536 and P1022 have a JOG feature, which provides
a dynamic mechanism to lower or raise the CPU core clock at runtime.

This patch adds the support to change CPU frequency using the standard
cpufreq interface. The ratio CORE to CCB can be 1:1(except MPC8536), 3:2,
2:1, 5:2, 3:1, 7:2 and 4:1.

Two CPU cores on P1022 must not in the low power state during the frequency
transition. The driver uses a atomic counter to meet the requirement.

The jog mode frequency transition process on the MPC8536 is similar to
the deep sleep process. The driver need save the CPU state and restore
it after CPU warm reset.

Note:
 * The I/O peripherals such as PCIe and eTSEC may lose packets during
   the jog mode frequency transition.
 * The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
   Subsequent revisions of MPC8536 have corrected the erratum.

Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
CC: Scott Wood <scottwood@freescale.com>
---
 arch/powerpc/platforms/85xx/Makefile |    1 +
 drivers/cpufreq/Kconfig.powerpc      |   10 +
 drivers/cpufreq/Makefile             |    1 +
 drivers/cpufreq/mpc85xx-cpufreq.c    |  390 ++++++++++++++++++++++++++++++++++
 4 files changed, 402 insertions(+), 0 deletions(-)
 create mode 100644 drivers/cpufreq/mpc85xx-cpufreq.c

diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index a35bab7..da53bde 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,6 +3,7 @@
 #
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_FSL_PMC)	+= sleep.o
+obj-$(CONFIG_CPU_FREQ_MPC85xx)	+= sleep.o
 
 obj-y += common.o
 
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index e76992f..ba06a00 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -5,3 +5,13 @@ config CPU_FREQ_MAPLE
 	help
 	  This adds support for frequency switching on Maple 970FX
 	  Evaluation Board and compatible boards (IBM JS2x blades).
+
+config CPU_FREQ_MPC85xx
+	bool "Support for Freescale MPC85xx CPU freq"
+	depends on PPC_85xx && PPC32 && !PPC_E500MC
+	select CPU_FREQ_TABLE
+	help
+	  This adds support for dynamic frequency switching on
+	  Freescale MPC85xx by cpufreq interface. MPC8536 and P1022
+	  have a JOG feature, which provides a dynamic mechanism
+	  to lower or raise the CPU core clock at runtime.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 863fd18..e7aecc5 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -61,3 +61,4 @@ obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
 ##################################################################################
 # PowerPC platform drivers
 obj-$(CONFIG_CPU_FREQ_MAPLE)		+= maple-cpufreq.o
+obj-$(CONFIG_CPU_FREQ_MPC85xx)		+= mpc85xx-cpufreq.o
diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c
new file mode 100644
index 0000000..f56c826
--- /dev/null
+++ b/drivers/cpufreq/mpc85xx-cpufreq.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Author: Dave Liu <daveliu@freescale.com>
+ * Modifier: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * The cpufreq driver is for Freescale 85xx processor,
+ * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ *	Christian Krafft <krafft@de.ibm.com>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+#include <linux/suspend.h>
+#include <linux/cpu.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+
+#include <asm/prom.h>
+#include <asm/reg.h>
+#include <asm/machdep.h>
+
+#include <sysdev/fsl_soc.h>
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+
+static u32 sysfreq;
+static unsigned int max_pll[2];
+static atomic_t in_jog_process;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+static int (*set_pll)(unsigned int cpu, unsigned int pll);
+
+static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
+	{3,	0},
+	{4,	0},
+	{5,	0},
+	{6,	0},
+	{7,	0},
+	{8,	0},
+	{0,	CPUFREQ_TABLE_END},
+};
+
+static struct cpufreq_frequency_table p1022_freqs_table[] = {
+	{2,	0},
+	{3,	0},
+	{4,	0},
+	{5,	0},
+	{6,	0},
+	{7,	0},
+	{8,	0},
+	{0,	CPUFREQ_TABLE_END},
+};
+
+#define FREQ_500MHz	500000000
+#define FREQ_800MHz	800000000
+
+#define CORE_RATIO_STRIDE	8
+#define CORE_RATIO_MASK		0x3f
+#define CORE_RATIO_SHIFT	16
+
+#define PORPLLSR	0x0	/* Power-On Reset PLL ratio status register */
+
+#define PMJCR		0x7c	/* Power Management Jog Control Register */
+#define PMJCR_CORE0_SPD	0x00001000
+#define PMJCR_CORE_SPD	0x00002000
+
+#define POWMGTCSR	0x80 /* Power management control and status register */
+#define POWMGTCSR_JOG		0x00200000
+#define POWMGTCSR_INT_MASK	0x00000f00
+
+static void spin_while_jogging(void *dummy)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	atomic_inc(&in_jog_process);
+
+	while (atomic_read(&in_jog_process) != 0)
+		barrier();
+
+	local_irq_restore(flags);
+}
+
+static int get_pll(int hw_cpu)
+{
+	int shift;
+	u32 val = in_be32(guts + PORPLLSR);
+
+	shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+
+	return (val >> shift) & CORE_RATIO_MASK;
+}
+
+static int mpc8536_set_pll(unsigned int cpu, unsigned int pll)
+{
+	u32 corefreq, val, mask;
+	unsigned int cur_pll = get_pll(0);
+	unsigned long flags;
+
+	if (pll == cur_pll)
+		return 0;
+
+	val = (pll & CORE_RATIO_MASK) << CORE_RATIO_SHIFT;
+
+	corefreq = sysfreq * pll / 2;
+	/*
+	 * Set the COREx_SPD bit if the requested core frequency
+	 * is larger than the threshold frequency.
+	 */
+	if (corefreq > FREQ_800MHz)
+			val |= PMJCR_CORE_SPD;
+
+	mask = (CORE_RATIO_MASK << CORE_RATIO_SHIFT) | PMJCR_CORE_SPD;
+	clrsetbits_be32(guts + PMJCR, mask, val);
+
+	/* readback to sync write */
+	in_be32(guts + PMJCR);
+
+	local_irq_save(flags);
+	mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_JOG);
+	local_irq_restore(flags);
+
+	/* verify */
+	cur_pll =  get_pll(0);
+	if (cur_pll != pll) {
+		pr_err("%s: error. The current PLL is %d instead of %d.\n",
+				__func__, cur_pll, pll);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int p1022_set_pll(unsigned int cpu, unsigned int pll)
+{
+	int index, hw_cpu = get_hard_smp_processor_id(cpu);
+	int shift;
+	u32 corefreq, val, mask = 0;
+	unsigned int cur_pll = get_pll(hw_cpu);
+	unsigned long flags;
+	int ret = 0;
+
+	if (pll == cur_pll)
+		return 0;
+
+	shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+	val = (pll & CORE_RATIO_MASK) << shift;
+
+	corefreq = sysfreq * pll / 2;
+	/*
+	 * Set the COREx_SPD bit if the requested core frequency
+	 * is larger than the threshold frequency.
+	 */
+	if (corefreq > FREQ_500MHz)
+		val |= PMJCR_CORE0_SPD << hw_cpu;
+
+	mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD << hw_cpu);
+	clrsetbits_be32(guts + PMJCR, mask, val);
+
+	/* readback to sync write */
+	in_be32(guts + PMJCR);
+
+	get_online_cpus();
+	/*
+	 * A Jog request can not be asserted when any core is in a low
+	 * power state on P1022. Before executing a jog request, any
+	 * core which is in a low power state must be waked by a
+	 * interrupt, and keep waking up until the sequence is
+	 * finished.
+	 */
+	for_each_present_cpu(index) {
+		if (!cpu_online(index)) {
+			put_online_cpus();
+			pr_err("%s: error, core%d is down.\n", __func__, index);
+			return -1;
+		}
+	}
+
+	atomic_set(&in_jog_process, 0);
+	smp_call_function(spin_while_jogging, NULL, 0);
+
+	local_irq_save(flags);
+
+	/* Wait for the other core to wake. */
+	if (!spin_event_timeout(atomic_read(&in_jog_process) == 1, 1000, 100)) {
+		pr_err("%s: timeout, the other core is not at running state.\n",
+					__func__);
+		ret = -1;
+		goto err;
+	}
+
+	out_be32(guts + POWMGTCSR, POWMGTCSR_JOG | POWMGTCSR_INT_MASK);
+
+	if (!spin_event_timeout(
+		(in_be32(guts + POWMGTCSR) & POWMGTCSR_JOG) == 0, 1000, 100)) {
+		pr_err("%s: timeout, fail to switch the core frequency.\n",
+				__func__);
+		ret = -1;
+		goto err;
+	}
+
+	clrbits32(guts + POWMGTCSR, POWMGTCSR_INT_MASK);
+	in_be32(guts + POWMGTCSR);
+
+	atomic_set(&in_jog_process, 0);
+err:
+	local_irq_restore(flags);
+	put_online_cpus();
+
+	/* verify */
+	cur_pll =  get_pll(hw_cpu);
+	if (cur_pll != pll) {
+		pr_err("%s: error, the current PLL of core %d is %d instead of %d.\n",
+				__func__, hw_cpu, cur_pll, pll);
+		return -1;
+	}
+
+	return ret;
+}
+
+/*
+ * cpufreq functions
+ */
+static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	unsigned int i, cur_pll;
+	int hw_cpu = get_hard_smp_processor_id(policy->cpu);
+
+	if (!cpu_present(policy->cpu))
+		return -ENODEV;
+
+	/* the latency of a transition, the unit is ns */
+	policy->cpuinfo.transition_latency = 2000;
+
+	cur_pll = get_pll(hw_cpu);
+
+	/* initialize frequency table */
+	pr_debug("core%d frequency table:\n", hw_cpu);
+	for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
+		if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
+			/* The frequency unit is kHz. */
+			mpc85xx_freqs[i].frequency =
+				(sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
+		} else {
+			mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
+		}
+
+		pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
+
+		if (mpc85xx_freqs[i].index == cur_pll)
+			policy->cur = mpc85xx_freqs[i].frequency;
+	}
+	pr_debug("current pll is at %d, and core freq is%d\n",
+			cur_pll, policy->cur);
+
+	cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
+
+	/*
+	 * This ensures that policy->cpuinfo_min
+	 * and policy->cpuinfo_max are set correctly.
+	 */
+	return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+
+	return 0;
+}
+
+static int mpc85xx_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
+			      unsigned int target_freq,
+			      unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	unsigned int new;
+	int ret = 0;
+
+	if (!set_pll)
+		return -ENODEV;
+
+	cpufreq_frequency_table_target(policy,
+				       mpc85xx_freqs,
+				       target_freq,
+				       relation,
+				       &new);
+
+	freqs.old = policy->cur;
+	freqs.new = mpc85xx_freqs[new].frequency;
+	freqs.cpu = policy->cpu;
+
+	mutex_lock(&mpc85xx_switch_mutex);
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
+	if (!ret) {
+		pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
+			 policy->cpu, mpc85xx_freqs[new].frequency,
+			 mpc85xx_freqs[new].index);
+
+		ppc_proc_freq = freqs.new * 1000ul;
+	}
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	mutex_unlock(&mpc85xx_switch_mutex);
+
+	return ret;
+}
+
+static struct cpufreq_driver mpc85xx_cpufreq_driver = {
+	.verify		= mpc85xx_cpufreq_verify,
+	.target		= mpc85xx_cpufreq_target,
+	.init		= mpc85xx_cpufreq_cpu_init,
+	.exit		= mpc85xx_cpufreq_cpu_exit,
+	.name		= "mpc85xx-JOG",
+	.owner		= THIS_MODULE,
+	.flags		= CPUFREQ_CONST_LOOPS,
+};
+
+static struct of_device_id mpc85xx_jog_ids[] = {
+	{ .compatible = "fsl,mpc8536-guts", },
+	{ .compatible = "fsl,p1022-guts", },
+	{}
+};
+
+static int __init mpc85xx_jog_init(void)
+{
+	struct device_node *np;
+	unsigned int svr;
+
+	np = of_find_matching_node(NULL, mpc85xx_jog_ids);
+	if (!np)
+		return -ENODEV;
+
+	guts = of_iomap(np, 0);
+	if (!guts) {
+		of_node_put(np);
+		return -ENODEV;
+	}
+
+	sysfreq = fsl_get_sys_freq();
+
+	if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
+		svr = mfspr(SPRN_SVR);
+		if ((svr & 0x7fff) == 0x10) {
+			pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
+			of_node_put(np);
+			return -ENODEV;
+		}
+		mpc85xx_freqs = mpc8536_freqs_table;
+		set_pll = mpc8536_set_pll;
+		max_pll[0] = get_pll(0);
+
+	} else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
+		mpc85xx_freqs = p1022_freqs_table;
+		set_pll = p1022_set_pll;
+		max_pll[0] = get_pll(0);
+		max_pll[1] = get_pll(1);
+	}
+
+	pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
+
+	of_node_put(np);
+	return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
+}
+
+device_initcall(mpc85xx_jog_init);
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 07/15] powerpc/85xx: add time base sync for SoCs based on e500mc/e5500
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

In the case of SMP, during the time base sync period, all time bases of
online cores must stop, then start simultaneously.

There is a RCPM (Run Control/Power Management) module in CoreNet based SoCs.
Define a struct ccsr_rcpm to describe the register map.

This patch supports SoCs based on e500mc/e5500, such as P4080, P5020,
etc.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/include/asm/fsl_guts.h |   38 +++++++++++++++++++++++++++++++++++
 arch/powerpc/platforms/85xx/smp.c   |   32 +++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index 77ced0b..4eac1cf 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -106,6 +106,44 @@ struct ccsr_guts {
 /* Alternate function signal multiplex control */
 #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
 
+struct ccsr_rcpm {
+	u8	res0000[4];
+	__be32	cdozsr;		/* 0x0004 - Core Doze Status Register */
+	u8	res0008[4];
+	__be32	cdozcr;		/* 0x000c - Core Doze Control Register */
+	u8	res0010[4];
+	__be32	cnapsr;		/* 0x0014 - Core Nap Status Register */
+	u8	res0018[4];
+	__be32	cnapcr;		/* 0x001c - Core Nap Control Register */
+	u8	res0020[4];
+	__be32	cdozpsr;	/* 0x0024 - Core Doze Previous Status Register */
+	u8	res0028[4];
+	__be32	cnappsr;	/* 0x002c - Core Nap Previous Status Register */
+	u8	res0030[4];
+	__be32	cwaitsr;	/* 0x0034 - Core Wait Status Register */
+	u8	res0038[4];
+	__be32	cwdtdsr;	/* 0x003c - Core watchdog detect status register */
+	__be32	powmgtcsr;	/* 0x0040 - Power Mangement Control & Status Register */
+	u8	res0044[12];
+	__be32	ippdexpcr;	/* 0x0050 - IP Powerdown Exception Control Register */
+	u8	res0054[16];
+	__be32	cpmimr;		/* 0x0064 - Core PM IRQ Mask Register */
+	u8	res0068[4];
+	__be32	cpmcimr;	/* 0x006c - Core PM Critical IRQ Mask Register */
+	u8	res0070[4];
+	__be32	cpmmcmr;	/* 0x0074 - Core PM Machine Check Mask Register */
+	u8	res0078[4];
+	__be32	cpmnmimr;	/* 0x007c - Core PM NMI Mask Register */
+	u8	res0080[4];
+	__be32	ctbenr;		/* 0x0084 - Core Time Base Enable Register */
+	u8	res0088[4];
+	__be32	ctbckselr;	/* 0x008c - Core Time Base Clock Select Register */
+	u8	res0090[4];
+	__be32	ctbhltcr;	/* 0x0094 - Core Time Base Halt Control Register */
+	u8	res0098[4];
+	__be32	cmcpmaskcr;	/* 0x00a4 - Core machine check mask control register */
+};
+
 #ifdef CONFIG_PPC_86xx
 
 #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6a17599..6c2fe6b 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -44,7 +44,36 @@ static struct ccsr_guts __iomem *guts;
 static u64 timebase;
 static int tb_req;
 static int tb_valid;
+static u32 cur_booting_core;
 
+#ifdef CONFIG_PPC_E500MC
+/* get a physical mask of online cores and booting core */
+static inline u32 get_phy_cpu_mask(void)
+{
+	u32 mask;
+	int cpu;
+
+	mask = 1 << cur_booting_core;
+	for_each_online_cpu(cpu)
+		mask |= 1 << get_hard_smp_processor_id(cpu);
+
+	return mask;
+}
+
+static void mpc85xx_timebase_freeze(int freeze)
+{
+	struct ccsr_rcpm __iomem *rcpm = (typeof(rcpm))guts;
+	u32 mask = get_phy_cpu_mask();
+
+	if (freeze)
+		clrbits32(&rcpm->ctbenr, mask);
+	else
+		setbits32(&rcpm->ctbenr, mask);
+
+	/* read back to push the previos write */
+	in_be32(&rcpm->ctbenr);
+}
+#else
 static void mpc85xx_timebase_freeze(int freeze)
 {
 	uint32_t mask;
@@ -57,6 +86,7 @@ static void mpc85xx_timebase_freeze(int freeze)
 
 	in_be32(&guts->devdisr);
 }
+#endif
 
 static void mpc85xx_give_timebase(void)
 {
@@ -244,6 +274,7 @@ out:
 	  __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
 	flush_spin_table(spin_table);
 #endif
+	cur_booting_core = hw_cpu;
 
 	local_irq_restore(flags);
 
@@ -378,6 +409,7 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = {
 	{ .compatible = "fsl,p1022-guts", },
 	{ .compatible = "fsl,p1023-guts", },
 	{ .compatible = "fsl,p2020-guts", },
+	{ .compatible = "fsl,qoriq-rcpm-1.0", },
 	{},
 };
 
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 07/15] powerpc/85xx: add time base sync for SoCs based on e500mc/e5500
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

In the case of SMP, during the time base sync period, all time bases of
online cores must stop, then start simultaneously.

There is a RCPM (Run Control/Power Management) module in CoreNet based SoCs.
Define a struct ccsr_rcpm to describe the register map.

This patch supports SoCs based on e500mc/e5500, such as P4080, P5020,
etc.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/include/asm/fsl_guts.h |   38 +++++++++++++++++++++++++++++++++++
 arch/powerpc/platforms/85xx/smp.c   |   32 +++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index 77ced0b..4eac1cf 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -106,6 +106,44 @@ struct ccsr_guts {
 /* Alternate function signal multiplex control */
 #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
 
+struct ccsr_rcpm {
+	u8	res0000[4];
+	__be32	cdozsr;		/* 0x0004 - Core Doze Status Register */
+	u8	res0008[4];
+	__be32	cdozcr;		/* 0x000c - Core Doze Control Register */
+	u8	res0010[4];
+	__be32	cnapsr;		/* 0x0014 - Core Nap Status Register */
+	u8	res0018[4];
+	__be32	cnapcr;		/* 0x001c - Core Nap Control Register */
+	u8	res0020[4];
+	__be32	cdozpsr;	/* 0x0024 - Core Doze Previous Status Register */
+	u8	res0028[4];
+	__be32	cnappsr;	/* 0x002c - Core Nap Previous Status Register */
+	u8	res0030[4];
+	__be32	cwaitsr;	/* 0x0034 - Core Wait Status Register */
+	u8	res0038[4];
+	__be32	cwdtdsr;	/* 0x003c - Core watchdog detect status register */
+	__be32	powmgtcsr;	/* 0x0040 - Power Mangement Control & Status Register */
+	u8	res0044[12];
+	__be32	ippdexpcr;	/* 0x0050 - IP Powerdown Exception Control Register */
+	u8	res0054[16];
+	__be32	cpmimr;		/* 0x0064 - Core PM IRQ Mask Register */
+	u8	res0068[4];
+	__be32	cpmcimr;	/* 0x006c - Core PM Critical IRQ Mask Register */
+	u8	res0070[4];
+	__be32	cpmmcmr;	/* 0x0074 - Core PM Machine Check Mask Register */
+	u8	res0078[4];
+	__be32	cpmnmimr;	/* 0x007c - Core PM NMI Mask Register */
+	u8	res0080[4];
+	__be32	ctbenr;		/* 0x0084 - Core Time Base Enable Register */
+	u8	res0088[4];
+	__be32	ctbckselr;	/* 0x008c - Core Time Base Clock Select Register */
+	u8	res0090[4];
+	__be32	ctbhltcr;	/* 0x0094 - Core Time Base Halt Control Register */
+	u8	res0098[4];
+	__be32	cmcpmaskcr;	/* 0x00a4 - Core machine check mask control register */
+};
+
 #ifdef CONFIG_PPC_86xx
 
 #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6a17599..6c2fe6b 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -44,7 +44,36 @@ static struct ccsr_guts __iomem *guts;
 static u64 timebase;
 static int tb_req;
 static int tb_valid;
+static u32 cur_booting_core;
 
+#ifdef CONFIG_PPC_E500MC
+/* get a physical mask of online cores and booting core */
+static inline u32 get_phy_cpu_mask(void)
+{
+	u32 mask;
+	int cpu;
+
+	mask = 1 << cur_booting_core;
+	for_each_online_cpu(cpu)
+		mask |= 1 << get_hard_smp_processor_id(cpu);
+
+	return mask;
+}
+
+static void mpc85xx_timebase_freeze(int freeze)
+{
+	struct ccsr_rcpm __iomem *rcpm = (typeof(rcpm))guts;
+	u32 mask = get_phy_cpu_mask();
+
+	if (freeze)
+		clrbits32(&rcpm->ctbenr, mask);
+	else
+		setbits32(&rcpm->ctbenr, mask);
+
+	/* read back to push the previos write */
+	in_be32(&rcpm->ctbenr);
+}
+#else
 static void mpc85xx_timebase_freeze(int freeze)
 {
 	uint32_t mask;
@@ -57,6 +86,7 @@ static void mpc85xx_timebase_freeze(int freeze)
 
 	in_be32(&guts->devdisr);
 }
+#endif
 
 static void mpc85xx_give_timebase(void)
 {
@@ -244,6 +274,7 @@ out:
 	  __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
 	flush_spin_table(spin_table);
 #endif
+	cur_booting_core = hw_cpu;
 
 	local_irq_restore(flags);
 
@@ -378,6 +409,7 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = {
 	{ .compatible = "fsl,p1022-guts", },
 	{ .compatible = "fsl,p1023-guts", },
 	{ .compatible = "fsl,p2020-guts", },
+	{ .compatible = "fsl,qoriq-rcpm-1.0", },
 	{},
 };
 
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 08/15] powerpc/85xx: add cpu hotplug support for e500mc/e5500
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

Add support to disable and re-enable individual cores at runtime.
This supports e500mc/e5500 core based SoCs.

To prevent the register access race, only read/write RCPM registers
in platform_cpu_die() on the boot cpu instead of accessing by individual
cpus. Platform implementations can override the platform_cpu_die().

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/Kconfig              |    2 +-
 arch/powerpc/include/asm/smp.h    |    1 +
 arch/powerpc/kernel/smp.c         |   16 ++++++++++-
 arch/powerpc/platforms/85xx/smp.c |   56 ++++++++++++++++++++++++++++++++++--
 4 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0e11a09..b6851be 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -347,7 +347,7 @@ config SWIOTLB
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
 	depends on SMP && HOTPLUG && (PPC_PSERIES || \
-	PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
+	PPC_PMAC || PPC_POWERNV || PPC_85xx)
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 195ce2a..95be584 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -60,6 +60,7 @@ extern void smp_generic_take_timebase(void);
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
 #ifdef CONFIG_HOTPLUG_CPU
+void platform_cpu_die(unsigned int cpu);
 extern void migrate_irqs(void);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 76bd9da..386c7ea 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -381,14 +381,28 @@ int generic_cpu_disable(void)
 	return 0;
 }
 
+/**
+ * platform_cpu_die() - do platform related operations on the boot cpu
+ * after CPU_DEAD is assigned to the variable cpu_state of the dying cpu.
+ * Platform implementations can override this.
+ *
+ * @cpu:	the cpu to die
+ */
+void __attribute__ ((weak)) platform_cpu_die(unsigned int cpu)
+{
+	return;
+}
+
 void generic_cpu_die(unsigned int cpu)
 {
 	int i;
 
 	for (i = 0; i < 100; i++) {
 		smp_rmb();
-		if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+			platform_cpu_die(cpu);
 			return;
+		}
 		msleep(100);
 	}
 	printk(KERN_ERR "CPU%d didn't die...\n", cpu);
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6c2fe6b..6eae2e0 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -40,7 +40,7 @@ struct epapr_spin_table {
 	u32	pir;
 };
 
-static struct ccsr_guts __iomem *guts;
+static void __iomem *guts_regs;
 static u64 timebase;
 static int tb_req;
 static int tb_valid;
@@ -62,7 +62,7 @@ static inline u32 get_phy_cpu_mask(void)
 
 static void mpc85xx_timebase_freeze(int freeze)
 {
-	struct ccsr_rcpm __iomem *rcpm = (typeof(rcpm))guts;
+	struct ccsr_rcpm __iomem *rcpm = guts_regs;
 	u32 mask = get_phy_cpu_mask();
 
 	if (freeze)
@@ -76,6 +76,7 @@ static void mpc85xx_timebase_freeze(int freeze)
 #else
 static void mpc85xx_timebase_freeze(int freeze)
 {
+	struct ccsr_guts __iomem *guts = guts_regs;
 	uint32_t mask;
 
 	mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
@@ -84,6 +85,7 @@ static void mpc85xx_timebase_freeze(int freeze)
 	else
 		clrbits32(&guts->devdisr, mask);
 
+	/* read back to push the previous write */
 	in_be32(&guts->devdisr);
 }
 #endif
@@ -128,7 +130,45 @@ static void mpc85xx_take_timebase(void)
 	local_irq_restore(flags);
 }
 
+static void core_reset_erratum(int hw_cpu)
+{
+#ifdef CONFIG_PPC_E500MC
+	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+
+	clrbits32(&rcpm->cnapcr, 1 << hw_cpu);
+#endif
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_PPC_E500MC
+static void __cpuinit smp_85xx_mach_cpu_die(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	local_irq_disable();
+	idle_task_exit();
+	mb();
+
+	mtspr(SPRN_TCR, 0);
+
+	__flush_disable_L1();
+	disable_backside_L2_cache();
+
+	generic_set_cpu_dead(cpu);
+
+	while (1);
+}
+
+void platform_cpu_die(unsigned int cpu)
+{
+	unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
+	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+
+	/* Core Nap Operation */
+	setbits32(&rcpm->cnapcr, 1 << hw_cpu);
+}
+#else
+/* for e500v1 and e500v2 */
 static void __cpuinit smp_85xx_mach_cpu_die(void)
 {
 	unsigned int cpu = smp_processor_id();
@@ -156,6 +196,7 @@ static void __cpuinit smp_85xx_mach_cpu_die(void)
 	while (1)
 		;
 }
+#endif /* CONFIG_PPC_E500MC */
 #endif
 
 static inline void flush_spin_table(void *spin_table)
@@ -228,6 +269,13 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		flush_spin_table(spin_table);
 
 		/*
+		 * Due to an erratum that core hard reset and core warm reset
+		 * are unable to wake up cores from power management modes,
+		 * wake up cores before reset.
+		 */
+		core_reset_erratum(hw_cpu);
+
+		/*
 		 * We don't set the BPTR register here since it already points
 		 * to the boot page properly.
 		 */
@@ -436,9 +484,9 @@ void __init mpc85xx_smp_init(void)
 
 	np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
 	if (np) {
-		guts = of_iomap(np, 0);
+		guts_regs = of_iomap(np, 0);
 		of_node_put(np);
-		if (!guts) {
+		if (!guts_regs) {
 			pr_err("%s: Could not map guts node address\n",
 								__func__);
 			return;
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 08/15] powerpc/85xx: add cpu hotplug support for e500mc/e5500
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

Add support to disable and re-enable individual cores at runtime.
This supports e500mc/e5500 core based SoCs.

To prevent the register access race, only read/write RCPM registers
in platform_cpu_die() on the boot cpu instead of accessing by individual
cpus. Platform implementations can override the platform_cpu_die().

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/Kconfig              |    2 +-
 arch/powerpc/include/asm/smp.h    |    1 +
 arch/powerpc/kernel/smp.c         |   16 ++++++++++-
 arch/powerpc/platforms/85xx/smp.c |   56 ++++++++++++++++++++++++++++++++++--
 4 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0e11a09..b6851be 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -347,7 +347,7 @@ config SWIOTLB
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
 	depends on SMP && HOTPLUG && (PPC_PSERIES || \
-	PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
+	PPC_PMAC || PPC_POWERNV || PPC_85xx)
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 195ce2a..95be584 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -60,6 +60,7 @@ extern void smp_generic_take_timebase(void);
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
 #ifdef CONFIG_HOTPLUG_CPU
+void platform_cpu_die(unsigned int cpu);
 extern void migrate_irqs(void);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 76bd9da..386c7ea 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -381,14 +381,28 @@ int generic_cpu_disable(void)
 	return 0;
 }
 
+/**
+ * platform_cpu_die() - do platform related operations on the boot cpu
+ * after CPU_DEAD is assigned to the variable cpu_state of the dying cpu.
+ * Platform implementations can override this.
+ *
+ * @cpu:	the cpu to die
+ */
+void __attribute__ ((weak)) platform_cpu_die(unsigned int cpu)
+{
+	return;
+}
+
 void generic_cpu_die(unsigned int cpu)
 {
 	int i;
 
 	for (i = 0; i < 100; i++) {
 		smp_rmb();
-		if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+			platform_cpu_die(cpu);
 			return;
+		}
 		msleep(100);
 	}
 	printk(KERN_ERR "CPU%d didn't die...\n", cpu);
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6c2fe6b..6eae2e0 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -40,7 +40,7 @@ struct epapr_spin_table {
 	u32	pir;
 };
 
-static struct ccsr_guts __iomem *guts;
+static void __iomem *guts_regs;
 static u64 timebase;
 static int tb_req;
 static int tb_valid;
@@ -62,7 +62,7 @@ static inline u32 get_phy_cpu_mask(void)
 
 static void mpc85xx_timebase_freeze(int freeze)
 {
-	struct ccsr_rcpm __iomem *rcpm = (typeof(rcpm))guts;
+	struct ccsr_rcpm __iomem *rcpm = guts_regs;
 	u32 mask = get_phy_cpu_mask();
 
 	if (freeze)
@@ -76,6 +76,7 @@ static void mpc85xx_timebase_freeze(int freeze)
 #else
 static void mpc85xx_timebase_freeze(int freeze)
 {
+	struct ccsr_guts __iomem *guts = guts_regs;
 	uint32_t mask;
 
 	mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
@@ -84,6 +85,7 @@ static void mpc85xx_timebase_freeze(int freeze)
 	else
 		clrbits32(&guts->devdisr, mask);
 
+	/* read back to push the previous write */
 	in_be32(&guts->devdisr);
 }
 #endif
@@ -128,7 +130,45 @@ static void mpc85xx_take_timebase(void)
 	local_irq_restore(flags);
 }
 
+static void core_reset_erratum(int hw_cpu)
+{
+#ifdef CONFIG_PPC_E500MC
+	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+
+	clrbits32(&rcpm->cnapcr, 1 << hw_cpu);
+#endif
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_PPC_E500MC
+static void __cpuinit smp_85xx_mach_cpu_die(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	local_irq_disable();
+	idle_task_exit();
+	mb();
+
+	mtspr(SPRN_TCR, 0);
+
+	__flush_disable_L1();
+	disable_backside_L2_cache();
+
+	generic_set_cpu_dead(cpu);
+
+	while (1);
+}
+
+void platform_cpu_die(unsigned int cpu)
+{
+	unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
+	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+
+	/* Core Nap Operation */
+	setbits32(&rcpm->cnapcr, 1 << hw_cpu);
+}
+#else
+/* for e500v1 and e500v2 */
 static void __cpuinit smp_85xx_mach_cpu_die(void)
 {
 	unsigned int cpu = smp_processor_id();
@@ -156,6 +196,7 @@ static void __cpuinit smp_85xx_mach_cpu_die(void)
 	while (1)
 		;
 }
+#endif /* CONFIG_PPC_E500MC */
 #endif
 
 static inline void flush_spin_table(void *spin_table)
@@ -228,6 +269,13 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		flush_spin_table(spin_table);
 
 		/*
+		 * Due to an erratum that core hard reset and core warm reset
+		 * are unable to wake up cores from power management modes,
+		 * wake up cores before reset.
+		 */
+		core_reset_erratum(hw_cpu);
+
+		/*
 		 * We don't set the BPTR register here since it already points
 		 * to the boot page properly.
 		 */
@@ -436,9 +484,9 @@ void __init mpc85xx_smp_init(void)
 
 	np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
 	if (np) {
-		guts = of_iomap(np, 0);
+		guts_regs = of_iomap(np, 0);
 		of_node_put(np);
-		if (!guts) {
+		if (!guts_regs) {
 			pr_err("%s: Could not map guts node address\n",
 								__func__);
 			return;
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 09/15] powerpc/rcpm: add sleep feature for SoCs using RCPM
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

The SoCs which have a RCPM (Run Control/Power Management) module
support power management feature. This patch implements sleep feature.

In sleep mode, the clocks of cores and unused IP blocks will be
turned off. The IP blocks which are allowed to wake up the system
are still running.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/Kconfig                |    4 +-
 arch/powerpc/include/asm/fsl_guts.h |    1 +
 arch/powerpc/platforms/85xx/Kconfig |    1 +
 arch/powerpc/sysdev/Kconfig         |    5 ++
 arch/powerpc/sysdev/Makefile        |    1 +
 arch/powerpc/sysdev/fsl_rcpm.c      |  101 +++++++++++++++++++++++++++++++++++
 6 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/sysdev/fsl_rcpm.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b6851be..0ad6e30 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -220,7 +220,7 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-		   (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
+		   FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \
 		   || 44x || 40x
 
 config PPC_DCR_NATIVE
@@ -694,7 +694,7 @@ config FSL_PCI
 config FSL_PMC
 	bool
 	default y
-	depends on SUSPEND && (PPC_85xx || PPC_86xx)
+	depends on SUSPEND && ((PPC_85xx && !PPC_E500MC) || PPC_86xx)
 	help
 	  Freescale MPC85xx/MPC86xx power management controller support
 	  (suspend/resume). For MPC83xx see platforms/83xx/suspend.c
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index 4eac1cf..b8a08d5 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -124,6 +124,7 @@ struct ccsr_rcpm {
 	u8	res0038[4];
 	__be32	cwdtdsr;	/* 0x003c - Core watchdog detect status register */
 	__be32	powmgtcsr;	/* 0x0040 - Power Mangement Control & Status Register */
+#define RCPM_POWMGTCSR_SLP	0x00020000
 	u8	res0044[12];
 	__be32	ippdexpcr;	/* 0x0050 - IP Powerdown Exception Control Register */
 	u8	res0054[16];
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 8f02b05..c0aa36e 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
 	select FSL_PCI if PCI
 	select SERIAL_8250_EXTENDED if SERIAL_8250
 	select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+	select FSL_CORENET_RCPM if SUSPEND && PPC_E500MC
 	default y
 
 if FSL_SOC_BOOKE
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index a84fecf..6c22d91 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -33,3 +33,8 @@ config SCOM_DEBUGFS
 config GE_FPGA
 	bool
 	default n
+
+config FSL_CORENET_RCPM
+	bool
+	help
+	 This option enables support for RCPM (Run Control/Power Management).
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index b0a518e..f12b856 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
+obj-$(CONFIG_FSL_CORENET_RCPM)	+= fsl_rcpm.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_IFC)		+= fsl_ifc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
new file mode 100644
index 0000000..fd789da
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -0,0 +1,101 @@
+/*
+ * RCPM(Run Control/Power Management) support
+ *
+ * Copyright 2012-2013 Freescale Semiconductor Inc.
+ *
+ * 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/types.h>
+#include <linux/errno.h>
+#include <linux/suspend.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/fsl_guts.h>
+
+static struct ccsr_rcpm __iomem *rcpm_regs;
+
+static int rcpm_suspend_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+
+		flush_dcache_L1();
+		flush_backside_L2_cache();
+
+		setbits32(&rcpm_regs->powmgtcsr, RCPM_POWMGTCSR_SLP);
+
+		/* At this point, the device is in sleep mode. */
+
+		/* Upon resume, wait for SLP bit to be clear. */
+		ret = spin_event_timeout(
+		  (in_be32(&rcpm_regs->powmgtcsr) & RCPM_POWMGTCSR_SLP) == 0,
+		  10000, 10);
+		if (!ret) {
+			pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+				__func__);
+			ret = -EINVAL;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+
+	}
+	return ret;
+}
+
+static int rcpm_suspend_valid(suspend_state_t state)
+{
+	if (state == PM_SUSPEND_STANDBY)
+		return 1;
+	else
+		return 0;
+}
+
+static const struct platform_suspend_ops rcpm_suspend_ops = {
+	.valid = rcpm_suspend_valid,
+	.enter = rcpm_suspend_enter,
+};
+
+static int rcpm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	rcpm_regs = of_iomap(np, 0);
+	if (!rcpm_regs)
+		return -ENOMEM;
+
+	suspend_set_ops(&rcpm_suspend_ops);
+
+	dev_info(&pdev->dev, "Freescale RCPM driver\n");
+	return 0;
+}
+
+static const struct of_device_id rcpm_ids[] = {
+	{ .compatible = "fsl,qoriq-rcpm-1.0", },
+	{ },
+};
+
+static struct platform_driver rcpm_driver = {
+	.driver = {
+		.name = "fsl-rcpm",
+		.of_match_table = rcpm_ids,
+	},
+	.probe = rcpm_probe,
+};
+
+static int __init rcpm_init(void)
+{
+	return platform_driver_register(&rcpm_driver);
+}
+
+device_initcall(rcpm_init);
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 09/15] powerpc/rcpm: add sleep feature for SoCs using RCPM
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

The SoCs which have a RCPM (Run Control/Power Management) module
support power management feature. This patch implements sleep feature.

In sleep mode, the clocks of cores and unused IP blocks will be
turned off. The IP blocks which are allowed to wake up the system
are still running.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/Kconfig                |    4 +-
 arch/powerpc/include/asm/fsl_guts.h |    1 +
 arch/powerpc/platforms/85xx/Kconfig |    1 +
 arch/powerpc/sysdev/Kconfig         |    5 ++
 arch/powerpc/sysdev/Makefile        |    1 +
 arch/powerpc/sysdev/fsl_rcpm.c      |  101 +++++++++++++++++++++++++++++++++++
 6 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/sysdev/fsl_rcpm.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b6851be..0ad6e30 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -220,7 +220,7 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-		   (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
+		   FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \
 		   || 44x || 40x
 
 config PPC_DCR_NATIVE
@@ -694,7 +694,7 @@ config FSL_PCI
 config FSL_PMC
 	bool
 	default y
-	depends on SUSPEND && (PPC_85xx || PPC_86xx)
+	depends on SUSPEND && ((PPC_85xx && !PPC_E500MC) || PPC_86xx)
 	help
 	  Freescale MPC85xx/MPC86xx power management controller support
 	  (suspend/resume). For MPC83xx see platforms/83xx/suspend.c
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index 4eac1cf..b8a08d5 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -124,6 +124,7 @@ struct ccsr_rcpm {
 	u8	res0038[4];
 	__be32	cwdtdsr;	/* 0x003c - Core watchdog detect status register */
 	__be32	powmgtcsr;	/* 0x0040 - Power Mangement Control & Status Register */
+#define RCPM_POWMGTCSR_SLP	0x00020000
 	u8	res0044[12];
 	__be32	ippdexpcr;	/* 0x0050 - IP Powerdown Exception Control Register */
 	u8	res0054[16];
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 8f02b05..c0aa36e 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
 	select FSL_PCI if PCI
 	select SERIAL_8250_EXTENDED if SERIAL_8250
 	select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+	select FSL_CORENET_RCPM if SUSPEND && PPC_E500MC
 	default y
 
 if FSL_SOC_BOOKE
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index a84fecf..6c22d91 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -33,3 +33,8 @@ config SCOM_DEBUGFS
 config GE_FPGA
 	bool
 	default n
+
+config FSL_CORENET_RCPM
+	bool
+	help
+	 This option enables support for RCPM (Run Control/Power Management).
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index b0a518e..f12b856 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
+obj-$(CONFIG_FSL_CORENET_RCPM)	+= fsl_rcpm.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_IFC)		+= fsl_ifc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
new file mode 100644
index 0000000..fd789da
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -0,0 +1,101 @@
+/*
+ * RCPM(Run Control/Power Management) support
+ *
+ * Copyright 2012-2013 Freescale Semiconductor Inc.
+ *
+ * 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/types.h>
+#include <linux/errno.h>
+#include <linux/suspend.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/fsl_guts.h>
+
+static struct ccsr_rcpm __iomem *rcpm_regs;
+
+static int rcpm_suspend_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+
+		flush_dcache_L1();
+		flush_backside_L2_cache();
+
+		setbits32(&rcpm_regs->powmgtcsr, RCPM_POWMGTCSR_SLP);
+
+		/* At this point, the device is in sleep mode. */
+
+		/* Upon resume, wait for SLP bit to be clear. */
+		ret = spin_event_timeout(
+		  (in_be32(&rcpm_regs->powmgtcsr) & RCPM_POWMGTCSR_SLP) == 0,
+		  10000, 10);
+		if (!ret) {
+			pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+				__func__);
+			ret = -EINVAL;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+
+	}
+	return ret;
+}
+
+static int rcpm_suspend_valid(suspend_state_t state)
+{
+	if (state == PM_SUSPEND_STANDBY)
+		return 1;
+	else
+		return 0;
+}
+
+static const struct platform_suspend_ops rcpm_suspend_ops = {
+	.valid = rcpm_suspend_valid,
+	.enter = rcpm_suspend_enter,
+};
+
+static int rcpm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	rcpm_regs = of_iomap(np, 0);
+	if (!rcpm_regs)
+		return -ENOMEM;
+
+	suspend_set_ops(&rcpm_suspend_ops);
+
+	dev_info(&pdev->dev, "Freescale RCPM driver\n");
+	return 0;
+}
+
+static const struct of_device_id rcpm_ids[] = {
+	{ .compatible = "fsl,qoriq-rcpm-1.0", },
+	{ },
+};
+
+static struct platform_driver rcpm_driver = {
+	.driver = {
+		.name = "fsl-rcpm",
+		.of_match_table = rcpm_ids,
+	},
+	.probe = rcpm_probe,
+};
+
+static int __init rcpm_init(void)
+{
+	return platform_driver_register(&rcpm_driver);
+}
+
+device_initcall(rcpm_init);
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 10/15] powerpc/85xx: fix 64-bit support for cpu hotplug
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

* The paca[cpu].cpu_start is used as a signal to indicate if the cpu
  should start. So it should be cleard in .cpu_die().
* The limit memory routine only needs to be ran once at boot time
  by the boot cpu. Prevent other cpus running it again.
* Rearrange the code segment in smp_85xx_kick_cpu() to share codes
  between PPC64 and PPC32 as far as possible.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/Kconfig              |    2 +-
 arch/powerpc/kernel/smp.c         |    3 +++
 arch/powerpc/mm/tlb_nohash.c      |    6 ++++--
 arch/powerpc/platforms/85xx/smp.c |   23 +++++++++++------------
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0ad6e30..aa5794b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -347,7 +347,7 @@ config SWIOTLB
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
 	depends on SMP && HOTPLUG && (PPC_PSERIES || \
-	PPC_PMAC || PPC_POWERNV || PPC_85xx)
+	PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE)
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 386c7ea..c8aa739 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -401,6 +401,9 @@ void generic_cpu_die(unsigned int cpu)
 		smp_rmb();
 		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
 			platform_cpu_die(cpu);
+#ifdef CONFIG_PPC64
+			paca[cpu].cpu_start = 0;
+#endif
 			return;
 		}
 		msleep(100);
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 6888cad..de7bf06 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -627,8 +627,10 @@ static void __early_init_mmu(int boot_cpu)
 		num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
 		linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
 
-		/* limit memory so we dont have linear faults */
-		memblock_enforce_memory_limit(linear_map_top);
+		if (boot_cpu) {
+			/* limit memory so we dont have linear faults */
+			memblock_enforce_memory_limit(linear_map_top);
+		}
 
 		patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
 		patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6eae2e0..74d8cde 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -251,10 +251,6 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		spin_table = phys_to_virt(*cpu_rel_addr);
 
 	local_irq_save(flags);
-#ifdef CONFIG_PPC32
-#ifdef CONFIG_HOTPLUG_CPU
-	/* Corresponding to generic_set_cpu_dead() */
-	generic_set_cpu_up(nr);
 
 	if (system_state == SYSTEM_RUNNING) {
 		/*
@@ -298,12 +294,19 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		/*  clear the acknowledge status */
 		__secondary_hold_acknowledge = -1;
 	}
-#endif
 	flush_spin_table(spin_table);
 	out_be32(&spin_table->pir, hw_cpu);
+#ifdef CONFIG_PPC32
 	out_be32(&spin_table->addr_l, __pa(__early_start));
+#else
+	out_be32(&spin_table->addr_h,
+		__pa(*(u64 *)generic_secondary_smp_init) >> 32);
+	out_be32(&spin_table->addr_l,
+		__pa(*(u64 *)generic_secondary_smp_init) & 0xffffffff);
+#endif
 	flush_spin_table(spin_table);
 
+#ifdef CONFIG_PPC32
 	/* Wait a bit for the CPU to ack. */
 	if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
 					10000, 100)) {
@@ -312,18 +315,14 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		ret = -ENOENT;
 		goto out;
 	}
-out:
 #else
 	smp_generic_kick_cpu(nr);
-
-	flush_spin_table(spin_table);
-	out_be32(&spin_table->pir, hw_cpu);
-	out_be64((u64 *)(&spin_table->addr_h),
-	  __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
-	flush_spin_table(spin_table);
 #endif
+	/* Corresponding to generic_set_cpu_dead() */
+	generic_set_cpu_up(nr);
 	cur_booting_core = hw_cpu;
 
+out:
 	local_irq_restore(flags);
 
 	if (ioremappable)
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 10/15] powerpc/85xx: fix 64-bit support for cpu hotplug
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

* The paca[cpu].cpu_start is used as a signal to indicate if the cpu
  should start. So it should be cleard in .cpu_die().
* The limit memory routine only needs to be ran once at boot time
  by the boot cpu. Prevent other cpus running it again.
* Rearrange the code segment in smp_85xx_kick_cpu() to share codes
  between PPC64 and PPC32 as far as possible.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/Kconfig              |    2 +-
 arch/powerpc/kernel/smp.c         |    3 +++
 arch/powerpc/mm/tlb_nohash.c      |    6 ++++--
 arch/powerpc/platforms/85xx/smp.c |   23 +++++++++++------------
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0ad6e30..aa5794b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -347,7 +347,7 @@ config SWIOTLB
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
 	depends on SMP && HOTPLUG && (PPC_PSERIES || \
-	PPC_PMAC || PPC_POWERNV || PPC_85xx)
+	PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE)
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 386c7ea..c8aa739 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -401,6 +401,9 @@ void generic_cpu_die(unsigned int cpu)
 		smp_rmb();
 		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
 			platform_cpu_die(cpu);
+#ifdef CONFIG_PPC64
+			paca[cpu].cpu_start = 0;
+#endif
 			return;
 		}
 		msleep(100);
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 6888cad..de7bf06 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -627,8 +627,10 @@ static void __early_init_mmu(int boot_cpu)
 		num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
 		linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
 
-		/* limit memory so we dont have linear faults */
-		memblock_enforce_memory_limit(linear_map_top);
+		if (boot_cpu) {
+			/* limit memory so we dont have linear faults */
+			memblock_enforce_memory_limit(linear_map_top);
+		}
 
 		patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
 		patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6eae2e0..74d8cde 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -251,10 +251,6 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		spin_table = phys_to_virt(*cpu_rel_addr);
 
 	local_irq_save(flags);
-#ifdef CONFIG_PPC32
-#ifdef CONFIG_HOTPLUG_CPU
-	/* Corresponding to generic_set_cpu_dead() */
-	generic_set_cpu_up(nr);
 
 	if (system_state == SYSTEM_RUNNING) {
 		/*
@@ -298,12 +294,19 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		/*  clear the acknowledge status */
 		__secondary_hold_acknowledge = -1;
 	}
-#endif
 	flush_spin_table(spin_table);
 	out_be32(&spin_table->pir, hw_cpu);
+#ifdef CONFIG_PPC32
 	out_be32(&spin_table->addr_l, __pa(__early_start));
+#else
+	out_be32(&spin_table->addr_h,
+		__pa(*(u64 *)generic_secondary_smp_init) >> 32);
+	out_be32(&spin_table->addr_l,
+		__pa(*(u64 *)generic_secondary_smp_init) & 0xffffffff);
+#endif
 	flush_spin_table(spin_table);
 
+#ifdef CONFIG_PPC32
 	/* Wait a bit for the CPU to ack. */
 	if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
 					10000, 100)) {
@@ -312,18 +315,14 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		ret = -ENOENT;
 		goto out;
 	}
-out:
 #else
 	smp_generic_kick_cpu(nr);
-
-	flush_spin_table(spin_table);
-	out_be32(&spin_table->pir, hw_cpu);
-	out_be64((u64 *)(&spin_table->addr_h),
-	  __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
-	flush_spin_table(spin_table);
 #endif
+	/* Corresponding to generic_set_cpu_dead() */
+	generic_set_cpu_up(nr);
 	cur_booting_core = hw_cpu;
 
+out:
 	local_irq_restore(flags);
 
 	if (ioremappable)
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 11/15] powerpc/rcpm: add struct ccsr_rcpm_v2
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

Add struct ccsr_rcpm_v2 to descibe the v2 RCPM register map on some SoCs,
such as T4240, etc.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/include/asm/fsl_guts.h |   66 +++++++++++++++++++++++++++++++++++
 1 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index b8a08d5..193d1f1 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -145,6 +145,72 @@ struct ccsr_rcpm {
 	__be32	cmcpmaskcr;	/* 0x00a4 - Core machine check mask control register */
 };
 
+struct ccsr_rcpm_v2 {
+	u8	res_00[12];
+	u32	tph10sr0;	/* Thread PH10 Status Register */
+	u8	res_10[12];
+	u32	tph10setr0;	/* Thread PH10 Set Control Register */
+	u8	res_20[12];
+	u32	tph10clrr0;	/* Thread PH10 Clear Control Register */
+	u8	res_30[12];
+	u32	tph10psr0;	/* Thread PH10 Previous Status Register */
+	u8	res_40[12];
+	u32	twaitsr0;	/* Thread Wait Status Register */
+	u8	res_50[96];
+	u32	pcph15sr;	/* Physical Core PH15 Status Register */
+	u32	pcph15setr;	/* Physical Core PH15 Set Control Register */
+	u32	pcph15clrr;	/* Physical Core PH15 Clear Control Register */
+	u32	pcph15psr;	/* Physical Core PH15 Prev Status Register */
+	u8	res_c0[16];
+	u32	pcph20sr;	/* Physical Core PH20 Status Register */
+	u32	pcph20setr;	/* Physical Core PH20 Set Control Register */
+	u32	pcph20clrr;	/* Physical Core PH20 Clear Control Register */
+	u32	pcph20psr;	/* Physical Core PH20 Prev Status Register */
+	u32	pcpw20sr;	/* Physical Core PW20 Status Register */
+	u8	res_e0[12];
+	u32	pcph30sr;	/* Physical Core PH30 Status Register */
+	u32	pcph30setr;	/* Physical Core PH30 Set Control Register */
+	u32	pcph30clrr;	/* Physical Core PH30 Clear Control Register */
+	u32	pcph30psr;	/* Physical Core PH30 Prev Status Register */
+	u8	res_100[32];
+	u32	ippwrgatecr;	/* IP Power Gating Control Register */
+	u8	res_124[12];
+	u32	powmgtcsr;	/* Power Management Control & Status Reg */
+#define RCPM_POWMGTCSR_LPM20_RQ		0x00100000
+#define RCPM_POWMGTCSR_LPM20_ST		0x00000200
+#define RCPM_POWMGTCSR_P_LPM20_ST	0x00000100
+	u8	res_134[12];
+	u32	ippdexpcr[4];	/* IP Powerdown Exception Control Reg */
+	u8	res_150[12];
+	u32	tpmimr0;	/* Thread PM Interrupt Mask Reg */
+	u8	res_160[12];
+	u32	tpmcimr0;	/* Thread PM Crit Interrupt Mask Reg */
+	u8	res_170[12];
+	u32	tpmmcmr0;	/* Thread PM Machine Check Interrupt Mask Reg */
+	u8	res_180[12];
+	u32	tpmnmimr0;	/* Thread PM NMI Mask Reg */
+	u8	res_190[12];
+	u32	tmcpmaskcr0;	/* Thread Machine Check Mask Control Reg */
+	u32	pctbenr;	/* Physical Core Time Base Enable Reg */
+	u32	pctbclkselr;	/* Physical Core Time Base Clock Select */
+	u32	tbclkdivr;	/* Time Base Clock Divider Register */
+	u8	res_1ac[4];
+	u32	ttbhltcr[4];	/* Thread Time Base Halt Control Register */
+	u32	clpcl10sr;	/* Cluster PCL10 Status Register */
+	u32	clpcl10setr;	/* Cluster PCL30 Set Control Register */
+	u32	clpcl10clrr;	/* Cluster PCL30 Clear Control Register */
+	u32	clpcl10psr;	/* Cluster PCL30 Prev Status Register */
+	u32	cddslpsetr;	/* Core Domain Deep Sleep Set Register */
+	u32	cddslpclrr;	/* Core Domain Deep Sleep Clear Register */
+	u32	cdpwroksetr;	/* Core Domain Power OK Set Register */
+	u32	cdpwrokclrr;	/* Core Domain Power OK Clear Register */
+	u32	cdpwrensr;	/* Core Domain Power Enable Status Register */
+	u32	cddslsr;	/* Core Domain Deep Sleep Status Register */
+	u8	res_1e8[8];
+	u32	dslpcntcr[8];	/* Deep Sleep Counter Cfg Register */
+	u8	res_300[3568];
+};
+
 #ifdef CONFIG_PPC_86xx
 
 #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 11/15] powerpc/rcpm: add struct ccsr_rcpm_v2
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

Add struct ccsr_rcpm_v2 to descibe the v2 RCPM register map on some SoCs,
such as T4240, etc.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/include/asm/fsl_guts.h |   66 +++++++++++++++++++++++++++++++++++
 1 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index b8a08d5..193d1f1 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -145,6 +145,72 @@ struct ccsr_rcpm {
 	__be32	cmcpmaskcr;	/* 0x00a4 - Core machine check mask control register */
 };
 
+struct ccsr_rcpm_v2 {
+	u8	res_00[12];
+	u32	tph10sr0;	/* Thread PH10 Status Register */
+	u8	res_10[12];
+	u32	tph10setr0;	/* Thread PH10 Set Control Register */
+	u8	res_20[12];
+	u32	tph10clrr0;	/* Thread PH10 Clear Control Register */
+	u8	res_30[12];
+	u32	tph10psr0;	/* Thread PH10 Previous Status Register */
+	u8	res_40[12];
+	u32	twaitsr0;	/* Thread Wait Status Register */
+	u8	res_50[96];
+	u32	pcph15sr;	/* Physical Core PH15 Status Register */
+	u32	pcph15setr;	/* Physical Core PH15 Set Control Register */
+	u32	pcph15clrr;	/* Physical Core PH15 Clear Control Register */
+	u32	pcph15psr;	/* Physical Core PH15 Prev Status Register */
+	u8	res_c0[16];
+	u32	pcph20sr;	/* Physical Core PH20 Status Register */
+	u32	pcph20setr;	/* Physical Core PH20 Set Control Register */
+	u32	pcph20clrr;	/* Physical Core PH20 Clear Control Register */
+	u32	pcph20psr;	/* Physical Core PH20 Prev Status Register */
+	u32	pcpw20sr;	/* Physical Core PW20 Status Register */
+	u8	res_e0[12];
+	u32	pcph30sr;	/* Physical Core PH30 Status Register */
+	u32	pcph30setr;	/* Physical Core PH30 Set Control Register */
+	u32	pcph30clrr;	/* Physical Core PH30 Clear Control Register */
+	u32	pcph30psr;	/* Physical Core PH30 Prev Status Register */
+	u8	res_100[32];
+	u32	ippwrgatecr;	/* IP Power Gating Control Register */
+	u8	res_124[12];
+	u32	powmgtcsr;	/* Power Management Control & Status Reg */
+#define RCPM_POWMGTCSR_LPM20_RQ		0x00100000
+#define RCPM_POWMGTCSR_LPM20_ST		0x00000200
+#define RCPM_POWMGTCSR_P_LPM20_ST	0x00000100
+	u8	res_134[12];
+	u32	ippdexpcr[4];	/* IP Powerdown Exception Control Reg */
+	u8	res_150[12];
+	u32	tpmimr0;	/* Thread PM Interrupt Mask Reg */
+	u8	res_160[12];
+	u32	tpmcimr0;	/* Thread PM Crit Interrupt Mask Reg */
+	u8	res_170[12];
+	u32	tpmmcmr0;	/* Thread PM Machine Check Interrupt Mask Reg */
+	u8	res_180[12];
+	u32	tpmnmimr0;	/* Thread PM NMI Mask Reg */
+	u8	res_190[12];
+	u32	tmcpmaskcr0;	/* Thread Machine Check Mask Control Reg */
+	u32	pctbenr;	/* Physical Core Time Base Enable Reg */
+	u32	pctbclkselr;	/* Physical Core Time Base Clock Select */
+	u32	tbclkdivr;	/* Time Base Clock Divider Register */
+	u8	res_1ac[4];
+	u32	ttbhltcr[4];	/* Thread Time Base Halt Control Register */
+	u32	clpcl10sr;	/* Cluster PCL10 Status Register */
+	u32	clpcl10setr;	/* Cluster PCL30 Set Control Register */
+	u32	clpcl10clrr;	/* Cluster PCL30 Clear Control Register */
+	u32	clpcl10psr;	/* Cluster PCL30 Prev Status Register */
+	u32	cddslpsetr;	/* Core Domain Deep Sleep Set Register */
+	u32	cddslpclrr;	/* Core Domain Deep Sleep Clear Register */
+	u32	cdpwroksetr;	/* Core Domain Power OK Set Register */
+	u32	cdpwrokclrr;	/* Core Domain Power OK Clear Register */
+	u32	cdpwrensr;	/* Core Domain Power Enable Status Register */
+	u32	cddslsr;	/* Core Domain Deep Sleep Status Register */
+	u8	res_1e8[8];
+	u32	dslpcntcr[8];	/* Deep Sleep Counter Cfg Register */
+	u8	res_300[3568];
+};
+
 #ifdef CONFIG_PPC_86xx
 
 #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

For e6500, two threads in one core share one time base. Just need
to do time base sync on first thread of one core, and skip it on
the other thread.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/platforms/85xx/smp.c |   52 +++++++++++++++++++++++++++++++-----
 1 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 74d8cde..5f3eee3 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -26,6 +26,7 @@
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
 #include <asm/fsl_guts.h>
+#include <asm/cputhreads.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/mpic.h>
@@ -45,6 +46,7 @@ static u64 timebase;
 static int tb_req;
 static int tb_valid;
 static u32 cur_booting_core;
+static bool rcpmv2;
 
 #ifdef CONFIG_PPC_E500MC
 /* get a physical mask of online cores and booting core */
@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
 	u32 mask;
 	int cpu;
 
-	mask = 1 << cur_booting_core;
-	for_each_online_cpu(cpu)
-		mask |= 1 << get_hard_smp_processor_id(cpu);
+	if (smt_capable()) {
+		/* two threads in one core share one time base */
+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
+		for_each_online_cpu(cpu)
+			mask |= 1 << cpu_core_index_of_thread(
+					get_hard_smp_processor_id(cpu));
+	} else {
+		mask = 1 << cur_booting_core;
+		for_each_online_cpu(cpu)
+			mask |= 1 << get_hard_smp_processor_id(cpu);
+	}
 
 	return mask;
 }
 
 static void mpc85xx_timebase_freeze(int freeze)
 {
-	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+	u32 *addr;
 	u32 mask = get_phy_cpu_mask();
 
+	if (rcpmv2)
+		addr = &((struct ccsr_rcpm_v2 *)guts_regs)->pctbenr;
+	else
+		addr = &((struct ccsr_rcpm *)guts_regs)->ctbenr;
+
 	if (freeze)
-		clrbits32(&rcpm->ctbenr, mask);
+		clrbits32(addr, mask);
 	else
-		setbits32(&rcpm->ctbenr, mask);
+		setbits32(addr, mask);
 
-	/* read back to push the previos write */
-	in_be32(&rcpm->ctbenr);
+	/* read back to push the previous write */
+	in_be32(addr);
 }
+
 #else
 static void mpc85xx_timebase_freeze(int freeze)
 {
@@ -94,6 +110,16 @@ static void mpc85xx_give_timebase(void)
 {
 	unsigned long flags;
 
+#ifdef CONFIG_PPC_E500MC
+	/*
+	 * If the booting thread is not the first thread of the core,
+	 * skip time base sync.
+	 */
+	if (smt_capable() &&
+		cur_booting_core != cpu_first_thread_sibling(cur_booting_core))
+		return;
+#endif
+
 	local_irq_save(flags);
 
 	while (!tb_req)
@@ -117,6 +143,12 @@ static void mpc85xx_take_timebase(void)
 {
 	unsigned long flags;
 
+#ifdef CONFIG_PPC_E500MC
+	if (smt_capable() &&
+		cur_booting_core != cpu_first_thread_sibling(cur_booting_core))
+		return;
+#endif
+
 	local_irq_save(flags);
 
 	tb_req = 1;
@@ -457,6 +489,7 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = {
 	{ .compatible = "fsl,p1023-guts", },
 	{ .compatible = "fsl,p2020-guts", },
 	{ .compatible = "fsl,qoriq-rcpm-1.0", },
+	{ .compatible = "fsl,qoriq-rcpm-2.0", },
 	{},
 };
 
@@ -483,6 +516,9 @@ void __init mpc85xx_smp_init(void)
 
 	np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
 	if (np) {
+		if (of_device_is_compatible(np, "fsl,qoriq-rcpm-2.0"))
+			rcpmv2 = true;
+
 		guts_regs = of_iomap(np, 0);
 		of_node_put(np);
 		if (!guts_regs) {
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

For e6500, two threads in one core share one time base. Just need
to do time base sync on first thread of one core, and skip it on
the other thread.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/platforms/85xx/smp.c |   52 +++++++++++++++++++++++++++++++-----
 1 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 74d8cde..5f3eee3 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -26,6 +26,7 @@
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
 #include <asm/fsl_guts.h>
+#include <asm/cputhreads.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/mpic.h>
@@ -45,6 +46,7 @@ static u64 timebase;
 static int tb_req;
 static int tb_valid;
 static u32 cur_booting_core;
+static bool rcpmv2;
 
 #ifdef CONFIG_PPC_E500MC
 /* get a physical mask of online cores and booting core */
@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
 	u32 mask;
 	int cpu;
 
-	mask = 1 << cur_booting_core;
-	for_each_online_cpu(cpu)
-		mask |= 1 << get_hard_smp_processor_id(cpu);
+	if (smt_capable()) {
+		/* two threads in one core share one time base */
+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
+		for_each_online_cpu(cpu)
+			mask |= 1 << cpu_core_index_of_thread(
+					get_hard_smp_processor_id(cpu));
+	} else {
+		mask = 1 << cur_booting_core;
+		for_each_online_cpu(cpu)
+			mask |= 1 << get_hard_smp_processor_id(cpu);
+	}
 
 	return mask;
 }
 
 static void mpc85xx_timebase_freeze(int freeze)
 {
-	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+	u32 *addr;
 	u32 mask = get_phy_cpu_mask();
 
+	if (rcpmv2)
+		addr = &((struct ccsr_rcpm_v2 *)guts_regs)->pctbenr;
+	else
+		addr = &((struct ccsr_rcpm *)guts_regs)->ctbenr;
+
 	if (freeze)
-		clrbits32(&rcpm->ctbenr, mask);
+		clrbits32(addr, mask);
 	else
-		setbits32(&rcpm->ctbenr, mask);
+		setbits32(addr, mask);
 
-	/* read back to push the previos write */
-	in_be32(&rcpm->ctbenr);
+	/* read back to push the previous write */
+	in_be32(addr);
 }
+
 #else
 static void mpc85xx_timebase_freeze(int freeze)
 {
@@ -94,6 +110,16 @@ static void mpc85xx_give_timebase(void)
 {
 	unsigned long flags;
 
+#ifdef CONFIG_PPC_E500MC
+	/*
+	 * If the booting thread is not the first thread of the core,
+	 * skip time base sync.
+	 */
+	if (smt_capable() &&
+		cur_booting_core != cpu_first_thread_sibling(cur_booting_core))
+		return;
+#endif
+
 	local_irq_save(flags);
 
 	while (!tb_req)
@@ -117,6 +143,12 @@ static void mpc85xx_take_timebase(void)
 {
 	unsigned long flags;
 
+#ifdef CONFIG_PPC_E500MC
+	if (smt_capable() &&
+		cur_booting_core != cpu_first_thread_sibling(cur_booting_core))
+		return;
+#endif
+
 	local_irq_save(flags);
 
 	tb_req = 1;
@@ -457,6 +489,7 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = {
 	{ .compatible = "fsl,p1023-guts", },
 	{ .compatible = "fsl,p2020-guts", },
 	{ .compatible = "fsl,qoriq-rcpm-1.0", },
+	{ .compatible = "fsl,qoriq-rcpm-2.0", },
 	{},
 };
 
@@ -483,6 +516,9 @@ void __init mpc85xx_smp_init(void)
 
 	np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
 	if (np) {
+		if (of_device_is_compatible(np, "fsl,qoriq-rcpm-2.0"))
+			rcpmv2 = true;
+
 		guts_regs = of_iomap(np, 0);
 		of_node_put(np);
 		if (!guts_regs) {
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

The L1 Data Cache of e6500 contains no modified data, no flush
is required.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/kernel/fsl_booke_cache.S |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/fsl_booke_cache.S b/arch/powerpc/kernel/fsl_booke_cache.S
index 232c47b..24a52bb 100644
--- a/arch/powerpc/kernel/fsl_booke_cache.S
+++ b/arch/powerpc/kernel/fsl_booke_cache.S
@@ -65,13 +65,22 @@ _GLOBAL(flush_dcache_L1)
 
 	blr
 
+#define PVR_E6500	0x8040
+
 /* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
 _GLOBAL(__flush_disable_L1)
+/* L1 Data Cache of e6500 contains no modified data, no flush is required */
+	mfspr	r3, SPRN_PVR
+	rlwinm	r4, r3, 16, 0xffff
+	lis	r5, 0
+	ori	r5, r5, PVR_E6500@l
+	cmpw	r4, r5
+	beq	2f
 	mflr	r10
 	bl	flush_dcache_L1	/* Flush L1 d-cache */
 	mtlr	r10
 
-	msync
+2:	msync
 	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
 	li	r5, 2
 	rlwimi	r4, r5, 0, 3
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

The L1 Data Cache of e6500 contains no modified data, no flush
is required.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/kernel/fsl_booke_cache.S |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/fsl_booke_cache.S b/arch/powerpc/kernel/fsl_booke_cache.S
index 232c47b..24a52bb 100644
--- a/arch/powerpc/kernel/fsl_booke_cache.S
+++ b/arch/powerpc/kernel/fsl_booke_cache.S
@@ -65,13 +65,22 @@ _GLOBAL(flush_dcache_L1)
 
 	blr
 
+#define PVR_E6500	0x8040
+
 /* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
 _GLOBAL(__flush_disable_L1)
+/* L1 Data Cache of e6500 contains no modified data, no flush is required */
+	mfspr	r3, SPRN_PVR
+	rlwinm	r4, r3, 16, 0xffff
+	lis	r5, 0
+	ori	r5, r5, PVR_E6500@l
+	cmpw	r4, r5
+	beq	2f
 	mflr	r10
 	bl	flush_dcache_L1	/* Flush L1 d-cache */
 	mtlr	r10
 
-	msync
+2:	msync
 	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
 	li	r5, 2
 	rlwimi	r4, r5, 0, 3
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 14/15] powerpc/smp: add cpu hotplug support for e6500
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

* Only if two threads of one core are offline, the core can
  enter PH20 state.
* Clear PH20 bits before core reset, or core will not restart.
* Introduced a variable l2cache_type in the struce cpu_spec to
  indentify the type of L2 cache.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/include/asm/cputable.h |   10 ++++++++
 arch/powerpc/kernel/cputable.c      |    5 ++++
 arch/powerpc/platforms/85xx/smp.c   |   40 +++++++++++++++++++++++++++++-----
 3 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index f326444..3715def 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -33,6 +33,13 @@ enum powerpc_pmc_type {
 	PPC_PMC_G4 = 3,
 };
 
+enum powerpc_l2cache_type {
+	PPC_L2_CACHE_DEFAULT = 0,
+	PPC_L2_CACHE_CORE    = 1, /* L2 cache used exclusively by one core */
+	PPC_L2_CACHE_CLUSTER = 2, /* L2 cache shared by a core cluster */
+	PPC_L2_CACHE_SOC     = 3, /* L2 cache shared by all cores */
+};
+
 struct pt_regs;
 
 extern int machine_check_generic(struct pt_regs *regs);
@@ -58,6 +65,9 @@ struct cpu_spec {
 	unsigned int	icache_bsize;
 	unsigned int	dcache_bsize;
 
+	/* L2 cache type */
+	enum powerpc_l2cache_type l2cache_type;
+
 	/* number of performance monitor counters */
 	unsigned int	num_pmcs;
 	enum powerpc_pmc_type pmc_type;
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index cc39139..a7329c1 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -2004,6 +2004,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_setup		= __setup_cpu_e500v1,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppc8540",
+		.l2cache_type		= PPC_L2_CACHE_SOC,
 	},
 	{	/* e500v2 */
 		.pvr_mask		= 0xffff0000,
@@ -2023,6 +2024,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_setup		= __setup_cpu_e500v2,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppc8548",
+		.l2cache_type		= PPC_L2_CACHE_SOC,
 	},
 	{	/* e500mc */
 		.pvr_mask		= 0xffff0000,
@@ -2040,6 +2042,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_setup		= __setup_cpu_e500mc,
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce500mc",
+		.l2cache_type		= PPC_L2_CACHE_CORE,
 	},
 #endif /* CONFIG_PPC32 */
 	{	/* e5500 */
@@ -2061,6 +2064,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce5500",
+		.l2cache_type		= PPC_L2_CACHE_CORE,
 	},
 	{	/* e6500 */
 		.pvr_mask		= 0xffff0000,
@@ -2082,6 +2086,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce6500",
+		.l2cache_type		= PPC_L2_CACHE_CLUSTER,
 	},
 #ifdef CONFIG_PPC32
 	{	/* default match */
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 5f3eee3..a8b4df7 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -166,13 +166,31 @@ static void core_reset_erratum(int hw_cpu)
 {
 #ifdef CONFIG_PPC_E500MC
 	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+	struct ccsr_rcpm_v2 __iomem *rcpm_v2 = guts_regs;
 
-	clrbits32(&rcpm->cnapcr, 1 << hw_cpu);
+	if (rcpmv2)
+		setbits32(&rcpm_v2->pcph20clrr,
+			1 << cpu_core_index_of_thread(hw_cpu));
+	else
+		clrbits32(&rcpm->cnapcr, 1 << hw_cpu);
 #endif
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 #ifdef CONFIG_PPC_E500MC
+static inline bool is_core_down(unsigned int thread)
+{
+	cpumask_t thd_mask;
+
+	if (!smt_capable())
+		return true;
+
+	cpumask_shift_left(&thd_mask, &threads_core_mask,
+			cpu_core_index_of_thread(thread) * threads_per_core);
+
+	return !cpumask_intersects(&thd_mask, cpu_online_mask);
+}
+
 static void __cpuinit smp_85xx_mach_cpu_die(void)
 {
 	unsigned int cpu = smp_processor_id();
@@ -183,8 +201,11 @@ static void __cpuinit smp_85xx_mach_cpu_die(void)
 
 	mtspr(SPRN_TCR, 0);
 
-	__flush_disable_L1();
-	disable_backside_L2_cache();
+	if (is_core_down(cpu))
+		__flush_disable_L1();
+
+	if (cur_cpu_spec->l2cache_type == PPC_L2_CACHE_CORE)
+		disable_backside_L2_cache();
 
 	generic_set_cpu_dead(cpu);
 
@@ -195,9 +216,16 @@ void platform_cpu_die(unsigned int cpu)
 {
 	unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
 	struct ccsr_rcpm __iomem *rcpm = guts_regs;
-
-	/* Core Nap Operation */
-	setbits32(&rcpm->cnapcr, 1 << hw_cpu);
+	struct ccsr_rcpm_v2 __iomem *rcpm_v2 = guts_regs;
+
+	if (rcpmv2 && is_core_down(cpu)) {
+		/* enter PH20 status */
+		setbits32(&rcpm_v2->pcph20setr,
+			1 << cpu_core_index_of_thread(hw_cpu));
+	} else if (!rcpmv2) {
+		/* Core Nap Operation */
+		setbits32(&rcpm->cnapcr, 1 << hw_cpu);
+	}
 }
 #else
 /* for e500v1 and e500v2 */
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 14/15] powerpc/smp: add cpu hotplug support for e6500
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

* Only if two threads of one core are offline, the core can
  enter PH20 state.
* Clear PH20 bits before core reset, or core will not restart.
* Introduced a variable l2cache_type in the struce cpu_spec to
  indentify the type of L2 cache.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/include/asm/cputable.h |   10 ++++++++
 arch/powerpc/kernel/cputable.c      |    5 ++++
 arch/powerpc/platforms/85xx/smp.c   |   40 +++++++++++++++++++++++++++++-----
 3 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index f326444..3715def 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -33,6 +33,13 @@ enum powerpc_pmc_type {
 	PPC_PMC_G4 = 3,
 };
 
+enum powerpc_l2cache_type {
+	PPC_L2_CACHE_DEFAULT = 0,
+	PPC_L2_CACHE_CORE    = 1, /* L2 cache used exclusively by one core */
+	PPC_L2_CACHE_CLUSTER = 2, /* L2 cache shared by a core cluster */
+	PPC_L2_CACHE_SOC     = 3, /* L2 cache shared by all cores */
+};
+
 struct pt_regs;
 
 extern int machine_check_generic(struct pt_regs *regs);
@@ -58,6 +65,9 @@ struct cpu_spec {
 	unsigned int	icache_bsize;
 	unsigned int	dcache_bsize;
 
+	/* L2 cache type */
+	enum powerpc_l2cache_type l2cache_type;
+
 	/* number of performance monitor counters */
 	unsigned int	num_pmcs;
 	enum powerpc_pmc_type pmc_type;
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index cc39139..a7329c1 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -2004,6 +2004,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_setup		= __setup_cpu_e500v1,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppc8540",
+		.l2cache_type		= PPC_L2_CACHE_SOC,
 	},
 	{	/* e500v2 */
 		.pvr_mask		= 0xffff0000,
@@ -2023,6 +2024,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_setup		= __setup_cpu_e500v2,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppc8548",
+		.l2cache_type		= PPC_L2_CACHE_SOC,
 	},
 	{	/* e500mc */
 		.pvr_mask		= 0xffff0000,
@@ -2040,6 +2042,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_setup		= __setup_cpu_e500mc,
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce500mc",
+		.l2cache_type		= PPC_L2_CACHE_CORE,
 	},
 #endif /* CONFIG_PPC32 */
 	{	/* e5500 */
@@ -2061,6 +2064,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce5500",
+		.l2cache_type		= PPC_L2_CACHE_CORE,
 	},
 	{	/* e6500 */
 		.pvr_mask		= 0xffff0000,
@@ -2082,6 +2086,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce6500",
+		.l2cache_type		= PPC_L2_CACHE_CLUSTER,
 	},
 #ifdef CONFIG_PPC32
 	{	/* default match */
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 5f3eee3..a8b4df7 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -166,13 +166,31 @@ static void core_reset_erratum(int hw_cpu)
 {
 #ifdef CONFIG_PPC_E500MC
 	struct ccsr_rcpm __iomem *rcpm = guts_regs;
+	struct ccsr_rcpm_v2 __iomem *rcpm_v2 = guts_regs;
 
-	clrbits32(&rcpm->cnapcr, 1 << hw_cpu);
+	if (rcpmv2)
+		setbits32(&rcpm_v2->pcph20clrr,
+			1 << cpu_core_index_of_thread(hw_cpu));
+	else
+		clrbits32(&rcpm->cnapcr, 1 << hw_cpu);
 #endif
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 #ifdef CONFIG_PPC_E500MC
+static inline bool is_core_down(unsigned int thread)
+{
+	cpumask_t thd_mask;
+
+	if (!smt_capable())
+		return true;
+
+	cpumask_shift_left(&thd_mask, &threads_core_mask,
+			cpu_core_index_of_thread(thread) * threads_per_core);
+
+	return !cpumask_intersects(&thd_mask, cpu_online_mask);
+}
+
 static void __cpuinit smp_85xx_mach_cpu_die(void)
 {
 	unsigned int cpu = smp_processor_id();
@@ -183,8 +201,11 @@ static void __cpuinit smp_85xx_mach_cpu_die(void)
 
 	mtspr(SPRN_TCR, 0);
 
-	__flush_disable_L1();
-	disable_backside_L2_cache();
+	if (is_core_down(cpu))
+		__flush_disable_L1();
+
+	if (cur_cpu_spec->l2cache_type == PPC_L2_CACHE_CORE)
+		disable_backside_L2_cache();
 
 	generic_set_cpu_dead(cpu);
 
@@ -195,9 +216,16 @@ void platform_cpu_die(unsigned int cpu)
 {
 	unsigned int hw_cpu = get_hard_smp_processor_id(cpu);
 	struct ccsr_rcpm __iomem *rcpm = guts_regs;
-
-	/* Core Nap Operation */
-	setbits32(&rcpm->cnapcr, 1 << hw_cpu);
+	struct ccsr_rcpm_v2 __iomem *rcpm_v2 = guts_regs;
+
+	if (rcpmv2 && is_core_down(cpu)) {
+		/* enter PH20 status */
+		setbits32(&rcpm_v2->pcph20setr,
+			1 << cpu_core_index_of_thread(hw_cpu));
+	} else if (!rcpmv2) {
+		/* Core Nap Operation */
+		setbits32(&rcpm->cnapcr, 1 << hw_cpu);
+	}
 }
 #else
 /* for e500v1 and e500v2 */
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 15/15] powerpc/rcpm: add sleep support for T4/B4 chips
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-19 10:47   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

RCPM unit controls the power managment of T4/B4 chips. Software can
access RCPM registers to put specific thread/core in PH10/PH15/PH20/PH30
state or put the device in LPM10/LPM20/LPM40 mode.

The RCPM unit supports several wake up sources through internal timers
and internal and external interrupts.

When the device enter sleep state, it will be put in LPM20 mode.
The command is "echo standby > /sys/power/state".

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/sysdev/fsl_rcpm.c |   54 +++++++++++++++++++++++++++++++++++++---
 1 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
index fd789da..10e5cb3 100644
--- a/arch/powerpc/sysdev/fsl_rcpm.c
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -20,6 +20,7 @@
 #include <asm/fsl_guts.h>
 
 static struct ccsr_rcpm __iomem *rcpm_regs;
+static struct ccsr_rcpm_v2 __iomem *rcpm2_regs;
 
 static int rcpm_suspend_enter(suspend_state_t state)
 {
@@ -53,6 +54,41 @@ static int rcpm_suspend_enter(suspend_state_t state)
 	return ret;
 }
 
+static int rcpm_v2_suspend_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+
+		/* clear previous LPM20 status */
+		setbits32(&rcpm2_regs->powmgtcsr, RCPM_POWMGTCSR_P_LPM20_ST);
+		/* enter LPM20 status */
+		setbits32(&rcpm2_regs->powmgtcsr, RCPM_POWMGTCSR_LPM20_RQ);
+
+		/* At this point, the device is in LPM20 status. */
+
+		/* resume ... */
+		ret = spin_event_timeout(
+		      (in_be32(&rcpm2_regs->powmgtcsr) & RCPM_POWMGTCSR_LPM20_ST)
+		      == 0, 10000, 10);
+		if (!ret) {
+			pr_err("%s: timeout waiting for LPM20 bit to be cleared\n",
+				__func__);
+			ret = -EINVAL;
+		}
+
+		break;
+
+	default:
+		ret = -EINVAL;
+
+	}
+
+	return ret;
+
+}
+
 static int rcpm_suspend_valid(suspend_state_t state)
 {
 	if (state == PM_SUSPEND_STANDBY)
@@ -63,16 +99,25 @@ static int rcpm_suspend_valid(suspend_state_t state)
 
 static const struct platform_suspend_ops rcpm_suspend_ops = {
 	.valid = rcpm_suspend_valid,
-	.enter = rcpm_suspend_enter,
 };
 
 static int rcpm_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 
-	rcpm_regs = of_iomap(np, 0);
-	if (!rcpm_regs)
-		return -ENOMEM;
+	if (of_device_is_compatible(np, "fsl,qoriq-rcpm-2.0")) {
+		rcpm2_regs = of_iomap(np, 0);
+		if (!rcpm2_regs)
+			return -ENOMEM;
+
+		rcpm_suspend_ops.enter = rcpm_v2_suspend_enter;
+	} else {
+		rcpm_regs = of_iomap(np, 0);
+		if (!rcpm_regs)
+			return -ENOMEM;
+
+		rcpm_suspend_ops.enter = rcpm_suspend_enter;
+	}
 
 	suspend_set_ops(&rcpm_suspend_ops);
 
@@ -82,6 +127,7 @@ static int rcpm_probe(struct platform_device *pdev)
 
 static const struct of_device_id rcpm_ids[] = {
 	{ .compatible = "fsl,qoriq-rcpm-1.0", },
+	{ .compatible = "fsl,qoriq-rcpm-2.0", },
 	{ },
 };
 
-- 
1.7.3



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v2 15/15] powerpc/rcpm: add sleep support for T4/B4 chips
@ 2013-04-19 10:47   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-19 10:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-kernel

From: Chen-Hui Zhao <chenhui.zhao@freescale.com>

RCPM unit controls the power managment of T4/B4 chips. Software can
access RCPM registers to put specific thread/core in PH10/PH15/PH20/PH30
state or put the device in LPM10/LPM20/LPM40 mode.

The RCPM unit supports several wake up sources through internal timers
and internal and external interrupts.

When the device enter sleep state, it will be put in LPM20 mode.
The command is "echo standby > /sys/power/state".

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
 arch/powerpc/sysdev/fsl_rcpm.c |   54 +++++++++++++++++++++++++++++++++++++---
 1 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
index fd789da..10e5cb3 100644
--- a/arch/powerpc/sysdev/fsl_rcpm.c
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -20,6 +20,7 @@
 #include <asm/fsl_guts.h>
 
 static struct ccsr_rcpm __iomem *rcpm_regs;
+static struct ccsr_rcpm_v2 __iomem *rcpm2_regs;
 
 static int rcpm_suspend_enter(suspend_state_t state)
 {
@@ -53,6 +54,41 @@ static int rcpm_suspend_enter(suspend_state_t state)
 	return ret;
 }
 
+static int rcpm_v2_suspend_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+
+		/* clear previous LPM20 status */
+		setbits32(&rcpm2_regs->powmgtcsr, RCPM_POWMGTCSR_P_LPM20_ST);
+		/* enter LPM20 status */
+		setbits32(&rcpm2_regs->powmgtcsr, RCPM_POWMGTCSR_LPM20_RQ);
+
+		/* At this point, the device is in LPM20 status. */
+
+		/* resume ... */
+		ret = spin_event_timeout(
+		      (in_be32(&rcpm2_regs->powmgtcsr) & RCPM_POWMGTCSR_LPM20_ST)
+		      == 0, 10000, 10);
+		if (!ret) {
+			pr_err("%s: timeout waiting for LPM20 bit to be cleared\n",
+				__func__);
+			ret = -EINVAL;
+		}
+
+		break;
+
+	default:
+		ret = -EINVAL;
+
+	}
+
+	return ret;
+
+}
+
 static int rcpm_suspend_valid(suspend_state_t state)
 {
 	if (state == PM_SUSPEND_STANDBY)
@@ -63,16 +99,25 @@ static int rcpm_suspend_valid(suspend_state_t state)
 
 static const struct platform_suspend_ops rcpm_suspend_ops = {
 	.valid = rcpm_suspend_valid,
-	.enter = rcpm_suspend_enter,
 };
 
 static int rcpm_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 
-	rcpm_regs = of_iomap(np, 0);
-	if (!rcpm_regs)
-		return -ENOMEM;
+	if (of_device_is_compatible(np, "fsl,qoriq-rcpm-2.0")) {
+		rcpm2_regs = of_iomap(np, 0);
+		if (!rcpm2_regs)
+			return -ENOMEM;
+
+		rcpm_suspend_ops.enter = rcpm_v2_suspend_enter;
+	} else {
+		rcpm_regs = of_iomap(np, 0);
+		if (!rcpm_regs)
+			return -ENOMEM;
+
+		rcpm_suspend_ops.enter = rcpm_suspend_enter;
+	}
 
 	suspend_set_ops(&rcpm_suspend_ops);
 
@@ -82,6 +127,7 @@ static int rcpm_probe(struct platform_device *pdev)
 
 static const struct of_device_id rcpm_ids[] = {
 	{ .compatible = "fsl,qoriq-rcpm-1.0", },
+	{ .compatible = "fsl,qoriq-rcpm-2.0", },
 	{ },
 };
 
-- 
1.7.3

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface
  2013-04-19 10:47   ` Zhao Chenhui
  (?)
@ 2013-04-22  3:25   ` Viresh Kumar
  2013-04-22 10:56       ` Zhao Chenhui
  -1 siblings, 1 reply; 66+ messages in thread
From: Viresh Kumar @ 2013-04-22  3:25 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On Fri, Apr 19, 2013 at 4:17 PM, Zhao Chenhui
<chenhui.zhao@freescale.com> wrote:
> diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c

> +#include <linux/module.h>
> +#include <linux/cpufreq.h>
> +#include <linux/of_platform.h>
> +#include <linux/suspend.h>
> +#include <linux/cpu.h>
> +#include <linux/time.h>
> +#include <linux/io.h>
> +#include <linux/smp.h>

Would be better to keep them in alphabetical order, so that we don't add
anything twice.

> +static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
> +{
> +       unsigned int i, cur_pll;
> +       int hw_cpu = get_hard_smp_processor_id(policy->cpu);
> +
> +       if (!cpu_present(policy->cpu))

This can't happen and so no need to check it.

> +               return -ENODEV;
> +
> +       /* the latency of a transition, the unit is ns */
> +       policy->cpuinfo.transition_latency = 2000;
> +
> +       cur_pll = get_pll(hw_cpu);
> +
> +       /* initialize frequency table */
> +       pr_debug("core%d frequency table:\n", hw_cpu);
> +       for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
> +               if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
> +                       /* The frequency unit is kHz. */
> +                       mpc85xx_freqs[i].frequency =
> +                               (sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
> +               } else {
> +                       mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
> +               }
> +
> +               pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
> +
> +               if (mpc85xx_freqs[i].index == cur_pll)
> +                       policy->cur = mpc85xx_freqs[i].frequency;
> +       }
> +       pr_debug("current pll is at %d, and core freq is%d\n",
> +                       cur_pll, policy->cur);
> +
> +       cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
> +
> +       /*
> +        * This ensures that policy->cpuinfo_min
> +        * and policy->cpuinfo_max are set correctly.
> +        */
> +       return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);

Call cpufreq_frequency_table_get_attr() at the end after above call is
successful.

> +}

> +static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
> +                             unsigned int target_freq,
> +                             unsigned int relation)

merge above two lines.

> +{
> +       struct cpufreq_freqs freqs;
> +       unsigned int new;
> +       int ret = 0;
> +
> +       if (!set_pll)
> +               return -ENODEV;
> +
> +       cpufreq_frequency_table_target(policy,
> +                                      mpc85xx_freqs,
> +                                      target_freq,
> +                                      relation,
> +                                      &new);

same.. merge all above to put it in a single line.

> +       freqs.old = policy->cur;
> +       freqs.new = mpc85xx_freqs[new].frequency;
> +       freqs.cpu = policy->cpu;

not required now.

> +       mutex_lock(&mpc85xx_switch_mutex);
> +       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);

ditto. Rebase over latest code from linux-next. This call has changed.

> +       ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
> +       if (!ret) {
> +               pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
> +                        policy->cpu, mpc85xx_freqs[new].frequency,
> +                        mpc85xx_freqs[new].index);
> +
> +               ppc_proc_freq = freqs.new * 1000ul;
> +       }
> +       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> +       mutex_unlock(&mpc85xx_switch_mutex);
> +
> +       return ret;
> +}

> +static int __init mpc85xx_jog_init(void)
> +{
> +       struct device_node *np;
> +       unsigned int svr;
> +
> +       np = of_find_matching_node(NULL, mpc85xx_jog_ids);
> +       if (!np)
> +               return -ENODEV;
> +
> +       guts = of_iomap(np, 0);
> +       if (!guts) {
> +               of_node_put(np);
> +               return -ENODEV;
> +       }
> +
> +       sysfreq = fsl_get_sys_freq();
> +
> +       if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
> +               svr = mfspr(SPRN_SVR);
> +               if ((svr & 0x7fff) == 0x10) {
> +                       pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
> +                       of_node_put(np);

unmap too??

> +                       return -ENODEV;
> +               }
> +               mpc85xx_freqs = mpc8536_freqs_table;
> +               set_pll = mpc8536_set_pll;
> +               max_pll[0] = get_pll(0);
> +
> +       } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
> +               mpc85xx_freqs = p1022_freqs_table;
> +               set_pll = p1022_set_pll;
> +               max_pll[0] = get_pll(0);
> +               max_pll[1] = get_pll(1);
> +       }
> +
> +       pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
> +
> +       of_node_put(np);
> +       return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
> +}
> +
> +device_initcall(mpc85xx_jog_init);

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface
  2013-04-22  3:25   ` Viresh Kumar
  2013-04-22 10:56       ` Zhao Chenhui
@ 2013-04-22 10:56       ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-22 10:56 UTC (permalink / raw)
  To: Viresh Kumar; +Cc: linuxppc-dev, linux-kernel, linux-pm, cpufreq

On Mon, Apr 22, 2013 at 08:55:35AM +0530, Viresh Kumar wrote:
> On Fri, Apr 19, 2013 at 4:17 PM, Zhao Chenhui
> <chenhui.zhao@freescale.com> wrote:
> > diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c
> 
> > +#include <linux/module.h>
> > +#include <linux/cpufreq.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/suspend.h>
> > +#include <linux/cpu.h>
> > +#include <linux/time.h>
> > +#include <linux/io.h>
> > +#include <linux/smp.h>
> 
> Would be better to keep them in alphabetical order, so that we don't add
> anything twice.

Good idea.

> 
> > +static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
> > +{
> > +       unsigned int i, cur_pll;
> > +       int hw_cpu = get_hard_smp_processor_id(policy->cpu);
> > +
> > +       if (!cpu_present(policy->cpu))
> 
> This can't happen and so no need to check it.
> 
> > +               return -ENODEV;
> > +
> > +       /* the latency of a transition, the unit is ns */
> > +       policy->cpuinfo.transition_latency = 2000;
> > +
> > +       cur_pll = get_pll(hw_cpu);
> > +
> > +       /* initialize frequency table */
> > +       pr_debug("core%d frequency table:\n", hw_cpu);
> > +       for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
> > +               if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
> > +                       /* The frequency unit is kHz. */
> > +                       mpc85xx_freqs[i].frequency =
> > +                               (sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
> > +               } else {
> > +                       mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
> > +               }
> > +
> > +               pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
> > +
> > +               if (mpc85xx_freqs[i].index == cur_pll)
> > +                       policy->cur = mpc85xx_freqs[i].frequency;
> > +       }
> > +       pr_debug("current pll is at %d, and core freq is%d\n",
> > +                       cur_pll, policy->cur);
> > +
> > +       cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
> > +
> > +       /*
> > +        * This ensures that policy->cpuinfo_min
> > +        * and policy->cpuinfo_max are set correctly.
> > +        */
> > +       return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
> 
> Call cpufreq_frequency_table_get_attr() at the end after above call is
> successful.
> 
> > +}
> 
> > +static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
> > +                             unsigned int target_freq,
> > +                             unsigned int relation)
> 
> merge above two lines.
> 
> > +{
> > +       struct cpufreq_freqs freqs;
> > +       unsigned int new;
> > +       int ret = 0;
> > +
> > +       if (!set_pll)
> > +               return -ENODEV;
> > +
> > +       cpufreq_frequency_table_target(policy,
> > +                                      mpc85xx_freqs,
> > +                                      target_freq,
> > +                                      relation,
> > +                                      &new);
> 
> same.. merge all above to put it in a single line.
> 
> > +       freqs.old = policy->cur;
> > +       freqs.new = mpc85xx_freqs[new].frequency;
> > +       freqs.cpu = policy->cpu;
> 
> not required now.
> 
> > +       mutex_lock(&mpc85xx_switch_mutex);
> > +       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
> 
> ditto. Rebase over latest code from linux-next. This call has changed.
> 
> > +       ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
> > +       if (!ret) {
> > +               pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
> > +                        policy->cpu, mpc85xx_freqs[new].frequency,
> > +                        mpc85xx_freqs[new].index);
> > +
> > +               ppc_proc_freq = freqs.new * 1000ul;
> > +       }
> > +       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> > +       mutex_unlock(&mpc85xx_switch_mutex);
> > +
> > +       return ret;
> > +}
> 
> > +static int __init mpc85xx_jog_init(void)
> > +{
> > +       struct device_node *np;
> > +       unsigned int svr;
> > +
> > +       np = of_find_matching_node(NULL, mpc85xx_jog_ids);
> > +       if (!np)
> > +               return -ENODEV;
> > +
> > +       guts = of_iomap(np, 0);
> > +       if (!guts) {
> > +               of_node_put(np);
> > +               return -ENODEV;
> > +       }
> > +
> > +       sysfreq = fsl_get_sys_freq();
> > +
> > +       if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
> > +               svr = mfspr(SPRN_SVR);
> > +               if ((svr & 0x7fff) == 0x10) {
> > +                       pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
> > +                       of_node_put(np);
> 
> unmap too??
> 
> > +                       return -ENODEV;
> > +               }
> > +               mpc85xx_freqs = mpc8536_freqs_table;
> > +               set_pll = mpc8536_set_pll;
> > +               max_pll[0] = get_pll(0);
> > +
> > +       } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
> > +               mpc85xx_freqs = p1022_freqs_table;
> > +               set_pll = p1022_set_pll;
> > +               max_pll[0] = get_pll(0);
> > +               max_pll[1] = get_pll(1);
> > +       }
> > +
> > +       pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
> > +
> > +       of_node_put(np);
> > +       return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
> > +}
> > +
> > +device_initcall(mpc85xx_jog_init);
> 

Thanks. I will fix them.

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface
@ 2013-04-22 10:56       ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-22 10:56 UTC (permalink / raw)
  To: Viresh Kumar; +Cc: linuxppc-dev, linux-kernel, linux-pm, cpufreq

On Mon, Apr 22, 2013 at 08:55:35AM +0530, Viresh Kumar wrote:
> On Fri, Apr 19, 2013 at 4:17 PM, Zhao Chenhui
> <chenhui.zhao@freescale.com> wrote:
> > diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c
> 
> > +#include <linux/module.h>
> > +#include <linux/cpufreq.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/suspend.h>
> > +#include <linux/cpu.h>
> > +#include <linux/time.h>
> > +#include <linux/io.h>
> > +#include <linux/smp.h>
> 
> Would be better to keep them in alphabetical order, so that we don't add
> anything twice.

Good idea.

> 
> > +static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
> > +{
> > +       unsigned int i, cur_pll;
> > +       int hw_cpu = get_hard_smp_processor_id(policy->cpu);
> > +
> > +       if (!cpu_present(policy->cpu))
> 
> This can't happen and so no need to check it.
> 
> > +               return -ENODEV;
> > +
> > +       /* the latency of a transition, the unit is ns */
> > +       policy->cpuinfo.transition_latency = 2000;
> > +
> > +       cur_pll = get_pll(hw_cpu);
> > +
> > +       /* initialize frequency table */
> > +       pr_debug("core%d frequency table:\n", hw_cpu);
> > +       for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
> > +               if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
> > +                       /* The frequency unit is kHz. */
> > +                       mpc85xx_freqs[i].frequency =
> > +                               (sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
> > +               } else {
> > +                       mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
> > +               }
> > +
> > +               pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
> > +
> > +               if (mpc85xx_freqs[i].index == cur_pll)
> > +                       policy->cur = mpc85xx_freqs[i].frequency;
> > +       }
> > +       pr_debug("current pll is at %d, and core freq is%d\n",
> > +                       cur_pll, policy->cur);
> > +
> > +       cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
> > +
> > +       /*
> > +        * This ensures that policy->cpuinfo_min
> > +        * and policy->cpuinfo_max are set correctly.
> > +        */
> > +       return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
> 
> Call cpufreq_frequency_table_get_attr() at the end after above call is
> successful.
> 
> > +}
> 
> > +static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
> > +                             unsigned int target_freq,
> > +                             unsigned int relation)
> 
> merge above two lines.
> 
> > +{
> > +       struct cpufreq_freqs freqs;
> > +       unsigned int new;
> > +       int ret = 0;
> > +
> > +       if (!set_pll)
> > +               return -ENODEV;
> > +
> > +       cpufreq_frequency_table_target(policy,
> > +                                      mpc85xx_freqs,
> > +                                      target_freq,
> > +                                      relation,
> > +                                      &new);
> 
> same.. merge all above to put it in a single line.
> 
> > +       freqs.old = policy->cur;
> > +       freqs.new = mpc85xx_freqs[new].frequency;
> > +       freqs.cpu = policy->cpu;
> 
> not required now.
> 
> > +       mutex_lock(&mpc85xx_switch_mutex);
> > +       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
> 
> ditto. Rebase over latest code from linux-next. This call has changed.
> 
> > +       ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
> > +       if (!ret) {
> > +               pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
> > +                        policy->cpu, mpc85xx_freqs[new].frequency,
> > +                        mpc85xx_freqs[new].index);
> > +
> > +               ppc_proc_freq = freqs.new * 1000ul;
> > +       }
> > +       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> > +       mutex_unlock(&mpc85xx_switch_mutex);
> > +
> > +       return ret;
> > +}
> 
> > +static int __init mpc85xx_jog_init(void)
> > +{
> > +       struct device_node *np;
> > +       unsigned int svr;
> > +
> > +       np = of_find_matching_node(NULL, mpc85xx_jog_ids);
> > +       if (!np)
> > +               return -ENODEV;
> > +
> > +       guts = of_iomap(np, 0);
> > +       if (!guts) {
> > +               of_node_put(np);
> > +               return -ENODEV;
> > +       }
> > +
> > +       sysfreq = fsl_get_sys_freq();
> > +
> > +       if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
> > +               svr = mfspr(SPRN_SVR);
> > +               if ((svr & 0x7fff) == 0x10) {
> > +                       pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
> > +                       of_node_put(np);
> 
> unmap too??
> 
> > +                       return -ENODEV;
> > +               }
> > +               mpc85xx_freqs = mpc8536_freqs_table;
> > +               set_pll = mpc8536_set_pll;
> > +               max_pll[0] = get_pll(0);
> > +
> > +       } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
> > +               mpc85xx_freqs = p1022_freqs_table;
> > +               set_pll = p1022_set_pll;
> > +               max_pll[0] = get_pll(0);
> > +               max_pll[1] = get_pll(1);
> > +       }
> > +
> > +       pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
> > +
> > +       of_node_put(np);
> > +       return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
> > +}
> > +
> > +device_initcall(mpc85xx_jog_init);
> 

Thanks. I will fix them.

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface
@ 2013-04-22 10:56       ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-22 10:56 UTC (permalink / raw)
  To: Viresh Kumar; +Cc: linuxppc-dev, linux-kernel, cpufreq, linux-pm

On Mon, Apr 22, 2013 at 08:55:35AM +0530, Viresh Kumar wrote:
> On Fri, Apr 19, 2013 at 4:17 PM, Zhao Chenhui
> <chenhui.zhao@freescale.com> wrote:
> > diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c
> 
> > +#include <linux/module.h>
> > +#include <linux/cpufreq.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/suspend.h>
> > +#include <linux/cpu.h>
> > +#include <linux/time.h>
> > +#include <linux/io.h>
> > +#include <linux/smp.h>
> 
> Would be better to keep them in alphabetical order, so that we don't add
> anything twice.

Good idea.

> 
> > +static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
> > +{
> > +       unsigned int i, cur_pll;
> > +       int hw_cpu = get_hard_smp_processor_id(policy->cpu);
> > +
> > +       if (!cpu_present(policy->cpu))
> 
> This can't happen and so no need to check it.
> 
> > +               return -ENODEV;
> > +
> > +       /* the latency of a transition, the unit is ns */
> > +       policy->cpuinfo.transition_latency = 2000;
> > +
> > +       cur_pll = get_pll(hw_cpu);
> > +
> > +       /* initialize frequency table */
> > +       pr_debug("core%d frequency table:\n", hw_cpu);
> > +       for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
> > +               if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
> > +                       /* The frequency unit is kHz. */
> > +                       mpc85xx_freqs[i].frequency =
> > +                               (sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
> > +               } else {
> > +                       mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
> > +               }
> > +
> > +               pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
> > +
> > +               if (mpc85xx_freqs[i].index == cur_pll)
> > +                       policy->cur = mpc85xx_freqs[i].frequency;
> > +       }
> > +       pr_debug("current pll is at %d, and core freq is%d\n",
> > +                       cur_pll, policy->cur);
> > +
> > +       cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
> > +
> > +       /*
> > +        * This ensures that policy->cpuinfo_min
> > +        * and policy->cpuinfo_max are set correctly.
> > +        */
> > +       return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
> 
> Call cpufreq_frequency_table_get_attr() at the end after above call is
> successful.
> 
> > +}
> 
> > +static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
> > +                             unsigned int target_freq,
> > +                             unsigned int relation)
> 
> merge above two lines.
> 
> > +{
> > +       struct cpufreq_freqs freqs;
> > +       unsigned int new;
> > +       int ret = 0;
> > +
> > +       if (!set_pll)
> > +               return -ENODEV;
> > +
> > +       cpufreq_frequency_table_target(policy,
> > +                                      mpc85xx_freqs,
> > +                                      target_freq,
> > +                                      relation,
> > +                                      &new);
> 
> same.. merge all above to put it in a single line.
> 
> > +       freqs.old = policy->cur;
> > +       freqs.new = mpc85xx_freqs[new].frequency;
> > +       freqs.cpu = policy->cpu;
> 
> not required now.
> 
> > +       mutex_lock(&mpc85xx_switch_mutex);
> > +       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
> 
> ditto. Rebase over latest code from linux-next. This call has changed.
> 
> > +       ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
> > +       if (!ret) {
> > +               pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
> > +                        policy->cpu, mpc85xx_freqs[new].frequency,
> > +                        mpc85xx_freqs[new].index);
> > +
> > +               ppc_proc_freq = freqs.new * 1000ul;
> > +       }
> > +       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> > +       mutex_unlock(&mpc85xx_switch_mutex);
> > +
> > +       return ret;
> > +}
> 
> > +static int __init mpc85xx_jog_init(void)
> > +{
> > +       struct device_node *np;
> > +       unsigned int svr;
> > +
> > +       np = of_find_matching_node(NULL, mpc85xx_jog_ids);
> > +       if (!np)
> > +               return -ENODEV;
> > +
> > +       guts = of_iomap(np, 0);
> > +       if (!guts) {
> > +               of_node_put(np);
> > +               return -ENODEV;
> > +       }
> > +
> > +       sysfreq = fsl_get_sys_freq();
> > +
> > +       if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
> > +               svr = mfspr(SPRN_SVR);
> > +               if ((svr & 0x7fff) == 0x10) {
> > +                       pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
> > +                       of_node_put(np);
> 
> unmap too??
> 
> > +                       return -ENODEV;
> > +               }
> > +               mpc85xx_freqs = mpc8536_freqs_table;
> > +               set_pll = mpc8536_set_pll;
> > +               max_pll[0] = get_pll(0);
> > +
> > +       } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
> > +               mpc85xx_freqs = p1022_freqs_table;
> > +               set_pll = p1022_set_pll;
> > +               max_pll[0] = get_pll(0);
> > +               max_pll[1] = get_pll(1);
> > +       }
> > +
> > +       pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
> > +
> > +       of_node_put(np);
> > +       return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
> > +}
> > +
> > +device_initcall(mpc85xx_jog_init);
> 

Thanks. I will fix them.

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [linuxppc-release] [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-23  9:53   ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-23  9:53 UTC (permalink / raw)
  To: Kumar Gala, Scott Wood; +Cc: linux-kernel, linuxppc-dev

Hi Kumar, Scott,

Do you have any comments on this set of patches?

Best Regards,
-Chenhui

On Fri, Apr 19, 2013 at 06:47:34PM +0800, Zhao Chenhui wrote:
> These cache operations support Freescale SoCs based on BOOK3E.
> Move L1 cache operations to fsl_booke_cache.S in order to maintain
> easily. And, add cache operations for backside L2 cache and platform cache.
> 
> The backside L2 cache appears on e500mc and e5500 core. The platform cache
> supported by this patch is L2 Look-Aside Cache, which appears on SoCs
> with e500v1/e500v2 core, such as MPC8572, P1020, etc.
> 
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  arch/powerpc/include/asm/cacheflush.h |    8 ++
>  arch/powerpc/kernel/Makefile          |    1 +
>  arch/powerpc/kernel/fsl_booke_cache.S |  210 +++++++++++++++++++++++++++++++++
>  arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
>  4 files changed, 219 insertions(+), 74 deletions(-)
>  create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S
> 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [linuxppc-release] [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
@ 2013-04-23  9:53   ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-23  9:53 UTC (permalink / raw)
  To: Kumar Gala, Scott Wood; +Cc: linuxppc-dev, linux-kernel

Hi Kumar, Scott,

Do you have any comments on this set of patches?

Best Regards,
-Chenhui

On Fri, Apr 19, 2013 at 06:47:34PM +0800, Zhao Chenhui wrote:
> These cache operations support Freescale SoCs based on BOOK3E.
> Move L1 cache operations to fsl_booke_cache.S in order to maintain
> easily. And, add cache operations for backside L2 cache and platform cache.
> 
> The backside L2 cache appears on e500mc and e5500 core. The platform cache
> supported by this patch is L2 Look-Aside Cache, which appears on SoCs
> with e500v1/e500v2 core, such as MPC8572, P1020, etc.
> 
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  arch/powerpc/include/asm/cacheflush.h |    8 ++
>  arch/powerpc/kernel/Makefile          |    1 +
>  arch/powerpc/kernel/fsl_booke_cache.S |  210 +++++++++++++++++++++++++++++++++
>  arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
>  4 files changed, 219 insertions(+), 74 deletions(-)
>  create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S
> 

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
  2013-04-19 10:47 ` Zhao Chenhui
@ 2013-04-23 23:46   ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-23 23:46 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:34 AM, Zhao Chenhui wrote:
> These cache operations support Freescale SoCs based on BOOK3E.
> Move L1 cache operations to fsl_booke_cache.S in order to maintain
> easily. And, add cache operations for backside L2 cache and platform  
> cache.
> 
> The backside L2 cache appears on e500mc and e5500 core. The platform  
> cache
> supported by this patch is L2 Look-Aside Cache, which appears on SoCs
> with e500v1/e500v2 core, such as MPC8572, P1020, etc.
> 
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  arch/powerpc/include/asm/cacheflush.h |    8 ++
>  arch/powerpc/kernel/Makefile          |    1 +
>  arch/powerpc/kernel/fsl_booke_cache.S |  210  
> +++++++++++++++++++++++++++++++++
>  arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
>  4 files changed, 219 insertions(+), 74 deletions(-)
>  create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S
> 
> diff --git a/arch/powerpc/include/asm/cacheflush.h  
> b/arch/powerpc/include/asm/cacheflush.h
> index b843e35..bc3f937 100644
> --- a/arch/powerpc/include/asm/cacheflush.h
> +++ b/arch/powerpc/include/asm/cacheflush.h
> @@ -32,6 +32,14 @@ extern void flush_dcache_page(struct page *page);
> 
>  extern void __flush_disable_L1(void);
> 
> +#ifdef CONFIG_FSL_SOC_BOOKE
> +void flush_dcache_L1(void);
> +void flush_backside_L2_cache(void);
> +void disable_backside_L2_cache(void);
> +void flush_disable_L2(void);
> +void invalidate_enable_L2(void);
> +#endif

Don't ifdef prototypes unless there's a good reason, such as providing  
an inline alternative.

Why do you have "flush_backside_L2_cache" and  
"disable_backside_L2_cache" as something different from  
"flush_disable_L2"?  The latter should flush whatever L2 is present.   
Don't treat pre-corenet as the default.

Why do we even need to distinguish L1 from L2 at all?  Shouldn't the  
function that gets exposed just be "flush and disable data caches that  
are specific to this cpu"?  What should happen on e6500?

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
@ 2013-04-23 23:46   ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-23 23:46 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:34 AM, Zhao Chenhui wrote:
> These cache operations support Freescale SoCs based on BOOK3E.
> Move L1 cache operations to fsl_booke_cache.S in order to maintain
> easily. And, add cache operations for backside L2 cache and platform =20
> cache.
>=20
> The backside L2 cache appears on e500mc and e5500 core. The platform =20
> cache
> supported by this patch is L2 Look-Aside Cache, which appears on SoCs
> with e500v1/e500v2 core, such as MPC8572, P1020, etc.
>=20
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  arch/powerpc/include/asm/cacheflush.h |    8 ++
>  arch/powerpc/kernel/Makefile          |    1 +
>  arch/powerpc/kernel/fsl_booke_cache.S |  210 =20
> +++++++++++++++++++++++++++++++++
>  arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
>  4 files changed, 219 insertions(+), 74 deletions(-)
>  create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S
>=20
> diff --git a/arch/powerpc/include/asm/cacheflush.h =20
> b/arch/powerpc/include/asm/cacheflush.h
> index b843e35..bc3f937 100644
> --- a/arch/powerpc/include/asm/cacheflush.h
> +++ b/arch/powerpc/include/asm/cacheflush.h
> @@ -32,6 +32,14 @@ extern void flush_dcache_page(struct page *page);
>=20
>  extern void __flush_disable_L1(void);
>=20
> +#ifdef CONFIG_FSL_SOC_BOOKE
> +void flush_dcache_L1(void);
> +void flush_backside_L2_cache(void);
> +void disable_backside_L2_cache(void);
> +void flush_disable_L2(void);
> +void invalidate_enable_L2(void);
> +#endif

Don't ifdef prototypes unless there's a good reason, such as providing =20
an inline alternative.

Why do you have "flush_backside_L2_cache" and =20
"disable_backside_L2_cache" as something different from =20
"flush_disable_L2"?  The latter should flush whatever L2 is present.  =20
Don't treat pre-corenet as the default.

Why do we even need to distinguish L1 from L2 at all?  Shouldn't the =20
function that gets exposed just be "flush and disable data caches that =20
are specific to this cpu"?  What should happen on e6500?

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support
  2013-04-19 10:47   ` Zhao Chenhui
@ 2013-04-23 23:53     ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-23 23:53 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:35 AM, Zhao Chenhui wrote:
>  static int pmc_suspend_enter(suspend_state_t state)
>  {
> -	int ret;
> +	int ret = 0;
> +
> +	switch (state) {
> +#ifdef CONFIG_PPC_85xx
> +	case PM_SUSPEND_MEM:
> +#ifdef CONFIG_SPE
> +		enable_kernel_spe();
> +#endif
> +		enable_kernel_fp();

Why does enable_kernel_spe() need an ifdef but enable_kernel_fp()  
doesn't?

> +	case PM_SUSPEND_STANDBY:
> +#ifdef CONFIG_FSL_SOC_BOOKE
> +		flush_dcache_L1();
> +#endif
> +		setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);

Only L1, even on e500mc?

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support
@ 2013-04-23 23:53     ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-23 23:53 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:35 AM, Zhao Chenhui wrote:
>  static int pmc_suspend_enter(suspend_state_t state)
>  {
> -	int ret;
> +	int ret =3D 0;
> +
> +	switch (state) {
> +#ifdef CONFIG_PPC_85xx
> +	case PM_SUSPEND_MEM:
> +#ifdef CONFIG_SPE
> +		enable_kernel_spe();
> +#endif
> +		enable_kernel_fp();

Why does enable_kernel_spe() need an ifdef but enable_kernel_fp() =20
doesn't?

> +	case PM_SUSPEND_STANDBY:
> +#ifdef CONFIG_FSL_SOC_BOOKE
> +		flush_dcache_L1();
> +#endif
> +		setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);

Only L1, even on e500mc?

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 07/15] powerpc/85xx: add time base sync for SoCs based on e500mc/e5500
  2013-04-19 10:47   ` Zhao Chenhui
@ 2013-04-23 23:58     ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-23 23:58 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:40 AM, Zhao Chenhui wrote:
> From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> 
> In the case of SMP, during the time base sync period, all time bases  
> of
> online cores must stop, then start simultaneously.
> 
> There is a RCPM (Run Control/Power Management) module in CoreNet  
> based SoCs.
> Define a struct ccsr_rcpm to describe the register map.
> 
> This patch supports SoCs based on e500mc/e5500, such as P4080, P5020,
> etc.
> 
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  arch/powerpc/include/asm/fsl_guts.h |   38  
> +++++++++++++++++++++++++++++++++++
>  arch/powerpc/platforms/85xx/smp.c   |   32  
> +++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/fsl_guts.h  
> b/arch/powerpc/include/asm/fsl_guts.h
> index 77ced0b..4eac1cf 100644
> --- a/arch/powerpc/include/asm/fsl_guts.h
> +++ b/arch/powerpc/include/asm/fsl_guts.h
> @@ -106,6 +106,44 @@ struct ccsr_guts {
>  /* Alternate function signal multiplex control */
>  #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
> 
> +struct ccsr_rcpm {
> +	u8	res0000[4];
> +	__be32	cdozsr;		/* 0x0004 - Core Doze Status Register */
> +	u8	res0008[4];
> +	__be32	cdozcr;		/* 0x000c - Core Doze Control Register  
> */
> +	u8	res0010[4];
> +	__be32	cnapsr;		/* 0x0014 - Core Nap Status Register */
> +	u8	res0018[4];
> +	__be32	cnapcr;		/* 0x001c - Core Nap Control Register */
> +	u8	res0020[4];
> +	__be32	cdozpsr;	/* 0x0024 - Core Doze Previous Status  
> Register */
> +	u8	res0028[4];
> +	__be32	cnappsr;	/* 0x002c - Core Nap Previous Status  
> Register */
> +	u8	res0030[4];
> +	__be32	cwaitsr;	/* 0x0034 - Core Wait Status Register */
> +	u8	res0038[4];
> +	__be32	cwdtdsr;	/* 0x003c - Core watchdog detect status  
> register */
> +	__be32	powmgtcsr;	/* 0x0040 - Power Mangement Control &  
> Status Register */
> +	u8	res0044[12];
> +	__be32	ippdexpcr;	/* 0x0050 - IP Powerdown Exception  
> Control Register */
> +	u8	res0054[16];
> +	__be32	cpmimr;		/* 0x0064 - Core PM IRQ Mask Register */
> +	u8	res0068[4];
> +	__be32	cpmcimr;	/* 0x006c - Core PM Critical IRQ Mask  
> Register */
> +	u8	res0070[4];
> +	__be32	cpmmcmr;	/* 0x0074 - Core PM Machine Check Mask  
> Register */
> +	u8	res0078[4];
> +	__be32	cpmnmimr;	/* 0x007c - Core PM NMI Mask Register */
> +	u8	res0080[4];
> +	__be32	ctbenr;		/* 0x0084 - Core Time Base Enable  
> Register */
> +	u8	res0088[4];
> +	__be32	ctbckselr;	/* 0x008c - Core Time Base Clock Select  
> Register */
> +	u8	res0090[4];
> +	__be32	ctbhltcr;	/* 0x0094 - Core Time Base Halt Control  
> Register */
> +	u8	res0098[4];
> +	__be32	cmcpmaskcr;	/* 0x00a4 - Core machine check mask  
> control register */
> +};
> +
>  #ifdef CONFIG_PPC_86xx
> 
>  #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA  
> controller/channel set to SSI */
> diff --git a/arch/powerpc/platforms/85xx/smp.c  
> b/arch/powerpc/platforms/85xx/smp.c
> index 6a17599..6c2fe6b 100644
> --- a/arch/powerpc/platforms/85xx/smp.c
> +++ b/arch/powerpc/platforms/85xx/smp.c
> @@ -44,7 +44,36 @@ static struct ccsr_guts __iomem *guts;
>  static u64 timebase;
>  static int tb_req;
>  static int tb_valid;
> +static u32 cur_booting_core;
> 
> +#ifdef CONFIG_PPC_E500MC
> +/* get a physical mask of online cores and booting core */
> +static inline u32 get_phy_cpu_mask(void)
> +{
> +	u32 mask;
> +	int cpu;
> +
> +	mask = 1 << cur_booting_core;
> +	for_each_online_cpu(cpu)
> +		mask |= 1 << get_hard_smp_processor_id(cpu);
> +
> +	return mask;
> +}
> +
> +static void mpc85xx_timebase_freeze(int freeze)
> +{
> +	struct ccsr_rcpm __iomem *rcpm = (typeof(rcpm))guts;
> +	u32 mask = get_phy_cpu_mask();
> +
> +	if (freeze)
> +		clrbits32(&rcpm->ctbenr, mask);
> +	else
> +		setbits32(&rcpm->ctbenr, mask);
> +
> +	/* read back to push the previos write */
> +	in_be32(&rcpm->ctbenr);
> +}
> +#else

Please determine the timebase sync implementation at runtime, rather  
than relying on our current inability to have e500v2 and e500mc in the  
same kernel.  e6500 will be different from e5500, but both can be in  
the same kernel image.

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 07/15] powerpc/85xx: add time base sync for SoCs based on e500mc/e5500
@ 2013-04-23 23:58     ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-23 23:58 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:40 AM, Zhao Chenhui wrote:
> From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
>=20
> In the case of SMP, during the time base sync period, all time bases =20
> of
> online cores must stop, then start simultaneously.
>=20
> There is a RCPM (Run Control/Power Management) module in CoreNet =20
> based SoCs.
> Define a struct ccsr_rcpm to describe the register map.
>=20
> This patch supports SoCs based on e500mc/e5500, such as P4080, P5020,
> etc.
>=20
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
>  arch/powerpc/include/asm/fsl_guts.h |   38 =20
> +++++++++++++++++++++++++++++++++++
>  arch/powerpc/platforms/85xx/smp.c   |   32 =20
> +++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+), 0 deletions(-)
>=20
> diff --git a/arch/powerpc/include/asm/fsl_guts.h =20
> b/arch/powerpc/include/asm/fsl_guts.h
> index 77ced0b..4eac1cf 100644
> --- a/arch/powerpc/include/asm/fsl_guts.h
> +++ b/arch/powerpc/include/asm/fsl_guts.h
> @@ -106,6 +106,44 @@ struct ccsr_guts {
>  /* Alternate function signal multiplex control */
>  #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
>=20
> +struct ccsr_rcpm {
> +	u8	res0000[4];
> +	__be32	cdozsr;		/* 0x0004 - Core Doze Status Register */
> +	u8	res0008[4];
> +	__be32	cdozcr;		/* 0x000c - Core Doze Control Register =20
> */
> +	u8	res0010[4];
> +	__be32	cnapsr;		/* 0x0014 - Core Nap Status Register */
> +	u8	res0018[4];
> +	__be32	cnapcr;		/* 0x001c - Core Nap Control Register */
> +	u8	res0020[4];
> +	__be32	cdozpsr;	/* 0x0024 - Core Doze Previous Status =20
> Register */
> +	u8	res0028[4];
> +	__be32	cnappsr;	/* 0x002c - Core Nap Previous Status =20
> Register */
> +	u8	res0030[4];
> +	__be32	cwaitsr;	/* 0x0034 - Core Wait Status Register */
> +	u8	res0038[4];
> +	__be32	cwdtdsr;	/* 0x003c - Core watchdog detect status =20
> register */
> +	__be32	powmgtcsr;	/* 0x0040 - Power Mangement Control & =20
> Status Register */
> +	u8	res0044[12];
> +	__be32	ippdexpcr;	/* 0x0050 - IP Powerdown Exception =20
> Control Register */
> +	u8	res0054[16];
> +	__be32	cpmimr;		/* 0x0064 - Core PM IRQ Mask Register */
> +	u8	res0068[4];
> +	__be32	cpmcimr;	/* 0x006c - Core PM Critical IRQ Mask =20
> Register */
> +	u8	res0070[4];
> +	__be32	cpmmcmr;	/* 0x0074 - Core PM Machine Check Mask =20
> Register */
> +	u8	res0078[4];
> +	__be32	cpmnmimr;	/* 0x007c - Core PM NMI Mask Register */
> +	u8	res0080[4];
> +	__be32	ctbenr;		/* 0x0084 - Core Time Base Enable =20
> Register */
> +	u8	res0088[4];
> +	__be32	ctbckselr;	/* 0x008c - Core Time Base Clock Select =20
> Register */
> +	u8	res0090[4];
> +	__be32	ctbhltcr;	/* 0x0094 - Core Time Base Halt Control =20
> Register */
> +	u8	res0098[4];
> +	__be32	cmcpmaskcr;	/* 0x00a4 - Core machine check mask =20
> control register */
> +};
> +
>  #ifdef CONFIG_PPC_86xx
>=20
>  #define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA =20
> controller/channel set to SSI */
> diff --git a/arch/powerpc/platforms/85xx/smp.c =20
> b/arch/powerpc/platforms/85xx/smp.c
> index 6a17599..6c2fe6b 100644
> --- a/arch/powerpc/platforms/85xx/smp.c
> +++ b/arch/powerpc/platforms/85xx/smp.c
> @@ -44,7 +44,36 @@ static struct ccsr_guts __iomem *guts;
>  static u64 timebase;
>  static int tb_req;
>  static int tb_valid;
> +static u32 cur_booting_core;
>=20
> +#ifdef CONFIG_PPC_E500MC
> +/* get a physical mask of online cores and booting core */
> +static inline u32 get_phy_cpu_mask(void)
> +{
> +	u32 mask;
> +	int cpu;
> +
> +	mask =3D 1 << cur_booting_core;
> +	for_each_online_cpu(cpu)
> +		mask |=3D 1 << get_hard_smp_processor_id(cpu);
> +
> +	return mask;
> +}
> +
> +static void mpc85xx_timebase_freeze(int freeze)
> +{
> +	struct ccsr_rcpm __iomem *rcpm =3D (typeof(rcpm))guts;
> +	u32 mask =3D get_phy_cpu_mask();
> +
> +	if (freeze)
> +		clrbits32(&rcpm->ctbenr, mask);
> +	else
> +		setbits32(&rcpm->ctbenr, mask);
> +
> +	/* read back to push the previos write */
> +	in_be32(&rcpm->ctbenr);
> +}
> +#else

Please determine the timebase sync implementation at runtime, rather =20
than relying on our current inability to have e500v2 and e500mc in the =20
same kernel.  e6500 will be different from e5500, but both can be in =20
the same kernel image.

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation
  2013-04-19 10:47   ` Zhao Chenhui
@ 2013-04-24  0:00     ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-24  0:00 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:46 AM, Zhao Chenhui wrote:
> From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> 
> The L1 Data Cache of e6500 contains no modified data, no flush
> is required.
> 
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
>  arch/powerpc/kernel/fsl_booke_cache.S |   11 ++++++++++-
>  1 files changed, 10 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/fsl_booke_cache.S  
> b/arch/powerpc/kernel/fsl_booke_cache.S
> index 232c47b..24a52bb 100644
> --- a/arch/powerpc/kernel/fsl_booke_cache.S
> +++ b/arch/powerpc/kernel/fsl_booke_cache.S
> @@ -65,13 +65,22 @@ _GLOBAL(flush_dcache_L1)
> 
>  	blr
> 
> +#define PVR_E6500	0x8040
> +
>  /* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
>  _GLOBAL(__flush_disable_L1)
> +/* L1 Data Cache of e6500 contains no modified data, no flush is  
> required */
> +	mfspr	r3, SPRN_PVR
> +	rlwinm	r4, r3, 16, 0xffff
> +	lis	r5, 0
> +	ori	r5, r5, PVR_E6500@l
> +	cmpw	r4, r5
> +	beq	2f
>  	mflr	r10
>  	bl	flush_dcache_L1	/* Flush L1 d-cache */
>  	mtlr	r10
> 
> -	msync
> +2:	msync
>  	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
>  	li	r5, 2
>  	rlwimi	r4, r5, 0, 3

Note that disabling the cache is a core operation, rather than a thread  
operation.  Is this only called when the second thread is disabled?

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation
@ 2013-04-24  0:00     ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-24  0:00 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:46 AM, Zhao Chenhui wrote:
> From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
>=20
> The L1 Data Cache of e6500 contains no modified data, no flush
> is required.
>=20
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
>  arch/powerpc/kernel/fsl_booke_cache.S |   11 ++++++++++-
>  1 files changed, 10 insertions(+), 1 deletions(-)
>=20
> diff --git a/arch/powerpc/kernel/fsl_booke_cache.S =20
> b/arch/powerpc/kernel/fsl_booke_cache.S
> index 232c47b..24a52bb 100644
> --- a/arch/powerpc/kernel/fsl_booke_cache.S
> +++ b/arch/powerpc/kernel/fsl_booke_cache.S
> @@ -65,13 +65,22 @@ _GLOBAL(flush_dcache_L1)
>=20
>  	blr
>=20
> +#define PVR_E6500	0x8040
> +
>  /* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
>  _GLOBAL(__flush_disable_L1)
> +/* L1 Data Cache of e6500 contains no modified data, no flush is =20
> required */
> +	mfspr	r3, SPRN_PVR
> +	rlwinm	r4, r3, 16, 0xffff
> +	lis	r5, 0
> +	ori	r5, r5, PVR_E6500@l
> +	cmpw	r4, r5
> +	beq	2f
>  	mflr	r10
>  	bl	flush_dcache_L1	/* Flush L1 d-cache */
>  	mtlr	r10
>=20
> -	msync
> +2:	msync
>  	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
>  	li	r5, 2
>  	rlwimi	r4, r5, 0, 3

Note that disabling the cache is a core operation, rather than a thread =20
operation.  Is this only called when the second thread is disabled?

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-19 10:47   ` Zhao Chenhui
@ 2013-04-24  0:04     ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-24  0:04 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> 
> For e6500, two threads in one core share one time base. Just need
> to do time base sync on first thread of one core, and skip it on
> the other thread.
> 
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
>  arch/powerpc/platforms/85xx/smp.c |   52  
> +++++++++++++++++++++++++++++++-----
>  1 files changed, 44 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/85xx/smp.c  
> b/arch/powerpc/platforms/85xx/smp.c
> index 74d8cde..5f3eee3 100644
> --- a/arch/powerpc/platforms/85xx/smp.c
> +++ b/arch/powerpc/platforms/85xx/smp.c
> @@ -26,6 +26,7 @@
>  #include <asm/cacheflush.h>
>  #include <asm/dbell.h>
>  #include <asm/fsl_guts.h>
> +#include <asm/cputhreads.h>
> 
>  #include <sysdev/fsl_soc.h>
>  #include <sysdev/mpic.h>
> @@ -45,6 +46,7 @@ static u64 timebase;
>  static int tb_req;
>  static int tb_valid;
>  static u32 cur_booting_core;
> +static bool rcpmv2;
> 
>  #ifdef CONFIG_PPC_E500MC
>  /* get a physical mask of online cores and booting core */
> @@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
>  	u32 mask;
>  	int cpu;
> 
> -	mask = 1 << cur_booting_core;
> -	for_each_online_cpu(cpu)
> -		mask |= 1 << get_hard_smp_processor_id(cpu);
> +	if (smt_capable()) {
> +		/* two threads in one core share one time base */
> +		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> +		for_each_online_cpu(cpu)
> +			mask |= 1 << cpu_core_index_of_thread(
> +					get_hard_smp_processor_id(cpu));
> +	} else {
> +		mask = 1 << cur_booting_core;
> +		for_each_online_cpu(cpu)
> +			mask |= 1 << get_hard_smp_processor_id(cpu);
> +	}

Where is smt_capable defined()?  I assume somewhere in the patchset but  
it's a pain to search 12 patches...

Is this really about whether we're SMT-capable or whether we have rcpm  
v2?

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-24  0:04     ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-24  0:04 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
>=20
> For e6500, two threads in one core share one time base. Just need
> to do time base sync on first thread of one core, and skip it on
> the other thread.
>=20
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
>  arch/powerpc/platforms/85xx/smp.c |   52 =20
> +++++++++++++++++++++++++++++++-----
>  1 files changed, 44 insertions(+), 8 deletions(-)
>=20
> diff --git a/arch/powerpc/platforms/85xx/smp.c =20
> b/arch/powerpc/platforms/85xx/smp.c
> index 74d8cde..5f3eee3 100644
> --- a/arch/powerpc/platforms/85xx/smp.c
> +++ b/arch/powerpc/platforms/85xx/smp.c
> @@ -26,6 +26,7 @@
>  #include <asm/cacheflush.h>
>  #include <asm/dbell.h>
>  #include <asm/fsl_guts.h>
> +#include <asm/cputhreads.h>
>=20
>  #include <sysdev/fsl_soc.h>
>  #include <sysdev/mpic.h>
> @@ -45,6 +46,7 @@ static u64 timebase;
>  static int tb_req;
>  static int tb_valid;
>  static u32 cur_booting_core;
> +static bool rcpmv2;
>=20
>  #ifdef CONFIG_PPC_E500MC
>  /* get a physical mask of online cores and booting core */
> @@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
>  	u32 mask;
>  	int cpu;
>=20
> -	mask =3D 1 << cur_booting_core;
> -	for_each_online_cpu(cpu)
> -		mask |=3D 1 << get_hard_smp_processor_id(cpu);
> +	if (smt_capable()) {
> +		/* two threads in one core share one time base */
> +		mask =3D 1 << cpu_core_index_of_thread(cur_booting_core);
> +		for_each_online_cpu(cpu)
> +			mask |=3D 1 << cpu_core_index_of_thread(
> +					get_hard_smp_processor_id(cpu));
> +	} else {
> +		mask =3D 1 << cur_booting_core;
> +		for_each_online_cpu(cpu)
> +			mask |=3D 1 << get_hard_smp_processor_id(cpu);
> +	}

Where is smt_capable defined()?  I assume somewhere in the patchset but =20
it's a pain to search 12 patches...

Is this really about whether we're SMT-capable or whether we have rcpm =20
v2?

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
  2013-04-23 23:46   ` Scott Wood
@ 2013-04-24 11:08     ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-24 11:08 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 06:46:10PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:34 AM, Zhao Chenhui wrote:
> >These cache operations support Freescale SoCs based on BOOK3E.
> >Move L1 cache operations to fsl_booke_cache.S in order to maintain
> >easily. And, add cache operations for backside L2 cache and
> >platform cache.
> >
> >The backside L2 cache appears on e500mc and e5500 core. The
> >platform cache
> >supported by this patch is L2 Look-Aside Cache, which appears on SoCs
> >with e500v1/e500v2 core, such as MPC8572, P1020, etc.
> >
> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >Signed-off-by: Li Yang <leoli@freescale.com>
> >---
> > arch/powerpc/include/asm/cacheflush.h |    8 ++
> > arch/powerpc/kernel/Makefile          |    1 +
> > arch/powerpc/kernel/fsl_booke_cache.S |  210
> >+++++++++++++++++++++++++++++++++
> > arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
> > 4 files changed, 219 insertions(+), 74 deletions(-)
> > create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S
> >
> >diff --git a/arch/powerpc/include/asm/cacheflush.h
> >b/arch/powerpc/include/asm/cacheflush.h
> >index b843e35..bc3f937 100644
> >--- a/arch/powerpc/include/asm/cacheflush.h
> >+++ b/arch/powerpc/include/asm/cacheflush.h
> >@@ -32,6 +32,14 @@ extern void flush_dcache_page(struct page *page);
> >
> > extern void __flush_disable_L1(void);
> >
> >+#ifdef CONFIG_FSL_SOC_BOOKE
> >+void flush_dcache_L1(void);
> >+void flush_backside_L2_cache(void);
> >+void disable_backside_L2_cache(void);
> >+void flush_disable_L2(void);
> >+void invalidate_enable_L2(void);
> >+#endif
> 
> Don't ifdef prototypes unless there's a good reason, such as
> providing an inline alternative.

I'll get rid of this "#ifdef".

> 
> Why do you have "flush_backside_L2_cache" and
> "disable_backside_L2_cache" as something different from
> "flush_disable_L2"?  The latter should flush whatever L2 is present.
> Don't treat pre-corenet as the default.
> 

These L2 caches are very different. The backside L2 is integrated in
the e500mc/e5500 core and controlled by SPR registers. But, the latter
L2 cache is on the SoC and controlled by registers mapped in CCSR.

> Why do we even need to distinguish L1 from L2 at all?  Shouldn't the
> function that gets exposed just be "flush and disable data caches
> that are specific to this cpu"?  What should happen on e6500?
> 
> -Scott

Yes. It is a good idea to use a set of uniform functions to operate the caches of
e500/e500mc/e5500/e6500 and SoCs. I'll think over your comments.

Thanks for you comments.

-Chenhui



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E
@ 2013-04-24 11:08     ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-24 11:08 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 06:46:10PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:34 AM, Zhao Chenhui wrote:
> >These cache operations support Freescale SoCs based on BOOK3E.
> >Move L1 cache operations to fsl_booke_cache.S in order to maintain
> >easily. And, add cache operations for backside L2 cache and
> >platform cache.
> >
> >The backside L2 cache appears on e500mc and e5500 core. The
> >platform cache
> >supported by this patch is L2 Look-Aside Cache, which appears on SoCs
> >with e500v1/e500v2 core, such as MPC8572, P1020, etc.
> >
> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >Signed-off-by: Li Yang <leoli@freescale.com>
> >---
> > arch/powerpc/include/asm/cacheflush.h |    8 ++
> > arch/powerpc/kernel/Makefile          |    1 +
> > arch/powerpc/kernel/fsl_booke_cache.S |  210
> >+++++++++++++++++++++++++++++++++
> > arch/powerpc/kernel/head_fsl_booke.S  |   74 ------------
> > 4 files changed, 219 insertions(+), 74 deletions(-)
> > create mode 100644 arch/powerpc/kernel/fsl_booke_cache.S
> >
> >diff --git a/arch/powerpc/include/asm/cacheflush.h
> >b/arch/powerpc/include/asm/cacheflush.h
> >index b843e35..bc3f937 100644
> >--- a/arch/powerpc/include/asm/cacheflush.h
> >+++ b/arch/powerpc/include/asm/cacheflush.h
> >@@ -32,6 +32,14 @@ extern void flush_dcache_page(struct page *page);
> >
> > extern void __flush_disable_L1(void);
> >
> >+#ifdef CONFIG_FSL_SOC_BOOKE
> >+void flush_dcache_L1(void);
> >+void flush_backside_L2_cache(void);
> >+void disable_backside_L2_cache(void);
> >+void flush_disable_L2(void);
> >+void invalidate_enable_L2(void);
> >+#endif
> 
> Don't ifdef prototypes unless there's a good reason, such as
> providing an inline alternative.

I'll get rid of this "#ifdef".

> 
> Why do you have "flush_backside_L2_cache" and
> "disable_backside_L2_cache" as something different from
> "flush_disable_L2"?  The latter should flush whatever L2 is present.
> Don't treat pre-corenet as the default.
> 

These L2 caches are very different. The backside L2 is integrated in
the e500mc/e5500 core and controlled by SPR registers. But, the latter
L2 cache is on the SoC and controlled by registers mapped in CCSR.

> Why do we even need to distinguish L1 from L2 at all?  Shouldn't the
> function that gets exposed just be "flush and disable data caches
> that are specific to this cpu"?  What should happen on e6500?
> 
> -Scott

Yes. It is a good idea to use a set of uniform functions to operate the caches of
e500/e500mc/e5500/e6500 and SoCs. I'll think over your comments.

Thanks for you comments.

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation
  2013-04-24  0:00     ` Scott Wood
@ 2013-04-24 11:14       ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-24 11:14 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 07:00:49PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:46 AM, Zhao Chenhui wrote:
> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >
> >The L1 Data Cache of e6500 contains no modified data, no flush
> >is required.
> >
> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >Signed-off-by: Li Yang <leoli@freescale.com>
> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >---
> > arch/powerpc/kernel/fsl_booke_cache.S |   11 ++++++++++-
> > 1 files changed, 10 insertions(+), 1 deletions(-)
> >
> >diff --git a/arch/powerpc/kernel/fsl_booke_cache.S
> >b/arch/powerpc/kernel/fsl_booke_cache.S
> >index 232c47b..24a52bb 100644
> >--- a/arch/powerpc/kernel/fsl_booke_cache.S
> >+++ b/arch/powerpc/kernel/fsl_booke_cache.S
> >@@ -65,13 +65,22 @@ _GLOBAL(flush_dcache_L1)
> >
> > 	blr
> >
> >+#define PVR_E6500	0x8040
> >+
> > /* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
> > _GLOBAL(__flush_disable_L1)
> >+/* L1 Data Cache of e6500 contains no modified data, no flush is
> >required */
> >+	mfspr	r3, SPRN_PVR
> >+	rlwinm	r4, r3, 16, 0xffff
> >+	lis	r5, 0
> >+	ori	r5, r5, PVR_E6500@l
> >+	cmpw	r4, r5
> >+	beq	2f
> > 	mflr	r10
> > 	bl	flush_dcache_L1	/* Flush L1 d-cache */
> > 	mtlr	r10
> >
> >-	msync
> >+2:	msync
> > 	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
> > 	li	r5, 2
> > 	rlwimi	r4, r5, 0, 3
> 
> Note that disabling the cache is a core operation, rather than a
> thread operation.  Is this only called when the second thread is
> disabled?
> 
> -Scott

It is called only when a core is down.
I can add a comment in the code.

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation
@ 2013-04-24 11:14       ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-24 11:14 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 07:00:49PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:46 AM, Zhao Chenhui wrote:
> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >
> >The L1 Data Cache of e6500 contains no modified data, no flush
> >is required.
> >
> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >Signed-off-by: Li Yang <leoli@freescale.com>
> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >---
> > arch/powerpc/kernel/fsl_booke_cache.S |   11 ++++++++++-
> > 1 files changed, 10 insertions(+), 1 deletions(-)
> >
> >diff --git a/arch/powerpc/kernel/fsl_booke_cache.S
> >b/arch/powerpc/kernel/fsl_booke_cache.S
> >index 232c47b..24a52bb 100644
> >--- a/arch/powerpc/kernel/fsl_booke_cache.S
> >+++ b/arch/powerpc/kernel/fsl_booke_cache.S
> >@@ -65,13 +65,22 @@ _GLOBAL(flush_dcache_L1)
> >
> > 	blr
> >
> >+#define PVR_E6500	0x8040
> >+
> > /* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
> > _GLOBAL(__flush_disable_L1)
> >+/* L1 Data Cache of e6500 contains no modified data, no flush is
> >required */
> >+	mfspr	r3, SPRN_PVR
> >+	rlwinm	r4, r3, 16, 0xffff
> >+	lis	r5, 0
> >+	ori	r5, r5, PVR_E6500@l
> >+	cmpw	r4, r5
> >+	beq	2f
> > 	mflr	r10
> > 	bl	flush_dcache_L1	/* Flush L1 d-cache */
> > 	mtlr	r10
> >
> >-	msync
> >+2:	msync
> > 	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
> > 	li	r5, 2
> > 	rlwimi	r4, r5, 0, 3
> 
> Note that disabling the cache is a core operation, rather than a
> thread operation.  Is this only called when the second thread is
> disabled?
> 
> -Scott

It is called only when a core is down.
I can add a comment in the code.

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-24  0:04     ` Scott Wood
@ 2013-04-24 11:29       ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-24 11:29 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >
> >For e6500, two threads in one core share one time base. Just need
> >to do time base sync on first thread of one core, and skip it on
> >the other thread.
> >
> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >Signed-off-by: Li Yang <leoli@freescale.com>
> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >---
> > arch/powerpc/platforms/85xx/smp.c |   52
> >+++++++++++++++++++++++++++++++-----
> > 1 files changed, 44 insertions(+), 8 deletions(-)
> >
> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> >b/arch/powerpc/platforms/85xx/smp.c
> >index 74d8cde..5f3eee3 100644
> >--- a/arch/powerpc/platforms/85xx/smp.c
> >+++ b/arch/powerpc/platforms/85xx/smp.c
> >@@ -26,6 +26,7 @@
> > #include <asm/cacheflush.h>
> > #include <asm/dbell.h>
> > #include <asm/fsl_guts.h>
> >+#include <asm/cputhreads.h>
> >
> > #include <sysdev/fsl_soc.h>
> > #include <sysdev/mpic.h>
> >@@ -45,6 +46,7 @@ static u64 timebase;
> > static int tb_req;
> > static int tb_valid;
> > static u32 cur_booting_core;
> >+static bool rcpmv2;
> >
> > #ifdef CONFIG_PPC_E500MC
> > /* get a physical mask of online cores and booting core */
> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> > 	u32 mask;
> > 	int cpu;
> >
> >-	mask = 1 << cur_booting_core;
> >-	for_each_online_cpu(cpu)
> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> >+	if (smt_capable()) {
> >+		/* two threads in one core share one time base */
> >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >+		for_each_online_cpu(cpu)
> >+			mask |= 1 << cpu_core_index_of_thread(
> >+					get_hard_smp_processor_id(cpu));
> >+	} else {
> >+		mask = 1 << cur_booting_core;
> >+		for_each_online_cpu(cpu)
> >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> >+	}
> 
> Where is smt_capable defined()?  I assume somewhere in the patchset
> but it's a pain to search 12 patches...
> 

It is defined in arch/powerpc/include/asm/topology.h.
	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))

Thanks for your review again.

> Is this really about whether we're SMT-capable or whether we have
> rcpm v2?
> 
> -Scott

I think this "if" statement can be removed. The cpu_core_index_of_thread()
can return the correct cpu number with thread or without thread.

Like this:
static inline u32 get_phy_cpu_mask(void)
{
	u32 mask;
	int cpu;

	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
	for_each_online_cpu(cpu)
		mask |= 1 << cpu_core_index_of_thread(
				get_hard_smp_processor_id(cpu));

	return mask;
}

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-24 11:29       ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-24 11:29 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >
> >For e6500, two threads in one core share one time base. Just need
> >to do time base sync on first thread of one core, and skip it on
> >the other thread.
> >
> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >Signed-off-by: Li Yang <leoli@freescale.com>
> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >---
> > arch/powerpc/platforms/85xx/smp.c |   52
> >+++++++++++++++++++++++++++++++-----
> > 1 files changed, 44 insertions(+), 8 deletions(-)
> >
> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> >b/arch/powerpc/platforms/85xx/smp.c
> >index 74d8cde..5f3eee3 100644
> >--- a/arch/powerpc/platforms/85xx/smp.c
> >+++ b/arch/powerpc/platforms/85xx/smp.c
> >@@ -26,6 +26,7 @@
> > #include <asm/cacheflush.h>
> > #include <asm/dbell.h>
> > #include <asm/fsl_guts.h>
> >+#include <asm/cputhreads.h>
> >
> > #include <sysdev/fsl_soc.h>
> > #include <sysdev/mpic.h>
> >@@ -45,6 +46,7 @@ static u64 timebase;
> > static int tb_req;
> > static int tb_valid;
> > static u32 cur_booting_core;
> >+static bool rcpmv2;
> >
> > #ifdef CONFIG_PPC_E500MC
> > /* get a physical mask of online cores and booting core */
> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> > 	u32 mask;
> > 	int cpu;
> >
> >-	mask = 1 << cur_booting_core;
> >-	for_each_online_cpu(cpu)
> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> >+	if (smt_capable()) {
> >+		/* two threads in one core share one time base */
> >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >+		for_each_online_cpu(cpu)
> >+			mask |= 1 << cpu_core_index_of_thread(
> >+					get_hard_smp_processor_id(cpu));
> >+	} else {
> >+		mask = 1 << cur_booting_core;
> >+		for_each_online_cpu(cpu)
> >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> >+	}
> 
> Where is smt_capable defined()?  I assume somewhere in the patchset
> but it's a pain to search 12 patches...
> 

It is defined in arch/powerpc/include/asm/topology.h.
	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))

Thanks for your review again.

> Is this really about whether we're SMT-capable or whether we have
> rcpm v2?
> 
> -Scott

I think this "if" statement can be removed. The cpu_core_index_of_thread()
can return the correct cpu number with thread or without thread.

Like this:
static inline u32 get_phy_cpu_mask(void)
{
	u32 mask;
	int cpu;

	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
	for_each_online_cpu(cpu)
		mask |= 1 << cpu_core_index_of_thread(
				get_hard_smp_processor_id(cpu));

	return mask;
}

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-24 11:29       ` Zhao Chenhui
@ 2013-04-24 22:38         ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-24 22:38 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel, r58472

On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> > On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> > >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> > >
> > >For e6500, two threads in one core share one time base. Just need
> > >to do time base sync on first thread of one core, and skip it on
> > >the other thread.
> > >
> > >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> > >Signed-off-by: Li Yang <leoli@freescale.com>
> > >Signed-off-by: Andy Fleming <afleming@freescale.com>
> > >---
> > > arch/powerpc/platforms/85xx/smp.c |   52
> > >+++++++++++++++++++++++++++++++-----
> > > 1 files changed, 44 insertions(+), 8 deletions(-)
> > >
> > >diff --git a/arch/powerpc/platforms/85xx/smp.c
> > >b/arch/powerpc/platforms/85xx/smp.c
> > >index 74d8cde..5f3eee3 100644
> > >--- a/arch/powerpc/platforms/85xx/smp.c
> > >+++ b/arch/powerpc/platforms/85xx/smp.c
> > >@@ -26,6 +26,7 @@
> > > #include <asm/cacheflush.h>
> > > #include <asm/dbell.h>
> > > #include <asm/fsl_guts.h>
> > >+#include <asm/cputhreads.h>
> > >
> > > #include <sysdev/fsl_soc.h>
> > > #include <sysdev/mpic.h>
> > >@@ -45,6 +46,7 @@ static u64 timebase;
> > > static int tb_req;
> > > static int tb_valid;
> > > static u32 cur_booting_core;
> > >+static bool rcpmv2;
> > >
> > > #ifdef CONFIG_PPC_E500MC
> > > /* get a physical mask of online cores and booting core */
> > >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> > > 	u32 mask;
> > > 	int cpu;
> > >
> > >-	mask = 1 << cur_booting_core;
> > >-	for_each_online_cpu(cpu)
> > >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> > >+	if (smt_capable()) {
> > >+		/* two threads in one core share one time base */
> > >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> > >+		for_each_online_cpu(cpu)
> > >+			mask |= 1 << cpu_core_index_of_thread(
> > >+					get_hard_smp_processor_id(cpu));
> > >+	} else {
> > >+		mask = 1 << cur_booting_core;
> > >+		for_each_online_cpu(cpu)
> > >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> > >+	}
> >
> > Where is smt_capable defined()?  I assume somewhere in the patchset
> > but it's a pain to search 12 patches...
> >
> 
> It is defined in arch/powerpc/include/asm/topology.h.
> 	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> 
> Thanks for your review again.

We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't claim  
that feature yet, except in our SDK kernel.  That doesn't change the  
topology of CPU numbering.

> > Is this really about whether we're SMT-capable or whether we have
> > rcpm v2?
> >
> > -Scott
> 
> I think this "if" statement can be removed. The  
> cpu_core_index_of_thread()
> can return the correct cpu number with thread or without thread.
> 
> Like this:
> static inline u32 get_phy_cpu_mask(void)
> {
> 	u32 mask;
> 	int cpu;
> 
> 	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> 	for_each_online_cpu(cpu)
> 		mask |= 1 << cpu_core_index_of_thread(
> 				get_hard_smp_processor_id(cpu));
> 
> 	return mask;
> }

Likewise, this will get it wrong if SMT is disabled or not yet  
implemented on a core.

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-24 22:38         ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-24 22:38 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel, r58472

On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> > On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> > >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> > >
> > >For e6500, two threads in one core share one time base. Just need
> > >to do time base sync on first thread of one core, and skip it on
> > >the other thread.
> > >
> > >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> > >Signed-off-by: Li Yang <leoli@freescale.com>
> > >Signed-off-by: Andy Fleming <afleming@freescale.com>
> > >---
> > > arch/powerpc/platforms/85xx/smp.c |   52
> > >+++++++++++++++++++++++++++++++-----
> > > 1 files changed, 44 insertions(+), 8 deletions(-)
> > >
> > >diff --git a/arch/powerpc/platforms/85xx/smp.c
> > >b/arch/powerpc/platforms/85xx/smp.c
> > >index 74d8cde..5f3eee3 100644
> > >--- a/arch/powerpc/platforms/85xx/smp.c
> > >+++ b/arch/powerpc/platforms/85xx/smp.c
> > >@@ -26,6 +26,7 @@
> > > #include <asm/cacheflush.h>
> > > #include <asm/dbell.h>
> > > #include <asm/fsl_guts.h>
> > >+#include <asm/cputhreads.h>
> > >
> > > #include <sysdev/fsl_soc.h>
> > > #include <sysdev/mpic.h>
> > >@@ -45,6 +46,7 @@ static u64 timebase;
> > > static int tb_req;
> > > static int tb_valid;
> > > static u32 cur_booting_core;
> > >+static bool rcpmv2;
> > >
> > > #ifdef CONFIG_PPC_E500MC
> > > /* get a physical mask of online cores and booting core */
> > >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> > > 	u32 mask;
> > > 	int cpu;
> > >
> > >-	mask =3D 1 << cur_booting_core;
> > >-	for_each_online_cpu(cpu)
> > >-		mask |=3D 1 << get_hard_smp_processor_id(cpu);
> > >+	if (smt_capable()) {
> > >+		/* two threads in one core share one time base */
> > >+		mask =3D 1 << cpu_core_index_of_thread(cur_booting_core);
> > >+		for_each_online_cpu(cpu)
> > >+			mask |=3D 1 << cpu_core_index_of_thread(
> > >+					get_hard_smp_processor_id(cpu));
> > >+	} else {
> > >+		mask =3D 1 << cur_booting_core;
> > >+		for_each_online_cpu(cpu)
> > >+			mask |=3D 1 << get_hard_smp_processor_id(cpu);
> > >+	}
> >
> > Where is smt_capable defined()?  I assume somewhere in the patchset
> > but it's a pain to search 12 patches...
> >
>=20
> It is defined in arch/powerpc/include/asm/topology.h.
> 	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
>=20
> Thanks for your review again.

We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't claim =20
that feature yet, except in our SDK kernel.  That doesn't change the =20
topology of CPU numbering.

> > Is this really about whether we're SMT-capable or whether we have
> > rcpm v2?
> >
> > -Scott
>=20
> I think this "if" statement can be removed. The =20
> cpu_core_index_of_thread()
> can return the correct cpu number with thread or without thread.
>=20
> Like this:
> static inline u32 get_phy_cpu_mask(void)
> {
> 	u32 mask;
> 	int cpu;
>=20
> 	mask =3D 1 << cpu_core_index_of_thread(cur_booting_core);
> 	for_each_online_cpu(cpu)
> 		mask |=3D 1 << cpu_core_index_of_thread(
> 				get_hard_smp_processor_id(cpu));
>=20
> 	return mask;
> }

Likewise, this will get it wrong if SMT is disabled or not yet =20
implemented on a core.

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-24 22:38         ` Scott Wood
@ 2013-04-25  0:28           ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-25  0:28 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> >On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> >> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> >> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >> >
> >> >For e6500, two threads in one core share one time base. Just need
> >> >to do time base sync on first thread of one core, and skip it on
> >> >the other thread.
> >> >
> >> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >> >Signed-off-by: Li Yang <leoli@freescale.com>
> >> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >> >---
> >> > arch/powerpc/platforms/85xx/smp.c |   52
> >> >+++++++++++++++++++++++++++++++-----
> >> > 1 files changed, 44 insertions(+), 8 deletions(-)
> >> >
> >> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> >> >b/arch/powerpc/platforms/85xx/smp.c
> >> >index 74d8cde..5f3eee3 100644
> >> >--- a/arch/powerpc/platforms/85xx/smp.c
> >> >+++ b/arch/powerpc/platforms/85xx/smp.c
> >> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> >> > 	u32 mask;
> >> > 	int cpu;
> >> >
> >> >-	mask = 1 << cur_booting_core;
> >> >-	for_each_online_cpu(cpu)
> >> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >+	if (smt_capable()) {
> >> >+		/* two threads in one core share one time base */
> >> >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >> >+		for_each_online_cpu(cpu)
> >> >+			mask |= 1 << cpu_core_index_of_thread(
> >> >+					get_hard_smp_processor_id(cpu));
> >> >+	} else {
> >> >+		mask = 1 << cur_booting_core;
> >> >+		for_each_online_cpu(cpu)
> >> >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >+	}
> >>
> >> Where is smt_capable defined()?  I assume somewhere in the patchset
> >> but it's a pain to search 12 patches...
> >>
> >
> >It is defined in arch/powerpc/include/asm/topology.h.
> >	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> >
> >Thanks for your review again.
> 
> We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> claim that feature yet, except in our SDK kernel.  That doesn't
> change the topology of CPU numbering.
> 

Then, where can I get the thread information? dts?
Or, wait for upstream of the thread suppport of e6500.

> >> Is this really about whether we're SMT-capable or whether we have
> >> rcpm v2?
> >>
> >> -Scott
> >
> >I think this "if" statement can be removed. The
> >cpu_core_index_of_thread()
> >can return the correct cpu number with thread or without thread.
> >
> >Like this:
> >static inline u32 get_phy_cpu_mask(void)
> >{
> >	u32 mask;
> >	int cpu;
> >
> >	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >	for_each_online_cpu(cpu)
> >		mask |= 1 << cpu_core_index_of_thread(
> >				get_hard_smp_processor_id(cpu));
> >
> >	return mask;
> >}
> 
> Likewise, this will get it wrong if SMT is disabled or not yet
> implemented on a core.
> 
> -Scott

Let's look into cpu_core_index_of_thread() in arch/powerpc/kernel/smp.c.

  int cpu_core_index_of_thread(int cpu)                                          
  {                                                                              
      return cpu >> threads_shift;
  }

If no thread, the threads_shift is equal to 0. It can work with no
thread.

Perhaps, I should submit this patch after the thread patches for e6500.

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-25  0:28           ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-25  0:28 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> >On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> >> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> >> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >> >
> >> >For e6500, two threads in one core share one time base. Just need
> >> >to do time base sync on first thread of one core, and skip it on
> >> >the other thread.
> >> >
> >> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >> >Signed-off-by: Li Yang <leoli@freescale.com>
> >> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >> >---
> >> > arch/powerpc/platforms/85xx/smp.c |   52
> >> >+++++++++++++++++++++++++++++++-----
> >> > 1 files changed, 44 insertions(+), 8 deletions(-)
> >> >
> >> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> >> >b/arch/powerpc/platforms/85xx/smp.c
> >> >index 74d8cde..5f3eee3 100644
> >> >--- a/arch/powerpc/platforms/85xx/smp.c
> >> >+++ b/arch/powerpc/platforms/85xx/smp.c
> >> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> >> > 	u32 mask;
> >> > 	int cpu;
> >> >
> >> >-	mask = 1 << cur_booting_core;
> >> >-	for_each_online_cpu(cpu)
> >> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >+	if (smt_capable()) {
> >> >+		/* two threads in one core share one time base */
> >> >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >> >+		for_each_online_cpu(cpu)
> >> >+			mask |= 1 << cpu_core_index_of_thread(
> >> >+					get_hard_smp_processor_id(cpu));
> >> >+	} else {
> >> >+		mask = 1 << cur_booting_core;
> >> >+		for_each_online_cpu(cpu)
> >> >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >+	}
> >>
> >> Where is smt_capable defined()?  I assume somewhere in the patchset
> >> but it's a pain to search 12 patches...
> >>
> >
> >It is defined in arch/powerpc/include/asm/topology.h.
> >	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> >
> >Thanks for your review again.
> 
> We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> claim that feature yet, except in our SDK kernel.  That doesn't
> change the topology of CPU numbering.
> 

Then, where can I get the thread information? dts?
Or, wait for upstream of the thread suppport of e6500.

> >> Is this really about whether we're SMT-capable or whether we have
> >> rcpm v2?
> >>
> >> -Scott
> >
> >I think this "if" statement can be removed. The
> >cpu_core_index_of_thread()
> >can return the correct cpu number with thread or without thread.
> >
> >Like this:
> >static inline u32 get_phy_cpu_mask(void)
> >{
> >	u32 mask;
> >	int cpu;
> >
> >	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >	for_each_online_cpu(cpu)
> >		mask |= 1 << cpu_core_index_of_thread(
> >				get_hard_smp_processor_id(cpu));
> >
> >	return mask;
> >}
> 
> Likewise, this will get it wrong if SMT is disabled or not yet
> implemented on a core.
> 
> -Scott

Let's look into cpu_core_index_of_thread() in arch/powerpc/kernel/smp.c.

  int cpu_core_index_of_thread(int cpu)                                          
  {                                                                              
      return cpu >> threads_shift;
  }

If no thread, the threads_shift is equal to 0. It can work with no
thread.

Perhaps, I should submit this patch after the thread patches for e6500.

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-25  0:28           ` Zhao Chenhui
@ 2013-04-26  0:07             ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-26  0:07 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel, r58472

On 04/24/2013 07:28:18 PM, Zhao Chenhui wrote:
> On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> > On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> > >On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> > >> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> > >> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> > >> >
> > >> >For e6500, two threads in one core share one time base. Just  
> need
> > >> >to do time base sync on first thread of one core, and skip it on
> > >> >the other thread.
> > >> >
> > >> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> > >> >Signed-off-by: Li Yang <leoli@freescale.com>
> > >> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> > >> >---
> > >> > arch/powerpc/platforms/85xx/smp.c |   52
> > >> >+++++++++++++++++++++++++++++++-----
> > >> > 1 files changed, 44 insertions(+), 8 deletions(-)
> > >> >
> > >> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> > >> >b/arch/powerpc/platforms/85xx/smp.c
> > >> >index 74d8cde..5f3eee3 100644
> > >> >--- a/arch/powerpc/platforms/85xx/smp.c
> > >> >+++ b/arch/powerpc/platforms/85xx/smp.c
> > >> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> > >> > 	u32 mask;
> > >> > 	int cpu;
> > >> >
> > >> >-	mask = 1 << cur_booting_core;
> > >> >-	for_each_online_cpu(cpu)
> > >> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> > >> >+	if (smt_capable()) {
> > >> >+		/* two threads in one core share one time base  
> */
> > >> >+		mask = 1 <<  
> cpu_core_index_of_thread(cur_booting_core);
> > >> >+		for_each_online_cpu(cpu)
> > >> >+			mask |= 1 << cpu_core_index_of_thread(
> > >> >+					 
> get_hard_smp_processor_id(cpu));
> > >> >+	} else {
> > >> >+		mask = 1 << cur_booting_core;
> > >> >+		for_each_online_cpu(cpu)
> > >> >+			mask |= 1 <<  
> get_hard_smp_processor_id(cpu);
> > >> >+	}
> > >>
> > >> Where is smt_capable defined()?  I assume somewhere in the  
> patchset
> > >> but it's a pain to search 12 patches...
> > >>
> > >
> > >It is defined in arch/powerpc/include/asm/topology.h.
> > >	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> > >
> > >Thanks for your review again.
> >
> > We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> > claim that feature yet, except in our SDK kernel.  That doesn't
> > change the topology of CPU numbering.
> >
> 
> Then, where can I get the thread information? dts?
> Or, wait for upstream of the thread suppport of e6500.

It's an inherent property of e6500 (outside of some virtualization  
scenarios, but you wouldn't run this code under a hypervisor) that you  
have two threads per core (whether Linux uses them or not).  Or you  
could read TMCFG0[NTHRD] if you know you're on a chip that has TMRs but  
aren't positive it's an e6500, but I wouldn't bother.  If we do ever  
have such a chip, there are probably other things that will need  
updating.

> > >static inline u32 get_phy_cpu_mask(void)
> > >{
> > >	u32 mask;
> > >	int cpu;
> > >
> > >	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> > >	for_each_online_cpu(cpu)
> > >		mask |= 1 << cpu_core_index_of_thread(
> > >				get_hard_smp_processor_id(cpu));
> > >
> > >	return mask;
> > >}
> >
> > Likewise, this will get it wrong if SMT is disabled or not yet
> > implemented on a core.
> >
> > -Scott
> 
> Let's look into cpu_core_index_of_thread() in  
> arch/powerpc/kernel/smp.c.
> 
>   int cpu_core_index_of_thread(int cpu)
>   {
>       return cpu >> threads_shift;
>   }
> 
> If no thread, the threads_shift is equal to 0. It can work with no
> thread.

My point is that if threads are disabled, threads_shift will be 0, but  
e6500 cores will still be numbered 0, 2, 4, etc.

> Perhaps, I should submit this patch after the thread patches for  
> e6500.

Why?

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-26  0:07             ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-26  0:07 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel, r58472

On 04/24/2013 07:28:18 PM, Zhao Chenhui wrote:
> On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> > On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> > >On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> > >> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> > >> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> > >> >
> > >> >For e6500, two threads in one core share one time base. Just =20
> need
> > >> >to do time base sync on first thread of one core, and skip it on
> > >> >the other thread.
> > >> >
> > >> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> > >> >Signed-off-by: Li Yang <leoli@freescale.com>
> > >> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> > >> >---
> > >> > arch/powerpc/platforms/85xx/smp.c |   52
> > >> >+++++++++++++++++++++++++++++++-----
> > >> > 1 files changed, 44 insertions(+), 8 deletions(-)
> > >> >
> > >> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> > >> >b/arch/powerpc/platforms/85xx/smp.c
> > >> >index 74d8cde..5f3eee3 100644
> > >> >--- a/arch/powerpc/platforms/85xx/smp.c
> > >> >+++ b/arch/powerpc/platforms/85xx/smp.c
> > >> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> > >> > 	u32 mask;
> > >> > 	int cpu;
> > >> >
> > >> >-	mask =3D 1 << cur_booting_core;
> > >> >-	for_each_online_cpu(cpu)
> > >> >-		mask |=3D 1 << get_hard_smp_processor_id(cpu);
> > >> >+	if (smt_capable()) {
> > >> >+		/* two threads in one core share one time base =20
> */
> > >> >+		mask =3D 1 << =20
> cpu_core_index_of_thread(cur_booting_core);
> > >> >+		for_each_online_cpu(cpu)
> > >> >+			mask |=3D 1 << cpu_core_index_of_thread(
> > >> >+					=20
> get_hard_smp_processor_id(cpu));
> > >> >+	} else {
> > >> >+		mask =3D 1 << cur_booting_core;
> > >> >+		for_each_online_cpu(cpu)
> > >> >+			mask |=3D 1 << =20
> get_hard_smp_processor_id(cpu);
> > >> >+	}
> > >>
> > >> Where is smt_capable defined()?  I assume somewhere in the =20
> patchset
> > >> but it's a pain to search 12 patches...
> > >>
> > >
> > >It is defined in arch/powerpc/include/asm/topology.h.
> > >	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> > >
> > >Thanks for your review again.
> >
> > We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> > claim that feature yet, except in our SDK kernel.  That doesn't
> > change the topology of CPU numbering.
> >
>=20
> Then, where can I get the thread information? dts?
> Or, wait for upstream of the thread suppport of e6500.

It's an inherent property of e6500 (outside of some virtualization =20
scenarios, but you wouldn't run this code under a hypervisor) that you =20
have two threads per core (whether Linux uses them or not).  Or you =20
could read TMCFG0[NTHRD] if you know you're on a chip that has TMRs but =20
aren't positive it's an e6500, but I wouldn't bother.  If we do ever =20
have such a chip, there are probably other things that will need =20
updating.

> > >static inline u32 get_phy_cpu_mask(void)
> > >{
> > >	u32 mask;
> > >	int cpu;
> > >
> > >	mask =3D 1 << cpu_core_index_of_thread(cur_booting_core);
> > >	for_each_online_cpu(cpu)
> > >		mask |=3D 1 << cpu_core_index_of_thread(
> > >				get_hard_smp_processor_id(cpu));
> > >
> > >	return mask;
> > >}
> >
> > Likewise, this will get it wrong if SMT is disabled or not yet
> > implemented on a core.
> >
> > -Scott
>=20
> Let's look into cpu_core_index_of_thread() in =20
> arch/powerpc/kernel/smp.c.
>=20
>   int cpu_core_index_of_thread(int cpu)
>   {
>       return cpu >> threads_shift;
>   }
>=20
> If no thread, the threads_shift is equal to 0. It can work with no
> thread.

My point is that if threads are disabled, threads_shift will be 0, but =20
e6500 cores will still be numbered 0, 2, 4, etc.

> Perhaps, I should submit this patch after the thread patches for =20
> e6500.

Why?

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-26  0:07             ` Scott Wood
@ 2013-04-28  9:56               ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-28  9:56 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Thu, Apr 25, 2013 at 07:07:24PM -0500, Scott Wood wrote:
> On 04/24/2013 07:28:18 PM, Zhao Chenhui wrote:
> >On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> >> On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> >> >On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> >> >> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> >> >> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >> >> >
> >> >> >For e6500, two threads in one core share one time base. Just
> >need
> >> >> >to do time base sync on first thread of one core, and skip it on
> >> >> >the other thread.
> >> >> >
> >> >> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >> >> >Signed-off-by: Li Yang <leoli@freescale.com>
> >> >> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >> >> >---
> >> >> > arch/powerpc/platforms/85xx/smp.c |   52
> >> >> >+++++++++++++++++++++++++++++++-----
> >> >> > 1 files changed, 44 insertions(+), 8 deletions(-)
> >> >> >
> >> >> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> >> >> >b/arch/powerpc/platforms/85xx/smp.c
> >> >> >index 74d8cde..5f3eee3 100644
> >> >> >--- a/arch/powerpc/platforms/85xx/smp.c
> >> >> >+++ b/arch/powerpc/platforms/85xx/smp.c
> >> >> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> >> >> > 	u32 mask;
> >> >> > 	int cpu;
> >> >> >
> >> >> >-	mask = 1 << cur_booting_core;
> >> >> >-	for_each_online_cpu(cpu)
> >> >> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >> >+	if (smt_capable()) {
> >> >> >+		/* two threads in one core share one time base */
> >> >> >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >> >> >+		for_each_online_cpu(cpu)
> >> >> >+			mask |= 1 << cpu_core_index_of_thread(
> >> >> >+					get_hard_smp_processor_id(cpu));
> >> >> >+	} else {
> >> >> >+		mask = 1 << cur_booting_core;
> >> >> >+		for_each_online_cpu(cpu)
> >> >> >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >> >+	}
> >> >>
> >> >> Where is smt_capable defined()?  I assume somewhere in the
> >patchset
> >> >> but it's a pain to search 12 patches...
> >> >>
> >> >
> >> >It is defined in arch/powerpc/include/asm/topology.h.
> >> >	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> >> >
> >> >Thanks for your review again.
> >>
> >> We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> >> claim that feature yet, except in our SDK kernel.  That doesn't
> >> change the topology of CPU numbering.
> >>
> >
> >Then, where can I get the thread information? dts?
> >Or, wait for upstream of the thread suppport of e6500.
> 
> It's an inherent property of e6500 (outside of some virtualization
> scenarios, but you wouldn't run this code under a hypervisor) that
> you have two threads per core (whether Linux uses them or not).  Or
> you could read TMCFG0[NTHRD] if you know you're on a chip that has
> TMRs but aren't positive it's an e6500, but I wouldn't bother.  If
> we do ever have such a chip, there are probably other things that
> will need updating.
> 

But how to know that there are TMRs on a chip except by CPU_FTR_SMT.

> >> >static inline u32 get_phy_cpu_mask(void)
> >> >{
> >> >	u32 mask;
> >> >	int cpu;
> >> >
> >> >	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >> >	for_each_online_cpu(cpu)
> >> >		mask |= 1 << cpu_core_index_of_thread(
> >> >				get_hard_smp_processor_id(cpu));
> >> >
> >> >	return mask;
> >> >}
> >>
> >> Likewise, this will get it wrong if SMT is disabled or not yet
> >> implemented on a core.
> >>
> >> -Scott
> >
> >Let's look into cpu_core_index_of_thread() in
> >arch/powerpc/kernel/smp.c.
> >
> >  int cpu_core_index_of_thread(int cpu)
> >  {
> >      return cpu >> threads_shift;
> >  }
> >
> >If no thread, the threads_shift is equal to 0. It can work with no
> >thread.
> 
> My point is that if threads are disabled, threads_shift will be 0,
> but e6500 cores will still be numbered 0, 2, 4, etc.
> 
> >Perhaps, I should submit this patch after the thread patches for
> >e6500.
> 
> Why?
> 
> -Scott

Even if threads are disabled, the threads_shift derived from dts is right.
But, if there aren't the thread related patches existed in SDK, the threads_shift
gets a wrong value on T4.

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-28  9:56               ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-28  9:56 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Thu, Apr 25, 2013 at 07:07:24PM -0500, Scott Wood wrote:
> On 04/24/2013 07:28:18 PM, Zhao Chenhui wrote:
> >On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> >> On 04/24/2013 06:29:29 AM, Zhao Chenhui wrote:
> >> >On Tue, Apr 23, 2013 at 07:04:06PM -0500, Scott Wood wrote:
> >> >> On 04/19/2013 05:47:45 AM, Zhao Chenhui wrote:
> >> >> >From: Chen-Hui Zhao <chenhui.zhao@freescale.com>
> >> >> >
> >> >> >For e6500, two threads in one core share one time base. Just
> >need
> >> >> >to do time base sync on first thread of one core, and skip it on
> >> >> >the other thread.
> >> >> >
> >> >> >Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> >> >> >Signed-off-by: Li Yang <leoli@freescale.com>
> >> >> >Signed-off-by: Andy Fleming <afleming@freescale.com>
> >> >> >---
> >> >> > arch/powerpc/platforms/85xx/smp.c |   52
> >> >> >+++++++++++++++++++++++++++++++-----
> >> >> > 1 files changed, 44 insertions(+), 8 deletions(-)
> >> >> >
> >> >> >diff --git a/arch/powerpc/platforms/85xx/smp.c
> >> >> >b/arch/powerpc/platforms/85xx/smp.c
> >> >> >index 74d8cde..5f3eee3 100644
> >> >> >--- a/arch/powerpc/platforms/85xx/smp.c
> >> >> >+++ b/arch/powerpc/platforms/85xx/smp.c
> >> >> >@@ -53,26 +55,40 @@ static inline u32 get_phy_cpu_mask(void)
> >> >> > 	u32 mask;
> >> >> > 	int cpu;
> >> >> >
> >> >> >-	mask = 1 << cur_booting_core;
> >> >> >-	for_each_online_cpu(cpu)
> >> >> >-		mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >> >+	if (smt_capable()) {
> >> >> >+		/* two threads in one core share one time base */
> >> >> >+		mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >> >> >+		for_each_online_cpu(cpu)
> >> >> >+			mask |= 1 << cpu_core_index_of_thread(
> >> >> >+					get_hard_smp_processor_id(cpu));
> >> >> >+	} else {
> >> >> >+		mask = 1 << cur_booting_core;
> >> >> >+		for_each_online_cpu(cpu)
> >> >> >+			mask |= 1 << get_hard_smp_processor_id(cpu);
> >> >> >+	}
> >> >>
> >> >> Where is smt_capable defined()?  I assume somewhere in the
> >patchset
> >> >> but it's a pain to search 12 patches...
> >> >>
> >> >
> >> >It is defined in arch/powerpc/include/asm/topology.h.
> >> >	#define smt_capable()           (cpu_has_feature(CPU_FTR_SMT))
> >> >
> >> >Thanks for your review again.
> >>
> >> We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> >> claim that feature yet, except in our SDK kernel.  That doesn't
> >> change the topology of CPU numbering.
> >>
> >
> >Then, where can I get the thread information? dts?
> >Or, wait for upstream of the thread suppport of e6500.
> 
> It's an inherent property of e6500 (outside of some virtualization
> scenarios, but you wouldn't run this code under a hypervisor) that
> you have two threads per core (whether Linux uses them or not).  Or
> you could read TMCFG0[NTHRD] if you know you're on a chip that has
> TMRs but aren't positive it's an e6500, but I wouldn't bother.  If
> we do ever have such a chip, there are probably other things that
> will need updating.
> 

But how to know that there are TMRs on a chip except by CPU_FTR_SMT.

> >> >static inline u32 get_phy_cpu_mask(void)
> >> >{
> >> >	u32 mask;
> >> >	int cpu;
> >> >
> >> >	mask = 1 << cpu_core_index_of_thread(cur_booting_core);
> >> >	for_each_online_cpu(cpu)
> >> >		mask |= 1 << cpu_core_index_of_thread(
> >> >				get_hard_smp_processor_id(cpu));
> >> >
> >> >	return mask;
> >> >}
> >>
> >> Likewise, this will get it wrong if SMT is disabled or not yet
> >> implemented on a core.
> >>
> >> -Scott
> >
> >Let's look into cpu_core_index_of_thread() in
> >arch/powerpc/kernel/smp.c.
> >
> >  int cpu_core_index_of_thread(int cpu)
> >  {
> >      return cpu >> threads_shift;
> >  }
> >
> >If no thread, the threads_shift is equal to 0. It can work with no
> >thread.
> 
> My point is that if threads are disabled, threads_shift will be 0,
> but e6500 cores will still be numbered 0, 2, 4, etc.
> 
> >Perhaps, I should submit this patch after the thread patches for
> >e6500.
> 
> Why?
> 
> -Scott

Even if threads are disabled, the threads_shift derived from dts is right.
But, if there aren't the thread related patches existed in SDK, the threads_shift
gets a wrong value on T4.

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support
  2013-04-23 23:53     ` Scott Wood
@ 2013-04-28 10:20       ` Zhao Chenhui
  -1 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-28 10:20 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 06:53:20PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:35 AM, Zhao Chenhui wrote:
> > static int pmc_suspend_enter(suspend_state_t state)
> > {
> >-	int ret;
> >+	int ret = 0;
> >+
> >+	switch (state) {
> >+#ifdef CONFIG_PPC_85xx
> >+	case PM_SUSPEND_MEM:
> >+#ifdef CONFIG_SPE
> >+		enable_kernel_spe();
> >+#endif
> >+		enable_kernel_fp();
> 
> Why does enable_kernel_spe() need an ifdef but enable_kernel_fp()
> doesn't?
> 

will enclose it with CONFIG_PPC_FPU.

> >+	case PM_SUSPEND_STANDBY:
> >+#ifdef CONFIG_FSL_SOC_BOOKE
> >+		flush_dcache_L1();
> >+#endif
> >+		setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);
> 
> Only L1, even on e500mc?
> 
> -Scott

This patch is just for chips with pmc unit. They have no e500mc core.

-Chenhui


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support
@ 2013-04-28 10:20       ` Zhao Chenhui
  0 siblings, 0 replies; 66+ messages in thread
From: Zhao Chenhui @ 2013-04-28 10:20 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, linux-kernel, r58472

On Tue, Apr 23, 2013 at 06:53:20PM -0500, Scott Wood wrote:
> On 04/19/2013 05:47:35 AM, Zhao Chenhui wrote:
> > static int pmc_suspend_enter(suspend_state_t state)
> > {
> >-	int ret;
> >+	int ret = 0;
> >+
> >+	switch (state) {
> >+#ifdef CONFIG_PPC_85xx
> >+	case PM_SUSPEND_MEM:
> >+#ifdef CONFIG_SPE
> >+		enable_kernel_spe();
> >+#endif
> >+		enable_kernel_fp();
> 
> Why does enable_kernel_spe() need an ifdef but enable_kernel_fp()
> doesn't?
> 

will enclose it with CONFIG_PPC_FPU.

> >+	case PM_SUSPEND_STANDBY:
> >+#ifdef CONFIG_FSL_SOC_BOOKE
> >+		flush_dcache_L1();
> >+#endif
> >+		setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);
> 
> Only L1, even on e500mc?
> 
> -Scott

This patch is just for chips with pmc unit. They have no e500mc core.

-Chenhui

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
  2013-04-28  9:56               ` Zhao Chenhui
@ 2013-04-29 20:18                 ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-29 20:18 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel, r58472

On 04/28/2013 04:56:34 AM, Zhao Chenhui wrote:
> On Thu, Apr 25, 2013 at 07:07:24PM -0500, Scott Wood wrote:
> > On 04/24/2013 07:28:18 PM, Zhao Chenhui wrote:
> > >On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> > >> We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> > >> claim that feature yet, except in our SDK kernel.  That doesn't
> > >> change the topology of CPU numbering.
> > >>
> > >
> > >Then, where can I get the thread information? dts?
> > >Or, wait for upstream of the thread suppport of e6500.
> >
> > It's an inherent property of e6500 (outside of some virtualization
> > scenarios, but you wouldn't run this code under a hypervisor) that
> > you have two threads per core (whether Linux uses them or not).  Or
> > you could read TMCFG0[NTHRD] if you know you're on a chip that has
> > TMRs but aren't positive it's an e6500, but I wouldn't bother.  If
> > we do ever have such a chip, there are probably other things that
> > will need updating.
> >
> 
> But how to know that there are TMRs on a chip except by CPU_FTR_SMT.

I don't know.  I said I wouldn't bother. :-)

Just assume there are 2 threads per core on e6500.  Then you won't have  
a dependency on the threading patches, and you won't break if  
CPU_FTR_SMT gets disabled for some other reason, or if the threads are  
missing from the device tree for some reason (I've seen some people  
remove them manually in an attempt to disable threading -- I tell them  
not to when I see it, but eventually others will do it again).

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500
@ 2013-04-29 20:18                 ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-04-29 20:18 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel, r58472

On 04/28/2013 04:56:34 AM, Zhao Chenhui wrote:
> On Thu, Apr 25, 2013 at 07:07:24PM -0500, Scott Wood wrote:
> > On 04/24/2013 07:28:18 PM, Zhao Chenhui wrote:
> > >On Wed, Apr 24, 2013 at 05:38:16PM -0500, Scott Wood wrote:
> > >> We shouldn't base it on CPU_FTR_SMT.  For example, e6500 doesn't
> > >> claim that feature yet, except in our SDK kernel.  That doesn't
> > >> change the topology of CPU numbering.
> > >>
> > >
> > >Then, where can I get the thread information? dts?
> > >Or, wait for upstream of the thread suppport of e6500.
> >
> > It's an inherent property of e6500 (outside of some virtualization
> > scenarios, but you wouldn't run this code under a hypervisor) that
> > you have two threads per core (whether Linux uses them or not).  Or
> > you could read TMCFG0[NTHRD] if you know you're on a chip that has
> > TMRs but aren't positive it's an e6500, but I wouldn't bother.  If
> > we do ever have such a chip, there are probably other things that
> > will need updating.
> >
>=20
> But how to know that there are TMRs on a chip except by CPU_FTR_SMT.

I don't know.  I said I wouldn't bother. :-)

Just assume there are 2 threads per core on e6500.  Then you won't have =20
a dependency on the threading patches, and you won't break if =20
CPU_FTR_SMT gets disabled for some other reason, or if the threads are =20
missing from the device tree for some reason (I've seen some people =20
remove them manually in an attempt to disable threading -- I tell them =20
not to when I see it, but eventually others will do it again).

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 05/15] fsl_pmc: update device bindings
  2013-04-19 10:47   ` Zhao Chenhui
@ 2013-06-03 22:43     ` Scott Wood
  -1 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-06-03 22:43 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:38 AM, Zhao Chenhui wrote:
> From: Li Yang <leoli@freescale.com>
> 
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> ---
>  .../devicetree/bindings/powerpc/fsl/pmc.txt        |   59  
> +++++++++++--------
>  1 files changed, 34 insertions(+), 25 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt  
> b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
> index 07256b7..f1f749f 100644
> --- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
> +++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
> @@ -9,15 +9,20 @@ Properties:
> 
>    "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
>    compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
> -  whose PMC is compatible, and implies deep-sleep capability.
> +  whose PMC is compatible, and implies deep-sleep capability and
> +  wake on user defined packet(wakeup on ARP).
> +
> +  "fsl,p1022-pmc" should be listed for any chip whose PMC is
> +  compatible, and implies lossless Ethernet capability during sleep.
> 
>    "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
>    compatible; all statements below that apply to "fsl,mpc8548-pmc"  
> also
>    apply to "fsl,mpc8641d-pmc".
> 
>    Compatibility does not include bit assignments in  
> SCCR/PMCDR/DEVDISR; these
> -  bit assignments are indicated via the sleep specifier in each  
> device's
> -  sleep property.
> +  bit assignments are indicated via the clock nodes.  Device which  
> has a
> +  controllable clock source should have a "fsl,pmc-handle" property  
> pointing
> +  to the clock node.

Please respond to the feedback given on v1:
http://patchwork.ozlabs.org/patch/147177/

Also indicate, below the ---, what has changed from previous versions.

-Scott

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v2 05/15] fsl_pmc: update device bindings
@ 2013-06-03 22:43     ` Scott Wood
  0 siblings, 0 replies; 66+ messages in thread
From: Scott Wood @ 2013-06-03 22:43 UTC (permalink / raw)
  To: Zhao Chenhui; +Cc: linuxppc-dev, linux-kernel

On 04/19/2013 05:47:38 AM, Zhao Chenhui wrote:
> From: Li Yang <leoli@freescale.com>
>=20
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> ---
>  .../devicetree/bindings/powerpc/fsl/pmc.txt        |   59 =20
> +++++++++++--------
>  1 files changed, 34 insertions(+), 25 deletions(-)
>=20
> diff --git a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt =20
> b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
> index 07256b7..f1f749f 100644
> --- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
> +++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
> @@ -9,15 +9,20 @@ Properties:
>=20
>    "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
>    compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
> -  whose PMC is compatible, and implies deep-sleep capability.
> +  whose PMC is compatible, and implies deep-sleep capability and
> +  wake on user defined packet(wakeup on ARP).
> +
> +  "fsl,p1022-pmc" should be listed for any chip whose PMC is
> +  compatible, and implies lossless Ethernet capability during sleep.
>=20
>    "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
>    compatible; all statements below that apply to "fsl,mpc8548-pmc" =20
> also
>    apply to "fsl,mpc8641d-pmc".
>=20
>    Compatibility does not include bit assignments in =20
> SCCR/PMCDR/DEVDISR; these
> -  bit assignments are indicated via the sleep specifier in each =20
> device's
> -  sleep property.
> +  bit assignments are indicated via the clock nodes.  Device which =20
> has a
> +  controllable clock source should have a "fsl,pmc-handle" property =20
> pointing
> +  to the clock node.

Please respond to the feedback given on v1:
http://patchwork.ozlabs.org/patch/147177/

Also indicate, below the ---, what has changed from previous versions.

-Scott=

^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2013-06-03 22:43 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-19 10:47 [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E Zhao Chenhui
2013-04-19 10:47 ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 02/15] powerpc/85xx: add sleep and deep sleep support Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-23 23:53   ` Scott Wood
2013-04-23 23:53     ` Scott Wood
2013-04-28 10:20     ` Zhao Chenhui
2013-04-28 10:20       ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 03/15] fsl_pmc: Add API to enable device as wakeup event source Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 04/15] pm: add power node to dts Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 05/15] fsl_pmc: update device bindings Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-06-03 22:43   ` Scott Wood
2013-06-03 22:43     ` Scott Wood
2013-04-19 10:47 ` [PATCH v2 06/15] powerpc/85xx: add support to JOG feature using cpufreq interface Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-22  3:25   ` Viresh Kumar
2013-04-22 10:56     ` Zhao Chenhui
2013-04-22 10:56       ` Zhao Chenhui
2013-04-22 10:56       ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 07/15] powerpc/85xx: add time base sync for SoCs based on e500mc/e5500 Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-23 23:58   ` Scott Wood
2013-04-23 23:58     ` Scott Wood
2013-04-19 10:47 ` [PATCH v2 08/15] powerpc/85xx: add cpu hotplug support for e500mc/e5500 Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 09/15] powerpc/rcpm: add sleep feature for SoCs using RCPM Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 10/15] powerpc/85xx: fix 64-bit support for cpu hotplug Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 11/15] powerpc/rcpm: add struct ccsr_rcpm_v2 Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 12/15] powerpc/85xx: add time base sync support for e6500 Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-24  0:04   ` Scott Wood
2013-04-24  0:04     ` Scott Wood
2013-04-24 11:29     ` Zhao Chenhui
2013-04-24 11:29       ` Zhao Chenhui
2013-04-24 22:38       ` Scott Wood
2013-04-24 22:38         ` Scott Wood
2013-04-25  0:28         ` Zhao Chenhui
2013-04-25  0:28           ` Zhao Chenhui
2013-04-26  0:07           ` Scott Wood
2013-04-26  0:07             ` Scott Wood
2013-04-28  9:56             ` Zhao Chenhui
2013-04-28  9:56               ` Zhao Chenhui
2013-04-29 20:18               ` Scott Wood
2013-04-29 20:18                 ` Scott Wood
2013-04-19 10:47 ` [PATCH v2 13/15] powerpc/85xx: add support for e6500 L1 cache operation Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-24  0:00   ` Scott Wood
2013-04-24  0:00     ` Scott Wood
2013-04-24 11:14     ` Zhao Chenhui
2013-04-24 11:14       ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 14/15] powerpc/smp: add cpu hotplug support for e6500 Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-19 10:47 ` [PATCH v2 15/15] powerpc/rcpm: add sleep support for T4/B4 chips Zhao Chenhui
2013-04-19 10:47   ` Zhao Chenhui
2013-04-23  9:53 ` [linuxppc-release] [PATCH v2 01/15] powerpc/85xx: cache operations for Freescale SoCs based on BOOK3E Zhao Chenhui
2013-04-23  9:53   ` Zhao Chenhui
2013-04-23 23:46 ` Scott Wood
2013-04-23 23:46   ` Scott Wood
2013-04-24 11:08   ` Zhao Chenhui
2013-04-24 11:08     ` Zhao Chenhui

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.