• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <bpmp.h>
10 #include <common/debug.h>
11 #include <drivers/delay_timer.h>
12 #include <errno.h>
13 #include <lib/mmio.h>
14 #include <plat/common/platform.h>
15 #include <stdbool.h>
16 #include <string.h>
17 #include <tegra_def.h>
18 
19 #define BPMP_TIMEOUT	500 /* 500ms */
20 
21 static uint32_t channel_base[NR_CHANNELS];
22 static uint32_t bpmp_init_state = BPMP_INIT_PENDING;
23 
channel_field(unsigned int ch)24 static uint32_t channel_field(unsigned int ch)
25 {
26 	return mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET) & CH_MASK(ch);
27 }
28 
master_free(unsigned int ch)29 static bool master_free(unsigned int ch)
30 {
31 	return channel_field(ch) == MA_FREE(ch);
32 }
33 
master_acked(unsigned int ch)34 static bool master_acked(unsigned int ch)
35 {
36 	return channel_field(ch) == MA_ACKD(ch);
37 }
38 
signal_slave(unsigned int ch)39 static void signal_slave(unsigned int ch)
40 {
41 	mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET, CH_MASK(ch));
42 }
43 
free_master(unsigned int ch)44 static void free_master(unsigned int ch)
45 {
46 	mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET,
47 		      MA_ACKD(ch) ^ MA_FREE(ch));
48 }
49 
50 /* should be called with local irqs disabled */
tegra_bpmp_send_receive_atomic(int mrq,const void * ob_data,int ob_sz,void * ib_data,int ib_sz)51 int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz,
52 		void *ib_data, int ib_sz)
53 {
54 	unsigned int ch = (unsigned int)plat_my_core_pos();
55 	mb_data_t *p = (mb_data_t *)(uintptr_t)channel_base[ch];
56 	int32_t ret = -ETIMEDOUT, timeout = 0;
57 
58 	if (bpmp_init_state == BPMP_INIT_COMPLETE) {
59 
60 		/* loop until BPMP is free */
61 		for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) {
62 			if (master_free(ch) == true) {
63 				break;
64 			}
65 
66 			mdelay(1);
67 		}
68 
69 		if (timeout != BPMP_TIMEOUT) {
70 
71 			/* generate the command struct */
72 			p->code = mrq;
73 			p->flags = DO_ACK;
74 			(void)memcpy((void *)p->data, ob_data, (size_t)ob_sz);
75 
76 			/* signal command ready to the BPMP */
77 			signal_slave(ch);
78 			mmio_write_32(TEGRA_PRI_ICTLR_BASE + CPU_IEP_FIR_SET,
79 				      (1U << INT_SHR_SEM_OUTBOX_FULL));
80 
81 			/* loop until the command is executed */
82 			for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) {
83 				if (master_acked(ch) == true) {
84 					break;
85 				}
86 
87 				mdelay(1);
88 			}
89 
90 			if (timeout != BPMP_TIMEOUT) {
91 
92 				/* get the command response */
93 				(void)memcpy(ib_data, (const void *)p->data,
94 					     (size_t)ib_sz);
95 
96 				/* return error code */
97 				ret = p->code;
98 
99 				/* free this channel */
100 				free_master(ch);
101 			}
102 		}
103 
104 	} else {
105 		/* return error code */
106 		ret = -EINVAL;
107 	}
108 
109 	if (timeout == BPMP_TIMEOUT) {
110 		ERROR("Timed out waiting for bpmp's response\n");
111 	}
112 
113 	return ret;
114 }
115 
tegra_bpmp_init(void)116 int tegra_bpmp_init(void)
117 {
118 	uint32_t val, base, timeout = BPMP_TIMEOUT;
119 	unsigned int ch;
120 	int ret = 0;
121 
122 	if (bpmp_init_state == BPMP_INIT_PENDING) {
123 
124 		/* check if the bpmp processor is alive. */
125 		do {
126 			val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
127 			if (val != SIGN_OF_LIFE) {
128 				mdelay(1);
129 				timeout--;
130 			}
131 
132 		} while ((val != SIGN_OF_LIFE) && (timeout > 0U));
133 
134 		if (val == SIGN_OF_LIFE) {
135 
136 			/* check if clock for the atomics block is enabled */
137 			val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V);
138 			if ((val & CAR_ENABLE_ATOMICS) == 0) {
139 				ERROR("Clock to the atomics block is disabled\n");
140 			}
141 
142 			/* check if the atomics block is out of reset */
143 			val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V);
144 			if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) {
145 				ERROR("Reset to the atomics block is asserted\n");
146 			}
147 
148 			/* base address to get the result from Atomics */
149 			base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
150 
151 			/* channel area is setup by BPMP before signaling handshake */
152 			for (ch = 0; ch < NR_CHANNELS; ch++) {
153 
154 				/* issue command to get the channel base address */
155 				mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
156 					      ATOMIC_CMD_GET);
157 
158 				/* get the base address for the channel */
159 				channel_base[ch] = mmio_read_32(base);
160 
161 				/* increment result register offset */
162 				base += 4U;
163 			}
164 
165 			/* mark state as "initialized" */
166 			bpmp_init_state = BPMP_INIT_COMPLETE;
167 
168 			/* the channel values have to be visible across all cpus */
169 			flush_dcache_range((uint64_t)channel_base,
170 					   sizeof(channel_base));
171 			flush_dcache_range((uint64_t)&bpmp_init_state,
172 					   sizeof(bpmp_init_state));
173 
174 			INFO("%s: done\n", __func__);
175 
176 		} else {
177 			ERROR("BPMP not powered on\n");
178 
179 			/* bpmp is not present in the system */
180 			bpmp_init_state = BPMP_NOT_PRESENT;
181 
182 			/* communication timed out */
183 			ret = -ETIMEDOUT;
184 		}
185 	}
186 
187 	return ret;
188 }
189 
tegra_bpmp_suspend(void)190 void tegra_bpmp_suspend(void)
191 {
192 	/* freeze the interface */
193 	if (bpmp_init_state == BPMP_INIT_COMPLETE) {
194 		bpmp_init_state = BPMP_SUSPEND_ENTRY;
195 		flush_dcache_range((uint64_t)&bpmp_init_state,
196 				   sizeof(bpmp_init_state));
197 	}
198 }
199 
tegra_bpmp_resume(void)200 void tegra_bpmp_resume(void)
201 {
202 	uint32_t val, timeout = 0;
203 
204 	if (bpmp_init_state == BPMP_SUSPEND_ENTRY) {
205 
206 		/* check if the bpmp processor is alive. */
207 		do {
208 
209 			val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
210 			if (val != SIGN_OF_LIFE) {
211 				mdelay(1);
212 				timeout++;
213 			}
214 
215 		} while ((val != SIGN_OF_LIFE) && (timeout < BPMP_TIMEOUT));
216 
217 		if (val == SIGN_OF_LIFE) {
218 
219 			INFO("%s: BPMP took %d ms to resume\n", __func__, timeout);
220 
221 			/* mark state as "initialized" */
222 			bpmp_init_state = BPMP_INIT_COMPLETE;
223 
224 			/* state has to be visible across all cpus */
225 			flush_dcache_range((uint64_t)&bpmp_init_state,
226 					   sizeof(bpmp_init_state));
227 		} else {
228 			ERROR("BPMP not powered on\n");
229 		}
230 	}
231 }
232