[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