Re: [PATCH v6 1/5] powerpc/85xx: implement hardware timebase sync
From: Tabi Timur-B04825 <hidden>
Date: 2012-06-29 15:39:37
Also in:
lkml
On Tue, Jun 26, 2012 at 5:25 AM, Zhao Chenhui [off-list ref] wrote:
Do hardware timebase sync. Firstly, stop all timebases, and transfer the timebase value of the boot core to the other core. Finally, start all timebases. Only apply to dual-core chips, such as MPC8572, P2020, etc. Signed-off-by: Zhao Chenhui <redacted> Signed-off-by: Li Yang <redacted> --- Changes for v6: =A0* added 85xx_TB_SYNC =A0* added isync() after set_tb() =A0* removed extra entries from mpc85xx_smp_guts_ids =A0arch/powerpc/include/asm/fsl_guts.h | =A0 =A02 + =A0arch/powerpc/platforms/85xx/Kconfig | =A0 =A05 ++ =A0arch/powerpc/platforms/85xx/smp.c =A0 | =A0 84 +++++++++++++++++++++++=
++++++++++++
quoted hunk ↗ jump to hunk
=A03 files changed, 91 insertions(+), 0 deletions(-)diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/a=
sm/fsl_guts.h
quoted hunk ↗ jump to hunk
index aa4c488..dd5ba2c 100644--- a/arch/powerpc/include/asm/fsl_guts.h +++ b/arch/powerpc/include/asm/fsl_guts.h@@ -48,6 +48,8 @@ struct ccsr_guts {=A0 =A0 =A0 =A0 __be32 =A0dmuxcr; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* 0x.00=
68 - DMA Mux Control Register */
=A0 =A0 =A0 =A0 u8 =A0 =A0 res06c[0x70 - 0x6c]; =A0 =A0 =A0 =A0__be32 =A0devdisr; =A0 =A0 =A0 =A0/* 0x.0070 - Device Disa=
ble Control */
+#define CCSR_GUTS_DEVDISR_TB1 =A00x00001000 +#define CCSR_GUTS_DEVDISR_TB0 =A00x00004000 =A0 =A0 =A0 =A0__be32 =A0devdisr2; =A0 =A0 =A0 /* 0x.0074 - Device Disabl=
e Control 2 */
=A0 =A0 =A0 =A0u8 =A0 =A0 =A0res078[0x7c - 0x78]; =A0 =A0 =A0 =A0__be32 =A0pmjcr; =A0 =A0 =A0 =A0 =A0/* 0x.007c - 4 Power M=
anagement Jog Control Register */
quoted hunk ↗ jump to hunk
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms=
/85xx/Kconfig
quoted hunk ↗ jump to hunk
index f000d81..8dd7147 100644--- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE=A0 =A0 =A0 =A0select FSL_PCI if PCI =A0 =A0 =A0 =A0select SERIAL_8250_EXTENDED if SERIAL_8250 =A0 =A0 =A0 =A0select SERIAL_8250_SHARE_IRQ if SERIAL_8250 + =A0 =A0 =A0 select 85xx_TB_SYNC if KEXEC =A0 =A0 =A0 =A0default y =A0if FSL_SOC_BOOKE@@ -267,3 +268,7 @@ endif # FSL_SOC_BOOKE=A0config TQM85xx =A0 =A0 =A0 =A0bool + +config 85xx_TB_SYNC + =A0 =A0 =A0 bool + =A0 =A0 =A0 default ndiff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/8=
5xx/smp.c
quoted hunk ↗ jump to hunk
index ff42490..edb0cad 100644--- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c@@ -24,6 +24,7 @@=A0#include <asm/mpic.h> =A0#include <asm/cacheflush.h> =A0#include <asm/dbell.h> +#include <asm/fsl_guts.h> =A0#include <sysdev/fsl_soc.h> =A0#include <sysdev/mpic.h>@@ -42,6 +43,69 @@ extern void __early_start(void);=A0#define NUM_BOOT_ENTRY =A0 =A0 =A0 =A0 8 =A0#define SIZE_BOOT_ENTRY =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(NUM_BOOT_ENTRY=
* sizeof(u32))
+#ifdef CONFIG_85xx_TB_SYNC
+static struct ccsr_guts __iomem *guts;
+static u64 timebase;
+static int tb_req;
+static int tb_valid;
+
+static void mpc85xx_timebase_freeze(int freeze)
+{
+ =A0 =A0 =A0 unsigned int mask;'mask' should be uint32_t
+ + =A0 =A0 =A0 if (!guts) + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
This function should never be called if guts is NULL, so this check should be unnecessary.
+
+ =A0 =A0 =A0 mask =3D CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
+ =A0 =A0 =A0 if (freeze)
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(&guts->devdisr, mask);
+ =A0 =A0 =A0 else
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 clrbits32(&guts->devdisr, mask);
+
+ =A0 =A0 =A0 in_be32(&guts->devdisr);
+}
+
+static void mpc85xx_give_timebase(void)
+{
+ =A0 =A0 =A0 unsigned long flags;
+
+ =A0 =A0 =A0 local_irq_save(flags);
+
+ =A0 =A0 =A0 while (!tb_req)
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 barrier();I think tb_req and tb_valid need to be 'volatile'.
quoted hunk ↗ jump to hunk
+ =A0 =A0 =A0 tb_req =3D 0; + + =A0 =A0 =A0 mpc85xx_timebase_freeze(1); + =A0 =A0 =A0 timebase =3D get_tb(); + =A0 =A0 =A0 mb(); + =A0 =A0 =A0 tb_valid =3D 1; + + =A0 =A0 =A0 while (tb_valid) + =A0 =A0 =A0 =A0 =A0 =A0 =A0 barrier(); + + =A0 =A0 =A0 mpc85xx_timebase_freeze(0); + + =A0 =A0 =A0 local_irq_restore(flags); +} + +static void mpc85xx_take_timebase(void) +{ + =A0 =A0 =A0 unsigned long flags; + + =A0 =A0 =A0 local_irq_save(flags); + + =A0 =A0 =A0 tb_req =3D 1; + =A0 =A0 =A0 while (!tb_valid) + =A0 =A0 =A0 =A0 =A0 =A0 =A0 barrier(); + + =A0 =A0 =A0 set_tb(timebase >> 32, timebase & 0xffffffff); + =A0 =A0 =A0 isync(); + =A0 =A0 =A0 tb_valid =3D 0; + + =A0 =A0 =A0 local_irq_restore(flags); +} +#endif + =A0static int __init =A0smp_85xx_kick_cpu(int nr) =A0{@@ -228,6 +292,16 @@ smp_85xx_setup_cpu(int cpu_nr)=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0doorbell_setup_this_cpu(); =A0} +static const struct of_device_id mpc85xx_smp_guts_ids[] =3D { + =A0 =A0 =A0 { .compatible =3D "fsl,mpc8572-guts", }, + =A0 =A0 =A0 { .compatible =3D "fsl,p1020-guts", }, + =A0 =A0 =A0 { .compatible =3D "fsl,p1021-guts", }, + =A0 =A0 =A0 { .compatible =3D "fsl,p1022-guts", }, + =A0 =A0 =A0 { .compatible =3D "fsl,p1023-guts", }, + =A0 =A0 =A0 { .compatible =3D "fsl,p2020-guts", }, + =A0 =A0 =A0 {}, +};
I wonder if it's possible to dynamically generate the compatible string by using the SOC name?
quoted hunk ↗ jump to hunk
+ =A0void __init mpc85xx_smp_init(void) =A0{ =A0 =A0 =A0 =A0struct device_node *np;@@ -249,6 +323,16 @@ void __init mpc85xx_smp_init(void)=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0smp_85xx_ops.cause_ipi =3D doorbell_cause_=
ipi;
=A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 np =3D of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
+ =A0 =A0 =A0 if (np) {
+#ifdef CONFIG_85xx_TB_SYNC
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 guts =3D of_iomap(np, 0);You need to test the return value of of_iomap(). smp_85xx_ops should be set only if guts is not NULL.
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 smp_85xx_ops.give_timebase =3D mpc85xx_give=
_timebase;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 smp_85xx_ops.take_timebase =3D mpc85xx_take=
_timebase;
+#endif + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(np); + =A0 =A0 =A0 } + =A0 =A0 =A0 =A0smp_ops =3D &smp_85xx_ops; =A0#ifdef CONFIG_KEXEC -- 1.6.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" i=
n
the body of a message to majordomo@vger.kernel.org More majordomo info at =A0http://vger.kernel.org/majordomo-info.html Please read the FAQ at =A0http://www.tux.org/lkml/
--=20 Timur Tabi Linux kernel developer at Freescale=