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 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 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 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 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 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 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 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 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