1 /* 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 14 int 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 42 int 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 55 int 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 84 int 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 115 int 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 152 int 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 260 int 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 268 void 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 281 void 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 288 bool 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 298 int 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 } 343