xref: /NextBSD/sys/arm/amlogic/aml8726/aml8726_mp.c (revision 4557fabb34e865d7f40be64b39c9e34fa41dbb60)
1 /*-
2  * Copyright 2015 John Wehle <john@feith.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 /*
28  * Amlogic aml8726 multiprocessor support.
29  *
30  * Some processors require powering on which involves poking registers
31  * on the aobus and cbus ... it's expected that these locations are set
32  * in stone.
33  *
34  * Locking is not used as these routines should only be called by the BP
35  * during startup and should complete prior to the APs being released (the
36  * issue being to ensure that a register such as AML_SOC_CPU_CLK_CNTL_REG
37  * is not concurrently modified).
38  */
39 
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/bus.h>
45 #include <sys/kernel.h>
46 #include <sys/module.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/resource.h>
50 #include <sys/rman.h>
51 #include <sys/smp.h>
52 
53 #include <vm/vm.h>
54 #include <vm/pmap.h>
55 
56 #include <machine/bus.h>
57 #include <machine/smp.h>
58 #include <machine/fdt.h>
59 #include <machine/intr.h>
60 
61 #include <dev/fdt/fdt_common.h>
62 #include <dev/ofw/ofw_bus.h>
63 #include <dev/ofw/ofw_bus_subr.h>
64 
65 #include <arm/amlogic/aml8726/aml8726_soc.h>
66 
67 static const char *scu_compatible[] = {
68 	"arm,cortex-a5-scu",
69 	"arm,cortex-a9-scu",
70 	NULL
71 };
72 
73 static const char *scu_errata_764369[] = {
74 	"arm,cortex-a9-scu",
75 	NULL
76 };
77 
78 static const char *cpucfg_compatible[] = {
79 	"amlogic,aml8726-cpuconfig",
80 	NULL
81 };
82 
83 static struct {
84 	boolean_t errata_764369;
85 	u_long scu_size;
86 	struct resource scu_res;
87 	u_long cpucfg_size;
88 	struct resource cpucfg_res;
89 	struct resource aobus_res;
90 	struct resource cbus_res;
91 } aml8726_smp;
92 
93 #define	AML_SCU_CONTROL_REG			0
94 #define	AML_SCU_CONTROL_ENABLE			1
95 #define	AML_SCU_CONFIG_REG			4
96 #define	AML_SCU_CONFIG_NCPU_MASK		0x3
97 #define	AML_SCU_CPU_PWR_STATUS_REG		8
98 #define	AML_SCU_CPU_PWR_STATUS_CPU3_MASK	(3 << 24)
99 #define	AML_SCU_CPU_PWR_STATUS_CPU2_MASK	(3 << 16)
100 #define	AML_SCU_CPU_PWR_STATUS_CPU1_MASK	(3 << 8)
101 #define	AML_SCU_CPU_PWR_STATUS_CPU0_MASK	3
102 #define	AML_SCU_INV_TAGS_REG			12
103 #define	AML_SCU_DIAG_CONTROL_REG		48
104 #define	AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT	1
105 
106 #define	AML_CPUCONF_CONTROL_REG			0
107 #define	AML_CPUCONF_CPU1_ADDR_REG		4
108 #define	AML_CPUCONF_CPU2_ADDR_REG		8
109 #define	AML_CPUCONF_CPU3_ADDR_REG		12
110 
111 /* aobus */
112 
113 #define	AML_M8_CPU_PWR_CNTL0_REG		0xe0
114 #define	AML_M8B_CPU_PWR_CNTL0_MODE_CPU3_MASK	(3 << 22)
115 #define	AML_M8B_CPU_PWR_CNTL0_MODE_CPU2_MASK	(3 << 20)
116 #define	AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK	(3 << 18)
117 
118 #define	AML_M8_CPU_PWR_CNTL0_ISO_CPU3		(1 << 3)
119 #define	AML_M8_CPU_PWR_CNTL0_ISO_CPU2		(1 << 2)
120 #define	AML_M8_CPU_PWR_CNTL0_ISO_CPU1		(1 << 1)
121 
122 #define	AML_M8_CPU_PWR_CNTL1_REG		0xe4
123 #define	AML_M8B_CPU_PWR_CNTL1_PWR_CPU3		(1 << 19)
124 #define	AML_M8B_CPU_PWR_CNTL1_PWR_CPU2		(1 << 18)
125 #define	AML_M8B_CPU_PWR_CNTL1_PWR_CPU1		(1 << 17)
126 
127 #define	AML_M8_CPU_PWR_CNTL1_MODE_CPU3_MASK	(3 << 8)
128 #define	AML_M8_CPU_PWR_CNTL1_MODE_CPU2_MASK	(3 << 6)
129 #define	AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK	(3 << 4)
130 
131 #define	AML_M8B_CPU_PWR_MEM_PD0_REG		0xf4
132 #define	AML_M8B_CPU_PWR_MEM_PD0_CPU3		(0xf << 20)
133 #define	AML_M8B_CPU_PWR_MEM_PD0_CPU2		(0xf << 24)
134 #define	AML_M8B_CPU_PWR_MEM_PD0_CPU1		(0xf << 28)
135 
136 /* cbus */
137 
138 #define	AML_SOC_CPU_CLK_CNTL_REG		0x419c
139 #define	AML_M8_CPU_CLK_CNTL_RESET_CPU3		(1 << 27)
140 #define	AML_M8_CPU_CLK_CNTL_RESET_CPU2		(1 << 26)
141 #define	AML_M8_CPU_CLK_CNTL_RESET_CPU1		(1 << 25)
142 
143 #define	SCU_WRITE_4(reg, value)		bus_write_4(&aml8726_smp.scu_res,    \
144     (reg), (value))
145 #define	SCU_READ_4(reg)			bus_read_4(&aml8726_smp.scu_res, (reg))
146 #define	SCU_BARRIER(reg)		bus_barrier(&aml8726_smp.scu_res,    \
147     (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE))
148 
149 #define	CPUCONF_WRITE_4(reg, value)	bus_write_4(&aml8726_smp.cpucfg_res, \
150     (reg), (value))
151 #define	CPUCONF_READ_4(reg)		bus_read_4(&aml8726_smp.cpucfg_res,  \
152     (reg))
153 #define	CPUCONF_BARRIER(reg)		bus_barrier(&aml8726_smp.cpucfg_res, \
154     (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE))
155 
156 #define	AOBUS_WRITE_4(reg, value)	bus_write_4(&aml8726_smp.aobus_res,  \
157     (reg), (value))
158 #define	AOBUS_READ_4(reg)		bus_read_4(&aml8726_smp.aobus_res,   \
159     (reg))
160 #define	AOBUS_BARRIER(reg)		bus_barrier(&aml8726_smp.aobus_res,  \
161     (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE))
162 
163 #define	CBUS_WRITE_4(reg, value)	bus_write_4(&aml8726_smp.cbus_res,   \
164     (reg), (value))
165 #define CBUS_READ_4(reg)		bus_read_4(&aml8726_smp.cbus_res,    \
166     (reg))
167 #define	CBUS_BARRIER(reg)		bus_barrier(&aml8726_smp.cbus_res,   \
168     (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE))
169 
170 static phandle_t
find_node_for_device(const char * device,const char ** compatible)171 find_node_for_device(const char *device, const char **compatible)
172 {
173 	int i;
174 	phandle_t node;
175 
176 	/*
177 	 * Try to access the node directly i.e. through /aliases/.
178 	 */
179 
180 	if ((node = OF_finddevice(device)) != 0)
181 		for (i = 0; compatible[i]; i++)
182 			if (fdt_is_compatible_strict(node, compatible[i]))
183 				return node;
184 
185 	/*
186 	 * Find the node the long way.
187 	 */
188 
189 	for (i = 0; compatible[i]; i++) {
190 		if ((node = OF_finddevice("/soc")) == 0)
191 			return (0);
192 
193 		if ((node = fdt_find_compatible(node, compatible[i], 1)) != 0)
194 			return node;
195 	}
196 
197 	return (0);
198 }
199 
200 
201 static int
alloc_resource_for_node(phandle_t node,struct resource * res,u_long * size)202 alloc_resource_for_node(phandle_t node, struct resource *res, u_long *size)
203 {
204 	int err;
205 	u_long pbase, psize;
206 	u_long start;
207 
208 	if ((err = fdt_get_range(OF_parent(node), 0, &pbase, &psize)) != 0 ||
209 	    (err = fdt_regsize(node, &start, size)) != 0)
210 		return (err);
211 
212 	start += pbase;
213 
214 	memset(res, 0, sizeof(*res));
215 
216 	res->r_bustag = fdtbus_bs_tag;
217 
218 	err = bus_space_map(res->r_bustag, start, *size, 0, &res->r_bushandle);
219 
220 	return (err);
221 }
222 
223 
224 static void
power_on_cpu(int cpu)225 power_on_cpu(int cpu)
226 {
227 	uint32_t scpsr;
228 	uint32_t value;
229 
230 	if (cpu <= 0)
231 		return;
232 
233 	/*
234 	 * Power on the CPU if the intricate details are known, otherwise
235 	 * just hope for the best (it may have already be powered on by
236 	 * the hardware / firmware).
237 	 */
238 
239 	switch (aml8726_soc_hw_rev) {
240 	case AML_SOC_HW_REV_M8:
241 	case AML_SOC_HW_REV_M8B:
242 		/*
243 		 * Set the SCU power status for the CPU to normal mode.
244 		 */
245 		scpsr = SCU_READ_4(AML_SCU_CPU_PWR_STATUS_REG);
246 		scpsr &= ~(AML_SCU_CPU_PWR_STATUS_CPU1_MASK << ((cpu - 1) * 8));
247 		SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr);
248 		SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG);
249 
250 		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
251 			/*
252 			 * Reset may cause the current power status from the
253 			 * actual CPU to be written to the SCU (over-writing
254 			 * the value  we've just written) so set it to normal
255 			 * mode as well.
256 			 */
257 			 value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG);
258 			 value &= ~(AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK <<
259 			    ((cpu - 1) * 2));
260 			 AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value);
261 			 AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG);
262 		 }
263 
264 		DELAY(5);
265 
266 		/*
267 		 * Assert reset.
268 		 */
269 		value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG);
270 		value |= AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1);
271 		CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value);
272 		CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG);
273 
274 		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
275 			/*
276 			 * Release RAM pull-down.
277 			 */
278 			 value = AOBUS_READ_4(AML_M8B_CPU_PWR_MEM_PD0_REG);
279 			 value &= ~((uint32_t)AML_M8B_CPU_PWR_MEM_PD0_CPU1 >>
280 			    ((cpu - 1) * 4));
281 			 AOBUS_WRITE_4(AML_M8B_CPU_PWR_MEM_PD0_REG, value);
282 			 AOBUS_BARRIER(AML_M8B_CPU_PWR_MEM_PD0_REG);
283 		 }
284 
285 		/*
286 		 * Power on CPU.
287 		 */
288 		value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG);
289 		value &= ~(AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK <<
290 		    ((cpu - 1) * 2));
291 		AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL1_REG, value);
292 		AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL1_REG);
293 
294 		DELAY(10);
295 
296 		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
297 			/*
298 			 * Wait for power on confirmation.
299 			 */
300 			for ( ; ; ) {
301 				value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG);
302 				value &= AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 <<
303 				    (cpu - 1);
304 				if (value)
305 					break;
306 				DELAY(10);
307 			}
308 		}
309 
310 		/*
311 		 * Release peripheral clamp.
312 		 */
313 		value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG);
314 		value &= ~(AML_M8_CPU_PWR_CNTL0_ISO_CPU1 << (cpu - 1));
315 		AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value);
316 		AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG);
317 
318 		/*
319 		 * Release reset.
320 		 */
321 		value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG);
322 		value &= ~(AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1));
323 		CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value);
324 		CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG);
325 
326 		if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) {
327 			/*
328 			 * The Amlogic Linux platform code sets the SCU power
329 			 * status for the CPU again for some reason so we
330 			 * follow suit (perhaps in case the reset caused
331 			 * a stale power status from the actual CPU to be
332 			 * written to the SCU).
333 			 */
334 			SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr);
335 			SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG);
336 		}
337 		break;
338 	default:
339 		break;
340 	}
341 }
342 
343 
344 void
platform_mp_init_secondary(void)345 platform_mp_init_secondary(void)
346 {
347 
348 	/*
349 	 * Consider modifying the timer driver to support
350 	 * per-cpu timers and then enabling the timer for
351 	 * each AP.
352 	 */
353 
354 	 intr_pic_init_secondary();
355 }
356 
357 
358 void
platform_mp_setmaxid(void)359 platform_mp_setmaxid(void)
360 {
361 	int err;
362 	int i;
363 	int ncpu;
364 	phandle_t cpucfg_node;
365 	phandle_t scu_node;
366 	uint32_t value;
367 
368 	if (mp_ncpus != 0)
369 		return;
370 
371 	ncpu = 1;
372 
373 	/*
374 	 * Is the hardware necessary for SMP present?
375 	 */
376 
377 	if ((scu_node = find_node_for_device("scu", scu_compatible)) == 0)
378 		goto moveon;
379 
380 	if ((cpucfg_node = find_node_for_device("cpuconfig",
381 	    cpucfg_compatible)) == 0)
382 		goto moveon;
383 
384 	if (alloc_resource_for_node(scu_node, &aml8726_smp.scu_res,
385 	    &aml8726_smp.scu_size) != 0)
386 		panic("Could not allocate resource for SCU");
387 
388 	if (alloc_resource_for_node(cpucfg_node, &aml8726_smp.cpucfg_res,
389 	    &aml8726_smp.cpucfg_size) != 0)
390 		panic("Could not allocate resource for CPUCONFIG");
391 
392 
393 	/*
394 	 * Strictly speaking the aobus and cbus may not be required in
395 	 * order to start an AP (it depends on the processor), however
396 	 * always mapping them in simplifies the code.
397 	 */
398 
399 	aml8726_smp.aobus_res.r_bustag = fdtbus_bs_tag;
400 
401 	err = bus_space_map(aml8726_smp.aobus_res.r_bustag,
402 	    AML_SOC_AOBUS_BASE_ADDR, 0x100000,
403 	    0, &aml8726_smp.aobus_res.r_bushandle);
404 
405 	if (err)
406 		panic("Could not allocate resource for AOBUS");
407 
408 	aml8726_smp.cbus_res.r_bustag = fdtbus_bs_tag;
409 
410 	err = bus_space_map(aml8726_smp.cbus_res.r_bustag,
411 	    AML_SOC_CBUS_BASE_ADDR, 0x100000,
412 	    0, &aml8726_smp.cbus_res.r_bushandle);
413 
414 	if (err)
415 		panic("Could not allocate resource for CBUS");
416 
417 	aml8726_smp.errata_764369 = false;
418 	for (i = 0; scu_errata_764369[i]; i++)
419 		if (fdt_is_compatible_strict(scu_node, scu_errata_764369[i])) {
420 			aml8726_smp.errata_764369 = true;
421 			break;
422 		}
423 
424 	/*
425 	 * Read the number of CPUs present.
426 	 */
427 	value = SCU_READ_4(AML_SCU_CONFIG_REG);
428 	ncpu = (value & AML_SCU_CONFIG_NCPU_MASK) + 1;
429 
430 moveon:
431 	mp_ncpus = ncpu;
432 	mp_maxid = ncpu - 1;
433 }
434 
435 
436 int
platform_mp_probe(void)437 platform_mp_probe(void)
438 {
439 
440 	if (mp_ncpus == 0)
441 		platform_mp_setmaxid();
442 
443 	return (mp_ncpus > 1);
444 }
445 
446 
447 void
platform_mp_start_ap(void)448 platform_mp_start_ap(void)
449 {
450 	int i;
451 	uint32_t reg;
452 	uint32_t value;
453 	vm_paddr_t paddr;
454 
455 	if (mp_ncpus < 2)
456 		return;
457 
458 	/*
459 	 * Invalidate SCU cache tags.  The 0x0000ffff constant invalidates
460 	 * all ways on all cores 0-3.  Per the ARM docs, it's harmless to
461 	 * write to the bits for cores that are not present.
462 	 */
463 	SCU_WRITE_4(AML_SCU_INV_TAGS_REG, 0x0000ffff);
464 
465 	if (aml8726_smp.errata_764369) {
466 		/*
467 		 * Erratum ARM/MP: 764369 (problems with cache maintenance).
468 		 * Setting the "disable-migratory bit" in the undocumented SCU
469 		 * Diagnostic Control Register helps work around the problem.
470 		 */
471 		value = SCU_READ_4(AML_SCU_DIAG_CONTROL_REG);
472 		value |= AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT;
473 		SCU_WRITE_4(AML_SCU_DIAG_CONTROL_REG, value);
474 	}
475 
476 	/*
477 	 * Enable the SCU, then clean the cache on this core.  After these
478 	 * two operations the cache tag ram in the SCU is coherent with
479 	 * the contents of the cache on this core.  The other cores aren't
480 	 * running yet so their caches can't contain valid data yet, however
481 	 * we've initialized their SCU tag ram above, so they will be
482 	 * coherent from startup.
483 	 */
484 	value = SCU_READ_4(AML_SCU_CONTROL_REG);
485 	value |= AML_SCU_CONTROL_ENABLE;
486 	SCU_WRITE_4(AML_SCU_CONTROL_REG, value);
487 	SCU_BARRIER(AML_SCU_CONTROL_REG);
488 	cpu_idcache_wbinv_all();
489 
490 	/* Set the boot address and power on each AP. */
491 	paddr = pmap_kextract((vm_offset_t)mpentry);
492 	for (i = 1; i < mp_ncpus; i++) {
493 		reg = AML_CPUCONF_CPU1_ADDR_REG + ((i - 1) * 4);
494 		CPUCONF_WRITE_4(reg, paddr);
495 		CPUCONF_BARRIER(reg);
496 
497 		power_on_cpu(i);
498 	}
499 
500 	/*
501 	 * Enable the APs.
502 	 *
503 	 * The Amlogic Linux platform code sets the lsb for some reason
504 	 * in addition to the enable bit for each AP so we follow suit
505 	 * (the lsb may be the enable bit for the BP, though in that case
506 	 * it should already be set since it's currently running).
507 	 */
508 	value = CPUCONF_READ_4(AML_CPUCONF_CONTROL_REG);
509 	value |= 1;
510 	for (i = 1; i < mp_ncpus; i++)
511 		value |= (1 << i);
512 	CPUCONF_WRITE_4(AML_CPUCONF_CONTROL_REG, value);
513 	CPUCONF_BARRIER(AML_CPUCONF_CONTROL_REG);
514 
515 	/* Wakeup the now enabled APs */
516 	armv7_sev();
517 
518 	/*
519 	 * Free the resources which are not needed after startup.
520 	 */
521 	bus_space_unmap(aml8726_smp.scu_res.r_bustag,
522 	    aml8726_smp.scu_res.r_bushandle,
523 	    aml8726_smp.scu_size);
524 	bus_space_unmap(aml8726_smp.cpucfg_res.r_bustag,
525 	    aml8726_smp.cpucfg_res.r_bushandle,
526 	    aml8726_smp.cpucfg_size);
527 	bus_space_unmap(aml8726_smp.aobus_res.r_bustag,
528 	    aml8726_smp.aobus_res.r_bushandle,
529 	    0x100000);
530 	bus_space_unmap(aml8726_smp.cbus_res.r_bustag,
531 	    aml8726_smp.cbus_res.r_bushandle,
532 	    0x100000);
533 	memset(&aml8726_smp, 0, sizeof(aml8726_smp));
534 }
535 
536 void
platform_ipi_send(cpuset_t cpus,u_int ipi)537 platform_ipi_send(cpuset_t cpus, u_int ipi)
538 {
539 
540 	pic_ipi_send(cpus, ipi);
541 }
542 
543 /*
544  * Stub drivers for cosmetic purposes.
545  */
546 struct aml8726_scu_softc {
547 	device_t	dev;
548 };
549 
550 static int
aml8726_scu_probe(device_t dev)551 aml8726_scu_probe(device_t dev)
552 {
553 	int i;
554 
555 	for (i = 0; scu_compatible[i]; i++)
556 		if (ofw_bus_is_compatible(dev, scu_compatible[i]))
557 			break;
558 
559 	if (!scu_compatible[i])
560 		return (ENXIO);
561 
562 	device_set_desc(dev, "ARM Snoop Control Unit");
563 
564 	return (BUS_PROBE_DEFAULT);
565 }
566 
567 static int
aml8726_scu_attach(device_t dev)568 aml8726_scu_attach(device_t dev)
569 {
570 	struct aml8726_scu_softc *sc = device_get_softc(dev);
571 
572 	sc->dev = dev;
573 
574 	return (0);
575 }
576 
577 static int
aml8726_scu_detach(device_t dev)578 aml8726_scu_detach(device_t dev)
579 {
580 
581 	return (0);
582 }
583 
584 static device_method_t aml8726_scu_methods[] = {
585 	/* Device interface */
586 	DEVMETHOD(device_probe,		aml8726_scu_probe),
587 	DEVMETHOD(device_attach,	aml8726_scu_attach),
588 	DEVMETHOD(device_detach,	aml8726_scu_detach),
589 
590 	DEVMETHOD_END
591 };
592 
593 static driver_t aml8726_scu_driver = {
594 	"scu",
595 	aml8726_scu_methods,
596 	sizeof(struct aml8726_scu_softc),
597 };
598 
599 static devclass_t aml8726_scu_devclass;
600 
601 EARLY_DRIVER_MODULE(scu, simplebus, aml8726_scu_driver, aml8726_scu_devclass,
602     0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE);
603 
604 struct aml8726_cpucfg_softc {
605 	device_t	dev;
606 };
607 
608 static int
aml8726_cpucfg_probe(device_t dev)609 aml8726_cpucfg_probe(device_t dev)
610 {
611 	int i;
612 
613 	for (i = 0; cpucfg_compatible[i]; i++)
614 		if (ofw_bus_is_compatible(dev, cpucfg_compatible[i]))
615 			break;
616 
617 	if (!cpucfg_compatible[i])
618 		return (ENXIO);
619 
620 	device_set_desc(dev, "Amlogic CPU Config");
621 
622 	return (BUS_PROBE_DEFAULT);
623 }
624 
625 static int
aml8726_cpucfg_attach(device_t dev)626 aml8726_cpucfg_attach(device_t dev)
627 {
628 	struct aml8726_cpucfg_softc *sc = device_get_softc(dev);
629 
630 	sc->dev = dev;
631 
632 	return (0);
633 }
634 
635 static int
aml8726_cpucfg_detach(device_t dev)636 aml8726_cpucfg_detach(device_t dev)
637 {
638 
639 	return (0);
640 }
641 
642 static device_method_t aml8726_cpucfg_methods[] = {
643 	/* Device interface */
644 	DEVMETHOD(device_probe,		aml8726_cpucfg_probe),
645 	DEVMETHOD(device_attach,	aml8726_cpucfg_attach),
646 	DEVMETHOD(device_detach,	aml8726_cpucfg_detach),
647 
648 	DEVMETHOD_END
649 };
650 
651 static driver_t aml8726_cpucfg_driver = {
652 	"cpuconfig",
653 	aml8726_cpucfg_methods,
654 	sizeof(struct aml8726_cpucfg_softc),
655 };
656 
657 static devclass_t aml8726_cpucfg_devclass;
658 
659 EARLY_DRIVER_MODULE(cpuconfig, simplebus, aml8726_cpucfg_driver,
660     aml8726_cpucfg_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE);
661