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