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