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