All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Kettenis <kettenis@openbsd.org>
To: u-boot@lists.denx.de
Cc: sjg@chromium.org, jh80.chung@samsung.com, trini@konsulko.com,
	sven@svenpeter.dev, marcan@marcan.st, bmeng.cn@gmail.com,
	Mark Kettenis <kettenis@openbsd.org>
Subject: [PATCH 3/8] arm: apple: Add RTKit support
Date: Fri, 14 Jan 2022 12:04:33 +0100	[thread overview]
Message-ID: <20220114110438.58452-4-kettenis@openbsd.org> (raw)
In-Reply-To: <20220114110438.58452-1-kettenis@openbsd.org>

Most Apple IOPs run a firmware that is based on what Apple calls
RTKit. RTKit implements a common mailbox protocol.  This code
provides an implementation of the AP side of this protocol,
providing a function to initialize RTKit-based firmwares as well
as a function to do a clean shutdown of this firmware.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 arch/arm/include/asm/arch-apple/rtkit.h |  11 ++
 arch/arm/mach-apple/Makefile            |   1 +
 arch/arm/mach-apple/rtkit.c             | 231 ++++++++++++++++++++++++
 3 files changed, 243 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-apple/rtkit.h
 create mode 100644 arch/arm/mach-apple/rtkit.c

diff --git a/arch/arm/include/asm/arch-apple/rtkit.h b/arch/arm/include/asm/arch-apple/rtkit.h
new file mode 100644
index 0000000000..51f77f298c
--- /dev/null
+++ b/arch/arm/include/asm/arch-apple/rtkit.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#define APPLE_RTKIT_PWR_STATE_SLEEP	0x01
+#define APPLE_RTKIT_PWR_STATE_QUIESCED	0x10
+#define APPLE_RTKIT_PWR_STATE_ON	0x20
+
+int apple_rtkit_init(struct mbox_chan *);
+int apple_rtkit_shutdown(struct mbox_chan *, int);
diff --git a/arch/arm/mach-apple/Makefile b/arch/arm/mach-apple/Makefile
index e74a8c9df1..52f30a777b 100644
--- a/arch/arm/mach-apple/Makefile
+++ b/arch/arm/mach-apple/Makefile
@@ -2,3 +2,4 @@
 
 obj-y += board.o
 obj-y += lowlevel_init.o
