intel: mailbox: Enable sending large mailbox command
Allow mailbox command that is larger than mailbox command FIFO buffer size to be sent to SDM in multiple chunks. Signed-off-by: Abdul Halim, Muhammad Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com> Change-Id: I683d5f1d04c4fdf57d11ecae6232b7ed3fc49e26
This commit is contained in:
parent
4978bc2832
commit
d14e965c03
|
@ -11,32 +11,105 @@
|
||||||
#include "socfpga_mailbox.h"
|
#include "socfpga_mailbox.h"
|
||||||
#include "socfpga_sip_svc.h"
|
#include "socfpga_sip_svc.h"
|
||||||
|
|
||||||
|
|
||||||
|
static bool is_mailbox_cmdbuf_full(uint32_t cin)
|
||||||
|
{
|
||||||
|
uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
|
||||||
|
|
||||||
|
return (((cin + 1U) % MBOX_CMD_BUFFER_SIZE) == cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_mailbox_cmdbuf_empty(uint32_t cin)
|
||||||
|
{
|
||||||
|
uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
|
||||||
|
|
||||||
|
return (((cout + 1U) % MBOX_CMD_BUFFER_SIZE) == cin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_mailbox_cmdbuf_empty(uint32_t cin)
|
||||||
|
{
|
||||||
|
uint32_t timeout = 200U;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (is_mailbox_cmdbuf_empty(cin)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mdelay(10U);
|
||||||
|
} while (--timeout != 0U);
|
||||||
|
|
||||||
|
if (timeout == 0U) {
|
||||||
|
return MBOX_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MBOX_RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout,
|
||||||
|
uint32_t data,
|
||||||
|
bool *is_doorbell_triggered)
|
||||||
|
{
|
||||||
|
uint32_t timeout = 100U;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (is_mailbox_cmdbuf_full(*cin)) {
|
||||||
|
if (!(*is_doorbell_triggered)) {
|
||||||
|
mmio_write_32(MBOX_OFFSET +
|
||||||
|
MBOX_DOORBELL_TO_SDM, 1);
|
||||||
|
*is_doorbell_triggered = true;
|
||||||
|
}
|
||||||
|
mdelay(10U);
|
||||||
|
} else {
|
||||||
|
mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER +
|
||||||
|
(*cin * 4), data);
|
||||||
|
(*cin)++;
|
||||||
|
*cin %= MBOX_CMD_BUFFER_SIZE;
|
||||||
|
mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (--timeout != 0U);
|
||||||
|
|
||||||
|
if (timeout == 0U) {
|
||||||
|
return MBOX_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*is_doorbell_triggered) {
|
||||||
|
int ret = wait_for_mailbox_cmdbuf_empty(*cin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MBOX_RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
|
static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
uint32_t sdm_read_offset, cmd_free_offset;
|
uint32_t sdm_read_offset, cmd_free_offset;
|
||||||
int i;
|
uint32_t i;
|
||||||
|
int ret;
|
||||||
|
bool is_doorbell_triggered = false;
|
||||||
|
|
||||||
cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
|
cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
|
||||||
sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
|
sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
|
||||||
|
|
||||||
if ((cmd_free_offset < sdm_read_offset) &&
|
ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset,
|
||||||
(cmd_free_offset + len > sdm_read_offset)) {
|
header_cmd, &is_doorbell_triggered);
|
||||||
return MBOX_BUFFER_FULL;
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER + (cmd_free_offset++ * 4),
|
for (i = 0U; i < len; i++) {
|
||||||
header_cmd);
|
is_doorbell_triggered = false;
|
||||||
|
ret = write_mailbox_cmd_buffer(&cmd_free_offset,
|
||||||
|
sdm_read_offset, args[i],
|
||||||
for (i = 0; i < len; i++) {
|
&is_doorbell_triggered);
|
||||||
cmd_free_offset %= MBOX_CMD_BUFFER_SIZE;
|
if (ret != 0) {
|
||||||
mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER +
|
return ret;
|
||||||
(cmd_free_offset++ * 4), args[i]);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_free_offset %= MBOX_CMD_BUFFER_SIZE;
|
if (!is_doorbell_triggered) {
|
||||||
mmio_write_32(MBOX_OFFSET + MBOX_CIN, cmd_free_offset);
|
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return MBOX_RET_OK;
|
return MBOX_RET_OK;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +176,7 @@ int mailbox_poll_response(uint32_t job_id, int urgent, uint32_t *response,
|
||||||
& 1) {
|
& 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mdelay(25);
|
mdelay(10U);
|
||||||
} while (--timeout != 0U);
|
} while (--timeout != 0U);
|
||||||
|
|
||||||
if (timeout == 0U) {
|
if (timeout == 0U) {
|
||||||
|
@ -171,7 +244,7 @@ int iterate_resp(int mbox_resp_len, uint32_t *resp_buf, int resp_len)
|
||||||
int rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
|
int rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
|
||||||
|
|
||||||
while (mbox_resp_len > 0) {
|
while (mbox_resp_len > 0) {
|
||||||
timeout = 40;
|
timeout = 100U;
|
||||||
mbox_resp_len--;
|
mbox_resp_len--;
|
||||||
resp_data = mmio_read_32(MBOX_OFFSET +
|
resp_data = mmio_read_32(MBOX_OFFSET +
|
||||||
MBOX_RESP_BUFFER +
|
MBOX_RESP_BUFFER +
|
||||||
|
@ -189,7 +262,7 @@ int iterate_resp(int mbox_resp_len, uint32_t *resp_buf, int resp_len)
|
||||||
do {
|
do {
|
||||||
rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
|
rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
|
||||||
if (rout == rin) {
|
if (rout == rin) {
|
||||||
mdelay(25);
|
mdelay(10U);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +292,6 @@ int mailbox_send_cmd_async(uint32_t *job_id, unsigned int cmd, uint32_t *args,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1);
|
|
||||||
*job_id = (*job_id + 1) % MBOX_MAX_IND_JOB_ID;
|
*job_id = (*job_id + 1) % MBOX_MAX_IND_JOB_ID;
|
||||||
|
|
||||||
return MBOX_RET_OK;
|
return MBOX_RET_OK;
|
||||||
|
@ -234,6 +306,7 @@ int mailbox_send_cmd(uint32_t job_id, unsigned int cmd, uint32_t *args,
|
||||||
urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
|
urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
|
||||||
MBOX_STATUS_UA_MASK;
|
MBOX_STATUS_UA_MASK;
|
||||||
mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
|
mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
|
||||||
|
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
@ -247,7 +320,6 @@ int mailbox_send_cmd(uint32_t job_id, unsigned int cmd, uint32_t *args,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1);
|
|
||||||
status = mailbox_poll_response(job_id, urgent, response, resp_len);
|
status = mailbox_poll_response(job_id, urgent, response, resp_len);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
Loading…
Reference in New Issue