1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <lib/mmio.h> 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu #include <drivers/delay_timer.h> 10*91f16700Schasinglulu #include <platform_def.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include "socfpga_mailbox.h" 13*91f16700Schasinglulu #include "socfpga_plat_def.h" 14*91f16700Schasinglulu #include "socfpga_sip_svc.h" 15*91f16700Schasinglulu #include "socfpga_system_manager.h" 16*91f16700Schasinglulu 17*91f16700Schasinglulu static mailbox_payload_t mailbox_resp_payload; 18*91f16700Schasinglulu static mailbox_container_t mailbox_resp_ctr = {0, 0, &mailbox_resp_payload}; 19*91f16700Schasinglulu 20*91f16700Schasinglulu static bool is_mailbox_cmdbuf_full(uint32_t cin) 21*91f16700Schasinglulu { 22*91f16700Schasinglulu uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT); 23*91f16700Schasinglulu 24*91f16700Schasinglulu return (((cin + 1U) % MBOX_CMD_BUFFER_SIZE) == cout); 25*91f16700Schasinglulu } 26*91f16700Schasinglulu 27*91f16700Schasinglulu static bool is_mailbox_cmdbuf_empty(uint32_t cin) 28*91f16700Schasinglulu { 29*91f16700Schasinglulu uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT); 30*91f16700Schasinglulu 31*91f16700Schasinglulu return (((cout + 1U) % MBOX_CMD_BUFFER_SIZE) == cin); 32*91f16700Schasinglulu } 33*91f16700Schasinglulu 34*91f16700Schasinglulu static int wait_for_mailbox_cmdbuf_empty(uint32_t cin) 35*91f16700Schasinglulu { 36*91f16700Schasinglulu unsigned int timeout = 200U; 37*91f16700Schasinglulu 38*91f16700Schasinglulu do { 39*91f16700Schasinglulu if (is_mailbox_cmdbuf_empty(cin)) { 40*91f16700Schasinglulu break; 41*91f16700Schasinglulu } 42*91f16700Schasinglulu mdelay(10U); 43*91f16700Schasinglulu } while (--timeout != 0U); 44*91f16700Schasinglulu 45*91f16700Schasinglulu if (timeout == 0U) { 46*91f16700Schasinglulu return MBOX_TIMEOUT; 47*91f16700Schasinglulu } 48*91f16700Schasinglulu 49*91f16700Schasinglulu return MBOX_RET_OK; 50*91f16700Schasinglulu } 51*91f16700Schasinglulu 52*91f16700Schasinglulu static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout, 53*91f16700Schasinglulu uint32_t data, 54*91f16700Schasinglulu bool *is_doorbell_triggered) 55*91f16700Schasinglulu { 56*91f16700Schasinglulu unsigned int timeout = 100U; 57*91f16700Schasinglulu 58*91f16700Schasinglulu do { 59*91f16700Schasinglulu if (is_mailbox_cmdbuf_full(*cin)) { 60*91f16700Schasinglulu if (!(*is_doorbell_triggered)) { 61*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + 62*91f16700Schasinglulu MBOX_DOORBELL_TO_SDM, 1U); 63*91f16700Schasinglulu *is_doorbell_triggered = true; 64*91f16700Schasinglulu } 65*91f16700Schasinglulu mdelay(10U); 66*91f16700Schasinglulu } else { 67*91f16700Schasinglulu mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data); 68*91f16700Schasinglulu *cin %= MBOX_CMD_BUFFER_SIZE; 69*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin); 70*91f16700Schasinglulu break; 71*91f16700Schasinglulu } 72*91f16700Schasinglulu } while (--timeout != 0U); 73*91f16700Schasinglulu 74*91f16700Schasinglulu if (timeout == 0U) { 75*91f16700Schasinglulu return MBOX_TIMEOUT; 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu if (*is_doorbell_triggered) { 79*91f16700Schasinglulu int ret = wait_for_mailbox_cmdbuf_empty(*cin); 80*91f16700Schasinglulu return ret; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu return MBOX_RET_OK; 84*91f16700Schasinglulu } 85*91f16700Schasinglulu 86*91f16700Schasinglulu static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args, 87*91f16700Schasinglulu unsigned int len) 88*91f16700Schasinglulu { 89*91f16700Schasinglulu uint32_t sdm_read_offset, cmd_free_offset; 90*91f16700Schasinglulu unsigned int i; 91*91f16700Schasinglulu int ret; 92*91f16700Schasinglulu bool is_doorbell_triggered = false; 93*91f16700Schasinglulu 94*91f16700Schasinglulu cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN); 95*91f16700Schasinglulu sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT); 96*91f16700Schasinglulu 97*91f16700Schasinglulu ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset, 98*91f16700Schasinglulu header_cmd, &is_doorbell_triggered); 99*91f16700Schasinglulu if (ret != 0) { 100*91f16700Schasinglulu goto restart_mailbox; 101*91f16700Schasinglulu } 102*91f16700Schasinglulu 103*91f16700Schasinglulu for (i = 0U; i < len; i++) { 104*91f16700Schasinglulu is_doorbell_triggered = false; 105*91f16700Schasinglulu ret = write_mailbox_cmd_buffer(&cmd_free_offset, 106*91f16700Schasinglulu sdm_read_offset, args[i], 107*91f16700Schasinglulu &is_doorbell_triggered); 108*91f16700Schasinglulu if (ret != 0) { 109*91f16700Schasinglulu goto restart_mailbox; 110*91f16700Schasinglulu } 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); 114*91f16700Schasinglulu 115*91f16700Schasinglulu return MBOX_RET_OK; 116*91f16700Schasinglulu 117*91f16700Schasinglulu restart_mailbox: 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * Attempt to restart mailbox if the driver not able to write 120*91f16700Schasinglulu * into mailbox command buffer 121*91f16700Schasinglulu */ 122*91f16700Schasinglulu if (MBOX_CMD_MASK(header_cmd) != MBOX_CMD_RESTART) { 123*91f16700Schasinglulu INFO("Mailbox timed out: Attempting mailbox reset\n"); 124*91f16700Schasinglulu ret = mailbox_init(); 125*91f16700Schasinglulu 126*91f16700Schasinglulu if (ret == MBOX_TIMEOUT) { 127*91f16700Schasinglulu INFO("Error: Mailbox fail to restart\n"); 128*91f16700Schasinglulu } 129*91f16700Schasinglulu } 130*91f16700Schasinglulu 131*91f16700Schasinglulu return MBOX_TIMEOUT; 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu int mailbox_read_response(unsigned int *job_id, uint32_t *response, 135*91f16700Schasinglulu unsigned int *resp_len) 136*91f16700Schasinglulu { 137*91f16700Schasinglulu uint32_t rin; 138*91f16700Schasinglulu uint32_t rout; 139*91f16700Schasinglulu uint32_t resp_data; 140*91f16700Schasinglulu unsigned int ret_resp_len; 141*91f16700Schasinglulu 142*91f16700Schasinglulu if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) { 143*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); 144*91f16700Schasinglulu } 145*91f16700Schasinglulu 146*91f16700Schasinglulu rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); 147*91f16700Schasinglulu rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); 148*91f16700Schasinglulu 149*91f16700Schasinglulu if (rout != rin) { 150*91f16700Schasinglulu resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++)); 151*91f16700Schasinglulu 152*91f16700Schasinglulu rout %= MBOX_RESP_BUFFER_SIZE; 153*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); 154*91f16700Schasinglulu 155*91f16700Schasinglulu 156*91f16700Schasinglulu if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) { 157*91f16700Schasinglulu return MBOX_WRONG_ID; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu *job_id = MBOX_RESP_JOB_ID(resp_data); 161*91f16700Schasinglulu 162*91f16700Schasinglulu ret_resp_len = MBOX_RESP_LEN(resp_data); 163*91f16700Schasinglulu 164*91f16700Schasinglulu if (iterate_resp(ret_resp_len, response, resp_len) 165*91f16700Schasinglulu != MBOX_RET_OK) { 166*91f16700Schasinglulu return MBOX_TIMEOUT; 167*91f16700Schasinglulu } 168*91f16700Schasinglulu 169*91f16700Schasinglulu if (MBOX_RESP_ERR(resp_data) > 0U) { 170*91f16700Schasinglulu INFO("Error in response: %x\n", resp_data); 171*91f16700Schasinglulu return -MBOX_RESP_ERR(resp_data); 172*91f16700Schasinglulu } 173*91f16700Schasinglulu 174*91f16700Schasinglulu return MBOX_RET_OK; 175*91f16700Schasinglulu } 176*91f16700Schasinglulu return MBOX_NO_RESPONSE; 177*91f16700Schasinglulu } 178*91f16700Schasinglulu 179*91f16700Schasinglulu int mailbox_read_response_async(unsigned int *job_id, uint32_t *header, 180*91f16700Schasinglulu uint32_t *response, unsigned int *resp_len, 181*91f16700Schasinglulu uint8_t ignore_client_id) 182*91f16700Schasinglulu { 183*91f16700Schasinglulu uint32_t rin; 184*91f16700Schasinglulu uint32_t rout; 185*91f16700Schasinglulu uint32_t resp_data; 186*91f16700Schasinglulu uint32_t ret_resp_len = 0; 187*91f16700Schasinglulu uint8_t is_done = 0; 188*91f16700Schasinglulu uint32_t resp_len_check = 0; 189*91f16700Schasinglulu 190*91f16700Schasinglulu if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) { 191*91f16700Schasinglulu ret_resp_len = MBOX_RESP_LEN( 192*91f16700Schasinglulu mailbox_resp_ctr.payload->header) - 193*91f16700Schasinglulu mailbox_resp_ctr.index; 194*91f16700Schasinglulu } 195*91f16700Schasinglulu 196*91f16700Schasinglulu if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) { 197*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); 198*91f16700Schasinglulu } 199*91f16700Schasinglulu 200*91f16700Schasinglulu rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); 201*91f16700Schasinglulu rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); 202*91f16700Schasinglulu 203*91f16700Schasinglulu while (rout != rin && !is_done) { 204*91f16700Schasinglulu 205*91f16700Schasinglulu resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++)); 206*91f16700Schasinglulu 207*91f16700Schasinglulu rout %= MBOX_RESP_BUFFER_SIZE; 208*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); 209*91f16700Schasinglulu rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); 210*91f16700Schasinglulu 211*91f16700Schasinglulu if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) { 212*91f16700Schasinglulu mailbox_resp_ctr.payload->data[mailbox_resp_ctr.index] = resp_data; 213*91f16700Schasinglulu mailbox_resp_ctr.index++; 214*91f16700Schasinglulu ret_resp_len--; 215*91f16700Schasinglulu } else { 216*91f16700Schasinglulu if (!ignore_client_id) { 217*91f16700Schasinglulu if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) { 218*91f16700Schasinglulu *resp_len = 0; 219*91f16700Schasinglulu return MBOX_WRONG_ID; 220*91f16700Schasinglulu } 221*91f16700Schasinglulu } 222*91f16700Schasinglulu 223*91f16700Schasinglulu *job_id = MBOX_RESP_JOB_ID(resp_data); 224*91f16700Schasinglulu ret_resp_len = MBOX_RESP_LEN(resp_data); 225*91f16700Schasinglulu mailbox_resp_ctr.payload->header = resp_data; 226*91f16700Schasinglulu mailbox_resp_ctr.flag |= MBOX_PAYLOAD_FLAG_BUSY; 227*91f16700Schasinglulu } 228*91f16700Schasinglulu 229*91f16700Schasinglulu if (ret_resp_len == 0) { 230*91f16700Schasinglulu is_done = 1; 231*91f16700Schasinglulu } 232*91f16700Schasinglulu } 233*91f16700Schasinglulu 234*91f16700Schasinglulu if (is_done != 0) { 235*91f16700Schasinglulu 236*91f16700Schasinglulu /* copy header data to input address if applicable */ 237*91f16700Schasinglulu if (header != 0) { 238*91f16700Schasinglulu *header = mailbox_resp_ctr.payload->header; 239*91f16700Schasinglulu } 240*91f16700Schasinglulu 241*91f16700Schasinglulu /* copy response data to input buffer if applicable */ 242*91f16700Schasinglulu ret_resp_len = MBOX_RESP_LEN(mailbox_resp_ctr.payload->header); 243*91f16700Schasinglulu if ((ret_resp_len > 0) && (response != NULL) && (resp_len != NULL)) { 244*91f16700Schasinglulu if (*resp_len > ret_resp_len) { 245*91f16700Schasinglulu *resp_len = ret_resp_len; 246*91f16700Schasinglulu } 247*91f16700Schasinglulu 248*91f16700Schasinglulu resp_len_check = (uint32_t) *resp_len; 249*91f16700Schasinglulu 250*91f16700Schasinglulu if (resp_len_check > MBOX_DATA_MAX_LEN) { 251*91f16700Schasinglulu return MBOX_RET_ERROR; 252*91f16700Schasinglulu } 253*91f16700Schasinglulu 254*91f16700Schasinglulu memcpy((uint8_t *) response, 255*91f16700Schasinglulu (uint8_t *) mailbox_resp_ctr.payload->data, 256*91f16700Schasinglulu *resp_len * MBOX_WORD_BYTE); 257*91f16700Schasinglulu } 258*91f16700Schasinglulu 259*91f16700Schasinglulu /* reset async response param */ 260*91f16700Schasinglulu mailbox_resp_ctr.index = 0; 261*91f16700Schasinglulu mailbox_resp_ctr.flag = 0; 262*91f16700Schasinglulu 263*91f16700Schasinglulu if (MBOX_RESP_ERR(mailbox_resp_ctr.payload->header) > 0U) { 264*91f16700Schasinglulu INFO("Error in async response: %x\n", 265*91f16700Schasinglulu mailbox_resp_ctr.payload->header); 266*91f16700Schasinglulu return -MBOX_RESP_ERR(mailbox_resp_ctr.payload->header); 267*91f16700Schasinglulu } 268*91f16700Schasinglulu 269*91f16700Schasinglulu return MBOX_RET_OK; 270*91f16700Schasinglulu } 271*91f16700Schasinglulu 272*91f16700Schasinglulu *resp_len = 0; 273*91f16700Schasinglulu return (mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) ? MBOX_BUSY : MBOX_NO_RESPONSE; 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response, 277*91f16700Schasinglulu unsigned int *resp_len) 278*91f16700Schasinglulu { 279*91f16700Schasinglulu unsigned int timeout = 40U; 280*91f16700Schasinglulu unsigned int sdm_loop = 255U; 281*91f16700Schasinglulu unsigned int ret_resp_len; 282*91f16700Schasinglulu uint32_t rin; 283*91f16700Schasinglulu uint32_t rout; 284*91f16700Schasinglulu uint32_t resp_data; 285*91f16700Schasinglulu 286*91f16700Schasinglulu while (sdm_loop != 0U) { 287*91f16700Schasinglulu 288*91f16700Schasinglulu do { 289*91f16700Schasinglulu if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) 290*91f16700Schasinglulu == 1U) { 291*91f16700Schasinglulu break; 292*91f16700Schasinglulu } 293*91f16700Schasinglulu mdelay(10U); 294*91f16700Schasinglulu } while (--timeout != 0U); 295*91f16700Schasinglulu 296*91f16700Schasinglulu if (timeout == 0U) { 297*91f16700Schasinglulu break; 298*91f16700Schasinglulu } 299*91f16700Schasinglulu 300*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); 301*91f16700Schasinglulu 302*91f16700Schasinglulu if ((urgent & 1U) != 0U) { 303*91f16700Schasinglulu mdelay(5U); 304*91f16700Schasinglulu if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) & 305*91f16700Schasinglulu MBOX_STATUS_UA_MASK) ^ 306*91f16700Schasinglulu (urgent & MBOX_STATUS_UA_MASK)) { 307*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U); 308*91f16700Schasinglulu return MBOX_RET_OK; 309*91f16700Schasinglulu } 310*91f16700Schasinglulu 311*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U); 312*91f16700Schasinglulu INFO("Error: Mailbox did not get UA"); 313*91f16700Schasinglulu return MBOX_RET_ERROR; 314*91f16700Schasinglulu } 315*91f16700Schasinglulu 316*91f16700Schasinglulu rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); 317*91f16700Schasinglulu rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); 318*91f16700Schasinglulu 319*91f16700Schasinglulu while (rout != rin) { 320*91f16700Schasinglulu resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, 321*91f16700Schasinglulu (rout)++)); 322*91f16700Schasinglulu 323*91f16700Schasinglulu rout %= MBOX_RESP_BUFFER_SIZE; 324*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); 325*91f16700Schasinglulu 326*91f16700Schasinglulu if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID 327*91f16700Schasinglulu || MBOX_RESP_JOB_ID(resp_data) != job_id) { 328*91f16700Schasinglulu continue; 329*91f16700Schasinglulu } 330*91f16700Schasinglulu 331*91f16700Schasinglulu ret_resp_len = MBOX_RESP_LEN(resp_data); 332*91f16700Schasinglulu 333*91f16700Schasinglulu if (iterate_resp(ret_resp_len, response, resp_len) 334*91f16700Schasinglulu != MBOX_RET_OK) { 335*91f16700Schasinglulu return MBOX_TIMEOUT; 336*91f16700Schasinglulu } 337*91f16700Schasinglulu 338*91f16700Schasinglulu if (MBOX_RESP_ERR(resp_data) > 0U) { 339*91f16700Schasinglulu INFO("Error in response: %x\n", resp_data); 340*91f16700Schasinglulu return -MBOX_RESP_ERR(resp_data); 341*91f16700Schasinglulu } 342*91f16700Schasinglulu 343*91f16700Schasinglulu return MBOX_RET_OK; 344*91f16700Schasinglulu } 345*91f16700Schasinglulu 346*91f16700Schasinglulu sdm_loop--; 347*91f16700Schasinglulu } 348*91f16700Schasinglulu 349*91f16700Schasinglulu INFO("Timed out waiting for SDM\n"); 350*91f16700Schasinglulu return MBOX_TIMEOUT; 351*91f16700Schasinglulu } 352*91f16700Schasinglulu 353*91f16700Schasinglulu int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf, 354*91f16700Schasinglulu unsigned int *resp_len) 355*91f16700Schasinglulu { 356*91f16700Schasinglulu unsigned int timeout, total_resp_len = 0U; 357*91f16700Schasinglulu uint32_t resp_data; 358*91f16700Schasinglulu uint32_t rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); 359*91f16700Schasinglulu uint32_t rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT); 360*91f16700Schasinglulu 361*91f16700Schasinglulu while (mbox_resp_len > 0U) { 362*91f16700Schasinglulu timeout = 100U; 363*91f16700Schasinglulu mbox_resp_len--; 364*91f16700Schasinglulu resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++)); 365*91f16700Schasinglulu 366*91f16700Schasinglulu if ((resp_buf != NULL) && (resp_len != NULL) 367*91f16700Schasinglulu && (*resp_len != 0U)) { 368*91f16700Schasinglulu *(resp_buf + total_resp_len) 369*91f16700Schasinglulu = resp_data; 370*91f16700Schasinglulu *resp_len = *resp_len - 1; 371*91f16700Schasinglulu total_resp_len++; 372*91f16700Schasinglulu } 373*91f16700Schasinglulu rout %= MBOX_RESP_BUFFER_SIZE; 374*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout); 375*91f16700Schasinglulu 376*91f16700Schasinglulu do { 377*91f16700Schasinglulu rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN); 378*91f16700Schasinglulu if (rout == rin) { 379*91f16700Schasinglulu mdelay(10U); 380*91f16700Schasinglulu } else { 381*91f16700Schasinglulu break; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu timeout--; 384*91f16700Schasinglulu } while ((mbox_resp_len > 0U) && (timeout != 0U)); 385*91f16700Schasinglulu 386*91f16700Schasinglulu if (timeout == 0U) { 387*91f16700Schasinglulu INFO("Timed out waiting for SDM\n"); 388*91f16700Schasinglulu return MBOX_TIMEOUT; 389*91f16700Schasinglulu } 390*91f16700Schasinglulu } 391*91f16700Schasinglulu 392*91f16700Schasinglulu if (resp_len) 393*91f16700Schasinglulu *resp_len = total_resp_len; 394*91f16700Schasinglulu 395*91f16700Schasinglulu return MBOX_RET_OK; 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu int mailbox_send_cmd_async_ext(uint32_t header_cmd, uint32_t *args, 399*91f16700Schasinglulu unsigned int len) 400*91f16700Schasinglulu { 401*91f16700Schasinglulu return fill_mailbox_circular_buffer(header_cmd, args, len); 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args, 405*91f16700Schasinglulu unsigned int len, unsigned int indirect) 406*91f16700Schasinglulu { 407*91f16700Schasinglulu int status; 408*91f16700Schasinglulu 409*91f16700Schasinglulu status = fill_mailbox_circular_buffer( 410*91f16700Schasinglulu MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) | 411*91f16700Schasinglulu MBOX_JOB_ID_CMD(*job_id) | 412*91f16700Schasinglulu MBOX_CMD_LEN_CMD(len) | 413*91f16700Schasinglulu MBOX_INDIRECT(indirect) | 414*91f16700Schasinglulu cmd, args, len); 415*91f16700Schasinglulu if (status < 0) { 416*91f16700Schasinglulu return status; 417*91f16700Schasinglulu } 418*91f16700Schasinglulu 419*91f16700Schasinglulu *job_id = (*job_id + 1U) % MBOX_MAX_IND_JOB_ID; 420*91f16700Schasinglulu 421*91f16700Schasinglulu return MBOX_RET_OK; 422*91f16700Schasinglulu } 423*91f16700Schasinglulu 424*91f16700Schasinglulu int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args, 425*91f16700Schasinglulu unsigned int len, uint32_t urgent, uint32_t *response, 426*91f16700Schasinglulu unsigned int *resp_len) 427*91f16700Schasinglulu { 428*91f16700Schasinglulu int status = 0; 429*91f16700Schasinglulu 430*91f16700Schasinglulu if (urgent != 0U) { 431*91f16700Schasinglulu urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) & 432*91f16700Schasinglulu MBOX_STATUS_UA_MASK; 433*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd); 434*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); 435*91f16700Schasinglulu } 436*91f16700Schasinglulu 437*91f16700Schasinglulu else { 438*91f16700Schasinglulu status = fill_mailbox_circular_buffer( 439*91f16700Schasinglulu MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) | 440*91f16700Schasinglulu MBOX_JOB_ID_CMD(job_id) | 441*91f16700Schasinglulu MBOX_CMD_LEN_CMD(len) | 442*91f16700Schasinglulu cmd, args, len); 443*91f16700Schasinglulu } 444*91f16700Schasinglulu 445*91f16700Schasinglulu if (status != 0) { 446*91f16700Schasinglulu return status; 447*91f16700Schasinglulu } 448*91f16700Schasinglulu 449*91f16700Schasinglulu status = mailbox_poll_response(job_id, urgent, response, resp_len); 450*91f16700Schasinglulu 451*91f16700Schasinglulu return status; 452*91f16700Schasinglulu } 453*91f16700Schasinglulu 454*91f16700Schasinglulu void mailbox_clear_response(void) 455*91f16700Schasinglulu { 456*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_ROUT, 457*91f16700Schasinglulu mmio_read_32(MBOX_OFFSET + MBOX_RIN)); 458*91f16700Schasinglulu } 459*91f16700Schasinglulu 460*91f16700Schasinglulu void mailbox_set_int(uint32_t interrupt) 461*91f16700Schasinglulu { 462*91f16700Schasinglulu 463*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) | 464*91f16700Schasinglulu MBOX_UAE_BIT(interrupt)); 465*91f16700Schasinglulu } 466*91f16700Schasinglulu 467*91f16700Schasinglulu 468*91f16700Schasinglulu void mailbox_set_qspi_open(void) 469*91f16700Schasinglulu { 470*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); 471*91f16700Schasinglulu mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, NULL, 0U, 472*91f16700Schasinglulu CMD_CASUAL, NULL, NULL); 473*91f16700Schasinglulu } 474*91f16700Schasinglulu 475*91f16700Schasinglulu void mailbox_set_qspi_direct(void) 476*91f16700Schasinglulu { 477*91f16700Schasinglulu uint32_t response[1], qspi_clk, reg; 478*91f16700Schasinglulu unsigned int resp_len = ARRAY_SIZE(response); 479*91f16700Schasinglulu 480*91f16700Schasinglulu mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, NULL, 0U, 481*91f16700Schasinglulu CMD_CASUAL, response, &resp_len); 482*91f16700Schasinglulu 483*91f16700Schasinglulu qspi_clk = response[0]; 484*91f16700Schasinglulu INFO("QSPI ref clock: %u\n", qspi_clk); 485*91f16700Schasinglulu 486*91f16700Schasinglulu /* 487*91f16700Schasinglulu * Store QSPI ref clock frequency in BOOT_SCRATCH_COLD_0 register for 488*91f16700Schasinglulu * later boot loader (i.e. u-boot) use. 489*91f16700Schasinglulu * The frequency is stored in kHz and occupies BOOT_SCRATCH_COLD_0 490*91f16700Schasinglulu * register bits[27:0]. 491*91f16700Schasinglulu */ 492*91f16700Schasinglulu qspi_clk /= 1000; 493*91f16700Schasinglulu reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0)); 494*91f16700Schasinglulu reg &= ~SYSMGR_QSPI_REFCLK_MASK; 495*91f16700Schasinglulu reg |= qspi_clk & SYSMGR_QSPI_REFCLK_MASK; 496*91f16700Schasinglulu mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_0), reg); 497*91f16700Schasinglulu } 498*91f16700Schasinglulu 499*91f16700Schasinglulu void mailbox_set_qspi_close(void) 500*91f16700Schasinglulu { 501*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); 502*91f16700Schasinglulu mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, NULL, 0U, 503*91f16700Schasinglulu CMD_CASUAL, NULL, NULL); 504*91f16700Schasinglulu } 505*91f16700Schasinglulu 506*91f16700Schasinglulu void mailbox_qspi_set_cs(uint32_t device_select) 507*91f16700Schasinglulu { 508*91f16700Schasinglulu uint32_t cs_setting; 509*91f16700Schasinglulu 510*91f16700Schasinglulu /* QSPI device select settings at 31:28 */ 511*91f16700Schasinglulu cs_setting = (device_select << 28); 512*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); 513*91f16700Schasinglulu mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting, 514*91f16700Schasinglulu 1U, CMD_CASUAL, NULL, NULL); 515*91f16700Schasinglulu } 516*91f16700Schasinglulu 517*91f16700Schasinglulu void mailbox_hps_qspi_enable(void) 518*91f16700Schasinglulu { 519*91f16700Schasinglulu mailbox_set_qspi_open(); 520*91f16700Schasinglulu mailbox_set_qspi_direct(); 521*91f16700Schasinglulu } 522*91f16700Schasinglulu 523*91f16700Schasinglulu void mailbox_reset_cold(void) 524*91f16700Schasinglulu { 525*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); 526*91f16700Schasinglulu 527*91f16700Schasinglulu mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0U, 0U, 528*91f16700Schasinglulu CMD_CASUAL, NULL, NULL); 529*91f16700Schasinglulu } 530*91f16700Schasinglulu 531*91f16700Schasinglulu void mailbox_reset_warm(uint32_t reset_type) 532*91f16700Schasinglulu { 533*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE); 534*91f16700Schasinglulu 535*91f16700Schasinglulu reset_type = 0x01; // Warm reset header data must be 1 536*91f16700Schasinglulu mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, &reset_type, 1U, 537*91f16700Schasinglulu CMD_CASUAL, NULL, NULL); 538*91f16700Schasinglulu } 539*91f16700Schasinglulu 540*91f16700Schasinglulu int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, unsigned int resp_buf_len) 541*91f16700Schasinglulu { 542*91f16700Schasinglulu return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE, 543*91f16700Schasinglulu NULL, 0U, CMD_CASUAL, resp_buf, 544*91f16700Schasinglulu &resp_buf_len); 545*91f16700Schasinglulu } 546*91f16700Schasinglulu 547*91f16700Schasinglulu struct rsu_status_info { 548*91f16700Schasinglulu uint64_t current_image; 549*91f16700Schasinglulu uint64_t fail_image; 550*91f16700Schasinglulu uint32_t state; 551*91f16700Schasinglulu uint32_t version; 552*91f16700Schasinglulu uint32_t error_location; 553*91f16700Schasinglulu uint32_t error_details; 554*91f16700Schasinglulu uint32_t retry_counter; 555*91f16700Schasinglulu }; 556*91f16700Schasinglulu 557*91f16700Schasinglulu int mailbox_rsu_status(uint32_t *resp_buf, unsigned int resp_buf_len) 558*91f16700Schasinglulu { 559*91f16700Schasinglulu int ret; 560*91f16700Schasinglulu struct rsu_status_info *info = (struct rsu_status_info *)resp_buf; 561*91f16700Schasinglulu 562*91f16700Schasinglulu info->retry_counter = ~0U; 563*91f16700Schasinglulu 564*91f16700Schasinglulu ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0U, 565*91f16700Schasinglulu CMD_CASUAL, resp_buf, 566*91f16700Schasinglulu &resp_buf_len); 567*91f16700Schasinglulu 568*91f16700Schasinglulu if (ret < 0) { 569*91f16700Schasinglulu return ret; 570*91f16700Schasinglulu } 571*91f16700Schasinglulu 572*91f16700Schasinglulu if (info->retry_counter != ~0U) { 573*91f16700Schasinglulu if ((info->version & RSU_VERSION_ACMF_MASK) == 0U) { 574*91f16700Schasinglulu info->version |= RSU_VERSION_ACMF; 575*91f16700Schasinglulu } 576*91f16700Schasinglulu } 577*91f16700Schasinglulu 578*91f16700Schasinglulu return ret; 579*91f16700Schasinglulu } 580*91f16700Schasinglulu 581*91f16700Schasinglulu int mailbox_rsu_update(uint32_t *flash_offset) 582*91f16700Schasinglulu { 583*91f16700Schasinglulu return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE, 584*91f16700Schasinglulu flash_offset, 2U, 585*91f16700Schasinglulu CMD_CASUAL, NULL, NULL); 586*91f16700Schasinglulu } 587*91f16700Schasinglulu 588*91f16700Schasinglulu int mailbox_hps_stage_notify(uint32_t execution_stage) 589*91f16700Schasinglulu { 590*91f16700Schasinglulu return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY, 591*91f16700Schasinglulu &execution_stage, 1U, CMD_CASUAL, 592*91f16700Schasinglulu NULL, NULL); 593*91f16700Schasinglulu } 594*91f16700Schasinglulu 595*91f16700Schasinglulu int mailbox_init(void) 596*91f16700Schasinglulu { 597*91f16700Schasinglulu int status; 598*91f16700Schasinglulu 599*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE | 600*91f16700Schasinglulu MBOX_INT_FLAG_UAE); 601*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U); 602*91f16700Schasinglulu mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U); 603*91f16700Schasinglulu 604*91f16700Schasinglulu status = mailbox_send_cmd(0U, MBOX_CMD_RESTART, NULL, 0U, 605*91f16700Schasinglulu CMD_URGENT, NULL, NULL); 606*91f16700Schasinglulu 607*91f16700Schasinglulu if (status != 0) { 608*91f16700Schasinglulu return status; 609*91f16700Schasinglulu } 610*91f16700Schasinglulu 611*91f16700Schasinglulu mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE | 612*91f16700Schasinglulu MBOX_INT_FLAG_UAE); 613*91f16700Schasinglulu 614*91f16700Schasinglulu return MBOX_RET_OK; 615*91f16700Schasinglulu } 616*91f16700Schasinglulu 617*91f16700Schasinglulu int intel_mailbox_get_config_status(uint32_t cmd, bool init_done) 618*91f16700Schasinglulu { 619*91f16700Schasinglulu int status; 620*91f16700Schasinglulu uint32_t res, response[6]; 621*91f16700Schasinglulu unsigned int resp_len = ARRAY_SIZE(response); 622*91f16700Schasinglulu 623*91f16700Schasinglulu status = mailbox_send_cmd(MBOX_JOB_ID, cmd, NULL, 0U, CMD_CASUAL, 624*91f16700Schasinglulu response, &resp_len); 625*91f16700Schasinglulu 626*91f16700Schasinglulu if (status < 0) { 627*91f16700Schasinglulu return status; 628*91f16700Schasinglulu } 629*91f16700Schasinglulu 630*91f16700Schasinglulu res = response[RECONFIG_STATUS_STATE]; 631*91f16700Schasinglulu 632*91f16700Schasinglulu if (res == MBOX_CFGSTAT_VAB_BS_PREAUTH) { 633*91f16700Schasinglulu return MBOX_CFGSTAT_STATE_CONFIG; 634*91f16700Schasinglulu } 635*91f16700Schasinglulu 636*91f16700Schasinglulu if ((res != 0U) && (res != MBOX_CFGSTAT_STATE_CONFIG)) { 637*91f16700Schasinglulu return res; 638*91f16700Schasinglulu } 639*91f16700Schasinglulu 640*91f16700Schasinglulu res = response[RECONFIG_STATUS_PIN_STATUS]; 641*91f16700Schasinglulu if ((res & PIN_STATUS_NSTATUS) == 0U) { 642*91f16700Schasinglulu return MBOX_CFGSTAT_STATE_ERROR_HARDWARE; 643*91f16700Schasinglulu } 644*91f16700Schasinglulu 645*91f16700Schasinglulu res = response[RECONFIG_STATUS_SOFTFUNC_STATUS]; 646*91f16700Schasinglulu if ((res & SOFTFUNC_STATUS_SEU_ERROR) != 0U) { 647*91f16700Schasinglulu ERROR("SoftFunction Status SEU ERROR\n"); 648*91f16700Schasinglulu } 649*91f16700Schasinglulu 650*91f16700Schasinglulu if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U) { 651*91f16700Schasinglulu return MBOX_CFGSTAT_STATE_CONFIG; 652*91f16700Schasinglulu } 653*91f16700Schasinglulu 654*91f16700Schasinglulu if (init_done && (res & SOFTFUNC_STATUS_INIT_DONE) == 0U) { 655*91f16700Schasinglulu return MBOX_CFGSTAT_STATE_CONFIG; 656*91f16700Schasinglulu } 657*91f16700Schasinglulu 658*91f16700Schasinglulu return MBOX_RET_OK; 659*91f16700Schasinglulu } 660*91f16700Schasinglulu 661*91f16700Schasinglulu int intel_mailbox_is_fpga_not_ready(void) 662*91f16700Schasinglulu { 663*91f16700Schasinglulu int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true); 664*91f16700Schasinglulu 665*91f16700Schasinglulu if ((ret != MBOX_RET_OK) && (ret != MBOX_CFGSTAT_STATE_CONFIG)) { 666*91f16700Schasinglulu ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS, 667*91f16700Schasinglulu false); 668*91f16700Schasinglulu } 669*91f16700Schasinglulu 670*91f16700Schasinglulu return ret; 671*91f16700Schasinglulu } 672*91f16700Schasinglulu 673*91f16700Schasinglulu int mailbox_hwmon_readtemp(uint32_t chan, uint32_t *resp_buf) 674*91f16700Schasinglulu { 675*91f16700Schasinglulu unsigned int resp_len = sizeof(resp_buf); 676*91f16700Schasinglulu 677*91f16700Schasinglulu return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READTEMP, &chan, 1U, 678*91f16700Schasinglulu CMD_CASUAL, resp_buf, 679*91f16700Schasinglulu &resp_len); 680*91f16700Schasinglulu 681*91f16700Schasinglulu } 682*91f16700Schasinglulu 683*91f16700Schasinglulu int mailbox_hwmon_readvolt(uint32_t chan, uint32_t *resp_buf) 684*91f16700Schasinglulu { 685*91f16700Schasinglulu unsigned int resp_len = sizeof(resp_buf); 686*91f16700Schasinglulu 687*91f16700Schasinglulu return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READVOLT, &chan, 1U, 688*91f16700Schasinglulu CMD_CASUAL, resp_buf, 689*91f16700Schasinglulu &resp_len); 690*91f16700Schasinglulu } 691*91f16700Schasinglulu 692*91f16700Schasinglulu int mailbox_seu_err_status(uint32_t *resp_buf, unsigned int resp_buf_len) 693*91f16700Schasinglulu { 694*91f16700Schasinglulu 695*91f16700Schasinglulu return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_SEU_ERR_READ, NULL, 0U, 696*91f16700Schasinglulu CMD_CASUAL, resp_buf, 697*91f16700Schasinglulu &resp_buf_len); 698*91f16700Schasinglulu } 699