Page MenuHomeFreeBSD

D29136.id85360.diff
No OneTemporary

D29136.id85360.diff

diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c
--- a/sys/powerpc/aim/mp_cpudep.c
+++ b/sys/powerpc/aim/mp_cpudep.c
@@ -312,7 +312,8 @@
vers = mfpvr() >> 16;
/* The following is needed for restoring from sleep. */
- platform_smp_timebase_sync(0, 1);
+ if (PCPU_GET(restore))
+ platform_smp_timebase_sync(0, 1);
switch(vers) {
case IBM970:
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
--- a/sys/powerpc/powermac/macio.c
+++ b/sys/powerpc/powermac/macio.c
@@ -54,6 +54,7 @@
#include <dev/ofw/openfirm.h>
#include <powerpc/powermac/maciovar.h>
+#include <powerpc/powermac/platform_powermac.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -70,6 +71,9 @@
/* FCR registers */
int sc_memrid;
struct resource *sc_memr;
+
+ /* GPIO offsets */
+ int sc_timebase;
};
static MALLOC_DEFINE(M_MACIO, "macio", "macio device information");
@@ -89,6 +93,9 @@
struct resource *);
static struct resource_list *macio_get_resource_list (device_t, device_t);
static ofw_bus_get_devinfo_t macio_get_devinfo;
+#if !defined(__powerpc64__) && defined(SMP)
+static void macio_freeze_timebase(device_t, bool);
+#endif
/*
* Bus interface definition
@@ -430,6 +437,26 @@
}
}
+#if !defined(__powerpc64__) && defined(SMP)
+ /*
+ * Detect an SMP G4 machine.
+ *
+ * On SMP G4, timebase freeze is via a GPIO on macio.
+ *
+ * When we are on an SMP G4, we need to install a handler to
+ * perform timebase freeze/unfreeze on behalf of the platform.
+ */
+ if ((child = OF_finddevice("/cpus/PowerPC,G4@0")) != -1 &&
+ OF_peer(child) != -1) {
+ if (OF_getprop(child, "timebase-enable", &sc->sc_timebase,
+ sizeof(sc->sc_timebase)) <= 0)
+ sc->sc_timebase = KEYLARGO_GPIO_BASE + 0x09;
+ powermac_register_timebase(dev, macio_freeze_timebase);
+ device_printf(dev, "GPIO timebase control at 0x%x\n",
+ sc->sc_timebase);
+ }
+#endif
+
return (bus_generic_attach(dev));
}
@@ -693,3 +720,18 @@
return (0);
}
+
+#if !defined(__powerpc64__) && defined(SMP)
+static void
+macio_freeze_timebase(device_t dev, bool frozen)
+{
+ struct macio_softc *sc = device_get_softc(dev);
+
+ if (frozen) {
+ bus_write_1(sc->sc_memr, sc->sc_timebase, 4);
+ } else {
+ bus_write_1(sc->sc_memr, sc->sc_timebase, 0);
+ }
+ bus_read_1(sc->sc_memr, sc->sc_timebase);
+}
+#endif
diff --git a/sys/powerpc/powermac/platform_powermac.h b/sys/powerpc/powermac/platform_powermac.h
new file mode 100644
--- /dev/null
+++ b/sys/powerpc/powermac/platform_powermac.h
@@ -0,0 +1,34 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Brandon Bergren <bdragon@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PLATFORM_POWERMAC_H_
+#define _PLATFORM_POWERMAC_H_
+
+typedef void (*powermac_tb_disable_t)(device_t, bool);
+extern void powermac_register_timebase(device_t, powermac_tb_disable_t);
+
+#endif /* _PLATFORM_POWERMAC_H_ */
diff --git a/sys/powerpc/powermac/platform_powermac.c b/sys/powerpc/powermac/platform_powermac.c
--- a/sys/powerpc/powermac/platform_powermac.c
+++ b/sys/powerpc/powermac/platform_powermac.c
@@ -53,9 +53,17 @@
#include <dev/ofw/openfirm.h>
#include <machine/ofw_machdep.h>
+#include <powerpc/powermac/platform_powermac.h>
+
#include "platform_if.h"
-extern void *ap_pcpu;
+extern volatile void *ap_pcpu;
+
+static void dummy_timebase(device_t, bool);
+static device_t powermac_tb_dev;
+static void (*freeze_timebase)(device_t, bool) = dummy_timebase;
+
+void powermac_register_timebase(device_t, powermac_tb_disable_t);
static int powermac_probe(platform_t);
static int powermac_attach(platform_t);
@@ -391,11 +399,62 @@
#endif
}
+void
+powermac_register_timebase(device_t dev, powermac_tb_disable_t cb)
+{
+ powermac_tb_dev = dev;
+ freeze_timebase = cb;
+}
+
static void
powermac_smp_timebase_sync(platform_t plat, u_long tb, int ap)
{
+ static volatile bool tb_ready;
+ static volatile int cpu_done;
+ /*
+ * XXX Temporary fallback for platforms we don't know how to freeze.
+ *
+ * This needs to be replaced with a cpu-to-cpu software sync
+ * protocol, because this is not a consistent way to sync timebase.
+ */
mttb(tb);
+ if (freeze_timebase == dummy_timebase)
+ return;
+
+ if (ap) {
+ /* APs. Hold off until we get a stable timebase. */
+ critical_enter();
+ while (!tb_ready)
+ atomic_thread_fence_seq_cst();
+ mttb(tb);
+ atomic_add_int(&cpu_done, 1);
+ while (cpu_done < mp_ncpus)
+ atomic_thread_fence_seq_cst();
+ critical_exit();
+ } else {
+ /* BSP */
+ critical_enter();
+ /* Ensure cpu_done is zeroed so we can resync at runtime */
+ atomic_set_int(&cpu_done, 0);
+ freeze_timebase(powermac_tb_dev, true);
+ tb_ready = true;
+ mttb(tb);
+ atomic_add_int(&cpu_done, 1);
+ while (cpu_done < mp_ncpus)
+ atomic_thread_fence_seq_cst();
+ freeze_timebase(powermac_tb_dev, false);
+ /* Reset tb_ready so we can resync at runtime */
+ tb_ready = false;
+ critical_exit();
+ }
+}
+
+/* Fallback freeze. In case no real handler is found in the device tree. */
+static void
+dummy_timebase(device_t dev, bool freeze)
+{
+ /* Nothing to do here, move along. */
}
static void

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 10, 4:35 AM (11 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15739434
Default Alt Text
D29136.id85360.diff (6 KB)

Event Timeline