xref: /openbsd-src/sys/arch/arm64/dev/rtkit.c (revision c1a45aed656e7d5627c30c92421893a76f370ccb)
1 /*	$OpenBSD: rtkit.c,v 1.3 2022/01/10 09:07:28 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #include <machine/bus.h>
24 #include <machine/fdt.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_misc.h>
28 #include <dev/ofw/fdt.h>
29 
30 #include <arm64/dev/aplmbox.h>
31 #include <arm64/dev/rtkit.h>
32 
33 #define RTKIT_EP_MGMT			0
34 #define RTKIT_EP_CRASHLOG		1
35 #define RTKIT_EP_SYSLOG			2
36 #define RTKIT_EP_DEBUG			3
37 #define RTKIT_EP_IOREPORT		4
38 
39 #define RTKIT_MGMT_TYPE(x)		(((x) >> 52) & 0xff)
40 #define RTKIT_MGMT_TYPE_SHIFT		52
41 
42 #define RTKIT_MGMT_PWR_STATE(x)		(((x) >> 0) & 0xff)
43 #define RTKIT_MGMT_PWR_STATE_ON		0x20
44 
45 #define RTKIT_MGMT_HELLO		1
46 #define RTKIT_MGMT_HELLO_ACK		2
47 #define RTKIT_MGMT_STARTEP		5
48 #define RTKIT_MGMT_IOP_PWR_STATE	6
49 #define RTKIT_MGMT_IOP_PWR_STATE_ACK	7
50 #define RTKIT_MGMT_EPMAP		8
51 
52 #define RTKIT_MGMT_HELLO_MINVER(x)	(((x) >> 0) & 0xffff)
53 #define RTKIT_MGMT_HELLO_MINVER_SHIFT	0
54 #define RTKIT_MGMT_HELLO_MAXVER(x)	(((x) >> 16) & 0xffff)
55 #define RTKIT_MGMT_HELLO_MAXVER_SHIFT	16
56 
57 #define RTKIT_MGMT_STARTEP_EP_SHIFT	32
58 #define RTKIT_MGMT_STARTEP_START	(1ULL << 1)
59 
60 #define RTKIT_MGMT_EPMAP_LAST		(1ULL << 51)
61 #define RTKIT_MGMT_EPMAP_BASE(x)	(((x) >> 32) & 0x7)
62 #define RTKIT_MGMT_EPMAP_BASE_SHIFT	32
63 #define RTKIT_MGMT_EPMAP_BITMAP(x)	(((x) >> 0) & 0xffffffff)
64 #define RTKIT_MGMT_EPMAP_MORE		(1ULL << 0)
65 
66 #define RTKIT_BUFFER_REQUEST		1
67 #define RTKIT_BUFFER_ADDR(x)		(((x) >> 0) & 0xfffffffffff)
68 #define RTKIT_BUFFER_SIZE(x)		(((x) >> 44) & 0xff)
69 #define RTKIT_BUFFER_SIZE_SHIFT		44
70 
71 /* Versions we support. */
72 #define RTKIT_MINVER			11
73 #define RTKIT_MAXVER			12
74 
75 struct rtkit_state {
76 	struct mbox_channel	*mc;
77 	int			pwrstate;
78 	uint64_t		epmap;
79 	void			(*callback[32])(void *, uint64_t);
80 	void			*arg[32];
81 };
82 
83 int
84 rtkit_recv(struct mbox_channel *mc, struct aplmbox_msg *msg)
85 {
86 	int error, timo;
87 
88 	for (timo = 0; timo < 10000; timo++) {
89 		error = mbox_recv(mc, msg, sizeof(*msg));
90 		if (error == 0)
91 			break;
92 		delay(10);
93 	}
94 
95 	return error;
96 }
97 
98 int
99 rtkit_send(struct mbox_channel *mc, uint32_t endpoint,
100     uint64_t type, uint64_t data)
101 {
102 	struct aplmbox_msg msg;
103 
104 	msg.data0 = (type << RTKIT_MGMT_TYPE_SHIFT) | data;
105 	msg.data1 = endpoint;
106 	return mbox_send(mc, &msg, sizeof(msg));
107 }
108 
109 int
110 rtkit_start(struct rtkit_state *state, uint32_t endpoint)
111 {
112 	struct mbox_channel *mc = state->mc;
113 	uint64_t reply;
114 
115 	reply = ((uint64_t)endpoint << RTKIT_MGMT_STARTEP_EP_SHIFT);
116 	reply |= RTKIT_MGMT_STARTEP_START;
117 	return rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_STARTEP, reply);
118 }
119 
120 int
121 rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg)
122 {
123 	struct mbox_channel *mc = state->mc;
124 	uint64_t minver, maxver, ver;
125 	uint64_t base, bitmap, reply;
126 	uint32_t endpoint;
127 	int error;
128 
129 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
130 	case RTKIT_MGMT_HELLO:
131 		minver = RTKIT_MGMT_HELLO_MINVER(msg->data0);
132 		maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0);
133 		if (minver > RTKIT_MAXVER) {
134 			printf("unsupported minimum firmware version %lld\n",
135 			    minver);
136 			return EINVAL;
137 		}
138 		if (maxver < RTKIT_MINVER) {
139 			printf("unsupported maximum firmware version %lld\n",
140 			    maxver);
141 			return EINVAL;
142 		}
143 		ver = min(RTKIT_MAXVER, maxver);
144 		error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_HELLO_ACK,
145 		    (ver << RTKIT_MGMT_HELLO_MINVER_SHIFT) |
146 		    (ver << RTKIT_MGMT_HELLO_MAXVER_SHIFT));
147 		if (error)
148 			return error;
149 		break;
150 
151 	case RTKIT_MGMT_IOP_PWR_STATE_ACK:
152 		state->pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0);
153 		break;
154 
155 	case RTKIT_MGMT_EPMAP:
156 		base = RTKIT_MGMT_EPMAP_BASE(msg->data0);
157 		bitmap = RTKIT_MGMT_EPMAP_BITMAP(msg->data0);
158 		state->epmap |= (bitmap << (base * 32));
159 		reply = (base << RTKIT_MGMT_EPMAP_BASE_SHIFT);
160 		if (msg->data0 & RTKIT_MGMT_EPMAP_LAST)
161 			reply |= RTKIT_MGMT_EPMAP_LAST;
162 		else
163 			reply |= RTKIT_MGMT_EPMAP_MORE;
164 		error = rtkit_send(state->mc, RTKIT_EP_MGMT,
165 		    RTKIT_MGMT_EPMAP, reply);
166 		if (error)
167 			return error;
168 		if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) {
169 			for (endpoint = 1; endpoint < 32; endpoint++) {
170 				if ((state->epmap & (1ULL << endpoint)) == 0)
171 					continue;
172 
173 				switch (endpoint) {
174 				case RTKIT_EP_CRASHLOG:
175 				case RTKIT_EP_DEBUG:
176 				case RTKIT_EP_IOREPORT:
177 					error = rtkit_start(state, endpoint);
178 					if (error)
179 						return error;
180 					break;
181 				}
182 			}
183 		}
184 		break;
185 	default:
186 		printf("unhandled management event 0x%016lld\n", msg->data0);
187 		return EIO;
188 	}
189 
190 	return 0;
191 }
192 
193 int
194 rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg)
195 {
196 	struct mbox_channel *mc = state->mc;
197 	bus_addr_t addr;
198 	bus_size_t size;
199 	int error;
200 
201 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
202 	case RTKIT_BUFFER_REQUEST:
203 		addr = RTKIT_BUFFER_ADDR(msg->data0);
204 		size = RTKIT_BUFFER_SIZE(msg->data0);
205 		if (addr)
206 			break;
207 
208 		error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST,
209 		    size << RTKIT_BUFFER_SIZE_SHIFT | addr);
210 		if (error)
211 			return error;
212 		break;
213 	default:
214 		printf("unhandled crashlog event 0x%016llx\n", msg->data0);
215 		return EIO;
216 	}
217 
218 	return 0;
219 }
220 
221 int
222 rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg)
223 {
224 	struct mbox_channel *mc = state->mc;
225 	bus_addr_t addr;
226 	bus_size_t size;
227 	int error;
228 
229 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
230 	case RTKIT_BUFFER_REQUEST:
231 		addr = RTKIT_BUFFER_ADDR(msg->data0);
232 		size = RTKIT_BUFFER_SIZE(msg->data0);
233 		if (addr)
234 			break;
235 
236 		error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST,
237 		    size << RTKIT_BUFFER_SIZE_SHIFT | addr);
238 		if (error)
239 			return error;
240 		break;
241 	default:
242 		printf("unhandled ioreport event 0x%016llx\n", msg->data0);
243 		return EIO;
244 	}
245 
246 	return 0;
247 }
248 
249 int
250 rtkit_poll(struct rtkit_state *state)
251 {
252 	struct mbox_channel *mc = state->mc;
253 	struct aplmbox_msg msg;
254 	void (*callback)(void *, uint64_t);
255 	void *arg;
256 	uint32_t endpoint;
257 	int error;
258 
259 	error = rtkit_recv(mc, &msg);
260 	if (error)
261 		return error;
262 
263 	endpoint = msg.data1;
264 	switch (endpoint) {
265 	case RTKIT_EP_MGMT:
266 		error = rtkit_handle_mgmt(state, &msg);
267 		if (error)
268 			return error;
269 		break;
270 	case RTKIT_EP_CRASHLOG:
271 		error = rtkit_handle_crashlog(state, &msg);
272 		if (error)
273 			return error;
274 		break;
275 	case RTKIT_EP_IOREPORT:
276 		error = rtkit_handle_ioreport(state, &msg);
277 		if (error)
278 			return error;
279 		break;
280 	default:
281 		if (endpoint >= 32 && endpoint < 64 &&
282 		    state->callback[endpoint - 32]) {
283 			callback = state->callback[endpoint - 32];
284 			arg = state->arg[endpoint - 32];
285 			callback(arg, msg.data0);
286 			break;
287 		}
288 
289 		printf("unhandled endpoint %d\n", msg.data1);
290 		return EIO;
291 	}
292 
293 	return 0;
294 }
295 
296 void
297 rtkit_rx_callback(void *cookie)
298 {
299 	rtkit_poll(cookie);
300 }
301 
302 struct rtkit_state *
303 rtkit_init(int node, const char *name)
304 {
305 	struct rtkit_state *state;
306 	struct mbox_client client;
307 
308 	state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK | M_ZERO);
309 	client.mc_rx_callback = rtkit_rx_callback;
310 	client.mc_rx_arg = state;
311 	state->mc = mbox_channel(node, name, &client);
312 	if (state->mc == NULL) {
313 		free(state, M_DEVBUF, sizeof(*state));
314 		return NULL;
315 	}
316 
317 	return state;
318 }
319 
320 int
321 rtkit_boot(struct rtkit_state *state)
322 {
323 	struct mbox_channel *mc = state->mc;
324 	int error;
325 
326 	/* Wake up! */
327 	error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE,
328 	    RTKIT_MGMT_PWR_STATE_ON);
329 	if (error)
330 		return error;
331 
332 	while (state->pwrstate != RTKIT_MGMT_PWR_STATE_ON)
333 		rtkit_poll(state);
334 
335 	return 0;
336 }
337 
338 int
339 rtkit_start_endpoint(struct rtkit_state *state, uint32_t endpoint,
340     void (*callback)(void *, uint64_t), void *arg)
341 {
342 	if (endpoint < 32 || endpoint >= 64)
343 		return EINVAL;
344 
345 	if ((state->epmap & (1ULL << endpoint)) == 0)
346 		return EINVAL;
347 
348 	state->callback[endpoint - 32] = callback;
349 	state->arg[endpoint - 32] = arg;
350 	return rtkit_start(state, endpoint);
351 }
352 
353 int
354 rtkit_send_endpoint(struct rtkit_state *state, uint32_t endpoint,
355     uint64_t data)
356 {
357 	return rtkit_send(state->mc, endpoint, 0, data);
358 }
359