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