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