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