xref: /netbsd-src/sys/arch/arm/fdt/cpu_fdt.c (revision 7b4ce397cdd4c2ca586d2a402422262e1e25cc87)
1*7b4ce397Sriastradh /* $NetBSD: cpu_fdt.c,v 1.44 2024/05/10 14:42:21 riastradh Exp $ */
25ec28b37Sjmcneill 
35ec28b37Sjmcneill /*-
45ec28b37Sjmcneill  * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
55ec28b37Sjmcneill  * All rights reserved.
65ec28b37Sjmcneill  *
75ec28b37Sjmcneill  * Redistribution and use in source and binary forms, with or without
85ec28b37Sjmcneill  * modification, are permitted provided that the following conditions
95ec28b37Sjmcneill  * are met:
105ec28b37Sjmcneill  * 1. Redistributions of source code must retain the above copyright
115ec28b37Sjmcneill  *    notice, this list of conditions and the following disclaimer.
125ec28b37Sjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
135ec28b37Sjmcneill  *    notice, this list of conditions and the following disclaimer in the
145ec28b37Sjmcneill  *    documentation and/or other materials provided with the distribution.
155ec28b37Sjmcneill  *
165ec28b37Sjmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
175ec28b37Sjmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
185ec28b37Sjmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
195ec28b37Sjmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
205ec28b37Sjmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
215ec28b37Sjmcneill  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
225ec28b37Sjmcneill  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
235ec28b37Sjmcneill  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
245ec28b37Sjmcneill  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
255ec28b37Sjmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265ec28b37Sjmcneill  * SUCH DAMAGE.
275ec28b37Sjmcneill  */
285ec28b37Sjmcneill 
2966d31a2dSryo #include "opt_multiprocessor.h"
3066d31a2dSryo #include "psci_fdt.h"
3166d31a2dSryo 
325ec28b37Sjmcneill #include <sys/cdefs.h>
33*7b4ce397Sriastradh __KERNEL_RCSID(0, "$NetBSD: cpu_fdt.c,v 1.44 2024/05/10 14:42:21 riastradh Exp $");
345ec28b37Sjmcneill 
355ec28b37Sjmcneill #include <sys/param.h>
3666d31a2dSryo #include <sys/atomic.h>
375ec28b37Sjmcneill #include <sys/bus.h>
385ec28b37Sjmcneill #include <sys/device.h>
39ee91b1e5Sskrll #include <sys/lwp.h>
405ec28b37Sjmcneill #include <sys/systm.h>
415ec28b37Sjmcneill #include <sys/kernel.h>
425ec28b37Sjmcneill 
435ec28b37Sjmcneill #include <dev/fdt/fdtvar.h>
445ec28b37Sjmcneill 
45fe33aa27Sryo #include <arm/armreg.h>
465ec28b37Sjmcneill #include <arm/cpu.h>
47fe33aa27Sryo #include <arm/cpufunc.h>
48e1281176Sskrll #include <arm/cpuvar.h>
4966d31a2dSryo #include <arm/locore.h>
5066d31a2dSryo 
5166d31a2dSryo #include <arm/arm/psci.h>
5266d31a2dSryo #include <arm/fdt/arm_fdtvar.h>
5366d31a2dSryo #include <arm/fdt/psci_fdtvar.h>
5466d31a2dSryo 
5566d31a2dSryo #include <uvm/uvm_extern.h>
565ec28b37Sjmcneill 
575ec28b37Sjmcneill static int	cpu_fdt_match(device_t, cfdata_t, void *);
585ec28b37Sjmcneill static void	cpu_fdt_attach(device_t, device_t, void *);
595ec28b37Sjmcneill 
600a668ec7Spho CFATTACH_DECL2_NEW(cpu_fdt, 0,
610a668ec7Spho     cpu_fdt_match, cpu_fdt_attach, NULL, NULL,
620a668ec7Spho     cpu_rescan, cpu_childdetached);
635ec28b37Sjmcneill 
645ec28b37Sjmcneill static int
cpu_fdt_match(device_t parent,cfdata_t cf,void * aux)655ec28b37Sjmcneill cpu_fdt_match(device_t parent, cfdata_t cf, void *aux)
665ec28b37Sjmcneill {
675ec28b37Sjmcneill 	struct fdt_attach_args * const faa = aux;
68cb297a9cSjmcneill 	const int phandle = faa->faa_phandle;
6974b8f332Sjmcneill 	const char *device_type;
705ec28b37Sjmcneill 
7174b8f332Sjmcneill 	device_type = fdtbus_get_string(phandle, "device_type");
7253334e2eSjmcneill 
7374b8f332Sjmcneill 	return device_type != NULL && strcmp(device_type, "cpu") == 0;
745ec28b37Sjmcneill }
755ec28b37Sjmcneill 
765ec28b37Sjmcneill static void
cpu_fdt_attach(device_t parent,device_t self,void * aux)775ec28b37Sjmcneill cpu_fdt_attach(device_t parent, device_t self, void *aux)
785ec28b37Sjmcneill {
795ec28b37Sjmcneill 	struct fdt_attach_args * const faa = aux;
80cb297a9cSjmcneill 	const int phandle = faa->faa_phandle;
8174b8f332Sjmcneill 	bus_addr_t cpuid;
82b0829efdSmrg 	const uint32_t *cap_ptr;
83b0829efdSmrg 	int len;
845ec28b37Sjmcneill 
85b0829efdSmrg  	cap_ptr = fdtbus_get_prop(phandle, "capacity-dmips-mhz", &len);
86b0829efdSmrg 	if (cap_ptr && len == 4) {
87b0829efdSmrg 		prop_dictionary_t dict = device_properties(self);
88b0829efdSmrg 		uint32_t capacity_dmips_mhz = be32toh(*cap_ptr);
89b0829efdSmrg 
90b0829efdSmrg 		prop_dictionary_set_uint32(dict, "capacity_dmips_mhz",
91b0829efdSmrg 		    capacity_dmips_mhz);
92b0829efdSmrg 	}
93b0829efdSmrg 
9474b8f332Sjmcneill 	if (fdtbus_get_reg(phandle, 0, &cpuid, NULL) != 0)
95cb297a9cSjmcneill 		cpuid = 0;
965ec28b37Sjmcneill 
9753334e2eSjmcneill 	/* Attach the CPU */
98cb297a9cSjmcneill 	cpu_attach(self, cpuid);
9991a13c78Sjmcneill 
10091a13c78Sjmcneill 	/* Attach CPU frequency scaling provider */
101*7b4ce397Sriastradh 	config_found(self, faa, NULL, CFARGS(.iattr = "cpu"));
1025ec28b37Sjmcneill }
10366d31a2dSryo 
104c2ecc879Sjmcneill #if defined(MULTIPROCESSOR) && (NPSCI_FDT > 0 || defined(__aarch64__))
10566d31a2dSryo static register_t
cpu_fdt_mpstart_pa(void)10666d31a2dSryo cpu_fdt_mpstart_pa(void)
10766d31a2dSryo {
108e6c2e807Sskrll 	bool ok __diagused;
109e6c2e807Sskrll 	paddr_t pa;
110e6c2e807Sskrll 
111e6c2e807Sskrll 	ok = pmap_extract(pmap_kernel(), (vaddr_t)cpu_mpstart, &pa);
112e6c2e807Sskrll 	KASSERT(ok);
113e6c2e807Sskrll 
114e6c2e807Sskrll 	return pa;
11566d31a2dSryo }
116c2ecc879Sjmcneill #endif
11766d31a2dSryo 
118c2ecc879Sjmcneill #ifdef MULTIPROCESSOR
119f220cf33Sjmcneill static bool
arm_fdt_cpu_okay(const int child)120f220cf33Sjmcneill arm_fdt_cpu_okay(const int child)
121f220cf33Sjmcneill {
122f220cf33Sjmcneill 	const char *s;
123f220cf33Sjmcneill 
124f220cf33Sjmcneill 	s = fdtbus_get_string(child, "device_type");
125f220cf33Sjmcneill 	if (!s || strcmp(s, "cpu") != 0)
126f220cf33Sjmcneill 		return false;
127f220cf33Sjmcneill 
128f220cf33Sjmcneill 	s = fdtbus_get_string(child, "status");
129f220cf33Sjmcneill 	if (s) {
130f220cf33Sjmcneill 		if (strcmp(s, "okay") == 0)
131f220cf33Sjmcneill 			return false;
132f220cf33Sjmcneill 		if (strcmp(s, "disabled") == 0)
133f220cf33Sjmcneill 			return of_hasprop(child, "enable-method");
134f220cf33Sjmcneill 		return false;
135f220cf33Sjmcneill 	} else {
136f220cf33Sjmcneill 		return true;
137f220cf33Sjmcneill 	}
138f220cf33Sjmcneill }
1399cdcdf4aSjmcneill #endif /* MULTIPROCESSOR */
14066d31a2dSryo 
14166d31a2dSryo void
arm_fdt_cpu_bootstrap(void)14266d31a2dSryo arm_fdt_cpu_bootstrap(void)
14366d31a2dSryo {
14466d31a2dSryo #ifdef MULTIPROCESSOR
14566d31a2dSryo 	uint64_t mpidr, bp_mpidr;
14666d31a2dSryo 	u_int cpuindex;
147e6c2e807Sskrll 	int child;
14866d31a2dSryo 
14966d31a2dSryo 	const int cpus = OF_finddevice("/cpus");
15066d31a2dSryo 	if (cpus == -1) {
15166d31a2dSryo 		aprint_error("%s: no /cpus node found\n", __func__);
15266d31a2dSryo 		arm_cpu_max = 1;
15366d31a2dSryo 		return;
15466d31a2dSryo 	}
15566d31a2dSryo 
15666d31a2dSryo 	/* Count CPUs */
15766d31a2dSryo 	arm_cpu_max = 0;
15866d31a2dSryo 
15966d31a2dSryo 	/* MPIDR affinity levels of boot processor. */
16066d31a2dSryo 	bp_mpidr = cpu_mpidr_aff_read();
16166d31a2dSryo 
16262f6b38bSskrll 	/* Add APs to cpu_mpidr array */
16366d31a2dSryo 	cpuindex = 1;
16466d31a2dSryo 	for (child = OF_child(cpus); child; child = OF_peer(child)) {
165f220cf33Sjmcneill 		if (!arm_fdt_cpu_okay(child))
16666d31a2dSryo 			continue;
167e6c2e807Sskrll 
168e6c2e807Sskrll 		arm_cpu_max++;
16966d31a2dSryo 		if (fdtbus_get_reg64(child, 0, &mpidr, NULL) != 0)
17066d31a2dSryo 			continue;
17166d31a2dSryo 		if (mpidr == bp_mpidr)
17266d31a2dSryo 			continue; 	/* BP already started */
17366d31a2dSryo 
17466d31a2dSryo 		KASSERT(cpuindex < MAXCPUS);
17566d31a2dSryo 		cpu_mpidr[cpuindex] = mpidr;
176e6c2e807Sskrll 		cpu_dcache_wb_range((vaddr_t)&cpu_mpidr[cpuindex],
177e6c2e807Sskrll 		    sizeof(cpu_mpidr[cpuindex]));
178e6c2e807Sskrll 
179e6c2e807Sskrll 		cpuindex++;
180e6c2e807Sskrll 	}
181e6c2e807Sskrll #endif
182e6c2e807Sskrll }
183e6c2e807Sskrll 
1843bb9dca4Sjmcneill #ifdef MULTIPROCESSOR
18532689f21Sjmcneill static struct arm_cpu_method *
arm_fdt_cpu_enable_method_byname(const char * method)1867af73871Sjmcneill arm_fdt_cpu_enable_method_byname(const char *method)
1877af73871Sjmcneill {
1887af73871Sjmcneill 	__link_set_decl(arm_cpu_methods, struct arm_cpu_method);
1897af73871Sjmcneill 	struct arm_cpu_method * const *acmp;
1907af73871Sjmcneill 
1917af73871Sjmcneill 	__link_set_foreach(acmp, arm_cpu_methods) {
1927af73871Sjmcneill 		if (strcmp(method, (*acmp)->acm_compat) == 0)
1937af73871Sjmcneill 			return *acmp;
1947af73871Sjmcneill 	}
1957af73871Sjmcneill 
1967af73871Sjmcneill 	return NULL;
1977af73871Sjmcneill }
1987af73871Sjmcneill 
1997af73871Sjmcneill static struct arm_cpu_method *
arm_fdt_cpu_enable_method(int phandle)20032689f21Sjmcneill arm_fdt_cpu_enable_method(int phandle)
2013bb9dca4Sjmcneill {
20232689f21Sjmcneill 	const char *method;
20332689f21Sjmcneill 
20432689f21Sjmcneill  	method = fdtbus_get_string(phandle, "enable-method");
20532689f21Sjmcneill 	if (method == NULL)
20632689f21Sjmcneill 		return NULL;
20732689f21Sjmcneill 
2087af73871Sjmcneill 	return arm_fdt_cpu_enable_method_byname(method);
20932689f21Sjmcneill }
21032689f21Sjmcneill 
21132689f21Sjmcneill static int
arm_fdt_cpu_enable(int phandle,struct arm_cpu_method * acm)21232689f21Sjmcneill arm_fdt_cpu_enable(int phandle, struct arm_cpu_method *acm)
21332689f21Sjmcneill {
21432689f21Sjmcneill 	return acm->acm_enable(phandle);
2153bb9dca4Sjmcneill }
2163bb9dca4Sjmcneill #endif
2173bb9dca4Sjmcneill 
218a476a90dSskrll int
arm_fdt_cpu_mpstart(void)219e6c2e807Sskrll arm_fdt_cpu_mpstart(void)
220e6c2e807Sskrll {
221a476a90dSskrll 	int ret = 0;
222e6c2e807Sskrll #ifdef MULTIPROCESSOR
223e6c2e807Sskrll 	uint64_t mpidr, bp_mpidr;
2243bb9dca4Sjmcneill 	u_int cpuindex, i;
2253bb9dca4Sjmcneill 	int child, error;
22632689f21Sjmcneill 	struct arm_cpu_method *acm;
227e6c2e807Sskrll 
228e6c2e807Sskrll 	const int cpus = OF_finddevice("/cpus");
229e6c2e807Sskrll 	if (cpus == -1) {
230e6c2e807Sskrll 		aprint_error("%s: no /cpus node found\n", __func__);
231a476a90dSskrll 		return 0;
232e6c2e807Sskrll 	}
233e6c2e807Sskrll 
234e6c2e807Sskrll 	/* MPIDR affinity levels of boot processor. */
235e6c2e807Sskrll 	bp_mpidr = cpu_mpidr_aff_read();
236e6c2e807Sskrll 
237e6c2e807Sskrll 	/* Boot APs */
238e6c2e807Sskrll 	cpuindex = 1;
239e6c2e807Sskrll 	for (child = OF_child(cpus); child; child = OF_peer(child)) {
240e6c2e807Sskrll 		if (!arm_fdt_cpu_okay(child))
241e6c2e807Sskrll 			continue;
242e6c2e807Sskrll 
243e6c2e807Sskrll 		if (fdtbus_get_reg64(child, 0, &mpidr, NULL) != 0)
244e6c2e807Sskrll 			continue;
245030faca8Sskrll 
246e6c2e807Sskrll 		if (mpidr == bp_mpidr)
247e6c2e807Sskrll 			continue; 	/* BP already started */
248e6c2e807Sskrll 
24932689f21Sjmcneill 		acm = arm_fdt_cpu_enable_method(child);
25032689f21Sjmcneill 		if (acm == NULL)
25132689f21Sjmcneill 			acm = arm_fdt_cpu_enable_method(cpus);
25232689f21Sjmcneill 		if (acm == NULL)
2537af73871Sjmcneill 			acm = arm_fdt_cpu_enable_method_byname("psci");
2547af73871Sjmcneill 		if (acm == NULL)
25566d31a2dSryo 			continue;
25666d31a2dSryo 
25732689f21Sjmcneill 		error = arm_fdt_cpu_enable(child, acm);
2583bb9dca4Sjmcneill 		if (error != 0) {
2595776f3ebSskrll 			aprint_error("%s: failed to enable CPU %#" PRIx64 "\n",
2605776f3ebSskrll 			    __func__, mpidr);
26166d31a2dSryo 			continue;
26266d31a2dSryo 		}
26366d31a2dSryo 
26466d31a2dSryo 		/* Wake up AP in case firmware has placed it in WFE state */
26569120ac1Sskrll 		sev();
26666d31a2dSryo 
2673bb9dca4Sjmcneill 		/* Wait for AP to start */
268912cfa14Sjmcneill 		for (i = 0x10000000; i > 0; i--) {
26929224e5eSjmcneill 			if (cpu_hatched_p(cpuindex))
27066d31a2dSryo 				break;
27166d31a2dSryo 		}
272a476a90dSskrll 
273a476a90dSskrll 		if (i == 0) {
274a476a90dSskrll 			ret++;
2753bb9dca4Sjmcneill 			aprint_error("cpu%d: WARNING: AP failed to start\n", cpuindex);
276a476a90dSskrll 		}
2773bb9dca4Sjmcneill 
2783bb9dca4Sjmcneill 		cpuindex++;
2793bb9dca4Sjmcneill 	}
28066d31a2dSryo #endif /* MULTIPROCESSOR */
281a476a90dSskrll 	return ret;
28266d31a2dSryo }
2833bb9dca4Sjmcneill 
2843bb9dca4Sjmcneill static int
cpu_enable_nullop(int phandle)2853bb9dca4Sjmcneill cpu_enable_nullop(int phandle)
2863bb9dca4Sjmcneill {
2873bb9dca4Sjmcneill 	return ENXIO;
2883bb9dca4Sjmcneill }
2893bb9dca4Sjmcneill ARM_CPU_METHOD(default, "", cpu_enable_nullop);
2903bb9dca4Sjmcneill 
2913bb9dca4Sjmcneill #if defined(MULTIPROCESSOR) && NPSCI_FDT > 0
2923bb9dca4Sjmcneill static int
cpu_enable_psci(int phandle)2933bb9dca4Sjmcneill cpu_enable_psci(int phandle)
2943bb9dca4Sjmcneill {
2953bb9dca4Sjmcneill 	static bool psci_probed, psci_p;
2963bb9dca4Sjmcneill 	uint64_t mpidr;
2973bb9dca4Sjmcneill 	int ret;
2983bb9dca4Sjmcneill 
2993bb9dca4Sjmcneill 	if (!psci_probed) {
3003bb9dca4Sjmcneill 		psci_probed = true;
3013bb9dca4Sjmcneill 		psci_p = psci_fdt_preinit() == 0;
3023bb9dca4Sjmcneill 	}
3033bb9dca4Sjmcneill 	if (!psci_p)
3043bb9dca4Sjmcneill 		return ENXIO;
3053bb9dca4Sjmcneill 
3063bb9dca4Sjmcneill 	fdtbus_get_reg64(phandle, 0, &mpidr, NULL);
3073bb9dca4Sjmcneill 
308f72c8a3cSbad #if !defined(AARCH64)
309f72c8a3cSbad 	/*
31011c39ba5Sbad 	 * not necessary on AARCH64. beside there it hangs the system
311f72c8a3cSbad 	 * because cache ops are only functional after cpu_attach()
312f72c8a3cSbad 	 * was called.
313f72c8a3cSbad 	 */
314f72c8a3cSbad 	cpu_dcache_wbinv_all();
315f72c8a3cSbad #endif
3163bb9dca4Sjmcneill 	ret = psci_cpu_on(mpidr, cpu_fdt_mpstart_pa(), 0);
3173bb9dca4Sjmcneill 	if (ret != PSCI_SUCCESS)
3183bb9dca4Sjmcneill 		return EIO;
3193bb9dca4Sjmcneill 
3203bb9dca4Sjmcneill 	return 0;
3213bb9dca4Sjmcneill }
3223bb9dca4Sjmcneill ARM_CPU_METHOD(psci, "psci", cpu_enable_psci);
3233bb9dca4Sjmcneill #endif
3243bb9dca4Sjmcneill 
3258eb52256Sjmcneill #if defined(MULTIPROCESSOR) && defined(__aarch64__)
3268eb52256Sjmcneill static int
spintable_cpu_on(const int phandle,u_int cpuindex,paddr_t entry_point_address,paddr_t cpu_release_addr)32723255edfSjmcneill spintable_cpu_on(const int phandle, u_int cpuindex,
32823255edfSjmcneill     paddr_t entry_point_address, paddr_t cpu_release_addr)
3298eb52256Sjmcneill {
3308eb52256Sjmcneill 	/*
3318eb52256Sjmcneill 	 * we need devmap for cpu-release-addr in advance.
332c02d4e44Sskrll 	 * __HAVE_MM_MD_DIRECT_MAPPED_PHYS nor pmap work at this point.
3338eb52256Sjmcneill 	 */
3348eb52256Sjmcneill 	if (pmap_devmap_find_pa(cpu_release_addr, sizeof(paddr_t)) == NULL) {
3358eb52256Sjmcneill 		aprint_error("%s: devmap for cpu-release-addr"
3368eb52256Sjmcneill 		    " 0x%08"PRIxPADDR" required\n", __func__, cpu_release_addr);
3378eb52256Sjmcneill 		return -1;
3388eb52256Sjmcneill 	} else {
3398eb52256Sjmcneill 		extern struct bus_space arm_generic_bs_tag;
3408eb52256Sjmcneill 		bus_space_handle_t ioh;
3418eb52256Sjmcneill 
34223255edfSjmcneill 		const int parent = OF_parent(phandle);
34323255edfSjmcneill 		const int addr_cells = fdtbus_get_addr_cells(parent);
34423255edfSjmcneill 
3458eb52256Sjmcneill 		bus_space_map(&arm_generic_bs_tag, cpu_release_addr,
3468eb52256Sjmcneill 		    sizeof(paddr_t), 0, &ioh);
34723255edfSjmcneill 		if (addr_cells == 1) {
3488eb52256Sjmcneill 			bus_space_write_4(&arm_generic_bs_tag, ioh, 0,
3498eb52256Sjmcneill 			    entry_point_address);
35023255edfSjmcneill 		} else {
35123255edfSjmcneill 			bus_space_write_8(&arm_generic_bs_tag, ioh, 0,
35223255edfSjmcneill 			    entry_point_address);
35323255edfSjmcneill 		}
3548eb52256Sjmcneill 		bus_space_unmap(&arm_generic_bs_tag, ioh, sizeof(paddr_t));
3558eb52256Sjmcneill 	}
3568eb52256Sjmcneill 
3578eb52256Sjmcneill 	return 0;
3588eb52256Sjmcneill }
3598eb52256Sjmcneill 
3603bb9dca4Sjmcneill static int
cpu_enable_spin_table(int phandle)3613bb9dca4Sjmcneill cpu_enable_spin_table(int phandle)
3623bb9dca4Sjmcneill {
363cdd1c6dfSjmcneill 	uint64_t mpidr, addr;
3643bb9dca4Sjmcneill 	int ret;
3653bb9dca4Sjmcneill 
3663bb9dca4Sjmcneill 	fdtbus_get_reg64(phandle, 0, &mpidr, NULL);
3673bb9dca4Sjmcneill 
368cdd1c6dfSjmcneill 	if (of_getprop_uint64(phandle, "cpu-release-addr", &addr) != 0)
3693bb9dca4Sjmcneill 		return ENXIO;
3703bb9dca4Sjmcneill 
37123255edfSjmcneill 	ret = spintable_cpu_on(phandle, mpidr, cpu_fdt_mpstart_pa(),
37223255edfSjmcneill 	    (paddr_t)addr);
3733bb9dca4Sjmcneill 	if (ret != 0)
3743bb9dca4Sjmcneill 		return EIO;
3753bb9dca4Sjmcneill 
3763bb9dca4Sjmcneill 	return 0;
3773bb9dca4Sjmcneill }
3783bb9dca4Sjmcneill ARM_CPU_METHOD(spin_table, "spin-table", cpu_enable_spin_table);
3793bb9dca4Sjmcneill #endif
380