blob: 6e761243ccf3170f84b47584e1feecd165f7cb77 [file] [log] [blame]
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <errno.h>
#include <lib/mmio.h>
#include <sspm.h>
static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len)
{
while (len--) {
mmio_write_32(dst, *src);
dst += sizeof(uint32_t);
src++;
}
}
static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len)
{
while (len--) {
*dst = mmio_read_32(src);
dst++;
src += sizeof(uint32_t);
}
}
int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len)
{
if (slot >= 32) {
ERROR("%s:slot = %d\n", __func__, slot);
return -EINVAL;
}
if (data)
memcpy_from_sspm(data,
MBOX3_BASE + slot * 4,
len);
return 0;
}
int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len)
{
if (slot >= 32) {
ERROR("%s:slot = %d\n", __func__, slot);
return -EINVAL;
}
if (data)
memcpy_to_sspm(MBOX3_BASE + slot * 4,
data,
len);
return 0;
}
static int sspm_ipi_check_ack(uint32_t id)
{
int ret = 0;
if (id == IPI_ID_PLATFORM) {
if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1)
ret = -EINPROGRESS;
} else if (id == IPI_ID_SUSPEND) {
if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2)
ret = -EINPROGRESS;
} else {
ERROR("%s: id = %d\n", __func__, id);
ret = -EINVAL;
}
return ret;
}
int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data)
{
int ret = 0;
ret = sspm_ipi_check_ack(id);
if (ret)
return ret;
if (id == IPI_ID_PLATFORM) {
memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
data,
PINR_SIZE_PLATFORM);
dsb();
mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1);
} else if (id == IPI_ID_SUSPEND) {
memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
data,
PINR_SIZE_SUSPEND);
dsb();
mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS,
0x2);
}
return 0;
}
int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len)
{
int ret = 0;
ret = sspm_ipi_check_ack(id);
if (ret == -EINPROGRESS) {
if (id == IPI_ID_PLATFORM) {
memcpy_from_sspm(data,
MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
len);
dsb();
/* clear interrupt bit*/
mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS,
0x1);
ret = 0;
} else if (id == IPI_ID_SUSPEND) {
memcpy_from_sspm(data,
MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
len);
dsb();
/* clear interrupt bit*/
mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS,
0x2);
ret = 0;
}
} else if (ret == 0) {
ret = -EBUSY;
}
return ret;
}
int sspm_alive_show(void)
{
uint32_t ipi_data, count;
int ret = 0;
count = 5;
ipi_data = 0xdead;
if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) {
ERROR("sspm init send fail! ret=%d\n", ret);
return -1;
}
while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
&ipi_data,
sizeof(ipi_data) / sizeof(uint32_t))
&& count) {
mdelay(100);
count--;
}
return (ipi_data == 1) ? 0 : -1;
}