Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107493243
D29136.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D29136.diff
View Options
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -216,6 +216,7 @@
powerpc/powermac/pmu.c optional powermac pmu
powerpc/powermac/smu.c optional powermac smu
powerpc/powermac/smusat.c optional powermac smu
+powerpc/powermac/tbgpio.c optional powermac pci smp
powerpc/powermac/uninorth.c optional powermac
powerpc/powermac/uninorthpci.c optional powermac pci
powerpc/powermac/vcoregpio.c optional powermac
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 freeze)
+{
+ struct macio_softc *sc = device_get_softc(dev);
+
+ if (freeze) {
+ 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,15 @@
#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;
static int powermac_probe(platform_t);
static int powermac_attach(platform_t);
@@ -395,11 +401,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
diff --git a/sys/powerpc/powermac/tbgpio.c b/sys/powerpc/powermac/tbgpio.c
new file mode 100644
--- /dev/null
+++ b/sys/powerpc/powermac/tbgpio.c
@@ -0,0 +1,148 @@
+/*-
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/powermac/macgpiovar.h>
+#include <powerpc/powermac/platform_powermac.h>
+
+static int tbgpio_probe(device_t);
+static int tbgpio_attach(device_t);
+static void tbgpio_freeze_timebase(device_t, bool);
+
+static device_method_t tbgpio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tbgpio_probe),
+ DEVMETHOD(device_attach, tbgpio_attach),
+ DEVMETHOD_END
+};
+
+struct tbgpio_softc {
+ uint32_t sc_value;
+ uint32_t sc_mask;
+};
+
+static driver_t tbgpio_driver = {
+ "tbgpio",
+ tbgpio_methods,
+ sizeof(struct tbgpio_softc)
+};
+
+static devclass_t tbgpio_devclass;
+
+EARLY_DRIVER_MODULE(tbgpio, macgpio, tbgpio_driver, tbgpio_devclass, 0, 0,
+ BUS_PASS_CPU);
+
+static int
+tbgpio_probe(device_t dev)
+{
+ phandle_t node;
+ const char *name;
+ pcell_t pfunc[32];
+ int res;
+
+ name = ofw_bus_get_name(dev);
+ node = ofw_bus_get_node(dev);
+
+ if (strcmp(name, "timebase-enable") != 0)
+ return (ENXIO);
+
+ res = OF_getencprop(node, "platform-do-cpu-timebase", pfunc,
+ sizeof(pfunc));
+ if (res == -1)
+ return (ENXIO);
+
+ /*
+ * If this doesn't look like a simple gpio_write pfunc,
+ * complain about it so we can collect the pfunc.
+ */
+ if (res != 20 || pfunc[2] != 0x01) {
+ printf("\nUnknown platform function detected!\n");
+ printf("Please send a PR including the following data:\n");
+ printf("===================\n");
+ printf("Func: platform-do-cpu-timebase\n");
+ hexdump(pfunc, res, NULL, HD_OMIT_CHARS);
+ printf("===================\n");
+ return (ENXIO);
+ }
+
+ device_set_desc(dev, "CPU Timebase Control");
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+tbgpio_attach(device_t dev)
+{
+ phandle_t node;
+ struct tbgpio_softc *sc;
+
+ /*
+ * Structure of pfunc:
+ * pfunc[0]: phandle to /cpus
+ * pfunc[1]: flags
+ * pfunc[2]: 0x1 == CMD_WRITE_GPIO
+ * pfunc[3]: value
+ * pfunc[4]: mask
+ */
+ pcell_t pfunc[5];
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+
+ OF_getencprop(node, "platform-do-cpu-timebase", pfunc, sizeof(pfunc));
+
+ sc->sc_value = pfunc[3];
+ sc->sc_mask = pfunc[4];
+
+ powermac_register_timebase(dev, tbgpio_freeze_timebase);
+ return (0);
+}
+
+static void
+tbgpio_freeze_timebase(device_t dev, bool freeze)
+{
+ struct tbgpio_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ val = sc->sc_value;
+ if (freeze)
+ val = ~val;
+ val &= sc->sc_mask;
+
+ macgpio_write(dev, val);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 15, 11:41 PM (17 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15817382
Default Alt Text
D29136.diff (10 KB)
Attached To
Mode
D29136: WIP: [PowerPC] PowerMac timebase sync for G4
Attached
Detach File
Event Timeline
Log In to Comment