xref: /freebsd/sys/powerpc/powerpc/platform.c (revision 685dc743)
1b40ce02aSNathan Whitehorn /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
371e3c308SPedro F. Giffuni  *
4b40ce02aSNathan Whitehorn  * Copyright (c) 2005 Peter Grehan
5b40ce02aSNathan Whitehorn  * Copyright (c) 2009 Nathan Whitehorn
6b40ce02aSNathan Whitehorn  * All rights reserved.
7b40ce02aSNathan Whitehorn  *
8b40ce02aSNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
9b40ce02aSNathan Whitehorn  * modification, are permitted provided that the following conditions
10b40ce02aSNathan Whitehorn  * are met:
11b40ce02aSNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
12b40ce02aSNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
13b40ce02aSNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
14b40ce02aSNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
15b40ce02aSNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
16b40ce02aSNathan Whitehorn  *
17b40ce02aSNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18b40ce02aSNathan Whitehorn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19b40ce02aSNathan Whitehorn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20b40ce02aSNathan Whitehorn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21b40ce02aSNathan Whitehorn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22b40ce02aSNathan Whitehorn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23b40ce02aSNathan Whitehorn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24b40ce02aSNathan Whitehorn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25b40ce02aSNathan Whitehorn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26b40ce02aSNathan Whitehorn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27b40ce02aSNathan Whitehorn  * SUCH DAMAGE.
28b40ce02aSNathan Whitehorn  *
29b40ce02aSNathan Whitehorn  */
30b40ce02aSNathan Whitehorn 
31b40ce02aSNathan Whitehorn #include <sys/cdefs.h>
32b40ce02aSNathan Whitehorn /*
33b40ce02aSNathan Whitehorn  * Dispatch platform calls to the appropriate platform implementation
34b40ce02aSNathan Whitehorn  * through a previously registered kernel object.
35b40ce02aSNathan Whitehorn  */
36b40ce02aSNathan Whitehorn 
37b40ce02aSNathan Whitehorn #include <sys/param.h>
38b40ce02aSNathan Whitehorn #include <sys/kernel.h>
39b40ce02aSNathan Whitehorn #include <sys/lock.h>
40b40ce02aSNathan Whitehorn #include <sys/ktr.h>
41b40ce02aSNathan Whitehorn #include <sys/mutex.h>
42637f34cbSJustin Hibbits #include <sys/proc.h>
43b40ce02aSNathan Whitehorn #include <sys/systm.h>
446413b057SNathan Whitehorn #include <sys/smp.h>
45b40ce02aSNathan Whitehorn #include <sys/sysctl.h>
46b40ce02aSNathan Whitehorn #include <sys/types.h>
47b40ce02aSNathan Whitehorn 
48b40ce02aSNathan Whitehorn #include <vm/vm.h>
4949d9a597SJustin Hibbits #include <vm/vm_param.h>
50b40ce02aSNathan Whitehorn #include <vm/vm_page.h>
5149d9a597SJustin Hibbits #include <vm/vm_phys.h>
52b40ce02aSNathan Whitehorn 
53b2a237beSNathan Whitehorn #include <machine/cpu.h>
546413b057SNathan Whitehorn #include <machine/md_var.h>
55490ebb8fSJustin Hibbits #include <machine/ofw_machdep.h>
56b40ce02aSNathan Whitehorn #include <machine/platform.h>
57b40ce02aSNathan Whitehorn #include <machine/platformvar.h>
58b40ce02aSNathan Whitehorn #include <machine/smp.h>
5949d9a597SJustin Hibbits #include <machine/vmparam.h>
60b40ce02aSNathan Whitehorn 
61b40ce02aSNathan Whitehorn #include "platform_if.h"
62b40ce02aSNathan Whitehorn 
63b40ce02aSNathan Whitehorn static platform_def_t	*plat_def_impl;
64b40ce02aSNathan Whitehorn static platform_t	plat_obj;
65b40ce02aSNathan Whitehorn static struct kobj_ops	plat_kernel_kops;
66b40ce02aSNathan Whitehorn static struct platform_kobj	plat_kernel_obj;
67b40ce02aSNathan Whitehorn 
68b40ce02aSNathan Whitehorn static char plat_name[64] = "";
69dc1c5138SZhenlei Huang SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RDTUN,
70b40ce02aSNathan Whitehorn     plat_name, 0, "Platform currently in use");
71b40ce02aSNathan Whitehorn 
7249d9a597SJustin Hibbits static struct mem_affinity mem_info[VM_PHYSSEG_MAX + 1];
7349d9a597SJustin Hibbits static int vm_locality_table[MAXMEMDOM * MAXMEMDOM];
74c1cb22d7SNathan Whitehorn static struct mem_region pregions[PHYS_AVAIL_SZ];
7549d9a597SJustin Hibbits static struct numa_mem_region numa_pregions[PHYS_AVAIL_SZ];
76c1cb22d7SNathan Whitehorn static struct mem_region aregions[PHYS_AVAIL_SZ];
7749d9a597SJustin Hibbits static int nnumapregions, npregions, naregions;
786413b057SNathan Whitehorn 
79c1cb22d7SNathan Whitehorn /*
80c1cb22d7SNathan Whitehorn  * Memory region utilities: determine if two regions overlap,
81c1cb22d7SNathan Whitehorn  * and merge two overlapping regions into one
82c1cb22d7SNathan Whitehorn  */
83c1cb22d7SNathan Whitehorn static int
memr_overlap(struct mem_region * r1,struct mem_region * r2)84c1cb22d7SNathan Whitehorn memr_overlap(struct mem_region *r1, struct mem_region *r2)
85c1cb22d7SNathan Whitehorn {
86c1cb22d7SNathan Whitehorn 	if ((r1->mr_start + r1->mr_size) < r2->mr_start ||
87c1cb22d7SNathan Whitehorn 	    (r2->mr_start + r2->mr_size) < r1->mr_start)
88c1cb22d7SNathan Whitehorn 		return (FALSE);
89c1cb22d7SNathan Whitehorn 
90c1cb22d7SNathan Whitehorn 	return (TRUE);
91c1cb22d7SNathan Whitehorn }
92c1cb22d7SNathan Whitehorn 
93c1cb22d7SNathan Whitehorn static void
memr_merge(struct mem_region * from,struct mem_region * to)94c1cb22d7SNathan Whitehorn memr_merge(struct mem_region *from, struct mem_region *to)
95c1cb22d7SNathan Whitehorn {
96c1cb22d7SNathan Whitehorn 	vm_offset_t end;
97b3936ebeSJustin Hibbits 	end = uqmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
98b3936ebeSJustin Hibbits 	to->mr_start = uqmin(from->mr_start, to->mr_start);
99c1cb22d7SNathan Whitehorn 	to->mr_size = end - to->mr_start;
100c1cb22d7SNathan Whitehorn }
101c1cb22d7SNathan Whitehorn 
102c1cb22d7SNathan Whitehorn /*
103c1cb22d7SNathan Whitehorn  * Quick sort callout for comparing memory regions.
104c1cb22d7SNathan Whitehorn  */
105c1cb22d7SNathan Whitehorn static int
mr_cmp(const void * a,const void * b)106c1cb22d7SNathan Whitehorn mr_cmp(const void *a, const void *b)
107c1cb22d7SNathan Whitehorn {
108c1cb22d7SNathan Whitehorn 	const struct mem_region *regiona, *regionb;
109c1cb22d7SNathan Whitehorn 
110c1cb22d7SNathan Whitehorn 	regiona = a;
111c1cb22d7SNathan Whitehorn 	regionb = b;
112c1cb22d7SNathan Whitehorn 	if (regiona->mr_start < regionb->mr_start)
113c1cb22d7SNathan Whitehorn 		return (-1);
114c1cb22d7SNathan Whitehorn 	else if (regiona->mr_start > regionb->mr_start)
115c1cb22d7SNathan Whitehorn 		return (1);
116c1cb22d7SNathan Whitehorn 	else
117c1cb22d7SNathan Whitehorn 		return (0);
118c1cb22d7SNathan Whitehorn }
119c1cb22d7SNathan Whitehorn 
120b40ce02aSNathan Whitehorn void
numa_mem_regions(struct numa_mem_region ** phys,int * physsz)12149d9a597SJustin Hibbits numa_mem_regions(struct numa_mem_region **phys, int *physsz)
12249d9a597SJustin Hibbits {
12349d9a597SJustin Hibbits 	struct mem_affinity *mi;
12449d9a597SJustin Hibbits 	int i, j, maxdom, ndomain, offset;
12549d9a597SJustin Hibbits 
12649d9a597SJustin Hibbits 	nnumapregions = 0;
12749d9a597SJustin Hibbits 	PLATFORM_NUMA_MEM_REGIONS(plat_obj, numa_pregions, &nnumapregions);
12849d9a597SJustin Hibbits 
12949d9a597SJustin Hibbits 	if (physsz != NULL)
13049d9a597SJustin Hibbits 		*physsz = nnumapregions;
13149d9a597SJustin Hibbits 	if (phys != NULL)
13249d9a597SJustin Hibbits 		*phys = numa_pregions;
13349d9a597SJustin Hibbits 	if (physsz == NULL || phys == NULL) {
13449d9a597SJustin Hibbits 		printf("unset value\n");
13549d9a597SJustin Hibbits 		return;
13649d9a597SJustin Hibbits 	}
13749d9a597SJustin Hibbits 	maxdom = 0;
13849d9a597SJustin Hibbits 	for (i = 0; i < nnumapregions; i++)
13949d9a597SJustin Hibbits 		if (numa_pregions[i].mr_domain > maxdom)
14049d9a597SJustin Hibbits 			maxdom = numa_pregions[i].mr_domain;
14149d9a597SJustin Hibbits 
14249d9a597SJustin Hibbits 	mi = mem_info;
14349d9a597SJustin Hibbits 	for (i = 0; i < nnumapregions; i++, mi++) {
14449d9a597SJustin Hibbits 		mi->start = numa_pregions[i].mr_start;
14549d9a597SJustin Hibbits 		mi->end = numa_pregions[i].mr_start + numa_pregions[i].mr_size;
14649d9a597SJustin Hibbits 		mi->domain = numa_pregions[i].mr_domain;
14749d9a597SJustin Hibbits 	}
14849d9a597SJustin Hibbits 	offset = 0;
14949d9a597SJustin Hibbits 	vm_locality_table[offset] = 10;
15049d9a597SJustin Hibbits 	ndomain = maxdom + 1;
15149d9a597SJustin Hibbits 	if (ndomain > 1) {
15249d9a597SJustin Hibbits 		for (i = 0; i < ndomain; i++) {
15349d9a597SJustin Hibbits 			for (j = 0; j < ndomain; j++) {
15449d9a597SJustin Hibbits 				/*
15549d9a597SJustin Hibbits 				 * Not sure what these values should actually be
15649d9a597SJustin Hibbits 				 */
15749d9a597SJustin Hibbits 				if (i == j)
15849d9a597SJustin Hibbits 					vm_locality_table[offset] = 10;
15949d9a597SJustin Hibbits 				else
16049d9a597SJustin Hibbits 					vm_locality_table[offset] = 21;
16149d9a597SJustin Hibbits 				offset++;
16249d9a597SJustin Hibbits 			}
16349d9a597SJustin Hibbits 		}
16449d9a597SJustin Hibbits 	}
16549d9a597SJustin Hibbits 	vm_phys_register_domains(ndomain, mem_info, vm_locality_table);
16649d9a597SJustin Hibbits }
16749d9a597SJustin Hibbits 
16849d9a597SJustin Hibbits void
mem_regions(struct mem_region ** phys,int * physsz,struct mem_region ** avail,int * availsz)169b40ce02aSNathan Whitehorn mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
170b40ce02aSNathan Whitehorn     int *availsz)
171b40ce02aSNathan Whitehorn {
172c1cb22d7SNathan Whitehorn 	int i, j, still_merging;
173c1cb22d7SNathan Whitehorn 
174c1cb22d7SNathan Whitehorn 	if (npregions == 0) {
1754f412b06SNathan Whitehorn 		PLATFORM_MEM_REGIONS(plat_obj, pregions, &npregions,
176c1cb22d7SNathan Whitehorn 		    aregions, &naregions);
177c1cb22d7SNathan Whitehorn 		qsort(pregions, npregions, sizeof(*pregions), mr_cmp);
178c1cb22d7SNathan Whitehorn 		qsort(aregions, naregions, sizeof(*aregions), mr_cmp);
179c1cb22d7SNathan Whitehorn 
180c1cb22d7SNathan Whitehorn 		/* Remove overlapping available regions */
181c1cb22d7SNathan Whitehorn 		do {
182c1cb22d7SNathan Whitehorn 			still_merging = FALSE;
183c1cb22d7SNathan Whitehorn 			for (i = 0; i < naregions; i++) {
184c1cb22d7SNathan Whitehorn 				if (aregions[i].mr_size == 0)
185c1cb22d7SNathan Whitehorn 					continue;
186c1cb22d7SNathan Whitehorn 				for (j = i+1; j < naregions; j++) {
187c1cb22d7SNathan Whitehorn 					if (aregions[j].mr_size == 0)
188c1cb22d7SNathan Whitehorn 						continue;
189c1cb22d7SNathan Whitehorn 					if (!memr_overlap(&aregions[j],
190c1cb22d7SNathan Whitehorn 					    &aregions[i]))
191c1cb22d7SNathan Whitehorn 						continue;
192c1cb22d7SNathan Whitehorn 
193c1cb22d7SNathan Whitehorn 					memr_merge(&aregions[j], &aregions[i]);
194c1cb22d7SNathan Whitehorn 					/* mark inactive */
195c1cb22d7SNathan Whitehorn 					aregions[j].mr_size = 0;
196c1cb22d7SNathan Whitehorn 					still_merging = TRUE;
197c1cb22d7SNathan Whitehorn 				}
198c1cb22d7SNathan Whitehorn 			}
199c1cb22d7SNathan Whitehorn 		} while (still_merging == TRUE);
200c1cb22d7SNathan Whitehorn 
201c1cb22d7SNathan Whitehorn 		/* Collapse zero-length available regions */
202c1cb22d7SNathan Whitehorn 		for (i = 0; i < naregions; i++) {
203c1cb22d7SNathan Whitehorn 			if (aregions[i].mr_size == 0) {
204c1cb22d7SNathan Whitehorn 				memcpy(&aregions[i], &aregions[i+1],
205c1cb22d7SNathan Whitehorn 				    (naregions - i - 1)*sizeof(*aregions));
206c1cb22d7SNathan Whitehorn 				naregions--;
2076df3000cSAndreas Tobler 				i--;
208c1cb22d7SNathan Whitehorn 			}
209c1cb22d7SNathan Whitehorn 		}
210c1cb22d7SNathan Whitehorn 	}
2116413b057SNathan Whitehorn 
2121a60bed7SNathan Whitehorn 	if (phys != NULL)
2136413b057SNathan Whitehorn 		*phys = pregions;
2141a60bed7SNathan Whitehorn 	if (avail != NULL)
2156413b057SNathan Whitehorn 		*avail = aregions;
2161a60bed7SNathan Whitehorn 	if (physsz != NULL)
2176413b057SNathan Whitehorn 		*physsz = npregions;
2181a60bed7SNathan Whitehorn 	if (availsz != NULL)
2196413b057SNathan Whitehorn 		*availsz = naregions;
2206413b057SNathan Whitehorn }
2216413b057SNathan Whitehorn 
2226413b057SNathan Whitehorn int
mem_valid(vm_offset_t addr,int len)2236413b057SNathan Whitehorn mem_valid(vm_offset_t addr, int len)
2246413b057SNathan Whitehorn {
2256413b057SNathan Whitehorn 	int i;
2266413b057SNathan Whitehorn 
227c1cb22d7SNathan Whitehorn 	if (npregions == 0) {
228c1cb22d7SNathan Whitehorn 		struct mem_region *p, *a;
229c1cb22d7SNathan Whitehorn 		int na, np;
230c1cb22d7SNathan Whitehorn 		mem_regions(&p, &np, &a, &na);
231c1cb22d7SNathan Whitehorn 	}
2326413b057SNathan Whitehorn 
2336413b057SNathan Whitehorn 	for (i = 0; i < npregions; i++)
2346413b057SNathan Whitehorn 		if ((addr >= pregions[i].mr_start)
23587065c67SNathan Whitehorn 		   && (addr + len <= pregions[i].mr_start + pregions[i].mr_size))
2366413b057SNathan Whitehorn 			return (0);
2376413b057SNathan Whitehorn 
2386413b057SNathan Whitehorn 	return (EFAULT);
2396413b057SNathan Whitehorn }
2406413b057SNathan Whitehorn 
2416413b057SNathan Whitehorn vm_offset_t
platform_real_maxaddr(void)2426413b057SNathan Whitehorn platform_real_maxaddr(void)
2436413b057SNathan Whitehorn {
2446413b057SNathan Whitehorn 	return (PLATFORM_REAL_MAXADDR(plat_obj));
245b40ce02aSNathan Whitehorn }
246b40ce02aSNathan Whitehorn 
247b40ce02aSNathan Whitehorn const char *
installed_platform(void)248429ba161SPiotr Kubaj installed_platform(void)
249b40ce02aSNathan Whitehorn {
250b40ce02aSNathan Whitehorn 	return (plat_def_impl->name);
251b40ce02aSNathan Whitehorn }
252b40ce02aSNathan Whitehorn 
253b40ce02aSNathan Whitehorn u_long
platform_timebase_freq(struct cpuref * cpu)254b40ce02aSNathan Whitehorn platform_timebase_freq(struct cpuref *cpu)
255b40ce02aSNathan Whitehorn {
256b40ce02aSNathan Whitehorn 	return (PLATFORM_TIMEBASE_FREQ(plat_obj, cpu));
257b40ce02aSNathan Whitehorn }
258b40ce02aSNathan Whitehorn 
259e1c161e7SJustin Hibbits /*
260e1c161e7SJustin Hibbits  * Put the current CPU, as last step in suspend, to sleep
261e1c161e7SJustin Hibbits  */
262e1c161e7SJustin Hibbits void
platform_sleep(void)263429ba161SPiotr Kubaj platform_sleep(void)
264e1c161e7SJustin Hibbits {
265e1c161e7SJustin Hibbits         PLATFORM_SLEEP(plat_obj);
266e1c161e7SJustin Hibbits }
267e1c161e7SJustin Hibbits 
268b40ce02aSNathan Whitehorn int
platform_smp_first_cpu(struct cpuref * cpu)269b40ce02aSNathan Whitehorn platform_smp_first_cpu(struct cpuref *cpu)
270b40ce02aSNathan Whitehorn {
271b40ce02aSNathan Whitehorn 	return (PLATFORM_SMP_FIRST_CPU(plat_obj, cpu));
272b40ce02aSNathan Whitehorn }
273b40ce02aSNathan Whitehorn 
274b40ce02aSNathan Whitehorn int
platform_smp_next_cpu(struct cpuref * cpu)275b40ce02aSNathan Whitehorn platform_smp_next_cpu(struct cpuref *cpu)
276b40ce02aSNathan Whitehorn {
277b40ce02aSNathan Whitehorn 	return (PLATFORM_SMP_NEXT_CPU(plat_obj, cpu));
278b40ce02aSNathan Whitehorn }
279b40ce02aSNathan Whitehorn 
280b40ce02aSNathan Whitehorn int
platform_smp_get_bsp(struct cpuref * cpu)281b40ce02aSNathan Whitehorn platform_smp_get_bsp(struct cpuref *cpu)
282b40ce02aSNathan Whitehorn {
283b40ce02aSNathan Whitehorn 	return (PLATFORM_SMP_GET_BSP(plat_obj, cpu));
284b40ce02aSNathan Whitehorn }
285b40ce02aSNathan Whitehorn 
286b40ce02aSNathan Whitehorn int
platform_smp_start_cpu(struct pcpu * cpu)287b40ce02aSNathan Whitehorn platform_smp_start_cpu(struct pcpu *cpu)
288b40ce02aSNathan Whitehorn {
289b40ce02aSNathan Whitehorn 	return (PLATFORM_SMP_START_CPU(plat_obj, cpu));
290b40ce02aSNathan Whitehorn }
291b40ce02aSNathan Whitehorn 
2920658fe8cSNathan Whitehorn void
platform_smp_ap_init(void)293429ba161SPiotr Kubaj platform_smp_ap_init(void)
2940658fe8cSNathan Whitehorn {
2950658fe8cSNathan Whitehorn 	PLATFORM_SMP_AP_INIT(plat_obj);
2960658fe8cSNathan Whitehorn }
2970658fe8cSNathan Whitehorn 
298bba9cbe3SConrad Meyer void
platform_smp_probe_threads(void)299bba9cbe3SConrad Meyer platform_smp_probe_threads(void)
300bba9cbe3SConrad Meyer {
301bba9cbe3SConrad Meyer 	PLATFORM_SMP_PROBE_THREADS(plat_obj);
302bba9cbe3SConrad Meyer }
303bba9cbe3SConrad Meyer 
3046413b057SNathan Whitehorn #ifdef SMP
3056413b057SNathan Whitehorn struct cpu_group *
cpu_topo(void)3066413b057SNathan Whitehorn cpu_topo(void)
3076413b057SNathan Whitehorn {
3086413b057SNathan Whitehorn 	return (PLATFORM_SMP_TOPO(plat_obj));
3096413b057SNathan Whitehorn }
3106413b057SNathan Whitehorn #endif
3116413b057SNathan Whitehorn 
312490ebb8fSJustin Hibbits int
platform_node_numa_domain(phandle_t node)313490ebb8fSJustin Hibbits platform_node_numa_domain(phandle_t node)
314490ebb8fSJustin Hibbits {
315490ebb8fSJustin Hibbits 	return (PLATFORM_NODE_NUMA_DOMAIN(plat_obj, node));
316490ebb8fSJustin Hibbits }
317490ebb8fSJustin Hibbits 
318b40ce02aSNathan Whitehorn /*
319b2a237beSNathan Whitehorn  * Reset back to firmware.
320b2a237beSNathan Whitehorn  */
321b2a237beSNathan Whitehorn void
cpu_reset(void)322429ba161SPiotr Kubaj cpu_reset(void)
323b2a237beSNathan Whitehorn {
324b2a237beSNathan Whitehorn         PLATFORM_RESET(plat_obj);
325b2a237beSNathan Whitehorn }
326b2a237beSNathan Whitehorn 
platform_smp_timebase_sync(u_long tb,int ap)327de2dd83fSNathan Whitehorn void platform_smp_timebase_sync(u_long tb, int ap)
328de2dd83fSNathan Whitehorn {
329de2dd83fSNathan Whitehorn 
330de2dd83fSNathan Whitehorn 	PLATFORM_SMP_TIMEBASE_SYNC(plat_obj, tb, ap);
331de2dd83fSNathan Whitehorn }
332de2dd83fSNathan Whitehorn 
333b2a237beSNathan Whitehorn /*
334b40ce02aSNathan Whitehorn  * Platform install routines. Highest priority wins, using the same
335b40ce02aSNathan Whitehorn  * algorithm as bus attachment.
336b40ce02aSNathan Whitehorn  */
337b40ce02aSNathan Whitehorn SET_DECLARE(platform_set, platform_def_t);
338b40ce02aSNathan Whitehorn 
339b40ce02aSNathan Whitehorn void
platform_probe_and_attach(void)340429ba161SPiotr Kubaj platform_probe_and_attach(void)
341b40ce02aSNathan Whitehorn {
342b40ce02aSNathan Whitehorn 	platform_def_t	**platpp, *platp;
343b40ce02aSNathan Whitehorn 	int		prio, best_prio;
344b40ce02aSNathan Whitehorn 
345b40ce02aSNathan Whitehorn 	plat_obj = &plat_kernel_obj;
346b40ce02aSNathan Whitehorn 	best_prio = 0;
347b40ce02aSNathan Whitehorn 
348b40ce02aSNathan Whitehorn 	/*
349b40ce02aSNathan Whitehorn 	 * Try to locate the best platform kobj
350b40ce02aSNathan Whitehorn 	 */
351b40ce02aSNathan Whitehorn 	SET_FOREACH(platpp, platform_set) {
352b40ce02aSNathan Whitehorn 		platp = *platpp;
353b40ce02aSNathan Whitehorn 
354b40ce02aSNathan Whitehorn 		/*
355b40ce02aSNathan Whitehorn 		 * Take care of compiling the selected class, and
356b40ce02aSNathan Whitehorn 		 * then statically initialise the MMU object
357b40ce02aSNathan Whitehorn 		 */
358b40ce02aSNathan Whitehorn 		kobj_class_compile_static(platp, &plat_kernel_kops);
359d7ecd801SMarius Strobl 		kobj_init_static((kobj_t)plat_obj, platp);
360b40ce02aSNathan Whitehorn 
361b40ce02aSNathan Whitehorn 		prio = PLATFORM_PROBE(plat_obj);
362b40ce02aSNathan Whitehorn 
363b40ce02aSNathan Whitehorn 		/* Check for errors */
364b40ce02aSNathan Whitehorn 		if (prio > 0)
365b40ce02aSNathan Whitehorn 			continue;
366b40ce02aSNathan Whitehorn 
367b40ce02aSNathan Whitehorn 		/*
368b40ce02aSNathan Whitehorn 		 * Check if this module was specifically requested through
369b40ce02aSNathan Whitehorn 		 * the loader tunable we provide.
370b40ce02aSNathan Whitehorn 		 */
371b40ce02aSNathan Whitehorn 		if (strcmp(platp->name,plat_name) == 0) {
372b40ce02aSNathan Whitehorn 			plat_def_impl = platp;
373b40ce02aSNathan Whitehorn 			break;
374b40ce02aSNathan Whitehorn 		}
375b40ce02aSNathan Whitehorn 
376b40ce02aSNathan Whitehorn 		/* Otherwise, see if it is better than our current best */
377b40ce02aSNathan Whitehorn 		if (plat_def_impl == NULL || prio > best_prio) {
378b40ce02aSNathan Whitehorn 			best_prio = prio;
379b40ce02aSNathan Whitehorn 			plat_def_impl = platp;
380b40ce02aSNathan Whitehorn 		}
381b40ce02aSNathan Whitehorn 
382b40ce02aSNathan Whitehorn 		/*
3836413b057SNathan Whitehorn 		 * We can't free the KOBJ, since it is static. Reset the ops
3846413b057SNathan Whitehorn 		 * member of this class so that we can come back later.
385b40ce02aSNathan Whitehorn 		 */
3866413b057SNathan Whitehorn 		platp->ops = NULL;
387b40ce02aSNathan Whitehorn 	}
388b40ce02aSNathan Whitehorn 
389b40ce02aSNathan Whitehorn 	if (plat_def_impl == NULL)
390b40ce02aSNathan Whitehorn 		panic("No platform module found!");
391b40ce02aSNathan Whitehorn 
392b40ce02aSNathan Whitehorn 	/*
393b40ce02aSNathan Whitehorn 	 * Recompile to make sure we ended with the
394b40ce02aSNathan Whitehorn 	 * correct one, and then attach.
395b40ce02aSNathan Whitehorn 	 */
396b40ce02aSNathan Whitehorn 
397b40ce02aSNathan Whitehorn 	kobj_class_compile_static(plat_def_impl, &plat_kernel_kops);
398d7ecd801SMarius Strobl 	kobj_init_static((kobj_t)plat_obj, plat_def_impl);
399b40ce02aSNathan Whitehorn 
400b40ce02aSNathan Whitehorn 	strlcpy(plat_name,plat_def_impl->name,sizeof(plat_name));
401b40ce02aSNathan Whitehorn 
402b40ce02aSNathan Whitehorn 	PLATFORM_ATTACH(plat_obj);
403b40ce02aSNathan Whitehorn }
404