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