summaryrefslogtreecommitdiffstats
path: root/src/soc/cavium/cn81xx/sdram.c
blob: 1a6e759e6e108237eecd479e691869649f3bc8bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */

/*
 * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
 */

#include <console/console.h>
#include <soc/sdram.h>

#include <libbdk-arch/bdk-warn.h>
#include <libbdk-arch/bdk-csrs-rst.h>
#include <libbdk-boot/bdk-watchdog.h>
#include <libbdk-dram/bdk-dram-config.h>
#include <libbdk-dram/bdk-dram-test.h>
#include <libbdk-hal/bdk-config.h>
#include <libbdk-hal/bdk-utils.h>
#include <libbdk-hal/bdk-l2c.h>
#include <libdram/libdram-config.h>
#include <soc/ecam.h>
#include <device/pci_ops.h>
#include <device/mmio.h>
#include <device/pci.h>

size_t sdram_size_mb(void)
{
	return bdk_dram_get_size_mbytes(0);
}

#define BDK_RNM_CTL_STATUS	0
#define BDK_RNM_RANDOM		0x100000

#if ENV_ROMSTAGE
/* Enable RNG for DRAM init */
static void rnm_init(void)
{
	/* Bus numbers are hardcoded in ASIC. No need to program bridges. */
	pci_devfn_t dev = PCI_DEV(2, 0, 0);

	u64 *bar = (u64 *)ecam0_get_bar_val(dev, 0);
	if (!bar) {
		printk(BIOS_ERR, "RNG: Failed to get BAR0\n");
		return;
	}

	printk(BIOS_DEBUG, "RNG: BAR0 at %p\n", bar);

	u64 reg = read64(&bar[BDK_RNM_CTL_STATUS]);
	/*
	 * Enables the output of the RNG.
	 * Entropy enable for random number generator.
	 */
	reg |= 3;
	write64(&bar[BDK_RNM_CTL_STATUS], reg);

	/* Read back after enable so we know it is done. */
	reg = read64(&bar[BDK_RNM_CTL_STATUS]);
	/*
	 * Errata (RNM-22528) First consecutive reads to RNM_RANDOM return same
	 * value. Before using the random entropy, read RNM_RANDOM at least once
	 * and discard the data
	 */
	reg = read64(&bar[BDK_RNM_RANDOM]);
	printk(BIOS_SPEW, "RNG: RANDOM %llx\n", reg);
	reg = read64(&bar[BDK_RNM_RANDOM]);
	printk(BIOS_SPEW, "RNG: RANDOM %llx\n", reg);
}

/* based on bdk_boot_dram() */
void sdram_init(void)
{
	printk(BIOS_DEBUG, "Initializing DRAM\n");

	rnm_init();

	/**
	 * FIXME: second arg is actually a desired frequency if set (the
	 * function usually obtains frequency via the config). That might
	 * be useful if FDT or u-boot env is too cumbersome.
	 */
	int mbytes = bdk_dram_config(0, 0);
	if (mbytes < 0) {
		bdk_error("N0: Failed DRAM init\n");
		die("DRAM INIT FAILED !\n");
	}

	/* Poke the watchdog */
	bdk_watchdog_poke();

	/* Report DRAM status */
	printf("N0: DRAM:%s\n", bdk_dram_get_info_string(0));

	/* See if we should test this node's DRAM during boot */
	int test_dram = bdk_config_get_int(BDK_CONFIG_DRAM_BOOT_TEST, 0);
	if (test_dram == 1) {
		static const u8 tests[] = {13, 0, 1};
		for (size_t i = 0; i < ARRAY_SIZE(tests); i++) {
			/* Run the address test to make sure DRAM works */
			if (bdk_dram_test(tests[i], 4 * MiB,
					  sdram_size_mb() * MiB - 4 * MiB,
					  BDK_DRAM_TEST_NO_STATS |
					  BDK_DRAM_TEST_NODE0)) {
				printk(BIOS_CRIT, "%s: Failed DRAM test.\n",
				       __func__);
			}
			bdk_watchdog_poke();
		}
	} else {
		/* Run the address test to make sure DRAM works */
		if (bdk_dram_test(13, 4 * MiB,
			  sdram_size_mb() * MiB - 4 * MiB,
			  BDK_DRAM_TEST_NO_STATS |
			  BDK_DRAM_TEST_NODE0)) {
			/**
			 * FIXME(dhendrix): This should be handled by mainboard
			 * code since we don't necessarily have a BMC to report
			 * to. Also, we need to figure out if we need to keep
			 * going as to avoid getting into a boot loop.
			 */
			// bdk_boot_status(BDK_BOOT_STATUS_REQUEST_POWER_CYCLE);
			printk(BIOS_CRIT, "%s: Failed DRAM test.\n", __func__);
		}
	}

	bdk_watchdog_poke();

	/* Unlock L2 now that DRAM works */
	if (0 == bdk_numa_master()) {
		uint64_t l2_size = bdk_l2c_get_cache_size_bytes(0);
		BDK_TRACE(INIT, "Unlocking L2\n");
		bdk_l2c_unlock_mem_region(0, 0, l2_size);
		bdk_watchdog_poke();
	}

	printk(BIOS_INFO, "SDRAM initialization finished.\n");
}
#endif