blob: b7d60e157002769dc3549dafe67947717cfdcf49 [file] [log] [blame]
Hector Martin7466b6d2025-04-20 13:58:05 +02001// SPDX-License-Identifier: GPL-2.0+ OR MIT
2/*
3 * Copyright The Asahi Linux Contributors
4 */
5
6#include <dm.h>
7#include <mailbox.h>
8#include <mapmem.h>
9#include <reset.h>
10
11#include <asm/io.h>
12#include <asm/arch/rtkit.h>
13#include <linux/iopoll.h>
14
15/* ASC registers */
16#define REG_CPU_CTRL 0x0044
17#define REG_CPU_CTRL_RUN BIT(4)
18
Hector Martinfa522532025-04-20 13:58:08 +020019#define APPLE_RTKIT_EP_OSLOG 8
20
Hector Martin7466b6d2025-04-20 13:58:05 +020021struct rtkit_helper_priv {
22 void *asc; /* ASC registers */
23 struct mbox_chan chan;
24 struct apple_rtkit *rtk;
Hector Martinfa522532025-04-20 13:58:08 +020025 bool sram_stolen;
Hector Martin7466b6d2025-04-20 13:58:05 +020026};
27
Hector Martinfa522532025-04-20 13:58:08 +020028static int shmem_setup(void *cookie, struct apple_rtkit_buffer *buf) {
29 struct udevice *dev = cookie;
30 struct rtkit_helper_priv *priv = dev_get_priv(dev);
31
32 if (!buf->is_mapped) {
33 /*
34 * Special case: The OSLog buffer on MTP persists on Linux handoff.
35 * Steal some SRAM instead of putting this in DRAM, so we don't
36 * have to hand off DART/DAPF mappings.
37 */
38 if (buf->endpoint == APPLE_RTKIT_EP_OSLOG) {
39 if (priv->sram_stolen) {
40 printf("%s: Tried to map more than one OSLog buffer out of SRAM\n",
41 __func__);
42 } else {
43 fdt_size_t size;
44 fdt_addr_t addr;
45
46 addr = dev_read_addr_size_name(dev, "sram", &size);
47
48 if (addr != FDT_ADDR_T_NONE) {
49 buf->dva = ALIGN_DOWN(addr + size - buf->size, SZ_16K);
50 priv->sram_stolen = true;
51
52 return 0;
53 } else {
54 printf("%s: No SRAM, falling back to DRAM\n", __func__);
55 }
56 }
57 }
58
59 buf->buffer = memalign(SZ_16K, ALIGN(buf->size, SZ_16K));
60 if (!buf->buffer)
61 return -ENOMEM;
62
63 buf->dva = (u64)buf->buffer;
64 }
65 return 0;
66}
67
68static void shmem_destroy(void *cookie, struct apple_rtkit_buffer *buf) {
69 if (buf->buffer)
70 free(buf->buffer);
71}
72
Hector Martin7466b6d2025-04-20 13:58:05 +020073static int rtkit_helper_probe(struct udevice *dev)
74{
75 struct rtkit_helper_priv *priv = dev_get_priv(dev);
76 u32 ctrl;
77 int ret;
78
79 priv->asc = dev_read_addr_ptr(dev);
80 if (!priv->asc)
81 return -EINVAL;
82
83 ret = mbox_get_by_index(dev, 0, &priv->chan);
84 if (ret < 0)
85 return ret;
86
87 ctrl = readl(priv->asc + REG_CPU_CTRL);
88 writel(ctrl | REG_CPU_CTRL_RUN, priv->asc + REG_CPU_CTRL);
89
Hector Martinfa522532025-04-20 13:58:08 +020090 priv->rtk = apple_rtkit_init(&priv->chan, dev, shmem_setup, shmem_destroy);
Hector Martin7466b6d2025-04-20 13:58:05 +020091 if (!priv->rtk)
92 return -ENOMEM;
93
94 ret = apple_rtkit_boot(priv->rtk);
95 if (ret < 0) {
96 printf("%s: Helper apple_rtkit_boot returned: %d\n", __func__, ret);
97 return ret;
98 }
99
100 ret = apple_rtkit_set_ap_power(priv->rtk, APPLE_RTKIT_PWR_STATE_ON);
101 if (ret < 0) {
102 printf("%s: Helper apple_rtkit_set_ap_power returned: %d\n", __func__, ret);
103 return ret;
104 }
105
106 return 0;
107}
108
109static int rtkit_helper_remove(struct udevice *dev)
110{
111 struct rtkit_helper_priv *priv = dev_get_priv(dev);
112 u32 ctrl;
113
114 apple_rtkit_shutdown(priv->rtk, APPLE_RTKIT_PWR_STATE_QUIESCED);
115
116 ctrl = readl(priv->asc + REG_CPU_CTRL);
117 writel(ctrl & ~REG_CPU_CTRL_RUN, priv->asc + REG_CPU_CTRL);
118
119 apple_rtkit_free(priv->rtk);
120 priv->rtk = NULL;
121
122 return 0;
123}
124
125int apple_rtkit_helper_poll(struct udevice *dev, ulong timeout)
126{
127 struct rtkit_helper_priv *priv = dev_get_priv(dev);
128
129 return apple_rtkit_poll(priv->rtk, timeout);
130}
131
132static const struct udevice_id rtkit_helper_ids[] = {
133 { .compatible = "apple,rtk-helper-asc4" },
134 { /* sentinel */ }
135};
136
137U_BOOT_DRIVER(rtkit_helper) = {
138 .name = "rtkit_helper",
139 .id = UCLASS_MISC,
140 .of_match = rtkit_helper_ids,
141 .priv_auto = sizeof(struct rtkit_helper_priv),
142 .probe = rtkit_helper_probe,
143 .remove = rtkit_helper_remove,
144 .flags = DM_FLAG_OS_PREPARE,
145};