-/* $OpenBSD: cpu.c,v 1.37 2017/04/24 18:15:16 kettenis Exp $ */
+/* $OpenBSD: cpu.c,v 1.38 2017/04/27 22:41:46 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.56 2004/04/14 04:01:49 bsh Exp $ */
#include <uvm/uvm_extern.h>
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/fdt.h>
#include <arm/cpuconf.h>
#include <arm/undefined.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
char cpu_model[256];
-/* Prototypes */
+int cpu_match(struct device *, void *, void *);
+void cpu_attach(struct device *, struct device *, void *);
+
+struct cfattach cpu_ca = {
+ sizeof(struct device), cpu_match, cpu_attach
+};
+
+struct cfdriver cpu_cd = {
+ NULL, "cpu", DV_DULL
+};
+
void identify_arm_cpu(struct device *dv, struct cpu_info *);
-/*
- * Identify the master (boot) CPU
- */
-
+int
+cpu_match(struct device *parent, void *cfdata, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+ char buf[32];
+
+ if (OF_getprop(faa->fa_node, "device_type", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "cpu") == 0)
+ return 1;
+
+ return 0;
+}
+
void
-cpu_attach(struct device *dv)
+cpu_attach(struct device *parent, struct device *dev, void *aux)
{
- curcpu()->ci_dev = dv;
+ struct cpu_info *ci;
- /* Get the CPU ID from coprocessor 15 */
+ if (dev->dv_unit == 0) {
+ ci = curcpu();
+ ci->ci_dev = dev;
- curcpu()->ci_arm_cpuid = cpu_id();
- curcpu()->ci_arm_cputype = curcpu()->ci_arm_cpuid & CPU_ID_CPU_MASK;
- curcpu()->ci_arm_cpurev =
- curcpu()->ci_arm_cpuid & CPU_ID_REVISION_MASK;
+ /* Get the CPU ID from coprocessor 15 */
+ ci->ci_arm_cpuid = cpu_id();
+ ci->ci_arm_cputype =
+ ci->ci_arm_cpuid & CPU_ID_CPU_MASK;
+ ci->ci_arm_cpurev =
+ ci->ci_arm_cpuid & CPU_ID_REVISION_MASK;
- identify_arm_cpu(dv, curcpu());
+ identify_arm_cpu(dev, ci);
+ } else {
+ printf(": not configured");
+ }
}
enum cpu_class {
+++ /dev/null
-/* $OpenBSD: cpu_mainbus.c,v 1.2 2016/05/02 08:15:55 patrick Exp $ */
-/* $NetBSD: cpu_mainbus.c,v 1.3 2002/01/05 22:41:48 chris Exp $ */
-
-/*
- * Copyright (c) 1995 Mark Brinicombe.
- * Copyright (c) 1995 Brini.
- * All rights reserved.
- *
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Brini.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
- *
- * RiscBSD kernel project
- *
- * cpu.c
- *
- * Probing and configuration for the master cpu
- *
- * Created : 10/10/95
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/device.h>
-#include <sys/proc.h>
-#if 0
-#include <uvm/uvm_extern.h>
-#include <machine/io.h>
-#include <machine/conf.h>
-#endif
-#include <machine/cpu.h>
-#if 0
-#include <arm/cpus.h>
-#include <arm/undefined.h>
-#endif
-#include <arm/mainbus/mainbus.h>
-
-/*
- * Prototypes
- */
-static int cpu_mainbus_match (struct device *, void *, void *);
-static void cpu_mainbus_attach (struct device *, struct device *, void *);
-
-/*
- * int cpumatch(struct device *parent, struct cfdata *cf, void *aux)
- */
-
-static int
-cpu_mainbus_match(struct device *parent, void *vcf, void *aux)
-{
- union mainbus_attach_args *ma = aux;
- struct cfdata *cf = (struct cfdata *)vcf;
-
- return (strcmp(cf->cf_driver->cd_name, ma->ma_name) == 0);
-}
-
-/*
- * void cpusattach(struct device *parent, struct device *dev, void *aux)
- *
- * Attach the main cpu
- */
-
-static void
-cpu_mainbus_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
-{
- cpu_attach(self);
-}
-
-struct cfattach cpu_mainbus_ca = {
- sizeof(struct device), cpu_mainbus_match, cpu_mainbus_attach
-};
-
-struct cfdriver cpu_cd = {
- NULL, "cpu", DV_DULL
-};
-/* $OpenBSD: mainbus.c,v 1.15 2017/01/06 00:06:02 jsg Exp $ */
+/* $OpenBSD: mainbus.c,v 1.16 2017/04/27 22:41:46 kettenis Exp $ */
/*
* Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
+ * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
int mainbus_match(struct device *, void *, void *);
void mainbus_attach(struct device *, struct device *, void *);
-void mainbus_attach_node(struct device *, int);
+void mainbus_attach_node(struct device *, int, cfmatch_t);
+int mainbus_match_status(struct device *, void *, void *);
+void mainbus_attach_cpus(struct device *, cfmatch_t);
+int mainbus_match_primary(struct device *, void *, void *);
+int mainbus_match_secondary(struct device *, void *, void *);
void mainbus_attach_framebuffer(struct device *);
-int mainbus_legacy_search(struct device *, void *, void *);
-
struct mainbus_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
mainbus_attach(struct device *parent, struct device *self, void *aux)
{
struct mainbus_softc *sc = (struct mainbus_softc *)self;
- char buffer[128];
+ char model[128];
int node, len;
- if ((node = OF_peer(0)) == 0) {
- printf(": no device tree\n");
- config_search(mainbus_legacy_search, self, aux);
- return;
- }
+ if ((node = OF_peer(0)) == 0)
+ panic("mainbus: no device tree");
arm_intr_init_fdt();
sc->sc_acells = OF_getpropint(OF_peer(0), "#address-cells", 1);
sc->sc_scells = OF_getpropint(OF_peer(0), "#size-cells", 1);
- if ((len = OF_getprop(node, "model", buffer, sizeof(buffer))) > 0) {
- printf(": %s\n", buffer);
+ if ((len = OF_getprop(node, "model", model, sizeof(model))) > 0) {
+ printf(": %s\n", model);
hw_prod = malloc(len, M_DEVBUF, M_NOWAIT);
if (hw_prod)
- strlcpy(hw_prod, buffer, len);
+ strlcpy(hw_prod, model, len);
} else
printf(": unknown model\n");
- /* Attach CPU first. */
- mainbus_legacy_found(self, "cpu");
- platform_init_mainbus(self);
+ /* Attach primary CPU first. */
+ mainbus_attach_cpus(self, mainbus_match_primary);
- /* TODO: Scan for interrupt controllers and attach them first? */
+ platform_init_mainbus(self);
sc->sc_rangeslen = OF_getproplen(OF_peer(0), "ranges");
if (sc->sc_rangeslen > 0 && !(sc->sc_rangeslen % sizeof(uint32_t))) {
/* Scan the whole tree. */
for (node = OF_child(node); node != 0; node = OF_peer(node))
- mainbus_attach_node(self, node);
+ mainbus_attach_node(self, node, NULL);
mainbus_attach_framebuffer(self);
+
+ /* Attach secondary CPUs. */
+ mainbus_attach_cpus(self, mainbus_match_secondary);
}
/*
* Look for a driver that wants to be attached to this node.
*/
void
-mainbus_attach_node(struct device *self, int node)
+mainbus_attach_node(struct device *self, int node, cfmatch_t submatch)
{
struct mainbus_softc *sc = (struct mainbus_softc *)self;
struct fdt_attach_args fa;
- char buffer[128];
int i, len, line;
uint32_t *cell, *reg;
- if (!OF_getprop(node, "compatible", buffer, sizeof(buffer)))
+ if (OF_getproplen(node, "compatible") <= 0)
return;
- if (OF_getprop(node, "status", buffer, sizeof(buffer)))
- if (!strcmp(buffer, "disabled"))
- return;
-
memset(&fa, 0, sizeof(fa));
fa.fa_name = "";
fa.fa_node = node;
OF_getpropintarray(node, "interrupts", fa.fa_intr, len);
}
- /* TODO: attach the device's clocks first? */
-
- config_found(self, &fa, NULL);
+ if (submatch == NULL)
+ submatch = mainbus_match_status;
+ config_found_sm(self, &fa, NULL, submatch);
free(fa.fa_reg, M_DEVBUF, fa.fa_nreg * sizeof(struct fdt_reg));
free(fa.fa_intr, M_DEVBUF, fa.fa_nintr * sizeof(uint32_t));
}
+int
+mainbus_match_status(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *fa = aux;
+ struct cfdata *cf = match;
+ char buf[32];
+
+ if (OF_getprop(fa->fa_node, "status", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "disabled") == 0)
+ return 0;
+
+ return (*cf->cf_attach->ca_match)(parent, match, aux);
+}
+
void
-mainbus_attach_framebuffer(struct device *self)
+mainbus_attach_cpus(struct device *self, cfmatch_t match)
{
- int node = OF_finddevice("/chosen");
+ struct mainbus_softc *sc = (struct mainbus_softc *)self;
+ int node = OF_finddevice("/cpus");
+ int acells, scells;
if (node == 0)
return;
+ acells = sc->sc_acells;
+ scells = sc->sc_scells;
+ sc->sc_acells = OF_getpropint(node, "#address-cells", 1);
+ sc->sc_scells = OF_getpropint(node, "#size-cells", 0);
+
for (node = OF_child(node); node != 0; node = OF_peer(node))
- mainbus_attach_node(self, node);
+ mainbus_attach_node(self, node, match);
+
+ sc->sc_acells = acells;
+ sc->sc_scells = scells;
}
-/*
- * Legacy support for SoCs that do not use FDT.
- */
int
-mainbus_legacy_search(struct device *parent, void *match, void *aux)
+mainbus_match_primary(struct device *parent, void *match, void *aux)
{
- union mainbus_attach_args ma;
- struct cfdata *cf = match;
+ struct fdt_attach_args *fa = aux;
+ struct cfdata *cf = match;
+ uint32_t mpidr;
- memset(&ma, 0, sizeof(ma));
- ma.ma_name = cf->cf_driver->cd_name;
+ __asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r " (mpidr));
- /* allow for devices to be disabled in UKC */
- if ((*cf->cf_attach->ca_match)(parent, cf, &ma) == 0)
+ if (fa->fa_nreg < 1 || fa->fa_reg[0].addr != (mpidr & MPIDR_AFF))
return 0;
- config_attach(parent, cf, &ma, NULL);
- return 1;
+ return (*cf->cf_attach->ca_match)(parent, match, aux);
+}
+
+int
+mainbus_match_secondary(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *fa = aux;
+ struct cfdata *cf = match;
+ uint32_t mpidr;
+
+ __asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r " (mpidr));
+
+ if (fa->fa_nreg < 1 || fa->fa_reg[0].addr == (mpidr & MPIDR_AFF))
+ return 0;
+
+ return (*cf->cf_attach->ca_match)(parent, match, aux);
+}
+
+void
+mainbus_attach_framebuffer(struct device *self)
+{
+ int node = OF_finddevice("/chosen");
+
+ if (node == 0)
+ return;
+
+ for (node = OF_child(node); node != 0; node = OF_peer(node))
+ mainbus_attach_node(self, node, NULL);
}
+/*
+ * Legacy support for SoCs that do not fully use FDT.
+ */
void
mainbus_legacy_found(struct device *self, char *name)
{