arm: apple: rtkit: Add support for AP power & syslogs

This is required for MTP to work properly

Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
This commit is contained in:
Hector Martin 2025-04-20 13:58:03 +02:00 committed by Tom Rini
parent 13248ae93b
commit 72bc04b874
2 changed files with 111 additions and 37 deletions

View File

@ -26,4 +26,6 @@ struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, void *cookie,
apple_rtkit_shmem_destroy shmem_destroy); apple_rtkit_shmem_destroy shmem_destroy);
void apple_rtkit_free(struct apple_rtkit *rtk); void apple_rtkit_free(struct apple_rtkit *rtk);
int apple_rtkit_boot(struct apple_rtkit *rtk); int apple_rtkit_boot(struct apple_rtkit *rtk);
int apple_rtkit_set_ap_power(struct apple_rtkit *rtk, int pwrstate);
int apple_rtkit_poll(struct apple_rtkit *rtk, ulong timeout);
int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate); int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate);

View File

@ -36,6 +36,7 @@
#define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE 6 #define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE 6
#define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK 7 #define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK 7
#define APPLE_RTKIT_MGMT_SET_AP_PWR_STATE 11
#define APPLE_RTKIT_MGMT_EPMAP 8 #define APPLE_RTKIT_MGMT_EPMAP 8
#define APPLE_RTKIT_MGMT_EPMAP_LAST BIT(51) #define APPLE_RTKIT_MGMT_EPMAP_LAST BIT(51)
@ -64,6 +65,9 @@ struct apple_rtkit {
struct apple_rtkit_buffer syslog_buffer; struct apple_rtkit_buffer syslog_buffer;
struct apple_rtkit_buffer crashlog_buffer; struct apple_rtkit_buffer crashlog_buffer;
struct apple_rtkit_buffer ioreport_buffer; struct apple_rtkit_buffer ioreport_buffer;
int iop_pwr;
int ap_pwr;
}; };
struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, void *cookie, struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, void *cookie,
@ -150,6 +154,75 @@ static int rtkit_handle_buf_req(struct apple_rtkit *rtk, int endpoint, struct ap
return 0; return 0;
} }
int apple_rtkit_poll(struct apple_rtkit *rtk, ulong timeout)
{
struct apple_mbox_msg msg;
int ret;
int endpoint;
int msgtype;
ret = mbox_recv(rtk->chan, &msg, timeout);
if (ret < 0)
return ret;
endpoint = msg.msg1;
msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0);
if (endpoint == APPLE_RTKIT_EP_CRASHLOG ||
endpoint == APPLE_RTKIT_EP_SYSLOG ||
endpoint == APPLE_RTKIT_EP_IOREPORT) {
if (msgtype == APPLE_RTKIT_BUFFER_REQUEST) {
ret = rtkit_handle_buf_req(rtk, endpoint, &msg);
if (ret < 0)
return ret;
return 0;
}
}
if (endpoint == APPLE_RTKIT_EP_IOREPORT) {
// these two messages have to be ack-ed for proper startup
if (msgtype == 0xc || msgtype == 0x8) {
ret = mbox_send(rtk->chan, &msg);
if (ret < 0)
return ret;
return 0;
}
}
if (endpoint == APPLE_RTKIT_EP_SYSLOG) {
/* Ignore init */
if (msgtype == 0x8)
return 0;
/* Ack logs */
if (msgtype == 0x5) {
ret = mbox_send(rtk->chan, &msg);
if (ret < 0)
return ret;
return 0;
}
}
if (endpoint != APPLE_RTKIT_EP_MGMT) {
printf("%s: unexpected endpoint %d\n", __func__, endpoint);
return -EINVAL;
}
switch (msgtype) {
case APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK:
rtk->iop_pwr = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0);
return 0;
case APPLE_RTKIT_MGMT_SET_AP_PWR_STATE:
rtk->ap_pwr = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0);
return 0;
default:
printf("%s: unexpected message type %d\n", __func__, msgtype);
/* Just ignore it */
return 0;
}
}
int apple_rtkit_boot(struct apple_rtkit *rtk) int apple_rtkit_boot(struct apple_rtkit *rtk)
{ {
struct apple_mbox_msg msg; struct apple_mbox_msg msg;
@ -157,7 +230,7 @@ int apple_rtkit_boot(struct apple_rtkit *rtk)
int nendpoints = 0; int nendpoints = 0;
int endpoint; int endpoint;
int min_ver, max_ver, want_ver; int min_ver, max_ver, want_ver;
int msgtype, pwrstate; int msgtype;
u64 reply; u64 reply;
u32 bitmap, base; u32 bitmap, base;
int i, ret; int i, ret;
@ -276,46 +349,37 @@ wait_epmap:
return ret; return ret;
} }
pwrstate = APPLE_RTKIT_PWR_STATE_SLEEP; rtk->iop_pwr = APPLE_RTKIT_PWR_STATE_SLEEP;
while (pwrstate != APPLE_RTKIT_PWR_STATE_ON) { rtk->ap_pwr = APPLE_RTKIT_PWR_STATE_QUIESCED;
ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
while (rtk->iop_pwr != APPLE_RTKIT_PWR_STATE_ON) {
ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US);
if (ret < 0) if (ret < 0)
return ret; return ret;
}
endpoint = msg.msg1; return 0;
msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0); }
if (endpoint == APPLE_RTKIT_EP_CRASHLOG || int apple_rtkit_set_ap_power(struct apple_rtkit *rtk, int pwrstate)
endpoint == APPLE_RTKIT_EP_SYSLOG || {
endpoint == APPLE_RTKIT_EP_IOREPORT) { struct apple_mbox_msg msg;
if (msgtype == APPLE_RTKIT_BUFFER_REQUEST) { int ret;
ret = rtkit_handle_buf_req(rtk, endpoint, &msg);
if (ret < 0)
return ret;
continue;
}
}
if (endpoint == APPLE_RTKIT_EP_IOREPORT) { if (rtk->ap_pwr == pwrstate)
// these two messages have to be ack-ed for proper startup return 0;
if (msgtype == 0xc || msgtype == 0x8) {
ret = mbox_send(rtk->chan, &msg);
if (ret < 0)
return ret;
continue;
}
}
if (endpoint != APPLE_RTKIT_EP_MGMT) { msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_AP_PWR_STATE) |
printf("%s: unexpected endpoint %d\n", __func__, endpoint); FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate);
return -EINVAL; msg.msg1 = APPLE_RTKIT_EP_MGMT;
} ret = mbox_send(rtk->chan, &msg);
if (msgtype != APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK) { if (ret < 0)
printf("%s: unexpected message type %d\n", __func__, msgtype); return ret;
return -EINVAL;
}
pwrstate = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0); while (rtk->ap_pwr != pwrstate) {
ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US);
if (ret < 0)
return ret;
} }
return 0; return 0;
@ -326,6 +390,12 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate)
struct apple_mbox_msg msg; struct apple_mbox_msg msg;
int ret; int ret;
if (rtk->ap_pwr != APPLE_RTKIT_PWR_STATE_QUIESCED) {
ret = apple_rtkit_set_ap_power(rtk, APPLE_RTKIT_PWR_STATE_QUIESCED);
if (ret < 0)
return ret;
}
msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) | msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) |
FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate); FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate);
msg.msg1 = APPLE_RTKIT_EP_MGMT; msg.msg1 = APPLE_RTKIT_EP_MGMT;
@ -333,9 +403,11 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk, int pwrstate)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US); while (rtk->iop_pwr != pwrstate) {
if (ret < 0) ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US);
return ret; if (ret < 0)
return ret;
}
return 0; return 0;
} }