[coreboot-gerrit] Change in coreboot[master]: soc/cavium: Implement L2C functions without the need of BDK
Patrick Rudolph (Code Review)
gerrit at coreboot.org
Mon Mar 26 16:19:02 CEST 2018
Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/25370
Change subject: soc/cavium: Implement L2C functions without the need of BDK
......................................................................
soc/cavium: Implement L2C functions without the need of BDK
* Implement functions to handle L2C.
* Don't use BDK functions any more.
* Flush L2 cache after loading the payload using memmove. Fixes payload booting.
TODO: Find out why L2 is not point of unification.
Change-Id: I697de35522af55fa8f40f4502e8245d31d07ba5f
Signed-off-by: Patrick Rudolph <patrick.rudolph at 9elements.com>
---
M src/soc/cavium/cn81xx/Makefile.inc
A src/soc/cavium/cn81xx/include/soc/l2c.h
A src/soc/cavium/cn81xx/l2c.c
M src/soc/cavium/cn81xx/sdram.c
4 files changed, 426 insertions(+), 8 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/70/25370/1
diff --git a/src/soc/cavium/cn81xx/Makefile.inc b/src/soc/cavium/cn81xx/Makefile.inc
index ac4dee2..d4fc57d 100644
--- a/src/soc/cavium/cn81xx/Makefile.inc
+++ b/src/soc/cavium/cn81xx/Makefile.inc
@@ -38,7 +38,7 @@
romstage-y += spi.c
romstage-y += uart.c
romstage-$(CONFIG_DRIVERS_UART) += uart.c
-
+romstage-y += l2c.c
romstage-y += sdram.c
romstage-y += ../common/cbmem.c
romstage-y += ../common/lame_string.c
@@ -87,6 +87,7 @@
ramstage-y += uart.c
ramstage-$(CONFIG_DRIVERS_UART) += uart.c
ramstage-y += sdram.c
+ramstage-y += l2c.c
ramstage-y += bl31_plat_params.c
#BL31_MAKEARGS += PLAT=qemu M0_CROSS_COMPILE="$(CROSS_COMPILE_arm)"
diff --git a/src/soc/cavium/cn81xx/include/soc/l2c.h b/src/soc/cavium/cn81xx/include/soc/l2c.h
new file mode 100644
index 0000000..f6e216e
--- /dev/null
+++ b/src/soc/cavium/cn81xx/include/soc/l2c.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2003-2017 Cavium Inc. (support at cavium.com). All rights
+ * reserved.
+ * Copyright 2017-present Facebook, Inc.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SOC_CAVIUM_CN81XX_L2C_H__
+#define __SOC_CAVIUM_CN81XX_L2C_H__
+
+#include <arch/cache.h>
+#include <inttypes.h>
+
+struct cn81xx_l2c_tad {
+ u64 prf;
+ u8 rsvd0[0xf8];
+ u64 pfc;
+ u8 rsvd1[0xfef8];
+ u64 tag;
+ u64 stat;
+ u8 rsvd2[0xfff0];
+ u64 dll;
+ u8 rsvd3[0xfff8];
+ u64 int_w1c;
+ u64 int_w1s;
+ u8 rsvd4[0x10];
+ u64 int_ena_w1c;
+ u64 int_ena_w1s;
+ u8 rsvd5[0xffd0];
+ u64 timetwo;
+ u8 rsvd6[0xf8];
+ u64 timeout;
+ u8 rsvd7[0xfef8];
+ u64 err;
+ u8 rsvd8[0xf8];
+ u64 tqd_err;
+ u8 rsvd9[0xf8];
+ u64 ttg_err;
+ u8 rsvd10[0xfdf8];
+ u64 tbf_bist_status;
+ u8 rsvd11[0xf8];
+ u64 tdt_bist_status;
+ u8 rsvd12[0xf8];
+ u64 ttg_bist_status;
+};
+check_member(cn81xx_l2c_tad, ttg_bist_status, 0x70200 - 0x10000);
+
+#define L2C_TAD_INT_W1C_L2DSBE (1 << 0)
+#define L2C_TAD_INT_W1C_L2DDBE (1 << 1)
+#define L2C_TAD_INT_W1C_SBFSBE (1 << 2)
+#define L2C_TAD_INT_W1C_SBFDBE (1 << 3)
+#define L2C_TAD_INT_W1C_FPFSBE (1 << 4)
+#define L2C_TAD_INT_W1C_FPFDBE (1 << 5)
+#define L2C_TAD_INT_W1C_TAGSBE (1 << 8)
+#define L2C_TAD_INT_W1C_TAGDBE (1 << 9)
+#define L2C_TAD_INT_W1C_NOWAY (1 << 10)
+#define L2C_TAD_INT_W1C_WRNXM (1 << 13)
+#define L2C_TAD_INT_W1C_RDNXM (1 << 14)
+#define L2C_TAD_INT_W1C_RDDISLMC (1 << 15)
+#define L2C_TAD_INT_W1C_WRDISLMC (1 << 16)
+#define L2C_TAD_INT_W1C_LFBTO (1 << 17)
+#define L2C_TAD_INT_W1C_GSYNCTO (1 << 18)
+#define L2C_TAD_INT_W1C_TDDISOCI (1 << 34)
+#define L2C_TAD_INT_W1C_WRDISOCI (1 << 35)
+
+
+/* Flush L2 Cache */
+void l2c_flush(void);
+
+/* Unlock L2 Cache sets */
+size_t l2c_unlock_mem_region(uint64_t start, uint64_t len);
+
+/* Return the L2 Cache size in bytes */
+size_t l2c_get_cache_size_bytes(void);
+
+/* Return the number of sets in the L2 Cache */
+size_t l2c_get_num_sets(void);
+
+/* Return the number of associations in the L2 Cache */
+size_t l2c_get_num_assoc(void);
+
+#endif /* __SOC_CAVIUM_CN81XX_L2C_H__ */
diff --git a/src/soc/cavium/cn81xx/l2c.c b/src/soc/cavium/cn81xx/l2c.c
new file mode 100644
index 0000000..75c106d
--- /dev/null
+++ b/src/soc/cavium/cn81xx/l2c.c
@@ -0,0 +1,337 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2003-2017 Cavium Inc. (support at cavium.com). All rights
+ * reserved.
+ * Copyright 2018-present Facebook, Inc.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch/cache.h>
+#include <inttypes.h>
+#include <soc/asm.h>
+#include <soc/l2c.h>
+#include <arch/io.h>
+
+#include <console/console.h>
+#include <program_loading.h>
+#include <libbdk-arch/bdk-asm.h>
+
+/* Flush L2 Cache */
+void l2c_flush(void)
+{
+ /* The number of ways can be reduced with fuses, but the equations below
+ assume the max number of ways */
+ const size_t MAX_WAYS = 16;
+ const size_t num_sets = l2c_get_num_sets();
+ const size_t num_ways = l2c_get_num_assoc();
+ const size_t cache_line_size = dcache_line_bytes();
+
+ printk(BIOS_DEBUG, "L2C: flush\n");
+
+ int is_rtg = 1; /* Clear remote tags */
+ for (int l2_way = 0; l2_way < num_ways; l2_way++) {
+ for (int l2_set = 0; l2_set < num_sets; l2_set++) {
+ const uint64_t encoded = cache_line_size *
+ (l2_set + num_sets * (l2_way + (is_rtg * MAX_WAYS)));
+ BDK_CACHE_WBI_L2_INDEXED(encoded);
+ }
+ }
+
+ is_rtg = 0; /* Clear local tags */
+ for (int l2_way = 0; l2_way < num_ways; l2_way++) {
+ for (int l2_set = 0; l2_set < num_sets; l2_set++) {
+ const uint64_t encoded = cache_line_size *
+ (l2_set + num_sets * (l2_way + (is_rtg * MAX_WAYS)));
+ BDK_CACHE_WBI_L2_INDEXED(encoded);
+ }
+ }
+}
+
+void platform_segment_loaded(uintptr_t start, size_t size, int flags)
+{
+#if ENV_RAMSTAGE
+ l2c_flush();
+#endif
+}
+
+/* Unlock L2 Cache sets */
+size_t l2c_unlock_mem_region(uint64_t start, uint64_t len)
+{
+ const size_t cache_line_size = dcache_line_bytes();
+ const size_t cache_line_mask = cache_line_size - 1;
+
+ /* Round start/end to cache line boundaries */
+ len += start & cache_line_mask;
+ start &= ~cache_line_mask;
+ len = (len + cache_line_mask) & ~cache_line_mask;
+ void *ptr = (void *)start;
+
+ printk(BIOS_DEBUG, "L2C: unlock [%p, %p)\n", ptr, ptr + len);
+
+ while (len > 0) {
+ /* Must use invalidate version to release lock */
+ BDK_CACHE_WBI_L2(ptr);
+ ptr += cache_line_size;
+ len -= cache_line_size;
+ }
+
+ return 0;
+}
+
+/* Return the L2 Cache size in bytes */
+size_t l2c_get_cache_size_bytes(void)
+{
+ return l2c_get_num_sets() * l2c_get_num_assoc() *
+ dcache_line_bytes();
+}
+
+/**
+ * Register (SYSREG) ap_csselr_el1
+ *
+ * AP Cache Size Selection Register
+ * Selects the current Cache Size ID Register, AP_CCSIDR_EL1, by specifying the
+ * required cache level and the cache type (either instruction or data cache).
+ */
+union bdk_ap_csselr_el1
+{
+ uint32_t u;
+ struct bdk_ap_csselr_el1_s
+ {
+ /**< [ 0: 0](R/W) Instruction not Data bit.
+ * 0 = Data or unified cache.
+ * 1 = Instruction cache. */
+ uint32_t ind : 1;
+ /**< [ 3: 1](R/W) Cache level of required cache. */
+ uint32_t level : 3;
+ uint32_t reserved_4_31 : 28;
+ } s;
+};
+
+/**
+ * Register (SYSREG) ap_ccsidr_el1
+ *
+ * AP Current Cache Size ID Register
+ * This register provides information about the architecture of the currently
+ * selected cache. AP_CSSELR_EL1 selects which Cache Size ID Register is
+ * accessible.
+ */
+union bdk_ap_ccsidr_el1
+{
+ uint32_t u;
+ struct bdk_ap_ccsidr_el1_cn81xx
+ {
+/**< [ 2: 0](RO) Cache-line size, in
+ * (Log2(Number of bytes in cache line)) - 4.
+ * For CNXXXX, 128 bytes.
+ */
+ uint32_t linesize : 3;
+
+/**< [ 12: 3](RO) Associativity of cache minus 1, therefore a
+ * value of 0 indicates an associativity of 1. The associativity
+ * does not have to be a power of 2.
+ * For CNXXXX L1D (AP_CSSELR_EL1[LEVEL] = 0x0, AP_CSSELR_EL1[IND] = 0), is 31.
+ * For CNXXXX L1I (AP_CSSELR_EL1[LEVEL] = 0x0, AP_CSSELR_EL1[IND] = 1), is 38.
+ * For CN81XX L2 (AP_CSSELR_EL1[LEVEL] = 0x1, AP_CSSELR_EL1[IND] = 0), is 15.
+ * For CN80XX L2 (AP_CSSELR_EL1[LEVEL] = 0x1, AP_CSSELR_EL1[IND] = 0), is 7.
+ */
+
+ uint32_t associativity : 10;
+/**< [ 27: 13](RO) Number of sets in cache minus 1, therefore a
+ * value of 0 indicates 1 set in the cache. The number of sets
+ * does not have to be a power of 2.
+ * For CNXXXX L1D (AP_CSSELR_EL1[LEVEL] = 0x0, AP_CSSELR_EL1[IND] = 0), is 7.
+ * For CNXXXX L1I (AP_CSSELR_EL1[LEVEL] = 0x0, AP_CSSELR_EL1[IND] = 1), is 15.
+ * For CN81XX L2 (AP_CSSELR_EL1[LEVEL] = 0x1, AP_CSSELR_EL1[IND] = 0), is 1023.
+ * For CN80XX L2 (AP_CSSELR_EL1[LEVEL] = 0x1, AP_CSSELR_EL1[IND] = 0), is 1023.
+ */
+ uint32_t numsets : 15;
+
+/**< [ 28: 28](RO) Indicates whether the selected cache level supports
+ * write-allocation.
+ * 0 = Write-allocation not supported.
+ * 1 = Write-allocation supported.
+ * For CNXXXX does not apply as hardware managed coherence.
+ */
+ uint32_t wa : 1;
+
+/**< [ 29: 29](RO) Indicates whether the selected cache level supports
+ * read-allocation.
+ * 0 = Read-allocation not supported.
+ * 1 = Read-allocation supported.
+ * For CNXXXX does not apply as hardware managed coherence.
+ */
+ uint32_t ra : 1;
+
+/**< [ 30: 30](RO) Indicates whether the selected cache level supports
+ * write-back.
+ * 0 = Write-back not supported.
+ * 1 = Write-back supported.
+ * For CNXXXX does not apply as hardware managed coherence.
+ */
+ uint32_t wb : 1;
+
+/**< [ 31: 31](RO) Indicates whether the selected cache level supports
+ * write-through.
+ * 0 = Write-through not supported.
+ * 1 = Write-through supported.
+ * For CNXXXX does not apply as hardware managed coherence.
+ */
+ uint32_t wt : 1;
+ } s;
+};
+
+
+/* Return the number of sets in the L2 Cache */
+size_t l2c_get_num_sets(void)
+{
+ /* Select the L2 cache */
+ union bdk_ap_csselr_el1 csselr_el1;
+ csselr_el1.u = 0;
+ csselr_el1.s.ind = 0;
+ csselr_el1.s.level = 1;
+ BDK_MSR(CSSELR_EL1, csselr_el1.u);
+ /* Read its size */
+ union bdk_ap_ccsidr_el1 ccsidr_el1;
+ BDK_MRS(CCSIDR_EL1, ccsidr_el1.u);
+
+ printk(BIOS_DEBUG, "L2C: num sets %u\n", ccsidr_el1.s.numsets + 1);
+
+ return ccsidr_el1.s.numsets + 1;
+}
+
+// FIXME: Move to fuse.c
+#define MIO_FUS_DAT3 0x87e003001418ll
+
+/**
+ * Register (RSL) mio_fus_dat3
+ *
+ * MIO Fuse Data3 Register
+ */
+union cavm_mio_fus_dat3
+{
+ uint64_t u;
+ struct cavm_mio_fus_dat3_cn81xx {
+/**< [ 3: 0](RO) Coprocessor-clock PLL multiplier hardware limit. Indicates
+ * maximum value for PNR_MUL[5:1] straps. Any strap setting above this value
+ * will be ignored. A value of 0 indicates no hardware limit.
+ */
+ uint64_t pnr_pll_mul : 4;
+/**< [ 8: 4](RO) Core-clock PLL multiplier hardware limit. Indicates maximum
+ * value for PLL_MUL[5:1] straps. Any strap setting above this value will be
+ * ignored. A value of 0 indicates no hardware limit.
+ */
+ uint64_t core_pll_mul : 5;
+/**< [ 9: 9](RO) Reserved.
+ * Internal:
+ * When set to 1, TNS switching functionality is permanently disabled.
+ */
+ uint64_t tns_cripple : 1;
+/**< [ 13: 10](RO) Fuse information - HNA information (cluster mask). */
+ uint64_t hna_info_clm : 4;
+/**< [ 16: 14](RO) Fuse information - HNA information (DTE). */
+ uint64_t hna_info_dte : 3;
+/**< [ 17: 17](RO) Fuse information - HNA disable (DTE). */
+ uint64_t nohna_dte : 1;
+/**< [ 23: 18](RO) Fuse information - EMA1.
+ * Internal:
+ * Default value is 0x02. Soft or hard blow of these fuses will XOR with this
+ * value.
+ */
+ uint64_t ema1 : 6;
+/**< [ 24: 24](RO) Fuse information - HFA disable (HTE). */
+ uint64_t nodfa_dte : 1;
+/**< [ 25: 25](RO) Fuse information - ZIP disable. */
+ uint64_t nozip : 1;
+/**< [ 26: 26](RO) Fuse information - efuse ignore. */
+ uint64_t efus_ign : 1;
+/**< [ 27: 27](RO) Fuse information - efuse lockdown. */
+ uint64_t efus_lck : 1;
+/**< [ 28: 28](RO) Fuse information - When 0, BAR2 size conforms to PCIe
+ * specification. */
+ uint64_t bar2_sz_conf : 1;
+/**< [ 30: 29](RO) Fuse information - ZIP information. */
+ uint64_t zip_info : 2;
+/**< [ 31: 31](RO) If set, use the PLL output as the low-jitter reference clock
+ * to the rclk DLLs. Default is to use the internal input reference clock. */
+ uint64_t use_int_refclk : 1;
+/**< [ 34: 32](RO) Fuse information - L2C cripple:
+ * 0x0 = Full cache (16-way, 2 MB).
+ * 0x1 = 3/4 ways (12-way, 1.5 MB).
+ * 0x2 = 1/2 ways (8-way, 1 MB).
+ * 0x3 = 1/4 ways (4-way, 512 KB).
+ * 0x4-0x7 = Reserved.
+ */
+ uint64_t l2c_crip : 3;
+/**< [ 35: 35](RO/H) Fuse information - coprocessor-clock PLL control. */
+ uint64_t pll_half_dis : 1;
+/**< [ 36: 36](RO) Fuse information - efuse lockdown. */
+ uint64_t efus_lck_man : 1;
+/**< [ 37: 37](RO) Fuse information - efuse lockdown. */
+ uint64_t efus_lck_rsv : 1;
+/**< [ 39: 38](RO) Select CLKF denominator for BWADJ value.
+ * 0x0 = Selects CLKF/4.
+ * 0x1 = Selects CLKF/2.
+ * 0x2 = Selects CLKF/8.
+ */
+ uint64_t pll_bwadj_denom : 2;
+/**< [ 40: 40](RO) Fuse information - Select alternate PLL matrix. */
+ uint64_t pll_alt_matrix : 1;
+/**< [ 44: 41](RO) Fuse information - HFA information (cluster mask). */
+ uint64_t dfa_info_clm : 4;
+/**< [ 47: 45](RO) Fuse information - HFA information (HTE). */
+ uint64_t dfa_info_dte : 3;
+/**< [ 57: 48](RO) Reserved. */
+ uint64_t pll_ctl : 10;
+/**< [ 63: 58](RO) Fuse information - EMA0.
+ * Internal:
+ * Default value is 0x11. Soft or hard blow of these fuses will XOR with this
+ * value.
+ */
+ uint64_t ema0 : 6;
+ } s;
+};
+
+/* Return the number of associations in the L2 Cache */
+size_t l2c_get_num_assoc(void)
+{
+ /* Select the L2 cache */
+ union bdk_ap_csselr_el1 csselr_el1;
+ csselr_el1.u = 0;
+ csselr_el1.s.ind = 0;
+ csselr_el1.s.level = 1;
+ BDK_MSR(CSSELR_EL1, csselr_el1.u);
+ /* Read its size */
+ union bdk_ap_ccsidr_el1 ccsidr_el1;
+ BDK_MRS(CCSIDR_EL1, ccsidr_el1.u);
+ /* Store it for use later */
+ size_t ways = ccsidr_el1.s.associativity + 1;
+
+ /* Early chips didn't update the number of ways based on fusing */
+ if (ways == 16) {
+ /* The l2 can be reduced in 25% increments */
+ union cavm_mio_fus_dat3 mio_fus_dat3;
+ mio_fus_dat3.u = read64((u64 *)MIO_FUS_DAT3);
+ switch (mio_fus_dat3.s.l2c_crip) {
+ case 3: /* 1/4 size */
+ ways *= 1;
+ break;
+ case 2: /* 1/2 size */
+ ways *= 2;
+ break;
+ case 1: /* 3/4 size */
+ ways *= 3;
+ break;
+ default: /* Full size */
+ ways *= 4;
+ break;
+ }
+ ways /= 4;
+ }
+
+ printk(BIOS_DEBUG, "L2C: num ways %zu\n", ways);
+
+ return ways;
+}
+
diff --git a/src/soc/cavium/cn81xx/sdram.c b/src/soc/cavium/cn81xx/sdram.c
index b6b42f7..420f1b0 100644
--- a/src/soc/cavium/cn81xx/sdram.c
+++ b/src/soc/cavium/cn81xx/sdram.c
@@ -15,6 +15,7 @@
#include <console/console.h>
#include <soc/sdram.h>
+#include <soc/l2c.h>
#include <cbfs.h>
#include <soc/bdk/libbdk-arch/bdk-warn.h>
@@ -89,13 +90,9 @@
}
/* Unlock L2 now that DRAM works */
- if (node == bdk_numa_master())
- {
- uint64_t l2_size = bdk_l2c_get_cache_size_bytes(node);
- BDK_TRACE(INIT, "Unlocking L2\n");
- bdk_l2c_unlock_mem_region(node, 0, l2_size);
- bdk_watchdog_poke();
- }
+ size_t l2_size = l2c_get_cache_size_bytes();
+ l2c_unlock_mem_region(0, l2_size);
+ bdk_watchdog_poke();
printk(BIOS_INFO, "SDRAM initialization finished.\n");
}
--
To view, visit https://review.coreboot.org/25370
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I697de35522af55fa8f40f4502e8245d31d07ba5f
Gerrit-Change-Number: 25370
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph at 9elements.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180326/d546b7c2/attachment-0001.html>
More information about the coreboot-gerrit
mailing list