blob: 188302f7a8aa3e651261f86432800e24630ad1ab [file] [log] [blame]
Jit Loon Lim55bf2382023-05-17 12:26:11 +08001/*
2 * Copyright (c) 2022, Intel Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9#include <common/debug.h>
10#include "ddr.h"
11#include <lib/mmio.h>
12#include "socfpga_handoff.h"
13
14int ddr_calibration_check(void)
15{
16 // DDR calibration check
17 int status = 0;
18 uint32_t u32data_read = 0;
19
20 NOTICE("DDR: Access address 0x%x:...\n", IO96B_0_REG_BASE);
21 u32data_read = mmio_read_32(IO96B_0_REG_BASE);
22 NOTICE("DDR: Access address 0x%x: read 0x%04x\n", IO96B_0_REG_BASE, u32data_read);
23
24 if (u32data_read == -EPERM) {
25 status = -EPERM;
26 assert(u32data_read);
27 }
28
29 u32data_read = 0x0;
30 NOTICE("DDR: Access address 0x%x: ...\n", IO96B_1_REG_BASE);
31 u32data_read = mmio_read_32(IO96B_1_REG_BASE);
32 NOTICE("DDR: Access address 0x%x: read 0x%04x\n", IO96B_1_REG_BASE, u32data_read);
33
34 if (u32data_read == -EPERM) {
35 status = -EPERM;
36 assert(u32data_read);
37 }
38
39 return status;
40}
41
42int iossm_mb_init(void)
43{
44 // int status;
45
46 // Update according to IOSSM mailbox spec
47
48 // if (status) {
49 // return status;
50 // }
51
52 return 0;
53}
54
55int wait_respond(uint16_t timeout)
56{
57 uint32_t status = 0;
58 uint32_t count = 0;
59 uint32_t data = 0;
60
61 /* Wait status command response ready */
62 do {
63 data = mmio_read_32(IO96B_CSR_REG(CMD_RESPONSE_STATUS));
64 count++;
65 if (count >= timeout) {
66 return -ETIMEDOUT;
67 }
68
69 } while (STATUS_COMMAND_RESPONSE(data) != STATUS_COMMAND_RESPONSE_READY);
70
71 status = (data & STATUS_GENERAL_ERROR_MASK) >> STATUS_GENERAL_ERROR_OFFSET;
72 if (status != 0) {
73 return status;
74 }
75
76 status = (data & STATUS_CMD_RESPONSE_ERROR_MASK) >> STATUS_CMD_RESPONSE_ERROR_OFFSET;
77 if (status != 0) {
78 return status;
79 }
80
81 return status;
82}
83
84int iossm_mb_read_response(void)
85{
86 uint32_t status = 0;
87 unsigned int i;
88 uint32_t resp_data[IOSSM_RESP_MAX_WORD_SIZE];
89 uint32_t resp_param_reg;
90
91 // Check STATUS_CMD_RESPONSE_DATA_PTR_VALID in
92 // STATUS_COMMAND_RESPONSE to ensure data pointer response
93
94 /* Read CMD_RESPONSE_STATUS and CMD_RESPONSE_DATA_* */
95 resp_data[0] = mmio_read_32(IO96B_CSR_REG(CMD_RESPONSE_STATUS));
96 resp_data[0] = (resp_data[0] & CMD_RESPONSE_DATA_SHORT_MASK) >>
97 CMD_RESPONSE_DATA_SHORT_OFFSET;
98 resp_param_reg = CMD_RESPONSE_STATUS;
99 for (i = 1; i < IOSSM_RESP_MAX_WORD_SIZE; i++) {
100 resp_param_reg = resp_param_reg - CMD_RESPONSE_OFFSET;
101 resp_data[i] = mmio_read_32(IO96B_CSR_REG(resp_param_reg));
102 }
103
104 /* Wait for STATUS_COMMAND_RESPONSE_READY*/
105 status = wait_respond(1000);
106
107 /* Read CMD_RESPONSE_STATUS and CMD_RESPONSE_DATA_* */
108 mmio_setbits_32(STATUS_COMMAND_RESPONSE(IO96B_CSR_REG(
109 CMD_RESPONSE_STATUS)),
110 STATUS_COMMAND_RESPONSE_READY_CLEAR);
111
112 return status;
113}
114
115int iossm_mb_send(uint32_t cmd_target_ip_type, uint32_t cmd_target_ip_instance_id,
116 uint32_t cmd_type, uint32_t cmd_opcode, uint32_t *args,
117 unsigned int len)
118{
119 unsigned int i;
120 uint32_t status = 0;
121 uint32_t cmd_req;
122 uint32_t cmd_param_reg;
123
124 cmd_target_ip_type = (cmd_target_ip_type & CMD_TARGET_IP_TYPE_MASK) <<
125 CMD_TARGET_IP_TYPE_OFFSET;
126 cmd_target_ip_instance_id = (cmd_target_ip_instance_id &
127 CMD_TARGET_IP_INSTANCE_ID_MASK) <<
128 CMD_TARGET_IP_INSTANCE_ID_OFFSET;
129 cmd_type = (cmd_type & CMD_TYPE_MASK) << CMD_TYPE_OFFSET;
130 cmd_opcode = (cmd_opcode & CMD_OPCODE_MASK) << CMD_OPCODE_OFFSET;
131 cmd_req = cmd_target_ip_type | cmd_target_ip_instance_id | cmd_type |
132 cmd_opcode;
133
134 /* send mailbox request */
135 IOSSM_MB_WRITE(IO96B_CSR_REG(CMD_REQ), cmd_req);
136 if (len != 0) {
137 cmd_param_reg = CMD_REQ;
138 for (i = 0; i < len; i++) {
139 cmd_param_reg = cmd_param_reg - CMD_PARAM_OFFSET;
140 IOSSM_MB_WRITE(IO96B_CSR_REG(cmd_param_reg), args[i]);
141 }
142 }
143
144 status = iossm_mb_read_response();
145 if (status != 0) {
146 return status;
147 }
148
149 return status;
150}
151
152int ddr_iossm_mailbox_cmd(uint32_t cmd_opcode)
153{
154 // IOSSM
155 uint32_t status = 0;
156 unsigned int i = 0;
157 uint32_t payload[IOSSM_CMD_MAX_WORD_SIZE] = {0U};
158
159 switch (cmd_opcode) {
160 case CMD_INIT:
161 status = iossm_mb_init();
162 break;
163
164 case OPCODE_GET_MEM_INTF_INFO:
165 status = iossm_mb_send(0, 0, MBOX_CMD_GET_SYS_INFO,
166 OPCODE_GET_MEM_INTF_INFO, payload, i);
167 break;
168
169 case OPCODE_GET_MEM_TECHNOLOGY:
170 status = iossm_mb_send(0, 0, MBOX_CMD_GET_MEM_INFO,
171 OPCODE_GET_MEM_TECHNOLOGY, payload, i);
172 break;
173
174 case OPCODE_GET_MEM_WIDTH_INFO:
175 status = iossm_mb_send(0, 0, MBOX_CMD_GET_MEM_INFO,
176 OPCODE_GET_MEM_WIDTH_INFO, payload, i);
177 break;
178
179 case OPCODE_ECC_ENABLE_STATUS:
180 status = iossm_mb_send(0, 0,
181 MBOX_CMD_TRIG_CONTROLLER_OP, OPCODE_ECC_ENABLE_STATUS,
182 payload, i);
183 break;
184
185 case OPCODE_ECC_INTERRUPT_MASK:
186 // payload[i] = CMD_PARAM_0 [16:0]: ECC_INTERRUPT_MASK
187 status = iossm_mb_send(0, 0,
188 MBOX_CMD_TRIG_CONTROLLER_OP, OPCODE_ECC_INTERRUPT_MASK,
189 payload, i);
190 break;
191
192 case OPCODE_ECC_SCRUB_MODE_0_START:
193 // payload[i] = CMD_PARAM_0 [15:0]: ECC_SCRUB_INTERVAL
194 //i++;
195 // payload[i] = CMD_PARAM_1 [11:0]: ECC_SCRUB_LEN
196 //i++;
197 // payload[i] = CMD_PARAM_2 [0:0]: ECC_SCRUB_FULL_MEM
198 //i++;
199 // payload[i]= CMD_PARAM_3 [31:0]: ECC_SCRUB_START_ADDR [31:0]
200 //i++;
201 // payload[i] = CMD_PARAM_4 [5:0]: ECC_SCRUB_START_ADDR [36:32]
202 //i++;
203 // payload[i] = CMD_PARAM_5 [31:0]: ECC_SCRUB_END_ADDR [31:0]
204 //i++;
205 // payload[i] = CMD_PARAM_6 [5:0]: ECC_SCRUB_END_ADDR [36:32]
206 //i++;
207 status = iossm_mb_send(0, 0,
208 MBOX_CMD_TRIG_CONTROLLER_OP, OPCODE_ECC_SCRUB_MODE_0_START,
209 payload, i);
210 break;
211
212 case OPCODE_ECC_SCRUB_MODE_1_START:
213 // payload[i] = CMD_PARAM_0 [15:0]: ECC_SCRUB_IDLE_CNT
214 //i++;
215 // payload[i] = CMD_PARAM_1 [11:0]: ECC_SCRUB_LEN
216 //i++;
217 // payload[i] = CMD_PARAM_2 [0:0]: ECC_SCRUB_FULL_MEM
218 //i++;
219 // payload[i] = CMD_PARAM_3 [31:0]: ECC_SCRUB_START_ADDR [31:0]
220 //i++;
221 // payload[i] = CMD_PARAM_4 [5:0]: ECC_SCRUB_START_ADDR [36:32]
222 //i++;
223 // payload[i] = CMD_PARAM_5 [31:0]: ECC_SCRUB_END_ADDR [31:0]
224 //i++;
225 // payload[i] = CMD_PARAM_6 [5:0]: ECC_SCRUB_END_ADDR [36:32]
226 //i++;
227 status = iossm_mb_send(0, 0,
228 MBOX_CMD_TRIG_CONTROLLER_OP, OPCODE_ECC_SCRUB_MODE_1_START,
229 payload, i);
230 break;
231
232 case OPCODE_BIST_RESULTS_STATUS:
233 status = iossm_mb_send(0, 0,
234 MBOX_CMD_TRIG_CONTROLLER_OP, OPCODE_BIST_RESULTS_STATUS,
235 payload, i);
236 break;
237
238 case OPCODE_BIST_MEM_INIT_START:
239 status = iossm_mb_send(0, 0,
240 MBOX_CMD_TRIG_CONTROLLER_OP, OPCODE_BIST_MEM_INIT_START,
241 payload, i);
242 break;
243
244 case OPCODE_TRIG_MEM_CAL:
245 status = iossm_mb_send(0, 0, MBOX_CMD_TRIG_MEM_CAL_OP,
246 OPCODE_TRIG_MEM_CAL, payload, i);
247 break;
248
249 default:
250 break;
251 }
252
253 if (status == -EPERM) {
254 assert(status);
255 }
256
257 return status;
258}
259
260int ddr_config_handoff(handoff *hoff_ptr)
261{
262 /* Populate DDR handoff data */
263 /* TODO: To add in DDR handoff configuration once available */
264 return 0;
265}
266
267// DDR firewall and non secure access
268void ddr_enable_ns_access(void)
269{
270 /* Please set the ddr non secure registers accordingly */
271
272 mmio_setbits_32(CCU_REG(DMI0_DMIUSMCTCR),
273 CCU_DMI_ALLOCEN | CCU_DMI_LOOKUPEN);
274 mmio_setbits_32(CCU_REG(DMI1_DMIUSMCTCR),
275 CCU_DMI_ALLOCEN | CCU_DMI_LOOKUPEN);
276
277 /* TODO: To add in CCU NCORE OCRAM bypass mask for non secure registers */
278 NOTICE("DDR non secure configured\n");
279}
280
281void ddr_enable_firewall(void)
282{
283 /* Please set the ddr firewall registers accordingly */
284 /* TODO: To add in CCU NCORE OCRAM bypass mask for firewall registers */
285 NOTICE("DDR firewall enabled\n");
286}
287
288bool is_ddr_init_in_progress(void)
289{
290 uint32_t reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0));
291
292 if (reg & SOCFPGA_SYSMGR_BOOT_SCRATCH_POR_0_MASK) {
293 return true;
294 }
295 return false;
296}
297
298int ddr_init(void)
299{
300 // DDR driver initialization
301 int status = -EPERM;
302 uint32_t cmd_opcode = 0;
303
304 // Check and set Boot Scratch Register
305 if (is_ddr_init_in_progress()) {
306 return status;
307 }
308 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0), 0x01);
309
310 // Populate DDR handoff data
311 handoff reverse_handoff_ptr;
312
313 if (!socfpga_get_handoff(&reverse_handoff_ptr)) {
314 assert(status);
315 }
316 status = ddr_config_handoff(&reverse_handoff_ptr);
317 if (status == -EPERM) {
318 assert(status);
319 }
320
321 // CCU and firewall setup
322 ddr_enable_ns_access();
323 ddr_enable_firewall();
324
325 // DDR calibration check
326 status = ddr_calibration_check();
327 if (status == -EPERM) {
328 assert(status);
329 }
330
331 // DDR mailbox command
332 status = ddr_iossm_mailbox_cmd(cmd_opcode);
333 if (status != 0) {
334 assert(status);
335 }
336
337 // Check and set Boot Scratch Register
338 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0), 0x00);
339
340 NOTICE("DDR init successfully\n");
341 return status;
342}