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