xref: /freebsd/stand/powerpc/ofw/cas.c (revision f2e62e601304cea927bbeea70c484030b8e9fe45)
183e356c3SLeandro Lupori /*-
283e356c3SLeandro Lupori  * Copyright (c) 2019 Leandro Lupori
383e356c3SLeandro Lupori  *
483e356c3SLeandro Lupori  * Redistribution and use in source and binary forms, with or without
583e356c3SLeandro Lupori  * modification, are permitted provided that the following conditions
683e356c3SLeandro Lupori  * are met:
783e356c3SLeandro Lupori  * 1. Redistributions of source code must retain the above copyright
883e356c3SLeandro Lupori  *    notice, this list of conditions and the following disclaimer.
983e356c3SLeandro Lupori  * 2. Redistributions in binary form must reproduce the above copyright
1083e356c3SLeandro Lupori  *    notice, this list of conditions and the following disclaimer in the
1183e356c3SLeandro Lupori  *    documentation and/or other materials provided with the distribution.
1283e356c3SLeandro Lupori  *
1383e356c3SLeandro Lupori  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1483e356c3SLeandro Lupori  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1583e356c3SLeandro Lupori  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1683e356c3SLeandro Lupori  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1783e356c3SLeandro Lupori  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1883e356c3SLeandro Lupori  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1983e356c3SLeandro Lupori  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2083e356c3SLeandro Lupori  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2183e356c3SLeandro Lupori  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2283e356c3SLeandro Lupori  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2383e356c3SLeandro Lupori  * SUCH DAMAGE.
2483e356c3SLeandro Lupori  */
2583e356c3SLeandro Lupori 
2683e356c3SLeandro Lupori #include <openfirm.h>
2783e356c3SLeandro Lupori #include <stand.h>
2883e356c3SLeandro Lupori 
29f8328864SLeandro Lupori #include <sys/endian.h>
30f8328864SLeandro Lupori 
31a58abcdeSLeandro Lupori /* #define CAS_DEBUG */
32a58abcdeSLeandro Lupori #ifdef CAS_DEBUG
33a58abcdeSLeandro Lupori #define DPRINTF(fmt, ...)	printf(fmt, ## __VA_ARGS__)
34a58abcdeSLeandro Lupori #else
35a58abcdeSLeandro Lupori #define DPRINTF(fmt, ...)	do { ; } while (0)
36a58abcdeSLeandro Lupori #endif
37a58abcdeSLeandro Lupori 
3883e356c3SLeandro Lupori /* PVR */
39dbef5f71SJustin Hibbits #define PVR_CPU_P8E		0x004b0000
40dbef5f71SJustin Hibbits #define PVR_CPU_P8NVL		0x004c0000
41dbef5f71SJustin Hibbits #define PVR_CPU_P8		0x004d0000
42dbef5f71SJustin Hibbits #define PVR_CPU_P9		0x004e0000
43*f2e62e60SJustin Hibbits #define PVR_CPU_P10		0x00800000
44*f2e62e60SJustin Hibbits #define PVR_CPU_P11		0x00820000
45dbef5f71SJustin Hibbits #define PVR_CPU_MASK		0xffff0000
46dbef5f71SJustin Hibbits 
47dbef5f71SJustin Hibbits #define PVR_ISA_207		0x0f000004
48dbef5f71SJustin Hibbits #define PVR_ISA_300		0x0f000005
49*f2e62e60SJustin Hibbits #define PVR_ISA_31		0x0f000006
50dbef5f71SJustin Hibbits #define PVR_ISA_MASK		0xffffffff
5183e356c3SLeandro Lupori 
5283e356c3SLeandro Lupori /* loader version of kernel's CPU_MAXSIZE */
5383e356c3SLeandro Lupori #define MAX_CPUS		((uint32_t)256u)
5483e356c3SLeandro Lupori 
5583e356c3SLeandro Lupori /* Option Vectors' settings */
5683e356c3SLeandro Lupori 
5783e356c3SLeandro Lupori /* length of ignored OV */
5883e356c3SLeandro Lupori #define OV_IGN_LEN		0
5983e356c3SLeandro Lupori 
6083e356c3SLeandro Lupori /* byte 1 (of any OV) */
6183e356c3SLeandro Lupori #define OV_IGN			0x80
6283e356c3SLeandro Lupori 
6383e356c3SLeandro Lupori /* Option Vector 5 */
6483e356c3SLeandro Lupori 
6583e356c3SLeandro Lupori /* byte 2 */
6683e356c3SLeandro Lupori #define OV5_LPAR		0x80
6783e356c3SLeandro Lupori #define OV5_SPLPAR		0x40
6883e356c3SLeandro Lupori #define OV5_DRMEM		0x20
6983e356c3SLeandro Lupori #define OV5_LP			0x10
7083e356c3SLeandro Lupori #define OV5_ALPHA_PART		0x08
7183e356c3SLeandro Lupori #define OV5_DMA_DELAY		0x04
7283e356c3SLeandro Lupori #define OV5_DONATE_CPU		0x02
7383e356c3SLeandro Lupori #define OV5_MSI			0x01
7483e356c3SLeandro Lupori 
7583e356c3SLeandro Lupori /* 9-12: max cpus */
7683e356c3SLeandro Lupori #define OV5_MAX_CPUS(n)		((MAX_CPUS >> (3*8 - (n)*8)) & 0xff)
7783e356c3SLeandro Lupori 
7883e356c3SLeandro Lupori /* 13-14: LoPAPR Level */
7983e356c3SLeandro Lupori #define LOPAPR_LEVEL		0x0101	/* 1.1 */
8083e356c3SLeandro Lupori #define OV5_LOPAPR_LEVEL(n)	((LOPAPR_LEVEL >> (8 - (n)*8)) & 0xff)
8183e356c3SLeandro Lupori 
8283e356c3SLeandro Lupori /* byte 17: Platform Facilities */
8383e356c3SLeandro Lupori #define OV5_RNG			0x80
8483e356c3SLeandro Lupori #define OV5_COMP_ENG		0x40
8583e356c3SLeandro Lupori #define OV5_ENC_ENG		0x20
8683e356c3SLeandro Lupori 
8783e356c3SLeandro Lupori /* byte 21: Sub-Processors */
8883e356c3SLeandro Lupori #define OV5_NO_SUBPROCS		0
8983e356c3SLeandro Lupori #define OV5_SUBPROCS		1
9083e356c3SLeandro Lupori 
9183e356c3SLeandro Lupori /* byte 23: interrupt controller */
9283e356c3SLeandro Lupori #define OV5_INTC_XICS		0
9383e356c3SLeandro Lupori 
9483e356c3SLeandro Lupori /* byte 24: MMU */
95a58abcdeSLeandro Lupori #define OV5_MMU_INDEX		24
9683e356c3SLeandro Lupori #define OV5_MMU_HPT		0
97a58abcdeSLeandro Lupori #define OV5_MMU_RADIX		0x40
98a58abcdeSLeandro Lupori #define OV5_MMU_EITHER		0x80
99a58abcdeSLeandro Lupori #define OV5_MMU_DYNAMIC		0xc0
10083e356c3SLeandro Lupori 
10183e356c3SLeandro Lupori /* byte 25: HPT MMU Extensions */
102a58abcdeSLeandro Lupori #define OV5_HPT_EXT_INDEX	25
103a58abcdeSLeandro Lupori #define OV5_HPT_GTSE		0x40
10483e356c3SLeandro Lupori 
10583e356c3SLeandro Lupori /* byte 26: Radix MMU Extensions */
106a58abcdeSLeandro Lupori #define OV5_RADIX_EXT_INDEX	26
107a58abcdeSLeandro Lupori #define OV5_RADIX_GTSE		0x40
10883e356c3SLeandro Lupori 
10983e356c3SLeandro Lupori 
11083e356c3SLeandro Lupori struct pvr {
11183e356c3SLeandro Lupori 	uint32_t	mask;
11283e356c3SLeandro Lupori 	uint32_t	val;
11383e356c3SLeandro Lupori };
11483e356c3SLeandro Lupori 
11583e356c3SLeandro Lupori struct opt_vec_ignore {
11683e356c3SLeandro Lupori 	char	data[2];
11783e356c3SLeandro Lupori } __packed;
11883e356c3SLeandro Lupori 
11983e356c3SLeandro Lupori struct opt_vec4 {
12083e356c3SLeandro Lupori 	char data[3];
12183e356c3SLeandro Lupori } __packed;
12283e356c3SLeandro Lupori 
12383e356c3SLeandro Lupori struct opt_vec5 {
12483e356c3SLeandro Lupori 	char data[27];
12583e356c3SLeandro Lupori } __packed;
12683e356c3SLeandro Lupori 
12783e356c3SLeandro Lupori static struct ibm_arch_vec {
128*f2e62e60SJustin Hibbits 	struct pvr		pvr_list[10];
12983e356c3SLeandro Lupori 	uint8_t			num_opts;
13083e356c3SLeandro Lupori 	struct opt_vec_ignore	vec1;
13183e356c3SLeandro Lupori 	struct opt_vec_ignore	vec2;
13283e356c3SLeandro Lupori 	struct opt_vec_ignore	vec3;
13383e356c3SLeandro Lupori 	struct opt_vec4		vec4;
13483e356c3SLeandro Lupori 	struct opt_vec5		vec5;
13583e356c3SLeandro Lupori } __packed ibm_arch_vec = {
13683e356c3SLeandro Lupori 	/* pvr_list */ {
137f8328864SLeandro Lupori 		{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8) },
138f8328864SLeandro Lupori 		{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8E) },
139f8328864SLeandro Lupori 		{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8NVL) },
140f8328864SLeandro Lupori 		{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P9) },
141*f2e62e60SJustin Hibbits 		{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P10) },
142*f2e62e60SJustin Hibbits 		{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P11) },
143f8328864SLeandro Lupori 		{ htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_207) },
144f8328864SLeandro Lupori 		{ htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_300) },
145*f2e62e60SJustin Hibbits 		{ htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_31) },
14683e356c3SLeandro Lupori 		{ 0, 0xffffffffu }			/* terminator */
14783e356c3SLeandro Lupori 	},
14883e356c3SLeandro Lupori 	4,	/* num_opts (4 actually means 5 option vectors) */
14983e356c3SLeandro Lupori 	{ OV_IGN_LEN, OV_IGN },		/* OV1 */
15083e356c3SLeandro Lupori 	{ OV_IGN_LEN, OV_IGN },		/* OV2 */
15183e356c3SLeandro Lupori 	{ OV_IGN_LEN, OV_IGN },		/* OV3 */
15283e356c3SLeandro Lupori 	/* OV4 (can't be ignored) */ {
15383e356c3SLeandro Lupori 		sizeof(struct opt_vec4) - 2,	/* length (n-2) */
15483e356c3SLeandro Lupori 		0,
15583e356c3SLeandro Lupori 		10 /* Minimum VP entitled capacity percentage * 100
15683e356c3SLeandro Lupori 		    * (if absent assume 10%) */
15783e356c3SLeandro Lupori 	},
15883e356c3SLeandro Lupori 	/* OV5 */ {
15983e356c3SLeandro Lupori 		sizeof(struct opt_vec5) - 2,	/* length (n-2) */
16083e356c3SLeandro Lupori 		0,				/* don't ignore */
16183e356c3SLeandro Lupori 		OV5_LPAR | OV5_SPLPAR | OV5_LP | OV5_MSI,
16283e356c3SLeandro Lupori 		0,
16383e356c3SLeandro Lupori 		0,	/* Cooperative Memory Over-commitment */
16483e356c3SLeandro Lupori 		0,	/* Associativity Information Option */
16583e356c3SLeandro Lupori 		0,	/* Binary Option Controls */
16683e356c3SLeandro Lupori 		0,	/* Reserved */
16783e356c3SLeandro Lupori 		0,	/* Reserved */
16883e356c3SLeandro Lupori 		OV5_MAX_CPUS(0),
16983e356c3SLeandro Lupori 		OV5_MAX_CPUS(1),		/* 10 */
17083e356c3SLeandro Lupori 		OV5_MAX_CPUS(2),
17183e356c3SLeandro Lupori 		OV5_MAX_CPUS(3),
17283e356c3SLeandro Lupori 		OV5_LOPAPR_LEVEL(0),
17383e356c3SLeandro Lupori 		OV5_LOPAPR_LEVEL(1),
17483e356c3SLeandro Lupori 		0,	/* Reserved */
17583e356c3SLeandro Lupori 		0,	/* Reserved */
17683e356c3SLeandro Lupori 		0,	/* Platform Facilities */
17783e356c3SLeandro Lupori 		0,	/* Reserved */
17883e356c3SLeandro Lupori 		0,	/* Reserved */
17983e356c3SLeandro Lupori 		0,	/* Reserved */		/* 20 */
18083e356c3SLeandro Lupori 		OV5_NO_SUBPROCS,
18183e356c3SLeandro Lupori 		0,	/* DRMEM_V2 */
18283e356c3SLeandro Lupori 		OV5_INTC_XICS,
18383e356c3SLeandro Lupori 		OV5_MMU_HPT,
184a58abcdeSLeandro Lupori 		0,
185a58abcdeSLeandro Lupori 		0
18683e356c3SLeandro Lupori 	}
18783e356c3SLeandro Lupori };
18883e356c3SLeandro Lupori 
18983e356c3SLeandro Lupori int
ppc64_cas(void)19083e356c3SLeandro Lupori ppc64_cas(void)
19183e356c3SLeandro Lupori {
192a58abcdeSLeandro Lupori 	phandle_t pkg;
193a58abcdeSLeandro Lupori 	ihandle_t inst;
194*f2e62e60SJustin Hibbits 	cell_t err = 0;
195a58abcdeSLeandro Lupori 	uint8_t buf[16], idx, val;
196a58abcdeSLeandro Lupori 	int i, len, rc, radix_mmu;
197a58abcdeSLeandro Lupori 	const char *var;
198a58abcdeSLeandro Lupori 	char *ov5;
19983e356c3SLeandro Lupori 
200a58abcdeSLeandro Lupori 	pkg = OF_finddevice("/chosen");
201a58abcdeSLeandro Lupori 	if (pkg == -1) {
202a58abcdeSLeandro Lupori 		printf("cas: couldn't find /chosen\n");
203a58abcdeSLeandro Lupori 		return (-1);
20483e356c3SLeandro Lupori 	}
20583e356c3SLeandro Lupori 
206a58abcdeSLeandro Lupori 	len = OF_getprop(pkg, "ibm,arch-vec-5-platform-support", buf,
207a58abcdeSLeandro Lupori 	    sizeof(buf));
208a58abcdeSLeandro Lupori 	if (len == -1)
209a58abcdeSLeandro Lupori 		/* CAS not supported */
2109ae63185SBrandon Bergren 		return (0);
2119ae63185SBrandon Bergren 
212a58abcdeSLeandro Lupori 	radix_mmu = 0;
213a58abcdeSLeandro Lupori 	ov5 = ibm_arch_vec.vec5.data;
214a58abcdeSLeandro Lupori 	for (i = 0; i < len; i += 2) {
215a58abcdeSLeandro Lupori 		idx = buf[i];
216a58abcdeSLeandro Lupori 		val = buf[i + 1];
217a58abcdeSLeandro Lupori 		DPRINTF("idx 0x%02x val 0x%02x\n", idx, val);
218a58abcdeSLeandro Lupori 
219a58abcdeSLeandro Lupori 		switch (idx) {
220a58abcdeSLeandro Lupori 		case OV5_MMU_INDEX:
221a58abcdeSLeandro Lupori 			/*
222a58abcdeSLeandro Lupori 			 * Note that testing for OV5_MMU_RADIX/OV5_MMU_EITHER
223a58abcdeSLeandro Lupori 			 * also covers OV5_MMU_DYNAMIC.
224a58abcdeSLeandro Lupori 			 */
225a58abcdeSLeandro Lupori 			if ((val & OV5_MMU_RADIX) || (val & OV5_MMU_EITHER))
226a58abcdeSLeandro Lupori 				radix_mmu = 1;
227a58abcdeSLeandro Lupori 			break;
228a58abcdeSLeandro Lupori 
229a58abcdeSLeandro Lupori 		case OV5_RADIX_EXT_INDEX:
230a58abcdeSLeandro Lupori 			if (val & OV5_RADIX_GTSE)
231a58abcdeSLeandro Lupori 				ov5[idx] = OV5_RADIX_GTSE;
232a58abcdeSLeandro Lupori 			break;
233a58abcdeSLeandro Lupori 
234a58abcdeSLeandro Lupori 		case OV5_HPT_EXT_INDEX:
235a58abcdeSLeandro Lupori 		default:
236a58abcdeSLeandro Lupori 			break;
237a58abcdeSLeandro Lupori 		}
238a58abcdeSLeandro Lupori 	}
239a58abcdeSLeandro Lupori 
240a23e18eaSLeandro Lupori 	if (!radix_mmu)
241a23e18eaSLeandro Lupori 		/*
242a23e18eaSLeandro Lupori 		 * If radix is not supported, set radix_mmu to 0 to avoid
243a23e18eaSLeandro Lupori 		 * the kernel trying to use it and panic.
244a23e18eaSLeandro Lupori 		 */
245a23e18eaSLeandro Lupori 		setenv("radix_mmu", "0", 1);
246a23e18eaSLeandro Lupori 	else if ((var = getenv("radix_mmu")) != NULL && var[0] == '0')
247a58abcdeSLeandro Lupori 		radix_mmu = 0;
248a23e18eaSLeandro Lupori 	else
2498ecf9a8bSLeandro Lupori 		ov5[OV5_MMU_INDEX] = OV5_MMU_RADIX;
250a58abcdeSLeandro Lupori 
251a58abcdeSLeandro Lupori 	inst = OF_open("/");
252a58abcdeSLeandro Lupori 	if (inst == -1) {
25383e356c3SLeandro Lupori 		printf("cas: failed to open / node\n");
25483e356c3SLeandro Lupori 		return (-1);
25583e356c3SLeandro Lupori 	}
25683e356c3SLeandro Lupori 
257a58abcdeSLeandro Lupori 	DPRINTF("MMU 0x%02x RADIX_EXT 0x%02x\n",
258a58abcdeSLeandro Lupori 	    ov5[OV5_MMU_INDEX], ov5[OV5_RADIX_EXT_INDEX]);
259a58abcdeSLeandro Lupori 	rc = OF_call_method("ibm,client-architecture-support",
260a58abcdeSLeandro Lupori 	    inst, 1, 1, &ibm_arch_vec, &err);
261a58abcdeSLeandro Lupori 	if (rc != 0 || err) {
262a58abcdeSLeandro Lupori 		printf("cas: CAS method returned an error: rc %d err %jd\n",
263a58abcdeSLeandro Lupori 		    rc, (intmax_t)err);
26483e356c3SLeandro Lupori 		rc = -1;
26583e356c3SLeandro Lupori 	}
26683e356c3SLeandro Lupori 
267a58abcdeSLeandro Lupori 	OF_close(inst);
268a58abcdeSLeandro Lupori 	printf("cas: selected %s MMU\n", radix_mmu ? "radix" : "hash");
26983e356c3SLeandro Lupori 	return (rc);
27083e356c3SLeandro Lupori }
271