19fc34bbdSkenny liang /*
29fc34bbdSkenny liang * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
39fc34bbdSkenny liang *
49fc34bbdSkenny liang * SPDX-License-Identifier: BSD-3-Clause
59fc34bbdSkenny liang */
69fc34bbdSkenny liang #include <arch_helpers.h>
79fc34bbdSkenny liang #include <common/debug.h>
89fc34bbdSkenny liang #include <drivers/delay_timer.h>
99fc34bbdSkenny liang #include <errno.h>
109fc34bbdSkenny liang #include <lib/mmio.h>
119fc34bbdSkenny liang #include <sspm.h>
129fc34bbdSkenny liang
memcpy_to_sspm(uint32_t dst,uint32_t * src,uint32_t len)139fc34bbdSkenny liang static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len)
149fc34bbdSkenny liang {
159fc34bbdSkenny liang while (len--) {
169fc34bbdSkenny liang mmio_write_32(dst, *src);
179fc34bbdSkenny liang dst += sizeof(uint32_t);
189fc34bbdSkenny liang src++;
199fc34bbdSkenny liang }
209fc34bbdSkenny liang }
219fc34bbdSkenny liang
memcpy_from_sspm(uint32_t * dst,uint32_t src,uint32_t len)229fc34bbdSkenny liang static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len)
239fc34bbdSkenny liang {
249fc34bbdSkenny liang while (len--) {
259fc34bbdSkenny liang *dst = mmio_read_32(src);
269fc34bbdSkenny liang dst++;
279fc34bbdSkenny liang src += sizeof(uint32_t);
289fc34bbdSkenny liang }
299fc34bbdSkenny liang }
309fc34bbdSkenny liang
sspm_mbox_read(uint32_t slot,uint32_t * data,uint32_t len)319fc34bbdSkenny liang int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len)
329fc34bbdSkenny liang {
339fc34bbdSkenny liang if (slot >= 32) {
349fc34bbdSkenny liang ERROR("%s:slot = %d\n", __func__, slot);
359fc34bbdSkenny liang return -EINVAL;
369fc34bbdSkenny liang }
379fc34bbdSkenny liang
389fc34bbdSkenny liang if (data)
399fc34bbdSkenny liang memcpy_from_sspm(data,
409fc34bbdSkenny liang MBOX3_BASE + slot * 4,
419fc34bbdSkenny liang len);
429fc34bbdSkenny liang
439fc34bbdSkenny liang return 0;
449fc34bbdSkenny liang }
459fc34bbdSkenny liang
sspm_mbox_write(uint32_t slot,uint32_t * data,uint32_t len)469fc34bbdSkenny liang int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len)
479fc34bbdSkenny liang {
489fc34bbdSkenny liang if (slot >= 32) {
499fc34bbdSkenny liang ERROR("%s:slot = %d\n", __func__, slot);
509fc34bbdSkenny liang return -EINVAL;
519fc34bbdSkenny liang }
529fc34bbdSkenny liang
539fc34bbdSkenny liang if (data)
549fc34bbdSkenny liang memcpy_to_sspm(MBOX3_BASE + slot * 4,
559fc34bbdSkenny liang data,
569fc34bbdSkenny liang len);
579fc34bbdSkenny liang
589fc34bbdSkenny liang return 0;
599fc34bbdSkenny liang }
609fc34bbdSkenny liang
sspm_ipi_check_ack(uint32_t id)619fc34bbdSkenny liang static int sspm_ipi_check_ack(uint32_t id)
629fc34bbdSkenny liang {
639fc34bbdSkenny liang int ret = 0;
649fc34bbdSkenny liang
659fc34bbdSkenny liang if (id == IPI_ID_PLATFORM) {
669fc34bbdSkenny liang if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1)
679fc34bbdSkenny liang ret = -EINPROGRESS;
689fc34bbdSkenny liang } else if (id == IPI_ID_SUSPEND) {
699fc34bbdSkenny liang if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2)
709fc34bbdSkenny liang ret = -EINPROGRESS;
719fc34bbdSkenny liang } else {
729fc34bbdSkenny liang ERROR("%s: id = %d\n", __func__, id);
739fc34bbdSkenny liang ret = -EINVAL;
749fc34bbdSkenny liang }
759fc34bbdSkenny liang
769fc34bbdSkenny liang return ret;
779fc34bbdSkenny liang }
789fc34bbdSkenny liang
sspm_ipi_send_non_blocking(uint32_t id,uint32_t * data)799fc34bbdSkenny liang int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data)
809fc34bbdSkenny liang {
819fc34bbdSkenny liang int ret = 0;
829fc34bbdSkenny liang
839fc34bbdSkenny liang ret = sspm_ipi_check_ack(id);
849fc34bbdSkenny liang if (ret)
859fc34bbdSkenny liang return ret;
869fc34bbdSkenny liang
879fc34bbdSkenny liang if (id == IPI_ID_PLATFORM) {
889fc34bbdSkenny liang memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
899fc34bbdSkenny liang data,
909fc34bbdSkenny liang PINR_SIZE_PLATFORM);
919fc34bbdSkenny liang dsb();
929fc34bbdSkenny liang mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1);
939fc34bbdSkenny liang } else if (id == IPI_ID_SUSPEND) {
949fc34bbdSkenny liang memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
959fc34bbdSkenny liang data,
969fc34bbdSkenny liang PINR_SIZE_SUSPEND);
979fc34bbdSkenny liang dsb();
989fc34bbdSkenny liang mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS,
999fc34bbdSkenny liang 0x2);
1009fc34bbdSkenny liang }
1019fc34bbdSkenny liang
1029fc34bbdSkenny liang return 0;
1039fc34bbdSkenny liang }
1049fc34bbdSkenny liang
sspm_ipi_recv_non_blocking(uint32_t id,uint32_t * data,uint32_t len)1059fc34bbdSkenny liang int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len)
1069fc34bbdSkenny liang {
1079fc34bbdSkenny liang int ret = 0;
1089fc34bbdSkenny liang
1099fc34bbdSkenny liang ret = sspm_ipi_check_ack(id);
1109fc34bbdSkenny liang if (ret == -EINPROGRESS) {
1119fc34bbdSkenny liang if (id == IPI_ID_PLATFORM) {
1129fc34bbdSkenny liang memcpy_from_sspm(data,
1139fc34bbdSkenny liang MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
1149fc34bbdSkenny liang len);
1159fc34bbdSkenny liang dsb();
1169fc34bbdSkenny liang /* clear interrupt bit*/
1179fc34bbdSkenny liang mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS,
1189fc34bbdSkenny liang 0x1);
1199fc34bbdSkenny liang ret = 0;
1209fc34bbdSkenny liang } else if (id == IPI_ID_SUSPEND) {
1219fc34bbdSkenny liang memcpy_from_sspm(data,
1229fc34bbdSkenny liang MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
1239fc34bbdSkenny liang len);
1249fc34bbdSkenny liang dsb();
1259fc34bbdSkenny liang /* clear interrupt bit*/
1269fc34bbdSkenny liang mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS,
1279fc34bbdSkenny liang 0x2);
1289fc34bbdSkenny liang ret = 0;
1299fc34bbdSkenny liang }
1309fc34bbdSkenny liang } else if (ret == 0) {
1319fc34bbdSkenny liang ret = -EBUSY;
1329fc34bbdSkenny liang }
1339fc34bbdSkenny liang
1349fc34bbdSkenny liang return ret;
1359fc34bbdSkenny liang }
1369fc34bbdSkenny liang
sspm_alive_show(void)1379fc34bbdSkenny liang int sspm_alive_show(void)
1389fc34bbdSkenny liang {
1399fc34bbdSkenny liang uint32_t ipi_data, count;
1409fc34bbdSkenny liang int ret = 0;
1419fc34bbdSkenny liang
1429fc34bbdSkenny liang count = 5;
1439fc34bbdSkenny liang ipi_data = 0xdead;
1449fc34bbdSkenny liang
1459fc34bbdSkenny liang if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) {
1469fc34bbdSkenny liang ERROR("sspm init send fail! ret=%d\n", ret);
1479fc34bbdSkenny liang return -1;
1489fc34bbdSkenny liang }
1499fc34bbdSkenny liang
1509fc34bbdSkenny liang while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
1519fc34bbdSkenny liang &ipi_data,
152*420c26b3STinghan Shen sizeof(ipi_data) / sizeof(uint32_t))
1539fc34bbdSkenny liang && count) {
1549fc34bbdSkenny liang mdelay(100);
1559fc34bbdSkenny liang count--;
1569fc34bbdSkenny liang }
1579fc34bbdSkenny liang
1589fc34bbdSkenny liang return (ipi_data == 1) ? 0 : -1;
1599fc34bbdSkenny liang }
160