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
memcpy_to_sspm(uint32_t dst,uint32_t * src,uint32_t len)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
memcpy_from_sspm(uint32_t * dst,uint32_t src,uint32_t len)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
sspm_mbox_read(uint32_t slot,uint32_t * data,uint32_t len)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
sspm_mbox_write(uint32_t slot,uint32_t * data,uint32_t len)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
sspm_ipi_check_ack(uint32_t id)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
sspm_ipi_send_non_blocking(uint32_t id,uint32_t * data)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
sspm_ipi_recv_non_blocking(uint32_t id,uint32_t * data,uint32_t len)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
sspm_alive_show(void)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