* [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
@ 2011-11-16 9:55 Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support Zhao Chenhui
` (5 more replies)
0 siblings, 6 replies; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-16 9:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood
From: Li Yang <leoli@freescale.com>
The timebase sync is not only necessary when using KEXEC. It should also
be used by normal boot up and cpu hotplug. Remove the ifdef added by
the KEXEC patch.
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/platforms/85xx/smp.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 2df4785..6834447 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -114,10 +114,8 @@ smp_85xx_kick_cpu(int nr)
struct smp_ops_t smp_85xx_ops = {
.kick_cpu = smp_85xx_kick_cpu,
-#ifdef CONFIG_KEXEC
.give_timebase = smp_generic_give_timebase,
.take_timebase = smp_generic_take_timebase,
-#endif
};
#ifdef CONFIG_KEXEC
--
1.6.4.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
@ 2011-11-16 9:55 ` Zhao Chenhui
2011-11-16 19:02 ` Scott Wood
2011-11-16 9:55 ` [PATCH v2 3/7] powerpc/85xx: add sleep and deep sleep support Zhao Chenhui
` (4 subsequent siblings)
5 siblings, 1 reply; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-16 9:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood
From: Li Yang <leoli@freescale.com>
Add support to disable and re-enable individual cores at runtime
on MPC85xx/QorIQ SMP machines. Currently support e500v2 core.
MPC85xx machines use ePAPR spin-table in boot page for CPU kick-off.
This patch uses the boot page from bootloader to boot core at runtime.
It supports 32-bit and 36-bit physical address.
Add generic_set_cpu_up() to set cpu_state as CPU_UP_PREPARE in kick_cpu().
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>
---
Changes for v2:
- fix a sync issue by generic_set_cpu_up()
- put the dying core in nap state
- remove smp_85xx_unmap_bootpg() and smp_85xx_reset_core()
- use mpic_reset_core() to reset core
arch/powerpc/Kconfig | 5 +-
arch/powerpc/include/asm/smp.h | 2 +
arch/powerpc/kernel/head_fsl_booke.S | 28 ++++++
arch/powerpc/kernel/smp.c | 10 ++
arch/powerpc/platforms/85xx/smp.c | 170 +++++++++++++++++++++++++++-------
5 files changed, 179 insertions(+), 36 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b177caa..afe1682 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -212,7 +212,7 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
- (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x
+ PPC_85xx || PPC_86xx || PPC_PSERIES || 44x || 40x
config PPC_DCR_NATIVE
bool
@@ -323,7 +323,8 @@ config SWIOTLB
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
- depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
+ depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || \
+ PPC_PMAC || PPC_POWERNV || E500)
---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 adba970..7517863 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
void generic_cpu_die(unsigned int cpu);
void generic_mach_cpu_die(void);
void generic_set_cpu_dead(unsigned int cpu);
+void generic_set_cpu_up(unsigned int cpu);
int generic_check_cpu_restart(unsigned int cpu);
#endif
@@ -191,6 +192,7 @@ extern unsigned long __secondary_hold_spinloop;
extern unsigned long __secondary_hold_acknowledge;
extern char __secondary_hold;
+extern void __early_start(void);
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 9f5d210..1d93272 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -1004,6 +1004,34 @@ _GLOBAL(flush_dcache_L1)
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
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 6df7090..e2d4401 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -422,6 +422,16 @@ void generic_set_cpu_dead(unsigned int cpu)
per_cpu(cpu_state, cpu) = CPU_DEAD;
}
+/*
+ * The cpu_state should be set to CPU_UP_PREPARE in kick_cpu(), otherwise
+ * the cpu_state is always CPU_DEAD after calling generic_set_cpu_dead(),
+ * which makes the delay in generic_cpu_die() not happen.
+ */
+void generic_set_cpu_up(unsigned int cpu)
+{
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+}
+
int generic_check_cpu_restart(unsigned int cpu)
{
return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6834447..78732a5 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/kexec.h>
#include <linux/highmem.h>
+#include <linux/cpu.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
@@ -28,28 +29,78 @@
#include <sysdev/fsl_soc.h>
#include <sysdev/mpic.h>
-extern void __early_start(void);
-
-#define BOOT_ENTRY_ADDR_UPPER 0
-#define BOOT_ENTRY_ADDR_LOWER 1
-#define BOOT_ENTRY_R3_UPPER 2
-#define BOOT_ENTRY_R3_LOWER 3
-#define BOOT_ENTRY_RESV 4
-#define BOOT_ENTRY_PIR 5
-#define BOOT_ENTRY_R6_UPPER 6
-#define BOOT_ENTRY_R6_LOWER 7
-#define NUM_BOOT_ENTRY 8
-#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
-
-static int __init
-smp_85xx_kick_cpu(int nr)
+#define MPC85xx_BPTR_OFF 0x00020
+#define MPC85xx_BPTR_EN 0x80000000
+#define MPC85xx_BPTR_BOOT_PAGE_MASK 0x00ffffff
+
+struct epapr_spin_table {
+ u32 addr_h;
+ u32 addr_l;
+ u32 r3_h;
+ u32 r3_l;
+ u32 reserved;
+ u32 pir;
+};
+
+static void __cpuinit smp_85xx_setup_cpu(int cpu_nr);
+
+#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
+static __iomem u32 *bptr;
+
+extern void flush_disable_L1(void);
+
+static void __cpuinit smp_85xx_mach_cpu_die(void)
+{
+ unsigned int cpu = smp_processor_id();
+ register u32 tmp;
+
+ local_irq_disable();
+ idle_task_exit();
+ generic_set_cpu_dead(cpu);
+ mb();
+
+ mtspr(SPRN_TCR, 0);
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+ flush_disable_L1();
+
+ if (cpu_has_feature(CPU_FTR_CAN_NAP)) {
+ tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
+ mb();
+ isync();
+ mtspr(SPRN_HID0, tmp);
+ isync();
+
+ tmp = mfmsr();
+ tmp |= MSR_WE;
+ mb();
+ mtmsr(tmp);
+ isync();
+ }
+
+ for (;;);
+}
+
+static void __cpuinit smp_85xx_set_bootpg(u32 page)
+{
+ if (bptr != NULL) {
+ /* Set the BPTR to the boot page */
+ out_be32(bptr,
+ MPC85xx_BPTR_EN | (page & MPC85xx_BPTR_BOOT_PAGE_MASK));
+ }
+}
+#endif
+
+static int __cpuinit smp_85xx_kick_cpu(int nr)
+
{
unsigned long flags;
const u64 *cpu_rel_addr;
- __iomem u32 *bptr_vaddr;
+ __iomem struct epapr_spin_table *epapr;
struct device_node *np;
int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
int ioremappable;
+ int ret = 0;
WARN_ON(nr < 0 || nr >= NR_CPUS);
WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
@@ -57,10 +108,11 @@ smp_85xx_kick_cpu(int nr)
pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
np = of_get_cpu_node(nr, NULL);
- cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
+ cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
if (cpu_rel_addr == NULL) {
- printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
+ pr_err("%s: No cpu-release-addr for cpu %d\n",
+ __func__, nr);
return -ENOENT;
}
@@ -74,46 +126,83 @@ smp_85xx_kick_cpu(int nr)
/* Map the spin table */
if (ioremappable)
- bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
+ epapr = ioremap(*cpu_rel_addr, sizeof(struct epapr_spin_table));
else
- bptr_vaddr = phys_to_virt(*cpu_rel_addr);
+ epapr = phys_to_virt(*cpu_rel_addr);
local_irq_save(flags);
- out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
+ out_be32(&epapr->pir, hw_cpu);
#ifdef CONFIG_PPC32
- out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
+#ifdef CONFIG_HOTPLUG_CPU
+ /* Corresponding to generic_set_cpu_dead() */
+ generic_set_cpu_up(nr);
+
+ if (system_state == SYSTEM_RUNNING) {
+ out_be32(&epapr->addr_l, 0);
+
+ smp_85xx_set_bootpg((u32)(*cpu_rel_addr >> PAGE_SHIFT));
+ mpic_reset_core(hw_cpu);
+
+ /* wait until core is ready... */
+ n = 0;
+ while ((in_be32(&epapr->addr_l) != 1) && (++n < 1000))
+ udelay(100);
+ if (n >= 1000) {
+ pr_err("%s: timeout waiting for core %d to reset\n",
+ __func__, hw_cpu);
+ ret = -ENOENT;
+ goto out;
+ }
+ /* clear the acknowledge status */
+ __secondary_hold_acknowledge = -1;
+ }
+#endif
+ out_be32(&epapr->addr_l, __pa(__early_start));
if (!ioremappable)
- flush_dcache_range((ulong)bptr_vaddr,
- (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+ flush_dcache_range((ulong)epapr,
+ (ulong)epapr + sizeof(struct epapr_spin_table));
/* Wait a bit for the CPU to ack. */
+ n = 0;
while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
mdelay(1);
+ if (n >= 1000) {
+ pr_err("%s: timeout waiting for core %d to ack\n",
+ __func__, hw_cpu);
+ ret = -ENOENT;
+ goto out;
+ }
+out:
#else
smp_generic_kick_cpu(nr);
- out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
- __pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+ out_be64((u64 *)(&epapr->addr_h),
+ __pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
if (!ioremappable)
- flush_dcache_range((ulong)bptr_vaddr,
- (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+ flush_dcache_range((ulong)epapr,
+ (ulong)epapr + sizeof(struct epapr_spin_table));
#endif
local_irq_restore(flags);
if (ioremappable)
- iounmap(bptr_vaddr);
+ iounmap(epapr);
pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
- return 0;
+ return ret;
}
struct smp_ops_t smp_85xx_ops = {
.kick_cpu = smp_85xx_kick_cpu,
+ .setup_cpu = smp_85xx_setup_cpu,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = generic_cpu_disable,
+ .cpu_die = generic_cpu_die,
+#endif
.give_timebase = smp_generic_give_timebase,
.take_timebase = smp_generic_take_timebase,
};
@@ -215,8 +304,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
}
#endif /* CONFIG_KEXEC */
-static void __init
-smp_85xx_setup_cpu(int cpu_nr)
+static void __cpuinit smp_85xx_setup_cpu(int cpu_nr)
{
if (smp_85xx_ops.probe == smp_mpic_probe)
mpic_setup_this_cpu();
@@ -229,14 +317,24 @@ void __init mpc85xx_smp_init(void)
{
struct device_node *np;
- smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
-
np = of_find_node_by_type(NULL, "open-pic");
if (np) {
smp_85xx_ops.probe = smp_mpic_probe;
smp_85xx_ops.message_pass = smp_mpic_message_pass;
}
+ of_node_put(np);
+#ifdef CONFIG_HOTPLUG_CPU
+ bptr = NULL;
+ np = of_find_node_by_name(NULL, "ecm-law");
+ if (!np) {
+ pr_err("%s: can't find ecm-law node in dts\n", __func__);
+ return;
+ }
+ bptr = of_iomap(np, 0) + MPC85xx_BPTR_OFF;
+ of_node_put(np);
+#endif
+
if (cpu_has_feature(CPU_FTR_DBELL)) {
/*
* If left NULL, .message_pass defaults to
@@ -246,6 +344,10 @@ void __init mpc85xx_smp_init(void)
smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
}
+#ifdef CONFIG_HOTPLUG_CPU
+ ppc_md.cpu_die = smp_85xx_mach_cpu_die;
+#endif
+
smp_ops = &smp_85xx_ops;
#ifdef CONFIG_KEXEC
--
1.6.4.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 3/7] powerpc/85xx: add sleep and deep sleep support
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support Zhao Chenhui
@ 2011-11-16 9:55 ` Zhao Chenhui
2011-11-16 21:42 ` Scott Wood
2011-11-16 9:55 ` [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface Zhao Chenhui
` (3 subsequent siblings)
5 siblings, 1 reply; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-16 9:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood
From: Li Yang <leoli@freescale.com>
Some Freescale chips like MPC8536 and P1022 has deep sleep PM mode
in addtion to the sleep PM 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 deep sleep mode is equal to the Suspend-to-RAM state of Linux
Power Management.
Command to enter deep sleep mode.
echo mem > /sys/power/state
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: Jerry Huang <Chang-Ming.Huang@freescale.com>
Cc: Scott Wood <scottwood@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
Changes for V2:
- add enable_kernel_fp()
- rename functions and variables
- add pmc_flag
- remove the second parameter of mpc85xx_enter_deep_sleep()
- keep other bits intact when setting the deep sleep bit of
POWMGTSCR in mpc85xx_enter_deep_sleep()
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/l2cr_85xx.S | 53 +++
arch/powerpc/platforms/85xx/Makefile | 1 +
arch/powerpc/platforms/85xx/sleep.S | 605 ++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pmc.c | 98 +++++--
5 files changed, 738 insertions(+), 20 deletions(-)
create mode 100644 arch/powerpc/kernel/l2cr_85xx.S
create mode 100644 arch/powerpc/platforms/85xx/sleep.S
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index ce4f7f1..d5cc385 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
ifeq ($(CONFIG_PPC32),y)
obj-$(CONFIG_E500) += idle_e500.o
endif
+obj-$(CONFIG_PPC_85xx) += l2cr_85xx.o
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o
obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
diff --git a/arch/powerpc/kernel/l2cr_85xx.S b/arch/powerpc/kernel/l2cr_85xx.S
new file mode 100644
index 0000000..95dfef0
--- /dev/null
+++ b/arch/powerpc/kernel/l2cr_85xx.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All rights reserved.
+ * Scott Wood <scottwood@freescale.com>
+ * Dave Liu <daveliu@freescale.com>
+ * implement the L2 cache operations of e500 based L2 controller
+ *
+ * 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/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+ .section .text
+
+ /* r3 = virtual address of L2 controller, WIMG = 01xx */
+_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, 0xc0000000
+ stw r4, 0(r3)
+
+ /* Wait for the invalidate to finish */
+1: lwz r4, 0(r3)
+ andis. r4, r4, 0x4000
+ bne 1b
+ mbar
+
+ blr
+
+ /* r3 = virtual address of L2 controller, WIMG = 01xx */
+_GLOBAL(invalidate_enable_L2)
+ mbar
+ isync
+ lwz r4, 0(r3)
+ li r5, 3
+ rlwimi r4, r5, 30, 0xc0000000
+ stw r4, 0(r3)
+
+ /* Wait for the invalidate to finish */
+1: lwz r4, 0(r3)
+ andis. r4, r4, 0x4000
+ bne 1b
+ mbar
+
+ blr
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index bc5acb9..cec54c7 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_SUSPEND) += sleep.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/sleep.S b/arch/powerpc/platforms/85xx/sleep.S
new file mode 100644
index 0000000..3923bab
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/sleep.S
@@ -0,0 +1,605 @@
+/*
+ * Enter and leave deep sleep/sleep state on MPC85xx
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (C) 2006-2011 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>
+
+#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 POWMGTCSR_DPSLP_MASK 0x00100000
+
+#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 POWMGTCSR_DPSLP_MASK
+
+ .section .text
+ .align 12
+
+ /*
+ * r3 = high word of physical address of CCSR
+ * r4 = low word of physical address of CCSR
+ */
+_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 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 */
+ lis r5, 0x100f
+ mtspr SPRN_MAS0, r5
+ lis r5, 0xc000
+ ori r5, r5, 0x0500
+ mtspr SPRN_MAS1, r5
+ lis r5, 0xf000
+ ori r5, r5, 0x000a
+ mtspr SPRN_MAS2, r5
+ rlwinm r5, r4, 0, 0xfffff000
+ ori r5, r5, 0x0005
+ mtspr SPRN_MAS3, r5
+ mtspr SPRN_MAS7, r3
+ isync
+ tlbwe
+ isync
+
+ lis r3, 0xf000
+ lwz r4, 0x20(r3)
+ stw r4, SS_BPTR(r10)
+
+ lis r3, 0xf002 /* L2 cache controller at CCSR+0x20000 */
+ 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, 1
+ mtspr SPRN_L1CSR1, r4
+ isync
+
+ /* Set boot page translation */
+ lis r3, 0xf000
+ lis r4, (mpc85xx_deep_resume - PAGE_OFFSET)@h
+ ori r4, r4, (mpc85xx_deep_resume - PAGE_OFFSET)@l
+ rlwinm r4, r4, 20, 0x000fffff
+ oris r4, r4, 0x8000
+ stw r4, 0x20(r3)
+ lwz r4, 0x20(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 */
+ lis r3, 0xf00e
+ lwz r4, 0x84(r3)
+ clrlwi r4, r4, 16
+ oris r4, r4, 0x12a3
+ stw r4, 0x84(r3)
+ lwz r4, 0x84(r3)
+
+ /* set deep sleep bit in POWMGTSCR */
+ lis r3, powmgtreq@ha
+ lwz r8, powmgtreq@l(r3)
+
+ lis r3, 0xf00e
+ lwz r4, 0x80(r3)
+ or r4, r4, r8
+ stw r4, 0x80(r3)
+ lwz r4, 0x80(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, 0x80(r3)
+ andis. r6, r6, 0x0010
+ 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]. */
+ lis r4, 0x1001
+ mtspr SPRN_MAS0, r4
+ lis r4, 0xc000
+ ori r4, r4, 0x0800
+ mtspr SPRN_MAS1, r4
+ li r4, 0
+ mtspr SPRN_MAS2, r4
+ li r4, 0x0015
+ 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 */
+ lis r5, 0x100f
+ mtspr SPRN_MAS0, r5
+ lis r5, 0xc000
+ ori r5, r5, 0x0500
+ mtspr SPRN_MAS1, r5
+ lis r5, 0xf000
+ ori r5, r5, 0x000a
+ mtspr SPRN_MAS2, r5
+ rlwinm r5, r4, 0, 0xfffff000
+ ori r5, r5, 0x0005
+ mtspr SPRN_MAS3, r5
+ mtspr SPRN_MAS7, r3
+ isync
+ tlbwe
+ isync
+
+ lis r3, 0xf002 /* L2 cache controller at CCSR+0x20000 */
+ 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
+
+ lis r3, 0xf000
+ lwz r4, SS_BPTR(r10)
+ stw r4, 0x20(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.
+ */
+ lis r4, 0x100f
+ 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..d6c65a7 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 2007-2011 Freescale Semiconductor Inc.
*
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
@@ -19,39 +20,86 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/of_platform.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+
+#include <sysdev/fsl_soc.h>
struct pmc_regs {
__be32 devdisr;
- __be32 devdisr2;
- __be32 :32;
- __be32 :32;
- __be32 pmcsr;
-#define PMCSR_SLP (1 << 17)
+ __be32 res1;
+ __be32 res2;
+ __be32 pmjcr;
+ __be32 powmgtcsr;
+ __be32 res4;
+ __be32 res5;
+ __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
+
+#define POWMGTCSR_SLP_MASK 0x00020000
+
+/* 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);
static int pmc_suspend_enter(suspend_state_t state)
{
- int ret;
+ int ret = 0;
+ unsigned long flags;
+
+ switch (state) {
+ case PM_SUSPEND_MEM:
+#ifdef CONFIG_SPE
+ enable_kernel_spe();
+#endif
+ enable_kernel_fp();
+
+ pr_debug("%s: Entering deep sleep\n", __func__);
+
+ local_irq_save(flags);
+ mpc85xx_enter_deep_sleep(get_immrbase());
+ local_irq_restore(flags);
- setbits32(&pmc_regs->pmcsr, PMCSR_SLP);
- /* At this point, the CPU is asleep. */
+ pr_debug("%s: Resumed from deep sleep\n", __func__);
+ break;
- /* 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");
+ case PM_SUSPEND_STANDBY:
+ local_irq_save(flags);
+
+ setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP_MASK);
+ /* At this point, the CPU is asleep. */
+
+ local_irq_restore(flags);
+ /* Upon resume, wait for SLP bit to be clear. */
+ ret = spin_event_timeout(
+ (in_be32(&pmc_regs->powmgtcsr) & POWMGTCSR_SLP_MASK) == 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 +107,24 @@ 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\n");
return 0;
}
--
1.6.4.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 3/7] powerpc/85xx: add sleep and deep sleep support Zhao Chenhui
@ 2011-11-16 9:55 ` Zhao Chenhui
2011-11-17 0:17 ` Scott Wood
2011-11-16 9:55 ` [PATCH v2 5/7] fsl_pmc: update device bindings Zhao Chenhui
` (2 subsequent siblings)
5 siblings, 1 reply; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-16 9:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood
From: Li Yang <leoli@freescale.com>
Some 85xx silicons like MPC8536 and P1022 has the JOG PM feature.
The patch adds the support to change CPU frequency using the standard
cpufreq interface. Add the all PLL ratio core support. The ratio CORE
to CCB can 1:1(except MPC8536), 3:2, 2:1, 5:2, 3:1, 7:2 and 4:1.
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>
---
Changes for v2:
- rework set_pll(). wakeup all cores before issuing a jog request.
- use the platform driver framwork
arch/powerpc/platforms/85xx/Makefile | 1 +
arch/powerpc/platforms/85xx/cpufreq-jog.c | 322 +++++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig | 8 +
3 files changed, 331 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/85xx/cpufreq-jog.c
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index cec54c7..49a865a 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,6 +3,7 @@
#
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SUSPEND) += sleep.o
+obj-$(CONFIG_MPC85xx_CPUFREQ) += cpufreq-jog.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/cpufreq-jog.c b/arch/powerpc/platforms/85xx/cpufreq-jog.c
new file mode 100644
index 0000000..efe62b9
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/cpufreq-jog.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008-2011 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 <asm/prom.h>
+#include <asm/time.h>
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+#include <sysdev/fsl_soc.h>
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+static u32 sysfreq, threshold_freq;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+
+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_533MHz 533340000
+#define FREQ_800MHz 800000000
+
+#define CORE_RATIO_BITS 8
+#define CORE_RATIO_MASK 0x3f
+#define CORE0_RATIO_SHIFT 16
+
+#define PORPLLSR 0x0
+
+#define PMJCR 0x7c
+#define PMJCR_CORE0_SPD_MASK 0x00001000
+
+#define POWMGTCSR 0x80
+#define POWMGTCSR_LOSSLESS_MASK 0x00400000
+#define POWMGTCSR_JOG_MASK 0x00200000
+#define POWMGTCSR_CORE0_IRQ_MSK 0x80000000
+#define POWMGTCSR_CORE0_CI_MSK 0x40000000
+#define POWMGTCSR_CORE0_DOZING 0x00000008
+#define POWMGTCSR_CORE0_NAPPING 0x00000004
+
+/*
+ * hardware specific functions
+ */
+static int get_pll(int hw_cpu)
+{
+ int ret, shift;
+ u32 cur_pll = in_be32(guts + PORPLLSR);
+
+ shift = hw_cpu * CORE_RATIO_BITS + CORE0_RATIO_SHIFT;
+ ret = (cur_pll >> shift) & CORE_RATIO_MASK;
+ return ret;
+}
+
+static int set_pll(unsigned int cpu, unsigned int pll)
+{
+ void *powersave = NULL;
+ int hw_cpu = get_hard_smp_processor_id(cpu);
+ int shift, i;
+ u32 corefreq, val;
+ u32 mask;
+ unsigned long flags;
+ int ret = 0;
+
+ if (pll == get_pll(hw_cpu))
+ return 0;
+
+ shift = hw_cpu * CORE_RATIO_BITS + CORE0_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 > threshold_freq)
+ val |= PMJCR_CORE0_SPD_MASK << hw_cpu;
+
+ mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD_MASK << hw_cpu);
+ clrsetbits_be32(guts + PMJCR, mask, val);
+
+ /* readback to sync write */
+ val = in_be32(guts + PMJCR);
+
+ local_irq_save(flags);
+ /*
+ * A Jog request can not be asserted when any core is in a low power
+ * state. Before executing a jog request, any core which is in
+ * a low power state must be waked by a interrupt.
+ */
+ if (mpc85xx_freqs == p1022_freqs_table) {
+ powersave = ppc_md.power_save;
+ ppc_md.power_save = NULL;
+ wmb();
+ val = in_be32(guts + POWMGTCSR);
+ for_each_online_cpu(i) {
+ if (val & ((POWMGTCSR_CORE0_DOZING |
+ POWMGTCSR_CORE0_NAPPING) << (i * 2)))
+ smp_send_reschedule(i);
+ }
+ }
+ setbits32(guts + POWMGTCSR, POWMGTCSR_JOG_MASK);
+
+ if (powersave) {
+ ppc_md.power_save = powersave;
+ wmb();
+ }
+
+ local_irq_restore(flags);
+
+ /* verify */
+ if (!spin_event_timeout(get_pll(hw_cpu) == pll, 10000, 10)) {
+ pr_err("%s: Fail to switch the core frequency. "
+ "The current PLL of core %d is %d instead of %d.\n",
+ __func__, hw_cpu, get_pll(hw_cpu), pll);
+ ret = -EINVAL;
+ }
+
+ 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 -EINVAL;
+
+ /* 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++) {
+ /* The frequency unit is kHz. */
+ mpc85xx_freqs[i].frequency =
+ (sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
+ 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;
+
+ 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 int mpc85xx_job_probe(struct platform_device *ofdev)
+{
+ struct device_node *np = ofdev->dev.of_node;
+
+ if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
+ threshold_freq = FREQ_800MHz;
+ mpc85xx_freqs = mpc8536_freqs_table;
+ } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
+ threshold_freq = FREQ_533MHz;
+ mpc85xx_freqs = p1022_freqs_table;
+ }
+
+ sysfreq = fsl_get_sys_freq();
+
+ guts = of_iomap(np, 0);
+ if (guts == NULL)
+ return -ENOMEM;
+
+ pr_info("Freescale MPC85xx CPU frequency switching(JOG) driver\n");
+
+ return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
+}
+
+static int mpc85xx_jog_remove(struct platform_device *ofdev)
+{
+ iounmap(guts);
+ cpufreq_unregister_driver(&mpc85xx_cpufreq_driver);
+
+ return 0;
+}
+
+static struct of_device_id mpc85xx_jog_ids[] = {
+ { .compatible = "fsl,mpc8536-guts", },
+ { .compatible = "fsl,p1022-guts", },
+ {}
+};
+
+static struct platform_driver mpc85xx_jog_driver = {
+ .driver = {
+ .name = "mpc85xx_cpufreq_jog",
+ .owner = THIS_MODULE,
+ .of_match_table = mpc85xx_jog_ids,
+ },
+ .probe = mpc85xx_job_probe,
+ .remove = mpc85xx_jog_remove,
+};
+
+static int __init mpc85xx_jog_init(void)
+{
+ return platform_driver_register(&mpc85xx_jog_driver);
+}
+
+static void __exit mpc85xx_jog_exit(void)
+{
+ platform_driver_unregister(&mpc85xx_jog_driver);
+}
+
+module_init(mpc85xx_jog_init);
+module_exit(mpc85xx_jog_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dave Liu <daveliu@freescale.com>");
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index e458872..63bd32a 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -200,6 +200,14 @@ config CPU_FREQ_PMAC64
This adds support for frequency switching on Apple iMac G5,
and some of the more recent desktop G5 machines as well.
+config MPC85xx_CPUFREQ
+ bool "Support for Freescale MPC85xx CPU freq"
+ depends on PPC_85xx && PPC32
+ select CPU_FREQ_TABLE
+ help
+ This adds support for frequency switching on Freescale MPC85xx,
+ currently including P1022 and MPC8536.
+
config PPC_PASEMI_CPUFREQ
bool "Support for PA Semi PWRficient"
depends on PPC_PASEMI
--
1.6.4.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 5/7] fsl_pmc: update device bindings
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
` (2 preceding siblings ...)
2011-11-16 9:55 ` [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface Zhao Chenhui
@ 2011-11-16 9:55 ` Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 6/7] fsl_pmc: Add API to enable device as wakeup event source Zhao Chenhui
2011-11-16 18:42 ` [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Scott Wood
5 siblings, 0 replies; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-16 9:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood
From: Li Yang <leoli@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
.../devicetree/bindings/powerpc/fsl/pmc.txt | 63 +++++++++++--------
1 files changed, 36 insertions(+), 27 deletions(-)
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
index 07256b7..d84b4f8 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
@@ -9,22 +9,27 @@ 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 "clk-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
block.
- For devices compatible with "fsl,mpc8548-pmc", the first resource
- is a 32-byte block beginning with DEVDISR.
+ For devices compatible with "fsl,mpc8548-pmc", the second resource
+ is a 32-byte block beginning with DEVDISR if supported.
- interrupts: For "fsl,mpc8349-pmc"-compatible devices, the first
resource is the PMC block interrupt.
@@ -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.6.4.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 6/7] fsl_pmc: Add API to enable device as wakeup event source
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
` (3 preceding siblings ...)
2011-11-16 9:55 ` [PATCH v2 5/7] fsl_pmc: update device bindings Zhao Chenhui
@ 2011-11-16 9:55 ` Zhao Chenhui
2011-11-16 18:42 ` [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Scott Wood
5 siblings, 0 replies; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-16 9:55 UTC (permalink / raw)
To: linuxppc-dev; +Cc: scottwood
Add APIs for setting wakeup source and lossless Ethernet in low power modes.
These APIs can be used by wake-on-packet feature.
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>
---
Changes for v2:
- rename functions
- add pmc_flag
arch/powerpc/sysdev/fsl_pmc.c | 72 ++++++++++++++++++++++++++++++++++++++++-
arch/powerpc/sysdev/fsl_soc.h | 9 +++++
2 files changed, 80 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index d6c65a7..6a2f8b4 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -40,13 +40,83 @@ static unsigned int pmc_flag;
#define PMC_SLEEP 0x1
#define PMC_DEEP_SLEEP 0x2
+#define PMC_LOSSLESS 0x4
#define POWMGTCSR_SLP_MASK 0x00020000
+#define POWMGTCSR_LOSSLESS_MASK 0x00400000
/* 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);
+#ifdef CONFIG_FSL_PMC
+/**
+ * mpc85xx_pmc_set_wake - enable OF device as wakeup event source
+ * @pdev: platform 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
+ * 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 platform_device *pdev, bool enable)
+{
+ int ret = 0;
+ struct device_node *clk_np;
+ u32 pmcdr_mask;
+
+ if (!pmc_regs) {
+ pr_err("%s: PMC is unavailable\n", __func__);
+ return -ENODEV;
+ }
+
+ if (enable && !device_may_wakeup(&pdev->dev))
+ return -EINVAL;
+
+ clk_np = of_parse_phandle(pdev->dev.of_node, "clk-handle", 0);
+ if (!clk_np)
+ return -EINVAL;
+
+ if (of_property_read_u32(clk_np, "fsl,pmcdr-mask", &pmcdr_mask)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ 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_MASK);
+ else
+ clrbits32(&pmc_regs->powmgtcsr,
+ POWMGTCSR_LOSSLESS_MASK);
+ }
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_lossless_ethernet);
+#endif
+
static int pmc_suspend_enter(suspend_state_t state)
{
int ret = 0;
@@ -120,7 +190,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 c6d0073..3422b0d 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -3,6 +3,7 @@
#ifdef __KERNEL__
#include <asm/mmu.h>
+#include <linux/platform_device.h>
struct spi_device;
@@ -21,6 +22,14 @@ struct device_node;
extern void fsl_rstcr_restart(char *cmd);
+#ifdef CONFIG_FSL_PMC
+int mpc85xx_pmc_set_wake(struct platform_device *pdev, bool enable);
+void mpc85xx_pmc_set_lossless_ethernet(int enable);
+#else
+#define mpc85xx_pmc_set_wake(pdev, enable)
+#define mpc85xx_pmc_set_lossless_ethernet(enable)
+#endif
+
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
/* The different ports that the DIU can be connected to */
--
1.6.4.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
` (4 preceding siblings ...)
2011-11-16 9:55 ` [PATCH v2 6/7] fsl_pmc: Add API to enable device as wakeup event source Zhao Chenhui
@ 2011-11-16 18:42 ` Scott Wood
2011-11-18 10:12 ` Zhao Chenhui
2011-11-18 14:35 ` Kumar Gala
5 siblings, 2 replies; 20+ messages in thread
From: Scott Wood @ 2011-11-16 18:42 UTC (permalink / raw)
To: Zhao Chenhui; +Cc: linuxppc-dev
On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> From: Li Yang <leoli@freescale.com>
>
> The timebase sync is not only necessary when using KEXEC. It should also
> be used by normal boot up and cpu hotplug. Remove the ifdef added by
> the KEXEC patch.
Again, no it should not be used by normal boot up (whether KEXEC support
is enabled or not). We should only do timebase sync when we actually
need to (when we've actually just reset a core), and we should do it the
way U-Boot does rather than with smp-tbsync.c.
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support
2011-11-16 9:55 ` [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support Zhao Chenhui
@ 2011-11-16 19:02 ` Scott Wood
2011-11-17 11:16 ` Li Yang-R58472
0 siblings, 1 reply; 20+ messages in thread
From: Scott Wood @ 2011-11-16 19:02 UTC (permalink / raw)
To: Zhao Chenhui; +Cc: linuxppc-dev
On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> +static void __cpuinit smp_85xx_mach_cpu_die(void)
> +{
> + unsigned int cpu = smp_processor_id();
> + register u32 tmp;
> +
> + local_irq_disable();
> + idle_task_exit();
> + generic_set_cpu_dead(cpu);
> + mb();
> +
> + mtspr(SPRN_TCR, 0);
> + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
Clearing these bits in TSR should be unnecessary since we clear TCR --
and doesn't really accomplish anything since the TSR bits can continue
to be set.
If watchdog is in use, we need to set the period to the highest possible
to effectively disable it.
> + if (cpu_has_feature(CPU_FTR_CAN_NAP)) {
Again, don't check this. On 85xx, we *always* can and should use nap
here. At best this is noise, at worst this will cause problems if
CONFIG_BDI_SWITCH is enabled, or if CPU_FTR_CAN_NAP is cleared for any
other reason (e.g. it's not set on e500mc, and the reason isn't that the
nap implementation is different (which it is), but that it's not usable
in the idle loop).
> +static int __cpuinit smp_85xx_kick_cpu(int nr)
> +
> {
> unsigned long flags;
> const u64 *cpu_rel_addr;
> - __iomem u32 *bptr_vaddr;
> + __iomem struct epapr_spin_table *epapr;
Please don't call this just "epapr". That's like calling a reference to
any powerpc-specific struct "powerpc".
How about "spin_table"?
> - out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
> + out_be32(&epapr->pir, hw_cpu);
> #ifdef CONFIG_PPC32
> - out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
> +#ifdef CONFIG_HOTPLUG_CPU
> + /* Corresponding to generic_set_cpu_dead() */
> + generic_set_cpu_up(nr);
> +
> + if (system_state == SYSTEM_RUNNING) {
> + out_be32(&epapr->addr_l, 0);
> +
> + smp_85xx_set_bootpg((u32)(*cpu_rel_addr >> PAGE_SHIFT));
As previously requested, please document why you're setting the boot
page here. This should really be done when you resume from deep sleep,
rather than here, and should be a restoration of the value that the
register held prior to deep sleep.
> struct smp_ops_t smp_85xx_ops = {
> .kick_cpu = smp_85xx_kick_cpu,
> + .setup_cpu = smp_85xx_setup_cpu,
> +#ifdef CONFIG_HOTPLUG_CPU
> + .cpu_disable = generic_cpu_disable,
> + .cpu_die = generic_cpu_die,
> +#endif
Only fill these fields in on e500v1/v2, until we properly support
e500mc. Likewise in ppc_md.cpu_die and anywhere else we advertise this
functionality.
> + of_node_put(np);
> +#ifdef CONFIG_HOTPLUG_CPU
> + bptr = NULL;
> + np = of_find_node_by_name(NULL, "ecm-law");
> + if (!np) {
> + pr_err("%s: can't find ecm-law node in dts\n", __func__);
> + return;
> + }
Look up by compatible, not name.
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/7] powerpc/85xx: add sleep and deep sleep support
2011-11-16 9:55 ` [PATCH v2 3/7] powerpc/85xx: add sleep and deep sleep support Zhao Chenhui
@ 2011-11-16 21:42 ` Scott Wood
0 siblings, 0 replies; 20+ messages in thread
From: Scott Wood @ 2011-11-16 21:42 UTC (permalink / raw)
To: Zhao Chenhui; +Cc: linuxppc-dev
On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> index ce4f7f1..d5cc385 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -63,6 +63,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
> ifeq ($(CONFIG_PPC32),y)
> obj-$(CONFIG_E500) += idle_e500.o
> endif
> +obj-$(CONFIG_PPC_85xx) += l2cr_85xx.o
Can you restrict this to e500v1/v2?
Also, don't call it "l2cr" -- that's a 6xx register that is not present
on 85xx.
> + .section .data
> + .align 5
> +mpc85xx_sleep_save_area:
> + .space STATE_SAVE_SIZE
> +ccsrbase_low:
> + .long 0
> +ccsrbase_high:
> + .long 0
> +powmgtreq:
> + .long POWMGTCSR_DPSLP_MASK
> +
> + .section .text
> + .align 12
> +
> + /*
> + * r3 = high word of physical address of CCSR
> + * r4 = low word of physical address of CCSR
> + */
The whole point of powmgtreq is to store a dynamically-passed-in
value... and it doesn't look like you add it in the jog patch.
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface
2011-11-16 9:55 ` [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface Zhao Chenhui
@ 2011-11-17 0:17 ` Scott Wood
2011-11-17 11:53 ` Zhao Chenhui
0 siblings, 1 reply; 20+ messages in thread
From: Scott Wood @ 2011-11-17 0:17 UTC (permalink / raw)
To: Zhao Chenhui; +Cc: linuxppc-dev
On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> From: Li Yang <leoli@freescale.com>
>
> Some 85xx silicons like MPC8536 and P1022 has the JOG PM feature.
P1023 as well -- any plan to support?
I see this in the p1022 and mpc8536 manuals:
> The system operates as if a request to enter sleep mode has occurred, with the exception that the
> values written into the PMCDR register (clock disable register for sleep/ deep sleep modes) are
> ignored, and it is treated as if every bit in PMCDR is a logic 1. This means that the eTSECs, USB
> controllers, DDR and eLBC will be stopped.
...which doesn't sound good.
> The patch adds the support to change CPU frequency using the standard
> cpufreq interface. Add the all PLL ratio core support. The ratio CORE
> to CCB can 1:1(except MPC8536), 3:2, 2:1, 5:2, 3:1, 7:2 and 4:1.
The ratios supported are implementation-specific. Only p1022 supports
1:1. p1023 supports only 3:2, 2:1, 5:2, and 3:1 (assuming the
preliminary manual I have is accurate).
> + local_irq_save(flags);
> + /*
> + * A Jog request can not be asserted when any core is in a low power
> + * state. Before executing a jog request, any core which is in
> + * a low power state must be waked by a interrupt.
> + */
> + if (mpc85xx_freqs == p1022_freqs_table) {
> + powersave = ppc_md.power_save;
> + ppc_md.power_save = NULL;
> + wmb();
> + val = in_be32(guts + POWMGTCSR);
> + for_each_online_cpu(i) {
> + if (val & ((POWMGTCSR_CORE0_DOZING |
> + POWMGTCSR_CORE0_NAPPING) << (i * 2)))
> + smp_send_reschedule(i);
> + }
> + }
This is racy, what if another core read ppc_md.power_save just before
you wrote NULL, but hasn't yet entered a low power state?
You should send a reschedule to all cores regardless of what you see in
POWMGTCSR.
The p1022 also says that MSR[EE] should be zero -- it is on this core,
but what about the other?
> + setbits32(guts + POWMGTCSR, POWMGTCSR_JOG_MASK);
This might work on p1022, but don't you have to go through a core reset
on mpc8536? In that case, you can't just set the bit, you have to go
through the deep sleep code to save/restore state.
P1022 also says, "Mask all the interrupts to the cores by setting the
bits CORE_UDE_MSK, CORE_MCP_MSK, CORE_INT_MSK and CORE_CINT_MSK in the
POWMGTCSR," which I don't see happening.
Though, this directly contradicts where it later says, "The user must
not issue a jog request at the same time as issuing a request
for another low power mode, or while the system is in the process of
entering a low power mode. This means that a jog request must not be
asserted when any other bit of POWMGTCSR is non-zero. If the user tries
to do this, the jog request is ignored."
POWMGTCSR must be zero except for the JOG bit, but you must set other
POWMGTCSR bits. Lovely. :-P I assume that the "This means..."
statement is just wrong, and you really are supposed to set those other
bits. P1023 refines the statement to, "This means that POWMGTCSR[JOG]
must not be asserted when any of the other power management request bits
(COREn_DOZ, SLP) in POWMGTCSR are set."
> + if (powersave) {
> + ppc_md.power_save = powersave;
> + wmb();
> + }
How do you know the jog has happened at this point? Just because you've
issued a store that requests it doesn't mean it has taken effect by the
time you execute the next instruction.
> + local_irq_restore(flags);
> +
> + /* verify */
> + if (!spin_event_timeout(get_pll(hw_cpu) == pll, 10000, 10)) {
> + pr_err("%s: Fail to switch the core frequency. "
> + "The current PLL of core %d is %d instead of %d.\n",
> + __func__, hw_cpu, get_pll(hw_cpu), pll);
> + ret = -EINVAL;
> + }
Shouldn't the pll be where it's supposed to be as soon as we resume
execution? I don't see a need to spin here, provided we properly wait
for the jog to happen earlier (which we want to do so that we don't
enable power_save and EE early).
> +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;
> +
> + 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);
I still do not understand what sense it makes to set a global variable
(ppc_proc_freq) to the frequency of a specific CPU.
> +static int mpc85xx_job_probe(struct platform_device *ofdev)
> +{
> + struct device_node *np = ofdev->dev.of_node;
> +
> + if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
> + threshold_freq = FREQ_800MHz;
> + mpc85xx_freqs = mpc8536_freqs_table;
> + } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
> + threshold_freq = FREQ_533MHz;
> + mpc85xx_freqs = p1022_freqs_table;
> + }
Maybe use .data in the of_device_id table, similar to
arch/powerpc/platforms/83xx/suspend.c? Though it's slightly less
convenient now that we need to call of_match_device() again in order to
get a match pointer.
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support
2011-11-16 19:02 ` Scott Wood
@ 2011-11-17 11:16 ` Li Yang-R58472
2011-11-17 19:44 ` Scott Wood
0 siblings, 1 reply; 20+ messages in thread
From: Li Yang-R58472 @ 2011-11-17 11:16 UTC (permalink / raw)
To: Wood Scott-B07421, Zhao Chenhui-B35336; +Cc: linuxppc-dev@lists.ozlabs.org
DQoNCj5DYzogbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7IExpIFlhbmctUjU4NDcyDQo+
U3ViamVjdDogUmU6IFtQQVRDSCB2MiAyLzddIHBvd2VycGMvODV4eDogYWRkIEhPVFBMVUdfQ1BV
IHN1cHBvcnQNCj4NCj5PbiAxMS8xNi8yMDExIDAzOjU1IEFNLCBaaGFvIENoZW5odWkgd3JvdGU6
DQo+PiArc3RhdGljIHZvaWQgX19jcHVpbml0IHNtcF84NXh4X21hY2hfY3B1X2RpZSh2b2lkKSB7
DQo+PiArCXVuc2lnbmVkIGludCBjcHUgPSBzbXBfcHJvY2Vzc29yX2lkKCk7DQo+PiArCXJlZ2lz
dGVyIHUzMiB0bXA7DQo+PiArDQo+PiArCWxvY2FsX2lycV9kaXNhYmxlKCk7DQo+PiArCWlkbGVf
dGFza19leGl0KCk7DQo+PiArCWdlbmVyaWNfc2V0X2NwdV9kZWFkKGNwdSk7DQo+PiArCW1iKCk7
DQo+PiArDQo+PiArCW10c3ByKFNQUk5fVENSLCAwKTsNCj4+ICsJbXRzcHIoU1BSTl9UU1IsIFRT
Ul9FTlcgfCBUU1JfV0lTIHwgVFNSX0RJUyB8IFRTUl9GSVMpOw0KPg0KPkNsZWFyaW5nIHRoZXNl
IGJpdHMgaW4gVFNSIHNob3VsZCBiZSB1bm5lY2Vzc2FyeSBzaW5jZSB3ZSBjbGVhciBUQ1IgLS0g
YW5kDQo+ZG9lc24ndCByZWFsbHkgYWNjb21wbGlzaCBhbnl0aGluZyBzaW5jZSB0aGUgVFNSIGJp
dHMgY2FuIGNvbnRpbnVlIHRvIGJlDQo+c2V0Lg0KDQpJIGFsc28gcmVjb21tZW5kIHNldHRpbmcg
dGhlIENPUkVfSVJRX01BU0sgYW5kIENPUkVfQ0lfTUFTSyBpbiB0aGUgUE9XTUdUQ1NSIHJlZ2lz
dGVyIHNvIHRoYXQgbm8gaW50ZXJydXB0IHdpbGwgd2FrZXVwIHRoZSBjb3JlIGZyb20gTkFQLg0K
DQo+DQo+SWYgd2F0Y2hkb2cgaXMgaW4gdXNlLCB3ZSBuZWVkIHRvIHNldCB0aGUgcGVyaW9kIHRv
IHRoZSBoaWdoZXN0IHBvc3NpYmxlDQo+dG8gZWZmZWN0aXZlbHkgZGlzYWJsZSBpdC4NCg0KU2V0
dGluZyBpdCB0byB0aGUgaGlnaGVzdCB0aW1lb3V0IGRvZXNuJ3QgcmVhbGx5IGRpc2FibGUgdGhl
IHdhdGNoZG9nLiAgVGhlIGJlc3Qgd2F5IGZvciBkaXNhYmxpbmcgdGhlIHdkdCBpcyB0byByZXNl
dCB0aGUgY29yZSwgYWx0aG91Z2ggaXQncyBhIGJpdCB0b28gY29tcGxleCB0byBkby4NCg0KPg0K
Pj4gKwlpZiAoY3B1X2hhc19mZWF0dXJlKENQVV9GVFJfQ0FOX05BUCkpIHsNCj4NCj5BZ2Fpbiwg
ZG9uJ3QgY2hlY2sgdGhpcy4gIE9uIDg1eHgsIHdlICphbHdheXMqIGNhbiBhbmQgc2hvdWxkIHVz
ZSBuYXAgaGVyZS4NCj5BdCBiZXN0IHRoaXMgaXMgbm9pc2UsIGF0IHdvcnN0IHRoaXMgd2lsbCBj
YXVzZSBwcm9ibGVtcyBpZg0KPkNPTkZJR19CRElfU1dJVENIIGlzIGVuYWJsZWQsIG9yIGlmIENQ
VV9GVFJfQ0FOX05BUCBpcyBjbGVhcmVkIGZvciBhbnkNCj5vdGhlciByZWFzb24gKGUuZy4gaXQn
cyBub3Qgc2V0IG9uIGU1MDBtYywgYW5kIHRoZSByZWFzb24gaXNuJ3QgdGhhdCB0aGUNCj5uYXAg
aW1wbGVtZW50YXRpb24gaXMgZGlmZmVyZW50ICh3aGljaCBpdCBpcyksIGJ1dCB0aGF0IGl0J3Mg
bm90IHVzYWJsZSBpbg0KPnRoZSBpZGxlIGxvb3ApLg0KPg0KPj4gK3N0YXRpYyBpbnQgX19jcHVp
bml0IHNtcF84NXh4X2tpY2tfY3B1KGludCBucikNCj4+ICsNCj4+ICB7DQo+PiAgCXVuc2lnbmVk
IGxvbmcgZmxhZ3M7DQo+PiAgCWNvbnN0IHU2NCAqY3B1X3JlbF9hZGRyOw0KPj4gLQlfX2lvbWVt
IHUzMiAqYnB0cl92YWRkcjsNCj4+ICsJX19pb21lbSBzdHJ1Y3QgZXBhcHJfc3Bpbl90YWJsZSAq
ZXBhcHI7DQo+DQo+UGxlYXNlIGRvbid0IGNhbGwgdGhpcyBqdXN0ICJlcGFwciIuICBUaGF0J3Mg
bGlrZSBjYWxsaW5nIGEgcmVmZXJlbmNlIHRvDQo+YW55IHBvd2VycGMtc3BlY2lmaWMgc3RydWN0
ICJwb3dlcnBjIi4NCj4NCj5Ib3cgYWJvdXQgInNwaW5fdGFibGUiPw0KDQpZb3UgbWVhbiB0aGUg
bmFtZSBvZiB0aGUgdmFyaWFibGUgbm90IHRoZSBzdHJ1Y3R1cmUsIHJpZ2h0PyAgSSBhZ3JlZS4N
Cg0KPg0KPj4gLQlvdXRfYmUzMihicHRyX3ZhZGRyICsgQk9PVF9FTlRSWV9QSVIsIGh3X2NwdSk7
DQo+PiArCW91dF9iZTMyKCZlcGFwci0+cGlyLCBod19jcHUpOw0KPj4gICNpZmRlZiBDT05GSUdf
UFBDMzINCj4+IC0Jb3V0X2JlMzIoYnB0cl92YWRkciArIEJPT1RfRU5UUllfQUREUl9MT1dFUiwg
X19wYShfX2Vhcmx5X3N0YXJ0KSk7DQo+PiArI2lmZGVmIENPTkZJR19IT1RQTFVHX0NQVQ0KPj4g
KwkvKiBDb3JyZXNwb25kaW5nIHRvIGdlbmVyaWNfc2V0X2NwdV9kZWFkKCkgKi8NCj4+ICsJZ2Vu
ZXJpY19zZXRfY3B1X3VwKG5yKTsNCj4+ICsNCj4+ICsJaWYgKHN5c3RlbV9zdGF0ZSA9PSBTWVNU
RU1fUlVOTklORykgew0KPj4gKwkJb3V0X2JlMzIoJmVwYXByLT5hZGRyX2wsIDApOw0KPj4gKw0K
Pj4gKwkJc21wXzg1eHhfc2V0X2Jvb3RwZygodTMyKSgqY3B1X3JlbF9hZGRyID4+IFBBR0VfU0hJ
RlQpKTsNCj4NCj5BcyBwcmV2aW91c2x5IHJlcXVlc3RlZCwgcGxlYXNlIGRvY3VtZW50IHdoeSB5
b3UncmUgc2V0dGluZyB0aGUgYm9vdCBwYWdlDQo+aGVyZS4gIFRoaXMgc2hvdWxkIHJlYWxseSBi
ZSBkb25lIHdoZW4geW91IHJlc3VtZSBmcm9tIGRlZXAgc2xlZXAsIHJhdGhlcg0KPnRoYW4gaGVy
ZSwgYW5kIHNob3VsZCBiZSBhIHJlc3RvcmF0aW9uIG9mIHRoZSB2YWx1ZSB0aGF0IHRoZSByZWdp
c3RlciBoZWxkDQo+cHJpb3IgdG8gZGVlcCBzbGVlcC4NCj4NCj4+ICBzdHJ1Y3Qgc21wX29wc190
IHNtcF84NXh4X29wcyA9IHsNCj4+ICAJLmtpY2tfY3B1ID0gc21wXzg1eHhfa2lja19jcHUsDQo+
PiArCS5zZXR1cF9jcHUJPSBzbXBfODV4eF9zZXR1cF9jcHUsDQo+PiArI2lmZGVmIENPTkZJR19I
T1RQTFVHX0NQVQ0KPj4gKwkuY3B1X2Rpc2FibGUJPSBnZW5lcmljX2NwdV9kaXNhYmxlLA0KPj4g
KwkuY3B1X2RpZQk9IGdlbmVyaWNfY3B1X2RpZSwNCj4+ICsjZW5kaWYNCj4NCj5Pbmx5IGZpbGwg
dGhlc2UgZmllbGRzIGluIG9uIGU1MDB2MS92MiwgdW50aWwgd2UgcHJvcGVybHkgc3VwcG9ydCBl
NTAwbWMuDQo+TGlrZXdpc2UgaW4gcHBjX21kLmNwdV9kaWUgYW5kIGFueXdoZXJlIGVsc2Ugd2Ug
YWR2ZXJ0aXNlIHRoaXMNCj5mdW5jdGlvbmFsaXR5Lg0KDQpJcyB0aGVyZSBhIHN0YW5kYXJkIGZ1
bmN0aW9uIGNhbGwgdGhhdCBjYW4gdGVsbCB0aGF0IGl0IGlzIGFuIGU1MDBtYyBub3QgbGVnYWN5
IGU1MDA/DQoNCi0gTGVvDQo=
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface
2011-11-17 0:17 ` Scott Wood
@ 2011-11-17 11:53 ` Zhao Chenhui
2011-11-17 19:54 ` Scott Wood
0 siblings, 1 reply; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-17 11:53 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Wed, Nov 16, 2011 at 06:17:56PM -0600, Scott Wood wrote:
> On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> > From: Li Yang <leoli@freescale.com>
> >
> > Some 85xx silicons like MPC8536 and P1022 has the JOG PM feature.
>
> P1023 as well -- any plan to support?
>
> I see this in the p1022 and mpc8536 manuals:
>
> > The system operates as if a request to enter sleep mode has occurred, with the exception that the
> > values written into the PMCDR register (clock disable register for sleep/ deep sleep modes) are
> > ignored, and it is treated as if every bit in PMCDR is a logic 1. This means that the eTSECs, USB
> > controllers, DDR and eLBC will be stopped.
>
> ...which doesn't sound good.
>
> > The patch adds the support to change CPU frequency using the standard
> > cpufreq interface. Add the all PLL ratio core support. The ratio CORE
> > to CCB can 1:1(except MPC8536), 3:2, 2:1, 5:2, 3:1, 7:2 and 4:1.
>
> The ratios supported are implementation-specific. Only p1022 supports
> 1:1. p1023 supports only 3:2, 2:1, 5:2, and 3:1 (assuming the
> preliminary manual I have is accurate).
>
> > + local_irq_save(flags);
> > + /*
> > + * A Jog request can not be asserted when any core is in a low power
> > + * state. Before executing a jog request, any core which is in
> > + * a low power state must be waked by a interrupt.
> > + */
> > + if (mpc85xx_freqs == p1022_freqs_table) {
> > + powersave = ppc_md.power_save;
> > + ppc_md.power_save = NULL;
> > + wmb();
> > + val = in_be32(guts + POWMGTCSR);
> > + for_each_online_cpu(i) {
> > + if (val & ((POWMGTCSR_CORE0_DOZING |
> > + POWMGTCSR_CORE0_NAPPING) << (i * 2)))
> > + smp_send_reschedule(i);
> > + }
> > + }
>
> This is racy, what if another core read ppc_md.power_save just before
> you wrote NULL, but hasn't yet entered a low power state?
>
Yes, It's rare but it is possible. Perhaps I can check if the core is
in ppc_md.power_save() by the flag _TLF_NAPPING.
> You should send a reschedule to all cores regardless of what you see in
> POWMGTCSR.
>
> The p1022 also says that MSR[EE] should be zero -- it is on this core,
> but what about the other?
>
> > + setbits32(guts + POWMGTCSR, POWMGTCSR_JOG_MASK);
>
> This might work on p1022, but don't you have to go through a core reset
> on mpc8536? In that case, you can't just set the bit, you have to go
> through the deep sleep code to save/restore state.
>
> P1022 also says, "Mask all the interrupts to the cores by setting the
> bits CORE_UDE_MSK, CORE_MCP_MSK, CORE_INT_MSK and CORE_CINT_MSK in the
> POWMGTCSR," which I don't see happening.
I will fix them.
>
> Though, this directly contradicts where it later says, "The user must
> not issue a jog request at the same time as issuing a request
> for another low power mode, or while the system is in the process of
> entering a low power mode. This means that a jog request must not be
> asserted when any other bit of POWMGTCSR is non-zero. If the user tries
> to do this, the jog request is ignored."
>
> POWMGTCSR must be zero except for the JOG bit, but you must set other
> POWMGTCSR bits. Lovely. :-P I assume that the "This means..."
> statement is just wrong, and you really are supposed to set those other
> bits. P1023 refines the statement to, "This means that POWMGTCSR[JOG]
> must not be asserted when any of the other power management request bits
> (COREn_DOZ, SLP) in POWMGTCSR are set."
>
> > + if (powersave) {
> > + ppc_md.power_save = powersave;
> > + wmb();
> > + }
>
> How do you know the jog has happened at this point? Just because you've
> issued a store that requests it doesn't mean it has taken effect by the
> time you execute the next instruction.
>
> > + local_irq_restore(flags);
> > +
> > + /* verify */
> > + if (!spin_event_timeout(get_pll(hw_cpu) == pll, 10000, 10)) {
> > + pr_err("%s: Fail to switch the core frequency. "
> > + "The current PLL of core %d is %d instead of %d.\n",
> > + __func__, hw_cpu, get_pll(hw_cpu), pll);
> > + ret = -EINVAL;
> > + }
>
> Shouldn't the pll be where it's supposed to be as soon as we resume
> execution? I don't see a need to spin here, provided we properly wait
> for the jog to happen earlier (which we want to do so that we don't
> enable power_save and EE early).
I found some delay is needed to wait the pll to update in tests.
-chenhui
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support
2011-11-17 11:16 ` Li Yang-R58472
@ 2011-11-17 19:44 ` Scott Wood
0 siblings, 0 replies; 20+ messages in thread
From: Scott Wood @ 2011-11-17 19:44 UTC (permalink / raw)
To: Li Yang-R58472
Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org,
Zhao Chenhui-B35336
On Thu, Nov 17, 2011 at 05:16:09AM -0600, Li Yang-R58472 wrote:
>
>
> >Cc: linuxppc-dev@lists.ozlabs.org; Li Yang-R58472
> >Subject: Re: [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support
> >
> >On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> >> +static void __cpuinit smp_85xx_mach_cpu_die(void) {
> >> + unsigned int cpu = smp_processor_id();
> >> + register u32 tmp;
> >> +
> >> + local_irq_disable();
> >> + idle_task_exit();
> >> + generic_set_cpu_dead(cpu);
> >> + mb();
> >> +
> >> + mtspr(SPRN_TCR, 0);
> >> + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
> >
> >Clearing these bits in TSR should be unnecessary since we clear TCR -- and
> >doesn't really accomplish anything since the TSR bits can continue to be
> >set.
>
> I also recommend setting the CORE_IRQ_MASK and CORE_CI_MASK in the
> POWMGTCSR register so that no interrupt will wakeup the core from NAP.
Any interrupt that we don't want to use as a wakeup source should already
be disabled at the MPIC. Won't disabling IRQs in POWMGTCSR prevent us
from being woken by devices that we want to use as a wakeup source?
> >If watchdog is in use, we need to set the period to the highest possible
> >to effectively disable it.
>
> Setting it to the highest timeout doesn't really disable the watchdog.
It means the watchdog won't expire for thousands of years, which is
beyond any reasonable design parameter for uptime.
We already do this in Topaz when entering nap.
> >> +static int __cpuinit smp_85xx_kick_cpu(int nr)
> >> +
> >> {
> >> unsigned long flags;
> >> const u64 *cpu_rel_addr;
> >> - __iomem u32 *bptr_vaddr;
> >> + __iomem struct epapr_spin_table *epapr;
> >
> >Please don't call this just "epapr". That's like calling a reference to
> >any powerpc-specific struct "powerpc".
> >
> >How about "spin_table"?
>
> You mean the name of the variable not the structure, right? I agree.
Right, the variable name.
> >> struct smp_ops_t smp_85xx_ops = {
> >> .kick_cpu = smp_85xx_kick_cpu,
> >> + .setup_cpu = smp_85xx_setup_cpu,
> >> +#ifdef CONFIG_HOTPLUG_CPU
> >> + .cpu_disable = generic_cpu_disable,
> >> + .cpu_die = generic_cpu_die,
> >> +#endif
> >
> >Only fill these fields in on e500v1/v2, until we properly support e500mc.
> >Likewise in ppc_md.cpu_die and anywhere else we advertise this
> >functionality.
>
> Is there a standard function call that can tell that it is an e500mc not legacy e500?
Use CONFIG_E500MC -- we don't support combined e500v2/e500mc kernels for
other reasons.
If that ever changes, we'll need to do something based on the cpu table.
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface
2011-11-17 11:53 ` Zhao Chenhui
@ 2011-11-17 19:54 ` Scott Wood
0 siblings, 0 replies; 20+ messages in thread
From: Scott Wood @ 2011-11-17 19:54 UTC (permalink / raw)
To: Zhao Chenhui; +Cc: linuxppc-dev
On Thu, Nov 17, 2011 at 07:53:22PM +0800, Zhao Chenhui wrote:
> On Wed, Nov 16, 2011 at 06:17:56PM -0600, Scott Wood wrote:
> > On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> > > + local_irq_save(flags);
> > > + /*
> > > + * A Jog request can not be asserted when any core is in a low power
> > > + * state. Before executing a jog request, any core which is in
> > > + * a low power state must be waked by a interrupt.
> > > + */
> > > + if (mpc85xx_freqs == p1022_freqs_table) {
> > > + powersave = ppc_md.power_save;
> > > + ppc_md.power_save = NULL;
> > > + wmb();
> > > + val = in_be32(guts + POWMGTCSR);
> > > + for_each_online_cpu(i) {
> > > + if (val & ((POWMGTCSR_CORE0_DOZING |
> > > + POWMGTCSR_CORE0_NAPPING) << (i * 2)))
> > > + smp_send_reschedule(i);
> > > + }
> > > + }
> >
> > This is racy, what if another core read ppc_md.power_save just before
> > you wrote NULL, but hasn't yet entered a low power state?
> >
>
> Yes, It's rare but it is possible. Perhaps I can check if the core is
> in ppc_md.power_save() by the flag _TLF_NAPPING.
There's still a race window between when power_save is checked and when
_TLF_NAPPING is set.
Just send the IPI unconditionally to all CPUs. Since we want to clear
MSR[EE] on all CPUs, what we really want is probably smp_call_function().
The called function would be entered with interrupts disabled, should
update an atomic counter to check in with the main core, and should wait
for the main core to indicate that jog is finished and it's OK to return.
> > > + local_irq_restore(flags);
> > > +
> > > + /* verify */
> > > + if (!spin_event_timeout(get_pll(hw_cpu) == pll, 10000, 10)) {
> > > + pr_err("%s: Fail to switch the core frequency. "
> > > + "The current PLL of core %d is %d instead of %d.\n",
> > > + __func__, hw_cpu, get_pll(hw_cpu), pll);
> > > + ret = -EINVAL;
> > > + }
> >
> > Shouldn't the pll be where it's supposed to be as soon as we resume
> > execution? I don't see a need to spin here, provided we properly wait
> > for the jog to happen earlier (which we want to do so that we don't
> > enable power_save and EE early).
>
> I found some delay is needed to wait the pll to update in tests.
This delay should happen earlier -- you should spin waiting for
POWMGTCSR[JOG] to clear before you enable interrupts, restore
ppc_md.power_save, or do any other cleanup that assumes you're done with
the jog.
Have you seen the PLL not be updated after POWMGTCSR[JOG] is clear?
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-16 18:42 ` [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Scott Wood
@ 2011-11-18 10:12 ` Zhao Chenhui
2011-11-18 14:35 ` Kumar Gala
1 sibling, 0 replies; 20+ messages in thread
From: Zhao Chenhui @ 2011-11-18 10:12 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
On Wed, Nov 16, 2011 at 12:42:14PM -0600, Scott Wood wrote:
> On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> > From: Li Yang <leoli@freescale.com>
> >
> > The timebase sync is not only necessary when using KEXEC. It should also
> > be used by normal boot up and cpu hotplug. Remove the ifdef added by
> > the KEXEC patch.
>
> Again, no it should not be used by normal boot up (whether KEXEC support
> is enabled or not). We should only do timebase sync when we actually
> need to (when we've actually just reset a core), and we should do it the
> way U-Boot does rather than with smp-tbsync.c.
>
> -Scott
OK. I'll do it the way U-Boot does.
Thanks.
-chenhui
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-16 18:42 ` [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Scott Wood
2011-11-18 10:12 ` Zhao Chenhui
@ 2011-11-18 14:35 ` Kumar Gala
2011-11-18 18:01 ` Scott Wood
1 sibling, 1 reply; 20+ messages in thread
From: Kumar Gala @ 2011-11-18 14:35 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Zhao Chenhui
On Nov 16, 2011, at 12:42 PM, Scott Wood wrote:
> On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
>> From: Li Yang <leoli@freescale.com>
>>=20
>> The timebase sync is not only necessary when using KEXEC. It should =
also
>> be used by normal boot up and cpu hotplug. Remove the ifdef added by
>> the KEXEC patch.
>=20
> Again, no it should not be used by normal boot up (whether KEXEC =
support
> is enabled or not). We should only do timebase sync when we actually
> need to (when we've actually just reset a core), and we should do it =
the
> way U-Boot does rather than with smp-tbsync.c.
How can we do u-boot bases timebase sync after the system us up and =
running? For example would we losing some ticks of time in the case =
that one core is up and we bring a second core online?
- k=
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-18 14:35 ` Kumar Gala
@ 2011-11-18 18:01 ` Scott Wood
2011-11-20 16:46 ` Kumar Gala
2011-11-22 9:29 ` Li Yang-R58472
0 siblings, 2 replies; 20+ messages in thread
From: Scott Wood @ 2011-11-18 18:01 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Zhao Chenhui
On Fri, Nov 18, 2011 at 08:35:02AM -0600, Kumar Gala wrote:
>
> On Nov 16, 2011, at 12:42 PM, Scott Wood wrote:
>
> > On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
> >> From: Li Yang <leoli@freescale.com>
> >>
> >> The timebase sync is not only necessary when using KEXEC. It should also
> >> be used by normal boot up and cpu hotplug. Remove the ifdef added by
> >> the KEXEC patch.
> >
> > Again, no it should not be used by normal boot up (whether KEXEC support
> > is enabled or not). We should only do timebase sync when we actually
> > need to (when we've actually just reset a core), and we should do it the
> > way U-Boot does rather than with smp-tbsync.c.
>
>
> How can we do u-boot bases timebase sync after the system us up and
> running? For example would we losing some ticks of time in the case
> that one core is up and we bring a second core online?
Yes, we'll lose a small handful of ticks relative to wall clock time --
but it'll be the same loss on all cores. It's better than possibly
having the timebase be imperfectly synchronized, and should complete more
quickly.
This is only during intrusive events such as kexec or deep sleep (we only
need to reset the core for jog on mpc8536 which has only one core).
During deep sleep all cores' timebases will be stopped. Kexec is
resetting the kernel; it's not going to care what the old timebase was,
and should resync from RTC.
Even if we end up using this for some future power management mode where
we take down some CPUs to the point their timebase stops, but never take
down others, the time loss should be negligible (for comparison, what's
the error tolerance on the crystal frequency?) and acceptable for what is
still a fairly intrusive and rare event.
-Scott
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-18 18:01 ` Scott Wood
@ 2011-11-20 16:46 ` Kumar Gala
2011-11-22 9:29 ` Li Yang-R58472
1 sibling, 0 replies; 20+ messages in thread
From: Kumar Gala @ 2011-11-20 16:46 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Zhao Chenhui
On Nov 18, 2011, at 12:01 PM, Scott Wood wrote:
> On Fri, Nov 18, 2011 at 08:35:02AM -0600, Kumar Gala wrote:
>>=20
>> On Nov 16, 2011, at 12:42 PM, Scott Wood wrote:
>>=20
>>> On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
>>>> From: Li Yang <leoli@freescale.com>
>>>>=20
>>>> The timebase sync is not only necessary when using KEXEC. It should =
also
>>>> be used by normal boot up and cpu hotplug. Remove the ifdef added =
by
>>>> the KEXEC patch.
>>>=20
>>> Again, no it should not be used by normal boot up (whether KEXEC =
support
>>> is enabled or not). We should only do timebase sync when we =
actually
>>> need to (when we've actually just reset a core), and we should do it =
the
>>> way U-Boot does rather than with smp-tbsync.c.
>>=20
>>=20
>> How can we do u-boot bases timebase sync after the system us up and
>> running? For example would we losing some ticks of time in the case
>> that one core is up and we bring a second core online?
>=20
> Yes, we'll lose a small handful of ticks relative to wall clock time =
--
> but it'll be the same loss on all cores. It's better than possibly
> having the timebase be imperfectly synchronized, and should complete =
more
> quickly.
Hmm, I wondering how many ticks it really is.
> This is only during intrusive events such as kexec or deep sleep (we =
only
> need to reset the core for jog on mpc8536 which has only one core).=20
> During deep sleep all cores' timebases will be stopped. Kexec is
> resetting the kernel; it's not going to care what the old timebase =
was,
> and should resync from RTC.
>=20
> Even if we end up using this for some future power management mode =
where
> we take down some CPUs to the point their timebase stops, but never =
take
> down others, the time loss should be negligible (for comparison, =
what's
> the error tolerance on the crystal frequency?) and acceptable for what =
is
> still a fairly intrusive and rare event.
I'm also concerned about how this ends up working for p4080 when we have =
to sync up to 8 cores or more in the future.
- k=
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-18 18:01 ` Scott Wood
2011-11-20 16:46 ` Kumar Gala
@ 2011-11-22 9:29 ` Li Yang-R58472
2011-11-22 16:05 ` Kumar Gala
1 sibling, 1 reply; 20+ messages in thread
From: Li Yang-R58472 @ 2011-11-22 9:29 UTC (permalink / raw)
To: Wood Scott-B07421, Kumar Gala
Cc: linuxppc-dev@lists.ozlabs.org, Zhao Chenhui-B35336
>Subject: Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled
>by KEXEC patch
>
>On Fri, Nov 18, 2011 at 08:35:02AM -0600, Kumar Gala wrote:
>>
>> On Nov 16, 2011, at 12:42 PM, Scott Wood wrote:
>>
>> > On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
>> >> From: Li Yang <leoli@freescale.com>
>> >>
>> >> The timebase sync is not only necessary when using KEXEC. It should
>also
>> >> be used by normal boot up and cpu hotplug. Remove the ifdef added by
>> >> the KEXEC patch.
>> >
>> > Again, no it should not be used by normal boot up (whether KEXEC
>support
>> > is enabled or not). We should only do timebase sync when we actually
>> > need to (when we've actually just reset a core), and we should do it
>the
>> > way U-Boot does rather than with smp-tbsync.c.
While looking into the timebase sync code in u-boot, I have a few questions=
.
/* enable time base at the platform */
if (whoami)
devdisr |=3D MPC85xx_DEVDISR_TB1;
else
devdisr |=3D MPC85xx_DEVDISR_TB0;
out_be32(&gur->devdisr, devdisr);
/* readback to sync write */
in_be32(&gur->devdisr);
mtspr(SPRN_TBWU, 0);
mtspr(SPRN_TBWL, 0);
What are the TBWU/TBWL registers? I can't find the definition of them in e=
ither e500 RM or booke RM. Are they valid to be used? What is the result =
of writing to them? Aren't the SPR registers core specific? How can we se=
t the TB for the other cores?
devdisr &=3D ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
out_be32(&gur->devdisr, devdisr);
Also in the UM, I read "Blocks disabled by DEVDISR must not be re-enabled w=
ithout a hard reset." Is it safe we enable it here?
- Leo
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch
2011-11-22 9:29 ` Li Yang-R58472
@ 2011-11-22 16:05 ` Kumar Gala
0 siblings, 0 replies; 20+ messages in thread
From: Kumar Gala @ 2011-11-22 16:05 UTC (permalink / raw)
To: Li Yang-R58472
Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org,
Zhao Chenhui-B35336
On Nov 22, 2011, at 3:29 AM, Li Yang-R58472 wrote:
>> Subject: Re: [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync =
disabled
>> by KEXEC patch
>>=20
>> On Fri, Nov 18, 2011 at 08:35:02AM -0600, Kumar Gala wrote:
>>>=20
>>> On Nov 16, 2011, at 12:42 PM, Scott Wood wrote:
>>>=20
>>>> On 11/16/2011 03:55 AM, Zhao Chenhui wrote:
>>>>> From: Li Yang <leoli@freescale.com>
>>>>>=20
>>>>> The timebase sync is not only necessary when using KEXEC. It =
should
>> also
>>>>> be used by normal boot up and cpu hotplug. Remove the ifdef added =
by
>>>>> the KEXEC patch.
>>>>=20
>>>> Again, no it should not be used by normal boot up (whether KEXEC
>> support
>>>> is enabled or not). We should only do timebase sync when we =
actually
>>>> need to (when we've actually just reset a core), and we should do =
it
>> the
>>>> way U-Boot does rather than with smp-tbsync.c.
>=20
> While looking into the timebase sync code in u-boot, I have a few =
questions.
>=20
> /* enable time base at the platform */
> if (whoami)
> devdisr |=3D MPC85xx_DEVDISR_TB1;
> else
> devdisr |=3D MPC85xx_DEVDISR_TB0;
> out_be32(&gur->devdisr, devdisr);
>=20
> /* readback to sync write */
> in_be32(&gur->devdisr);
>=20
> mtspr(SPRN_TBWU, 0);
> mtspr(SPRN_TBWL, 0);
>=20
> What are the TBWU/TBWL registers? I can't find the definition of them =
in either e500 RM or booke RM. Are they valid to be used? What is the =
result of writing to them? Aren't the SPR registers core specific? How =
can we set the TB for the other cores?
TBWU/TBWL are SPR 284/285 (they might be called something a little =
different in the manual).
You can only set the TB on the core itself. The way the u-boot code =
works is it sets TBL/TBU (TB) to 0 in release.S for secondary cores. In =
the code you reference we are setting TB on the 'master' core to 0 since =
we turned TB on earlier for the master core and now are resetting it to =
0 to sync all the cores.
>=20
> devdisr &=3D ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
> out_be32(&gur->devdisr, devdisr);
>=20
> Also in the UM, I read "Blocks disabled by DEVDISR must not be =
re-enabled without a hard reset." Is it safe we enable it here?
Yes this is safe, TB isn't truly a block. Manual should technically be =
updated to exclude TB.
- k=
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2011-11-22 16:05 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-16 9:55 [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 2/7] powerpc/85xx: add HOTPLUG_CPU support Zhao Chenhui
2011-11-16 19:02 ` Scott Wood
2011-11-17 11:16 ` Li Yang-R58472
2011-11-17 19:44 ` Scott Wood
2011-11-16 9:55 ` [PATCH v2 3/7] powerpc/85xx: add sleep and deep sleep support Zhao Chenhui
2011-11-16 21:42 ` Scott Wood
2011-11-16 9:55 ` [PATCH v2 4/7] powerpc/85xx: add support to JOG feature using cpufreq interface Zhao Chenhui
2011-11-17 0:17 ` Scott Wood
2011-11-17 11:53 ` Zhao Chenhui
2011-11-17 19:54 ` Scott Wood
2011-11-16 9:55 ` [PATCH v2 5/7] fsl_pmc: update device bindings Zhao Chenhui
2011-11-16 9:55 ` [PATCH v2 6/7] fsl_pmc: Add API to enable device as wakeup event source Zhao Chenhui
2011-11-16 18:42 ` [PATCH v2 1/7] powerpc/85xx: re-enable timebase sync disabled by KEXEC patch Scott Wood
2011-11-18 10:12 ` Zhao Chenhui
2011-11-18 14:35 ` Kumar Gala
2011-11-18 18:01 ` Scott Wood
2011-11-20 16:46 ` Kumar Gala
2011-11-22 9:29 ` Li Yang-R58472
2011-11-22 16:05 ` Kumar Gala
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).