+obj-y += rtkit.o
diff --git a/arch/arm/mach-apple/rtkit.c b/arch/arm/mach-apple/rtkit.c
new file mode 100644
index 0000000000..79048a801f
--- /dev/null
+++ b/arch/arm/mach-apple/rtkit.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
+ * (C) Copyright 2021 Copyright The Asahi Linux Contributors
+ */
+
+#include <common.h>
+#include <mailbox.h>
+#include <malloc.h>
+
+#include <asm/arch-apple/rtkit.h>
+#include <linux/apple-mailbox.h>
+#include <linux/bitfield.h>
+
+#define APPLE_RTKIT_EP_MGMT 0
+#define APPLE_RTKIT_EP_CRASHLOG	1
+#define APPLE_RTKIT_EP_SYSLOG 2
+#define APPLE_RTKIT_EP_DEBUG 3
+#define APPLE_RTKIT_EP_IOREPORT 4
+
+/* Messages for management endpoint. */
+#define APPLE_RTKIT_MGMT_TYPE GENMASK(59, 52)
+
+#define APPLE_RTKIT_MGMT_PWR_STATE GENMASK(15, 0)
+
+#define APPLE_RTKIT_MGMT_HELLO 1
+#define APPLE_RTKIT_MGMT_HELLO_REPLY 2
+#define APPLE_RTKIT_MGMT_HELLO_MINVER GENMASK(15, 0)
+#define APPLE_RTKIT_MGMT_HELLO_MAXVER GENMASK(31, 16)
+
+#define APPLE_RTKIT_MGMT_STARTEP 5
+#define APPLE_RTKIT_MGMT_STARTEP_EP GENMASK(39, 32)
+#define APPLE_RTKIT_MGMT_STARTEP_FLAG BIT(1)
+
+#define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE 6
+#define APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE_ACK 7
+
+#define APPLE_RTKIT_MGMT_EPMAP 8
+#define APPLE_RTKIT_MGMT_EPMAP_LAST BIT(51)
+#define APPLE_RTKIT_MGMT_EPMAP_BASE GENMASK(34, 32)
+#define APPLE_RTKIT_MGMT_EPMAP_BITMAP GENMASK(31, 0)
+
+#define APPLE_RTKIT_MGMT_EPMAP_REPLY 8
+#define APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE BIT(0)
+
+#define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11
+#define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12
+
+/* Messages for internal endpoints. */
+#define APPLE_RTKIT_BUFFER_REQUEST 1
+#define APPLE_RTKIT_BUFFER_REQUEST_SIZE GENMASK(51, 44)
+#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK(41, 0)
+
+int apple_rtkit_init(struct mbox_chan *chan)
+{
+	struct apple_mbox_msg msg;
+	int endpoints[256];
+	int nendpoints = 0;
+	int endpoint;
+	int min_ver, max_ver, want_ver;
+	int msgtype, pwrstate;
+	u64 reply;
+	u32 bitmap, base;
+	int i, ret;
+
+	/* Wakup the IOP. */
+	msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE) |
+		FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, APPLE_RTKIT_PWR_STATE_ON);
+	msg.msg1 = APPLE_RTKIT_EP_MGMT;
+	ret = mbox_send(chan, &msg);
+	if (ret < 0)
+		return ret;
+
+	/* Wait for protocol version negotiation message. */
+	ret = mbox_recv(chan, &msg, 10000);
+	if (ret < 0)
+		return ret;
+
+	endpoint = msg.msg1;
+	msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0);
+	if (endpoint != APPLE_RTKIT_EP_MGMT) {
+		printf("%s: unexpected endpoint %d\n", __func__, endpoint);
+		return -EINVAL;
+	}
+	if (msgtype != APPLE_RTKIT_MGMT_HELLO) {
+		printf("%s: unexpected message type %d\n", __func__, msgtype);
+		return -EINVAL;
+	}
+
+	min_ver = FIELD_GET(APPLE_RTKIT_MGMT_HELLO_MINVER, msg.msg0);
+	max_ver = FIELD_GET(APPLE_RTKIT_MGMT_HELLO_MAXVER, msg.msg0);
+	want_ver = min(APPLE_RTKIT_MAX_SUPPORTED_VERSION, max_ver);
+
+	if (min_ver > APPLE_RTKIT_MAX_SUPPORTED_VERSION) {
+		printf("%s: firmware min version %d is too new\n",
+		       __func__, min_ver);
+		return -ENOTSUPP;
+	}
+
+	if (max_ver < APPLE_RTKIT_MIN_SUPPORTED_VERSION) {
+		printf("%s: firmware max version %d is too old\n",
+		       __func__, max_ver);
+		return -ENOTSUPP;
+	}
+
+	/* Ack version. */
+	msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_HELLO_REPLY) |
+		FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MINVER, want_ver) |
+		FIELD_PREP(APPLE_RTKIT_MGMT_HELLO_MAXVER, want_ver);
+	msg.msg1 = APPLE_RTKIT_EP_MGMT;
+	ret = mbox_send(chan, &msg);
+	if (ret < 0)
+		return ret;
+
+wait_epmap:
+	/* Wait for endpoint map message. */
+	ret = mbox_recv(chan, &msg, 10000);
+	if (ret < 0)
+		return ret;
+
+	endpoint = msg.msg1;
+	msgtype = FIELD_GET(APPLE_RTKIT_MGMT_TYPE, msg.msg0);
+	if (endpoint != APPLE_RTKIT_EP_MGMT) {
+		printf("%s: unexpected endpoint %d\n", __func__, endpoint);
+		return -EINVAL;
+	}
+	if (msgtype != APPLE_RTKIT_MGMT_EPMAP) {
+		printf("%s: unexpected message type %d\n", __func__, msgtype);
+		return -EINVAL;
+	}
+
+	bitmap = FIELD_GET(APPLE_RTKIT_MGMT_EPMAP_BITMAP, msg.msg0);
+	base = FIELD_GET(APPLE_RTKIT_MGMT_EPMAP_BASE, msg.msg0);
+	for (i = 0; i < 32; i++) {
+		if (bitmap & (1U << i))
+			endpoints[nendpoints++] = base * 32 + i;
+	}
+
+	/* Ack endpoint map. */
+	reply = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_EPMAP_REPLY) |
+		FIELD_PREP(APPLE_RTKIT_MGMT_EPMAP_BASE, base);
+	if (msg.msg0 & APPLE_RTKIT_MGMT_EPMAP_LAST)
+		reply |= APPLE_RTKIT_MGMT_EPMAP_LAST;
+	else
+		reply |= APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE;
+	msg.msg0 = reply;
+	msg.msg1 = APPLE_RTKIT_EP_MGMT;
+	ret = mbox_send(chan, &msg);
+	if (ret < 0)
+		return ret;
+
+	if (reply & APPLE_RTKIT_MGMT_EPMAP_REPLY_MORE)
+		goto wait_epmap;
+
+	for (i = 0; i < nendpoints; i++) {
+		/* Don't start the syslog endpoint since we can't
+		   easily handle its messages in U-Boot. */
+		if (endpoints[i] == APPLE_RTKIT_EP_SYSLOG)
+			continue;
+
+		/* Request endpoint. */
+		msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_MGMT_STARTEP) |
+			FIELD_PREP(APPLE_RTKIT_MGMT_STARTEP_EP, endpoints[i]) |
+			APPLE_RTKIT_MGMT_STARTEP_FLAG;
+		msg.msg1 = APPLE_RTKIT_EP_MGMT;
+		ret = mbox_send(chan, &msg);
+		if (ret < 0)
+			return ret;
+	}
+
+	pwrstate = APPLE_RTKIT_PWR_STATE_SLEEP;
+	while (pwrstate != APPLE_RTKIT_PWR_STATE_ON) {
+		ret = mbox_recv(chan, &msg, 100000);
+		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) {
+			u64 addr = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg.msg0);
+			u64 size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg.msg0);
+
+			if (msgtype == APPLE_RTKIT_BUFFER_REQUEST && addr != 0)
+				continue;
+
+			msg.msg0 = FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, APPLE_RTKIT_BUFFER_REQUEST) |
+				FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, size) |
+				FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, addr);
+			msg.msg1 = endpoint;
+			ret = mbox_send(chan, &msg);
+			if (ret < 0)
+				return ret;
+			continue;
+		}
+
+		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;
+		}
+
+		pwrstate = FIELD_GET(APPLE_RTKIT_MGMT_PWR_STATE, msg.msg0);
+	}
+
+	return 0;
+}
+
+int apple_rtkit_shutdown(struct mbox_chan *chan, int pwrstate)
+{
+	struct apple_mbox_msg msg;
+	int 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;
+	ret = mbox_send(chan, &msg);
+	if (ret < 0)
+		return ret;
+
+	ret = mbox_recv(chan, &msg, 100000);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
-- 
2.34.1


  parent reply	other threads:[~2022-01-14 11:06 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-14 11:04 [PATCH 0/8] Apple M1 NVMe storage support Mark Kettenis
2022-01-14 11:04 ` [PATCH 1/8] nvme: Split out PCI support Mark Kettenis
2022-01-22  1:40   ` Simon Glass
2022-01-22 12:47     ` Mark Kettenis
2022-01-22 13:18       ` Simon Glass
2022-01-22 14:57         ` Mark Kettenis
2022-01-14 11:04 ` [PATCH 2/8] mailbox: apple: Add driver for Apple IOP mailbox Mark Kettenis
2022-01-22  1:40   ` Simon Glass
2022-01-22 13:54     ` Mark Kettenis
2022-01-22 17:17       ` Simon Glass
2022-01-14 11:04 ` Mark Kettenis [this message]
2022-01-22  1:40   ` [PATCH 3/8] arm: apple: Add RTKit support Simon Glass
2022-01-22 13:59     ` Mark Kettenis
2022-01-22 17:17       ` Simon Glass
2022-01-22 19:31         ` Mark Kettenis
2022-01-14 11:04 ` [PATCH 4/8] nvme: Introduce driver ops Mark Kettenis
2022-01-22  1:40   ` Simon Glass
2022-01-22 13:33     ` Mark Kettenis
2022-01-22 17:17       ` Simon Glass
2022-01-14 11:04 ` [PATCH 5/8] nvme: Add shutdown function Mark Kettenis
2022-01-22  1:40   ` Simon Glass
2022-01-14 11:04 ` [PATCH 6/8] power: domain: apple: Add reset support Mark Kettenis
2022-01-22  1:40   ` Simon Glass
2022-01-22 14:11     ` Mark Kettenis
2022-01-22 17:17       ` Simon Glass
2022-01-22 19:35         ` Mark Kettenis
2022-01-14 11:04 ` [PATCH 7/8] nvme: apple: Add driver for Apple NVMe storage controller Mark Kettenis
2022-01-22  1:40   ` Simon Glass
2022-01-22 14:45     ` Mark Kettenis
2022-01-22 17:17       ` Simon Glass
2022-01-22 17:41         ` Mark Kettenis
2022-01-22 18:28           ` Simon Glass
2022-01-14 11:04 ` [PATCH 8/8] configs: apple: Add NVMe boot target Mark Kettenis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220114110438.58452-4-kettenis@openbsd.org \
    --to=kettenis@openbsd.org \
    --cc=bmeng.cn@gmail.com \
    --cc=jh80.chung@samsung.com \
    --cc=marcan@marcan.st \
    --cc=sjg@chromium.org \
    --cc=sven@svenpeter.dev \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.