--- /dev/null
+/* $OpenBSD: cpu.c,v 1.1 2017/04/27 10:23:19 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
+ * 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+/* CPU Identification */
+#define CPU_IMPL_ARM 0x41
+
+#define CPU_PART_CORTEX_A53 0xd03
+#define CPU_PART_CORTEX_A35 0xd04
+#define CPU_PART_CORTEX_A57 0xd07
+#define CPU_PART_CORTEX_A72 0xd08
+#define CPU_PART_CORTEX_A73 0xd09
+
+#define CPU_IMPL(midr) (((midr) >> 24) & 0xff)
+#define CPU_PART(midr) (((midr) >> 4) & 0xfff)
+#define CPU_VAR(midr) (((midr) >> 20) & 0xf)
+#define CPU_REV(midr) (((midr) >> 0) & 0xf)
+
+struct cpu_cores {
+ int id;
+ char *name;
+};
+
+struct cpu_cores cpu_cores_none[] = {
+ { 0x0, "Unknown" },
+};
+
+struct cpu_cores cpu_cores_arm[] = {
+ { CPU_PART_CORTEX_A35, "Cortex-A35" },
+ { CPU_PART_CORTEX_A53, "Cortex-A53" },
+ { CPU_PART_CORTEX_A57, "Cortex-A57" },
+ { CPU_PART_CORTEX_A72, "Cortex-A72" },
+ { CPU_PART_CORTEX_A73, "Cortex-A73" },
+ { 0x0, "Unknown" },
+};
+
+/* arm cores makers */
+const struct implementers {
+ int id;
+ char *name;
+ struct cpu_cores *corelist;
+} cpu_implementers[] = {
+ { CPU_IMPL_ARM, "ARM", cpu_cores_arm },
+ { 0, "", NULL },
+};
+
+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
+cpu_identify(struct cpu_info *ci)
+{
+ uint64_t midr, impl, part;
+ char *impl_name = "Unknown";
+ char *part_name = "Unknown";
+ struct cpu_cores *coreselecter = cpu_cores_none;
+ int i;
+
+ midr = READ_SPECIALREG(midr_el1);
+ impl = CPU_IMPL(midr);
+ part = CPU_PART(midr);
+
+ for (i = 0; cpu_implementers[i].id != 0; i++) {
+ if (impl == cpu_implementers[i].id) {
+ impl_name = cpu_implementers[i].name;
+ coreselecter = cpu_implementers[i].corelist;
+ break;
+ }
+ }
+
+ for (i = 0; coreselecter[i].id != 0; i++) {
+ if (part == coreselecter[i].id) {
+ part_name = coreselecter[i].name;
+ break;
+ }
+ }
+
+ printf(" %s %s r%dp%d", impl_name, part_name, CPU_VAR(midr),
+ CPU_REV(midr));
+}
+
+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 *parent, struct device *dev, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+ struct cpu_info *ci;
+ uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
+
+ KASSERT(faa->fa_nreg > 0);
+
+ if (faa->fa_reg[0].addr == (mpidr & MPIDR_AFF)) {
+ ci = &cpu_info_primary;
+ ci->ci_cpuid = dev->dv_unit;
+ ci->ci_dev = dev;
+
+ printf(":");
+ cpu_identify(ci);
+ } else {
+ printf(": not configured");
+ }
+
+ printf("\n");
+}
-# $OpenBSD: GENERIC,v 1.22 2017/03/10 03:27:50 jsg Exp $
+# $OpenBSD: GENERIC,v 1.23 2017/04/27 10:23:19 kettenis Exp $
#
# GENERIC machine description file
#
# The main bus device
mainbus0 at root
+cpu0 at mainbus?
simplebus* at fdt?
scsibus* at scsi?
-# $OpenBSD: RAMDISK,v 1.19 2017/03/10 03:27:50 jsg Exp $
+# $OpenBSD: RAMDISK,v 1.20 2017/04/27 10:23:19 kettenis Exp $
#
# GENERIC machine description file
#
# The main bus device
mainbus0 at root
+cpu0 at mainbus?
simplebus* at fdt?
scsibus* at scsi?
-# $OpenBSD: files.arm64,v 1.11 2017/02/25 17:04:19 patrick Exp $
+# $OpenBSD: files.arm64,v 1.12 2017/04/27 10:23:19 kettenis Exp $
maxpartitions 16
maxusers 2 8 64
file arch/arm64/arm64/syscall.c
file arch/arm64/arm64/sys_machdep.c
+file arch/arm64/arm64/cpu.c
file arch/arm64/arm64/intr.c
file arch/arm64/arm64/softintr.c
file arch/arm64/arm64/vfp.c
include "dev/rasops/files.rasops"
include "dev/wsfont/files.wsfont"
+device cpu {}
+attach cpu at mainbus
+
#
# Machine-independent HID support
#
-/* $OpenBSD: mainbus.c,v 1.3 2017/02/22 22:55:27 patrick Exp $ */
+/* $OpenBSD: mainbus.c,v 1.4 2017/04/27 10:23:19 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 *);
struct mainbus_softc {
struct device sc_dev;
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)
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");
-
- /* TODO: Scan for interrupt controllers and attach them first? */
+ /* Attach primary CPU first. */
+ mainbus_attach_cpus(self, mainbus_match_primary);
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);
- }
+ for (node = OF_child(node); node != 0; node = OF_peer(node))
+ mainbus_attach_node(self, node, NULL);
+
+ /* 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));
}
-/*
- * Legacy support for SoCs that do not use FDT.
- */
+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_legacy_found(struct device *self, char *name)
+mainbus_attach_cpus(struct device *self, cfmatch_t match)
+{
+ 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", 2);
+ 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, match);
+
+ sc->sc_acells = acells;
+ sc->sc_scells = scells;
+}
+
+int
+mainbus_match_primary(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *fa = aux;
+ struct cfdata *cf = match;
+ uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
+
+ if (fa->fa_nreg < 1 || fa->fa_reg[0].addr != (mpidr & MPIDR_AFF))
+ return 0;
+
+ return (*cf->cf_attach->ca_match)(parent, match, aux);
+}
+
+int
+mainbus_match_secondary(struct device *parent, void *match, void *aux)
{
- union mainbus_attach_args ma;
+ struct fdt_attach_args *fa = aux;
+ struct cfdata *cf = match;
+ uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
- memset(&ma, 0, sizeof(ma));
- ma.ma_name = name;
+ if (fa->fa_nreg < 1 || fa->fa_reg[0].addr == (mpidr & MPIDR_AFF))
+ return 0;
- config_found(self, &ma, NULL);
+ return (*cf->cf_attach->ca_match)(parent, match, aux);
}
-/* $OpenBSD: mainbus.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */
+/* $OpenBSD: mainbus.h,v 1.2 2017/04/27 10:23:19 kettenis Exp $ */
/*
* Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
*
struct fdt_attach_args ma_faa;
};
-void mainbus_legacy_found(struct device *, char *);
-
#endif /* __MAINBUS_H__ */
-/* $OpenBSD: simplebus.c,v 1.6 2017/02/22 22:55:27 patrick Exp $ */
+/* $OpenBSD: simplebus.c,v 1.7 2017/04/27 10:23:19 kettenis Exp $ */
/*
* Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
*
{
struct simplebus_softc *sc = (struct simplebus_softc *)self;
struct fdt_attach_args fa;
- char buffer[128];
+ char buf[32];
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;
+ if (OF_getprop(node, "status", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "disabled") == 0)
+ return;
memset(&fa, 0, sizeof(fa));
fa.fa_name = "";
-/* $OpenBSD: armreg.h,v 1.3 2017/02/06 19:23:45 patrick Exp $ */
+/* $OpenBSD: armreg.h,v 1.4 2017/04/27 10:23:19 kettenis Exp $ */
/*-
* Copyright (c) 2013, 2014 Andrew Turner
* Copyright (c) 2015 The FreeBSD Foundation
#define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT)
#define CTR_ILINE_SIZE(reg) (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT)
+/* MPIDR_EL1 - Multiprocessor Affinity Register */
+#define MPIDR_AFF3 (0xFFULL << 32)
+#define MPIDR_AFF2 (0xFFULL << 16)
+#define MPIDR_AFF1 (0xFFULL << 8)
+#define MPIDR_AFF0 (0xFFULL << 0)
+#define MPIDR_AFF (MPIDR_AFF3|MPIDR_AFF2|MPIDR_AFF1|MPIDR_AFF0)
+
/* DCZID_EL0 - Data Cache Zero ID register */
#define DCZID_DZP (1 << 4) /* DC ZVA prohibited if non-0 */
#define DCZID_BS_SHIFT 0