|
@@ -25,6 +25,7 @@
|
|
|
#include <asm/mpic.h>
|
|
|
#include <asm/cacheflush.h>
|
|
|
#include <asm/dbell.h>
|
|
|
+#include <asm/fsl_guts.h>
|
|
|
|
|
|
#include <sysdev/fsl_soc.h>
|
|
|
#include <sysdev/mpic.h>
|
|
@@ -41,6 +42,64 @@ struct epapr_spin_table {
|
|
|
u32 pir;
|
|
|
};
|
|
|
|
|
|
+static struct ccsr_guts __iomem *guts;
|
|
|
+static u64 timebase;
|
|
|
+static int tb_req;
|
|
|
+static int tb_valid;
|
|
|
+
|
|
|
+static void mpc85xx_timebase_freeze(int freeze)
|
|
|
+{
|
|
|
+ uint32_t mask;
|
|
|
+
|
|
|
+ mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
|
|
|
+ if (freeze)
|
|
|
+ setbits32(&guts->devdisr, mask);
|
|
|
+ else
|
|
|
+ clrbits32(&guts->devdisr, mask);
|
|
|
+
|
|
|
+ in_be32(&guts->devdisr);
|
|
|
+}
|
|
|
+
|
|
|
+static void mpc85xx_give_timebase(void)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+
|
|
|
+ while (!tb_req)
|
|
|
+ barrier();
|
|
|
+ tb_req = 0;
|
|
|
+
|
|
|
+ mpc85xx_timebase_freeze(1);
|
|
|
+ timebase = get_tb();
|
|
|
+ mb();
|
|
|
+ tb_valid = 1;
|
|
|
+
|
|
|
+ while (tb_valid)
|
|
|
+ barrier();
|
|
|
+
|
|
|
+ mpc85xx_timebase_freeze(0);
|
|
|
+
|
|
|
+ local_irq_restore(flags);
|
|
|
+}
|
|
|
+
|
|
|
+static void mpc85xx_take_timebase(void)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+
|
|
|
+ tb_req = 1;
|
|
|
+ while (!tb_valid)
|
|
|
+ barrier();
|
|
|
+
|
|
|
+ set_tb(timebase >> 32, timebase & 0xffffffff);
|
|
|
+ isync();
|
|
|
+ tb_valid = 0;
|
|
|
+
|
|
|
+ local_irq_restore(flags);
|
|
|
+}
|
|
|
+
|
|
|
static int __init
|
|
|
smp_85xx_kick_cpu(int nr)
|
|
|
{
|
|
@@ -228,6 +287,16 @@ smp_85xx_setup_cpu(int cpu_nr)
|
|
|
doorbell_setup_this_cpu();
|
|
|
}
|
|
|
|
|
|
+static const struct of_device_id mpc85xx_smp_guts_ids[] = {
|
|
|
+ { .compatible = "fsl,mpc8572-guts", },
|
|
|
+ { .compatible = "fsl,p1020-guts", },
|
|
|
+ { .compatible = "fsl,p1021-guts", },
|
|
|
+ { .compatible = "fsl,p1022-guts", },
|
|
|
+ { .compatible = "fsl,p1023-guts", },
|
|
|
+ { .compatible = "fsl,p2020-guts", },
|
|
|
+ {},
|
|
|
+};
|
|
|
+
|
|
|
void __init mpc85xx_smp_init(void)
|
|
|
{
|
|
|
struct device_node *np;
|
|
@@ -249,6 +318,19 @@ void __init mpc85xx_smp_init(void)
|
|
|
smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
|
|
|
}
|
|
|
|
|
|
+ np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
|
|
|
+ if (np) {
|
|
|
+ guts = of_iomap(np, 0);
|
|
|
+ of_node_put(np);
|
|
|
+ if (!guts) {
|
|
|
+ pr_err("%s: Could not map guts node address\n",
|
|
|
+ __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
|
|
|
+ smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
|
|
|
+ }
|
|
|
+
|
|
|
smp_ops = &smp_85xx_ops;
|
|
|
|
|
|
#ifdef CONFIG_KEXEC
|