Makefile: remove extra include paths in INCLUDES
[project/bcm63xx/atf.git] / plat / nvidia / tegra / common / drivers / bpmp / bpmp.c
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
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
29 static bool master_free(unsigned int ch)
30 {
31 return channel_field(ch) == MA_FREE(ch);
32 }
33
34 static bool master_acked(unsigned int ch)
35 {
36 return channel_field(ch) == MA_ACKD(ch);
37 }
38
39 static void signal_slave(unsigned int ch)
40 {
41 mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET, CH_MASK(ch));
42 }
43
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 */
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
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
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
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 }