1 /* 2 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 #include <arch_helpers.h> 7 #include <common/debug.h> 8 #include <drivers/delay_timer.h> 9 #include <errno.h> 10 #include <lib/mmio.h> 11 #include <sspm.h> 12 13 static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len) 14 { 15 while (len--) { 16 mmio_write_32(dst, *src); 17 dst += sizeof(uint32_t); 18 src++; 19 } 20 } 21 22 static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len) 23 { 24 while (len--) { 25 *dst = mmio_read_32(src); 26 dst++; 27 src += sizeof(uint32_t); 28 } 29 } 30 31 int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len) 32 { 33 if (slot >= 32) { 34 ERROR("%s:slot = %d\n", __func__, slot); 35 return -EINVAL; 36 } 37 38 if (data) 39 memcpy_from_sspm(data, 40 MBOX3_BASE + slot * 4, 41 len); 42 43 return 0; 44 } 45 46 int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len) 47 { 48 if (slot >= 32) { 49 ERROR("%s:slot = %d\n", __func__, slot); 50 return -EINVAL; 51 } 52 53 if (data) 54 memcpy_to_sspm(MBOX3_BASE + slot * 4, 55 data, 56 len); 57 58 return 0; 59 } 60 61 static int sspm_ipi_check_ack(uint32_t id) 62 { 63 int ret = 0; 64 65 if (id == IPI_ID_PLATFORM) { 66 if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1) 67 ret = -EINPROGRESS; 68 } else if (id == IPI_ID_SUSPEND) { 69 if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2) 70 ret = -EINPROGRESS; 71 } else { 72 ERROR("%s: id = %d\n", __func__, id); 73 ret = -EINVAL; 74 } 75 76 return ret; 77 } 78 79 int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data) 80 { 81 int ret = 0; 82 83 ret = sspm_ipi_check_ack(id); 84 if (ret) 85 return ret; 86 87 if (id == IPI_ID_PLATFORM) { 88 memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4, 89 data, 90 PINR_SIZE_PLATFORM); 91 dsb(); 92 mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1); 93 } else if (id == IPI_ID_SUSPEND) { 94 memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4, 95 data, 96 PINR_SIZE_SUSPEND); 97 dsb(); 98 mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS, 99 0x2); 100 } 101 102 return 0; 103 } 104 105 int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len) 106 { 107 int ret = 0; 108 109 ret = sspm_ipi_check_ack(id); 110 if (ret == -EINPROGRESS) { 111 if (id == IPI_ID_PLATFORM) { 112 memcpy_from_sspm(data, 113 MBOX0_BASE + PINR_OFFSET_PLATFORM * 4, 114 len); 115 dsb(); 116 /* clear interrupt bit*/ 117 mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS, 118 0x1); 119 ret = 0; 120 } else if (id == IPI_ID_SUSPEND) { 121 memcpy_from_sspm(data, 122 MBOX1_BASE + PINR_OFFSET_SUSPEND * 4, 123 len); 124 dsb(); 125 /* clear interrupt bit*/ 126 mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS, 127 0x2); 128 ret = 0; 129 } 130 } else if (ret == 0) { 131 ret = -EBUSY; 132 } 133 134 return ret; 135 } 136 137 int sspm_alive_show(void) 138 { 139 uint32_t ipi_data, count; 140 int ret = 0; 141 142 count = 5; 143 ipi_data = 0xdead; 144 145 if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) { 146 ERROR("sspm init send fail! ret=%d\n", ret); 147 return -1; 148 } 149 150 while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM, 151 &ipi_data, 152 sizeof(ipi_data) / sizeof(uint32_t)) 153 && count) { 154 mdelay(100); 155 count--; 156 } 157 158 return (ipi_data == 1) ? 0 : -1; 159 } 160