From: Hector Martin <mar...@marcan.st>

This is required for MTP to work properly

Signed-off-by: Hector Martin <mar...@marcan.st>
Signed-off-by: Mark Kettenis <kette...@openbsd.org>
---
 arch/arm/include/asm/arch-apple/rtkit.h |   2 +
 arch/arm/mach-apple/rtkit.c             | 148 ++++++++++++++++++------
 2 files changed, 112 insertions(+), 38 deletions(-)

diff --git a/arch/arm/include/asm/arch-apple/rtkit.h 
b/arch/arm/include/asm/arch-apple/rtkit.h
index eff18ddb9d2..b795215feb7 100644
--- a/arch/arm/include/asm/arch-apple/rtkit.h
+++ b/arch/arm/include/asm/arch-apple/rtkit.h
@@ -26,4 +26,6 @@ struct apple_rtkit *apple_rtkit_init(struct mbox_chan *chan, 
void *cookie,
                                     apple_rtkit_shmem_destroy shmem_destroy);
 void apple_rtkit_free(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);
diff --git a/arch/arm/mach-apple/rtkit.c b/arch/arm/mach-apple/rtkit.c
index b8f4771e5e7..433ffb259ee 100644
--- a/arch/arm/mach-apple/rtkit.c
+++ b/arch/arm/mach-apple/rtkit.c
@@ -36,6 +36,7 @@
 
 #define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE 6
 #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_LAST BIT(51)
@@ -64,6 +65,9 @@ struct apple_rtkit {
        struct apple_rtkit_buffer syslog_buffer;
        struct apple_rtkit_buffer crashlog_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,
@@ -150,6 +154,75 @@ static int rtkit_handle_buf_req(struct apple_rtkit *rtk, 
int endpoint, struct ap
        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)
 {
        struct apple_mbox_msg msg;
@@ -157,7 +230,7 @@ int apple_rtkit_boot(struct apple_rtkit *rtk)
        int nendpoints = 0;
        int endpoint;
        int min_ver, max_ver, want_ver;
-       int msgtype, pwrstate;
+       int msgtype;
        u64 reply;
        u32 bitmap, base;
        int i, ret;
@@ -276,46 +349,37 @@ wait_epmap:
                        return ret;
        }
 
-       pwrstate = APPLE_RTKIT_PWR_STATE_SLEEP;
-       while (pwrstate != APPLE_RTKIT_PWR_STATE_ON) {
-               ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
+       rtk->iop_pwr = APPLE_RTKIT_PWR_STATE_SLEEP;
+       rtk->ap_pwr = APPLE_RTKIT_PWR_STATE_QUIESCED;
+
+       while (rtk->iop_pwr != APPLE_RTKIT_PWR_STATE_ON) {
+               ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US);
                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;
-                               continue;
-                       }
-               }
+       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;
-                               continue;
-                       }
-               }
+int apple_rtkit_set_ap_power(struct apple_rtkit *rtk, int pwrstate)
+{
+       struct apple_mbox_msg msg;
+       int ret;
 
-               if (endpoint != APPLE_RTKIT_EP_MGMT) {
-                       printf("%s: unexpected endpoint %d\n", __func__, 
endpoint);
-                       return -EINVAL;
-               }
-               if (msgtype != APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK) {
-                       printf("%s: unexpected message type %d\n", __func__, 
msgtype);
-                       return -EINVAL;
-               }
+       if (rtk->ap_pwr == pwrstate)
+               return 0;
 
-               pwrstate = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0);
+       msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, 
APPLE_RTKIT_MGMT_SET_AP_PWR_STATE) |
+               FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate);
+       msg.msg1 = APPLE_RTKIT_EP_MGMT;
+       ret = mbox_send(rtk->chan, &msg);
+       if (ret < 0)
+               return ret;
+
+       while (rtk->ap_pwr != pwrstate) {
+               ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US);
+               if (ret < 0)
+                       return ret;
        }
 
        return 0;
@@ -326,6 +390,12 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk, int 
pwrstate)
        struct apple_mbox_msg msg;
        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) |
                FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, pwrstate);
        msg.msg1 = APPLE_RTKIT_EP_MGMT;
@@ -333,9 +403,11 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk, int 
pwrstate)
        if (ret < 0)
                return ret;
 
-       ret = mbox_recv(rtk->chan, &msg, TIMEOUT_1SEC_US);
-       if (ret < 0)
-               return ret;
+       while (rtk->iop_pwr != pwrstate) {
+               ret = apple_rtkit_poll(rtk, TIMEOUT_1SEC_US);
+               if (ret < 0)
+                       return ret;
+       }
 
        return 0;
 }
-- 
2.49.0

Reply via email to