blob: 19f732609fc55d258b39b784c745ef9e5a82ab1e [file] [log] [blame]
Huayang Duanc2ef1022018-09-26 14:24:02 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2018 MediaTek Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Huayang Duan4d15d2f2018-09-26 21:23:53 +080016#include <assert.h>
Huayang Duan078332e2019-08-27 13:36:14 +080017#include <cbfs.h>
Huayang Duan4d15d2f2018-09-26 21:23:53 +080018#include <console/console.h>
Huayang Duan078332e2019-08-27 13:36:14 +080019#include <soc/dramc_param.h>
Huayang Duan4d15d2f2018-09-26 21:23:53 +080020#include <soc/dramc_pi_api.h>
Huayang Duanc2ef1022018-09-26 14:24:02 +080021#include <soc/emi.h>
Huayang Duan078332e2019-08-27 13:36:14 +080022#include <string.h>
Huayang Duan4d15d2f2018-09-26 21:23:53 +080023#include <symbols.h>
Huayang Duanc2ef1022018-09-26 14:24:02 +080024
Huayang Duan078332e2019-08-27 13:36:14 +080025static void mt_mem_test(void)
Huayang Duanc2ef1022018-09-26 14:24:02 +080026{
Huayang Duan4d15d2f2018-09-26 21:23:53 +080027 u64 rank_size[RANK_MAX];
28
Julius Wernercd49cce2019-03-05 16:53:33 -080029 if (CONFIG(MEMORY_TEST)) {
Huayang Duan4d15d2f2018-09-26 21:23:53 +080030 size_t r;
31 u8 *addr = _dram;
32
33 dramc_get_rank_size(rank_size);
34
35 for (r = RANK_0; r < RANK_MAX; r++) {
36 int i;
37
38 if (rank_size[r] == 0)
39 break;
40
41 i = complex_mem_test(addr, 0x2000);
42
43 printk(BIOS_DEBUG, "[MEM] complex R/W mem test %s : %d\n",
44 (i == 0) ? "pass" : "fail", i);
45
46 ASSERT(i == 0);
47
48 addr += rank_size[r];
49 }
50 }
Huayang Duanc2ef1022018-09-26 14:24:02 +080051}
Huayang Duan078332e2019-08-27 13:36:14 +080052
53static void dump_param_header(const struct dramc_param *dparam)
54{
55 const struct dramc_param_header *header = &dparam->header;
56
57 printk(BIOS_DEBUG, "header.status = %#x\n", header->status);
58 printk(BIOS_DEBUG, "header.magic = %#x (expected: %#x)\n",
59 header->magic, DRAMC_PARAM_HEADER_MAGIC);
60 printk(BIOS_DEBUG, "header.version = %#x (expected: %#x)\n",
61 header->version, DRAMC_PARAM_HEADER_VERSION);
62 printk(BIOS_DEBUG, "header.size = %#x (expected: %#lx)\n",
63 header->size, sizeof(*dparam));
64 printk(BIOS_DEBUG, "header.config = %#x\n", header->config);
65 printk(BIOS_DEBUG, "header.flags = %#x\n", header->flags);
66 printk(BIOS_DEBUG, "header.checksum = %#x\n", header->checksum);
67}
68
69static int dram_run_fast_calibration(const struct dramc_param *dparam,
70 u16 config)
71{
72 if (!is_valid_dramc_param(dparam)) {
73 printk(BIOS_WARNING,
74 "Invalid DRAM calibration data from flash\n");
75 dump_param_header(dparam);
76 return -1;
77 }
78
79 if (dparam->header.config != config) {
80 printk(BIOS_WARNING,
81 "Incompatible config for calibration data from flash "
82 "(expected: %#x, saved: %#x)\n",
83 config, dparam->header.config);
84 return -1;
85 }
86
87 return 0;
88}
89
90static int dram_run_full_calibration(struct dramc_param *dparam, u16 config)
91{
92 initialize_dramc_param(dparam, config);
93
94 /* Load and run the provided blob for full-calibration if available */
95 struct prog dram = PROG_INIT(PROG_REFCODE, CONFIG_CBFS_PREFIX "/dram");
96
97 if (prog_locate(&dram))
98 return -1;
99
100 if (cbfs_prog_stage_load(&dram))
101 return -2;
102
103 prog_set_entry(&dram, prog_entry(&dram), dparam);
104 prog_run(&dram);
105
106 if (dparam->header.status != DRAMC_SUCCESS) {
107 printk(BIOS_ERR, "Full calibration failed: status = %d\n",
108 dparam->header.status);
109 return -3;
110 }
111
112 if (!(dparam->header.flags & DRAMC_FLAG_HAS_SAVED_DATA)) {
113 printk(BIOS_ERR,
114 "Full calibration executed without saving parameters. "
115 "Please ensure the blob is built properly.\n");
116 return -4;
117 }
118
119 return 0;
120}
121
122static void set_source_to_flash(struct sdram_params *freq_params)
123{
124 for (u8 shuffle = DRAM_DFS_SHUFFLE_1; shuffle < DRAM_DFS_SHUFFLE_MAX;
125 shuffle++)
126 freq_params[shuffle].source = DRAMC_PARAM_SOURCE_FLASH;
127}
128
129static void init_sdram_params(struct sdram_params *dst,
130 const struct sdram_params *src)
131{
132 for (u8 shuffle = DRAM_DFS_SHUFFLE_1; shuffle < DRAM_DFS_SHUFFLE_MAX;
133 shuffle++)
134 memcpy(&dst[shuffle], src, sizeof(*dst));
135}
136
137void mt_mem_init(struct dramc_param_ops *dparam_ops)
138{
139 struct dramc_param *dparam = dparam_ops->param;
Huayang Duan078332e2019-08-27 13:36:14 +0800140
141 u16 config = 0;
142 if (CONFIG(MT8183_DRAM_EMCP))
143 config |= DRAMC_CONFIG_EMCP;
144
145 /* Load calibration params from flash and run fast calibration */
146 if (dparam_ops->read_from_flash(dparam)) {
147 if (dram_run_fast_calibration(dparam, config) == 0) {
148 printk(BIOS_INFO,
149 "DRAM calibraion params loaded from flash\n");
Yu-Ping Wu0e5b1962019-10-07 16:57:24 +0800150 mt_set_emi(dparam);
Huayang Duan078332e2019-08-27 13:36:14 +0800151 mt_mem_test();
152 return;
153 }
154 } else {
155 printk(BIOS_WARNING,
156 "Failed to read calibration data from flash\n");
157 }
158
159 /* Run full calibration */
160 int err = dram_run_full_calibration(dparam, config);
161 if (err == 0) {
162 printk(BIOS_INFO, "Successfully loaded DRAM blobs and "
163 "ran DRAM calibration\n");
164 set_source_to_flash(dparam->freq_params);
165 dparam_ops->write_to_flash(dparam);
166 printk(BIOS_DEBUG, "Calibration params saved to flash: "
167 "version=%#x, size=#%x\n",
168 dparam->header.version, dparam->header.size);
169 return;
170 }
171
172 printk(BIOS_ERR, "Failed to do full calibration (%d), "
173 "falling back to load default sdram param\n", err);
174
175 /* Init params from sdram configs and run partial calibration */
Yu-Ping Wu0e5b1962019-10-07 16:57:24 +0800176 init_sdram_params(dparam->freq_params, get_sdram_config());
177 mt_set_emi(dparam);
Huayang Duan078332e2019-08-27 13:36:14 +0800178 mt_mem_test();
179}