xref: /rk3399_ARM-atf/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c (revision 80cd7dd1bb7bcd79cbb9a91715cafc7cc1be665f)
1ee5b26fdSAndre Przywara /*
2ee5b26fdSAndre Przywara  * Copyright (c) 2024, ARM Limited. All rights reserved.
3ee5b26fdSAndre Przywara  *
4ee5b26fdSAndre Przywara  * SPDX-License-Identifier: BSD-3-Clause
5ee5b26fdSAndre Przywara  *
6ee5b26fdSAndre Przywara  * Amend the device tree to adjust the L2 cache size, which is different
7ee5b26fdSAndre Przywara  * between the revisions of the H616 chips: earlier versions have 256 KB of L2,
8ee5b26fdSAndre Przywara  * later versions 1 MB.
9ee5b26fdSAndre Przywara  * Read the cache ID registers and adjust the size and number of sets entries
10ee5b26fdSAndre Przywara  * in the L2 cache DT node.
11ee5b26fdSAndre Przywara  */
12ee5b26fdSAndre Przywara 
13ee5b26fdSAndre Przywara #include <common/fdt_wrappers.h>
14ee5b26fdSAndre Przywara #include <lib/utils_def.h>
15ee5b26fdSAndre Przywara #include <libfdt.h>
16ee5b26fdSAndre Przywara 
17ee5b26fdSAndre Przywara #define CACHE_L1D		0x0
18ee5b26fdSAndre Przywara #define CACHE_L1I		0x1
19ee5b26fdSAndre Przywara #define CACHE_L2U		0x2
20ee5b26fdSAndre Przywara 
21ee5b26fdSAndre Przywara #define CCSIDR_SETS_SHIFT	13
22ee5b26fdSAndre Przywara #define CCSIDR_SETS_MASK	GENMASK(14, 0)
23ee5b26fdSAndre Przywara #define CCSIDR_ASSOC_SHIFT	3
24ee5b26fdSAndre Przywara #define CCSIDR_ASSOC_MASK	GENMASK(9, 0)
25ee5b26fdSAndre Przywara #define CCSIDR_LSIZE_SHIFT	0
26ee5b26fdSAndre Przywara #define CCSIDR_LSIZE_MASK	GENMASK(2, 0)
27ee5b26fdSAndre Przywara 
armv8_get_ccsidr(unsigned int sel)28ee5b26fdSAndre Przywara static uint32_t armv8_get_ccsidr(unsigned int sel)
29ee5b26fdSAndre Przywara {
30ee5b26fdSAndre Przywara 	uint32_t reg;
31ee5b26fdSAndre Przywara 
32ee5b26fdSAndre Przywara 	__asm__ volatile ("msr CSSELR_EL1, %0\n" :: "r" (sel));
33ee5b26fdSAndre Przywara 	__asm__ volatile ("mrs %0, CCSIDR_EL1\n" : "=r" (reg));
34ee5b26fdSAndre Przywara 
35ee5b26fdSAndre Przywara 	return reg;
36ee5b26fdSAndre Przywara }
37ee5b26fdSAndre Przywara 
sunxi_soc_fdt_fixup(void * dtb)38ee5b26fdSAndre Przywara void sunxi_soc_fdt_fixup(void *dtb)
39ee5b26fdSAndre Przywara {
40ee5b26fdSAndre Przywara 	int node = fdt_path_offset(dtb, "/cpus/cpu@0");
41ee5b26fdSAndre Przywara 	uint32_t phandle, ccsidr, cell;
42ee5b26fdSAndre Przywara 	int sets, line_size, assoc;
43ee5b26fdSAndre Przywara 	int ret;
44ee5b26fdSAndre Przywara 
45ee5b26fdSAndre Przywara 	if (node < 0) {
46ee5b26fdSAndre Przywara 		return;
47ee5b26fdSAndre Przywara 	}
48ee5b26fdSAndre Przywara 
49ee5b26fdSAndre Przywara 	ret = fdt_read_uint32(dtb, node, "next-level-cache", &phandle);
50ee5b26fdSAndre Przywara 	if (ret != 0) {
51ee5b26fdSAndre Przywara 		return;
52ee5b26fdSAndre Przywara 	}
53ee5b26fdSAndre Przywara 
54ee5b26fdSAndre Przywara 	node = fdt_node_offset_by_phandle(dtb, phandle);
55*7300a4d1SAndre Przywara 	if (node < 0) {
56ee5b26fdSAndre Przywara 		return;
57ee5b26fdSAndre Przywara 	}
58ee5b26fdSAndre Przywara 
59ee5b26fdSAndre Przywara 	ccsidr = armv8_get_ccsidr(CACHE_L2U);
60ee5b26fdSAndre Przywara 	sets = ((ccsidr >> CCSIDR_SETS_SHIFT) & CCSIDR_SETS_MASK) + 1;
61ee5b26fdSAndre Przywara 	line_size = 16U << ((ccsidr >> CCSIDR_LSIZE_SHIFT) & CCSIDR_LSIZE_MASK);
62ee5b26fdSAndre Przywara 	assoc = ((ccsidr >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK) + 1;
63ee5b26fdSAndre Przywara 
64ee5b26fdSAndre Przywara 	cell = cpu_to_fdt32(sets);
65ee5b26fdSAndre Przywara 	fdt_setprop(dtb, node, "cache-sets", &cell, sizeof(cell));
66ee5b26fdSAndre Przywara 
67ee5b26fdSAndre Przywara 	cell = cpu_to_fdt32(line_size);
68ee5b26fdSAndre Przywara 	fdt_setprop(dtb, node, "cache-line-size", &cell, sizeof(cell));
69ee5b26fdSAndre Przywara 
70ee5b26fdSAndre Przywara 	cell = cpu_to_fdt32(sets * assoc * line_size);
71ee5b26fdSAndre Przywara 	fdt_setprop(dtb, node, "cache-size", &cell, sizeof(cell));
72ee5b26fdSAndre Przywara }
73