diff options
Diffstat (limited to 'sys/dev/ofw/ofw_cpu.c')
-rw-r--r-- | sys/dev/ofw/ofw_cpu.c | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/sys/dev/ofw/ofw_cpu.c b/sys/dev/ofw/ofw_cpu.c index e18004ae19d2..888af0440746 100644 --- a/sys/dev/ofw/ofw_cpu.c +++ b/sys/dev/ofw/ofw_cpu.c @@ -42,8 +42,9 @@ #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/ofw_cpu.h> -#if defined(__arm__) || defined(__arm64__) || defined(__riscv__) +#if defined(__arm__) || defined(__arm64__) || defined(__riscv) #include <dev/clk/clk.h> +#define HAS_CLK #endif static int ofw_cpulist_probe(device_t); @@ -123,7 +124,7 @@ ofw_cpulist_attach(device_t dev) free(dinfo, M_OFWCPU); continue; } - cdev = device_add_child(dev, NULL, -1); + cdev = device_add_child(dev, NULL, DEVICE_UNIT_ANY); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", dinfo->obd_name); @@ -134,7 +135,8 @@ ofw_cpulist_attach(device_t dev) device_set_ivars(cdev, dinfo); } - return (bus_generic_attach(dev)); + bus_attach_children(dev); + return (0); } static const struct ofw_bus_devinfo * @@ -151,7 +153,7 @@ static int ofw_cpu_read_ivar(device_t dev, device_t child, int index, struct ofw_cpu_softc { struct pcpu *sc_cpu_pcpu; uint32_t sc_nominal_mhz; - boolean_t sc_reg_valid; + bool sc_reg_valid; pcell_t sc_reg[2]; }; @@ -180,6 +182,24 @@ static driver_t ofw_cpu_driver = { DRIVER_MODULE(ofw_cpu, cpulist, ofw_cpu_driver, 0, 0); +static bool +ofw_cpu_is_runnable(phandle_t node) +{ + /* + * Per the DeviceTree Specification, a cpu node (under /cpus) that + * has 'status = disabled' indicates that "the CPU is in a quiescent + * state." + * + * A quiescent CPU that specifies an "enable-method", such as + * "spin-table", can still be used by the kernel. + * + * Lacking this, any CPU marked "disabled" or other non-okay status + * should be excluded from the kernel's view. + */ + return (ofw_bus_node_status_okay(node) || + OF_hasprop(node, "enable-method")); +} + static int ofw_cpu_probe(device_t dev) { @@ -188,6 +208,9 @@ ofw_cpu_probe(device_t dev) if (type == NULL || strcmp(type, "cpu") != 0) return (ENXIO); + if (!ofw_cpu_is_runnable(ofw_bus_get_node(dev))) + return (ENXIO); + device_set_desc(dev, "Open Firmware CPU"); if (!bootverbose && device_get_unit(dev) != 0) { device_quiet(dev); @@ -198,6 +221,30 @@ ofw_cpu_probe(device_t dev) } static int +get_freq_from_clk(device_t dev, struct ofw_cpu_softc *sc) +{ +#ifdef HAS_CLK + clk_t cpuclk; + uint64_t freq; + int rv; + + rv = clk_get_by_ofw_index(dev, 0, 0, &cpuclk); + if (rv == 0) { + rv = clk_get_freq(cpuclk, &freq); + if (rv != 0 && bootverbose) + device_printf(dev, + "Cannot get freq of property clocks\n"); + else + sc->sc_nominal_mhz = freq / 1000000; + } + + return (rv); +#else + return (ENODEV); +#endif +} + +static int ofw_cpu_attach(device_t dev) { struct ofw_cpulist_softc *psc; @@ -205,10 +252,6 @@ ofw_cpu_attach(device_t dev) phandle_t node; pcell_t cell; int rv; -#if defined(__arm__) || defined(__arm64__) || defined(__riscv__) - clk_t cpuclk; - uint64_t freq; -#endif sc = device_get_softc(dev); psc = device_get_softc(device_get_parent(dev)); @@ -275,18 +318,7 @@ ofw_cpu_attach(device_t dev) sc->sc_cpu_pcpu = pcpu_find(device_get_unit(dev)); if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) < 0) { -#if defined(__arm__) || defined(__arm64__) || defined(__riscv__) - rv = clk_get_by_ofw_index(dev, 0, 0, &cpuclk); - if (rv == 0) { - rv = clk_get_freq(cpuclk, &freq); - if (rv != 0 && bootverbose) - device_printf(dev, - "Cannot get freq of property clocks\n"); - else - sc->sc_nominal_mhz = freq / 1000000; - } else -#endif - { + if (get_freq_from_clk(dev, sc) != 0) { if (bootverbose) device_printf(dev, "missing 'clock-frequency' property\n"); @@ -297,8 +329,10 @@ ofw_cpu_attach(device_t dev) if (sc->sc_nominal_mhz != 0 && bootverbose) device_printf(dev, "Nominal frequency %dMhz\n", sc->sc_nominal_mhz); - bus_generic_probe(dev); - return (bus_generic_attach(dev)); + + bus_identify_children(dev); + bus_attach_children(dev); + return (0); } static int @@ -335,11 +369,10 @@ ofw_cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) } int -ofw_cpu_early_foreach(ofw_cpu_foreach_cb callback, boolean_t only_runnable) +ofw_cpu_early_foreach(ofw_cpu_foreach_cb callback, bool only_runnable) { phandle_t node, child; pcell_t addr_cells, reg[2]; - char status[16]; char device_type[16]; u_int id, next_id; int count, rv; @@ -376,14 +409,8 @@ ofw_cpu_early_foreach(ofw_cpu_foreach_cb callback, boolean_t only_runnable) * those that have been enabled, or do provide a method * to enable them. */ - if (only_runnable) { - status[0] = '\0'; - OF_getprop(child, "status", status, sizeof(status)); - if (status[0] != '\0' && strcmp(status, "okay") != 0 && - strcmp(status, "ok") != 0 && - !OF_hasprop(child, "enable-method")) - continue; - } + if (only_runnable && !ofw_cpu_is_runnable(child)) + continue; /* * Check we have a register to identify the cpu |