Page MenuHomeFreeBSD

D29136.diff
No OneTemporary

D29136.diff

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

Mime Type
text/plain
Expires
Tue, Sep 24, 12:24 AM (6 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12609100
Default Alt Text
D29136.diff (10 KB)

Event Timeline