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