apple_mbox.c revision 1.1 1 1.1 skrll /* $NetBSD: apple_mbox.c,v 1.1 2022/04/27 08:06:20 skrll Exp $ */
2 1.1 skrll /* $OpenBSD: apple_mbox.c,v 1.2 2022/01/04 20:55:48 kettenis Exp $ */
3 1.1 skrll
4 1.1 skrll /*-
5 1.1 skrll * Copyright (c) 2022 The NetBSD Foundation, Inc.
6 1.1 skrll * All rights reserved.
7 1.1 skrll *
8 1.1 skrll * This code is derived from software contributed to The NetBSD Foundation
9 1.1 skrll * by Nick Hudson
10 1.1 skrll *
11 1.1 skrll * Redistribution and use in source and binary forms, with or without
12 1.1 skrll * modification, are permitted provided that the following conditions
13 1.1 skrll * are met:
14 1.1 skrll * 1. Redistributions of source code must retain the above copyright
15 1.1 skrll * notice, this list of conditions and the following disclaimer.
16 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 skrll * notice, this list of conditions and the following disclaimer in the
18 1.1 skrll * documentation and/or other materials provided with the distribution.
19 1.1 skrll *
20 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.1 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.1 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.1 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.1 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.1 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.1 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.1 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.1 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.1 skrll * POSSIBILITY OF SUCH DAMAGE.
31 1.1 skrll */
32 1.1 skrll
33 1.1 skrll /*
34 1.1 skrll * Copyright (c) 2021 Mark Kettenis <kettenis (at) openbsd.org>
35 1.1 skrll *
36 1.1 skrll * Permission to use, copy, modify, and distribute this software for any
37 1.1 skrll * purpose with or without fee is hereby granted, provided that the above
38 1.1 skrll * copyright notice and this permission notice appear in all copies.
39 1.1 skrll *
40 1.1 skrll * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
41 1.1 skrll * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
42 1.1 skrll * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
43 1.1 skrll * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44 1.1 skrll * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
45 1.1 skrll * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
46 1.1 skrll * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47 1.1 skrll */
48 1.1 skrll
49 1.1 skrll #include <sys/cdefs.h>
50 1.1 skrll __KERNEL_RCSID(0, "$NetBSD: apple_mbox.c,v 1.1 2022/04/27 08:06:20 skrll Exp $");
51 1.1 skrll
52 1.1 skrll #include <sys/param.h>
53 1.1 skrll #include <sys/bus.h>
54 1.1 skrll #include <sys/device.h>
55 1.1 skrll
56 1.1 skrll #include <dev/fdt/fdtvar.h>
57 1.1 skrll
58 1.1 skrll #include <arm/apple/apple_mbox.h>
59 1.1 skrll
60 1.1 skrll #define MBOX_A2I_CTRL 0x110
61 1.1 skrll #define MBOX_A2I_CTRL_FULL __BIT(16)
62 1.1 skrll #define MBOX_I2A_CTRL 0x114
63 1.1 skrll #define MBOX_I2A_CTRL_EMPTY __BIT(17)
64 1.1 skrll #define MBOX_A2I_SEND0 0x800
65 1.1 skrll #define MBOX_A2I_SEND1 0x808
66 1.1 skrll #define MBOX_I2A_RECV0 0x830
67 1.1 skrll #define MBOX_I2A_RECV1 0x838
68 1.1 skrll
69 1.1 skrll #define MBOX_READ4(sc, reg) \
70 1.1 skrll (bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)))
71 1.1 skrll #define MBOX_READ8(sc, reg) \
72 1.1 skrll (bus_space_read_8((sc)->sc_bst, (sc)->sc_bsh, (reg)))
73 1.1 skrll #define MBOX_WRITE4(sc, reg, val) \
74 1.1 skrll bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
75 1.1 skrll #define MBOX_WRITE8(sc, reg, val) \
76 1.1 skrll bus_space_write_8((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
77 1.1 skrll
78 1.1 skrll static int apple_mbox_intr(void *);
79 1.1 skrll
80 1.1 skrll static struct mbox_interrupt {
81 1.1 skrll const char *mi_name;
82 1.1 skrll bool mi_claim;
83 1.1 skrll int (*mi_handler)(void *);
84 1.1 skrll } mbox_interrupts[] = {
85 1.1 skrll {
86 1.1 skrll .mi_name = "send-empty",
87 1.1 skrll .mi_claim = false,
88 1.1 skrll .mi_handler = apple_mbox_intr,
89 1.1 skrll },
90 1.1 skrll {
91 1.1 skrll .mi_name = "send-not-empty",
92 1.1 skrll .mi_claim = false,
93 1.1 skrll },
94 1.1 skrll {
95 1.1 skrll .mi_name = "recv-empty",
96 1.1 skrll .mi_claim = false,
97 1.1 skrll },
98 1.1 skrll {
99 1.1 skrll .mi_name = "recv-not-empty",
100 1.1 skrll .mi_claim = true,
101 1.1 skrll .mi_handler = apple_mbox_intr,
102 1.1 skrll },
103 1.1 skrll };
104 1.1 skrll
105 1.1 skrll struct apple_mbox_softc {
106 1.1 skrll device_t sc_dev;
107 1.1 skrll int sc_phandle;
108 1.1 skrll bus_space_tag_t sc_bst;
109 1.1 skrll bus_space_handle_t sc_bsh;
110 1.1 skrll
111 1.1 skrll void *sc_intr[__arraycount(mbox_interrupts)];
112 1.1 skrll void (*sc_rx_callback)(void *);
113 1.1 skrll void *sc_rx_arg;
114 1.1 skrll
115 1.1 skrll // struct fdtbus_mbox_device sc_md;
116 1.1 skrll };
117 1.1 skrll
118 1.1 skrll static const struct device_compatible_entry compat_data[] = {
119 1.1 skrll { .compat = "apple,asc-mailbox" },
120 1.1 skrll { .compat = "apple,asc-mailbox-v4" },
121 1.1 skrll DEVICE_COMPAT_EOL
122 1.1 skrll };
123 1.1 skrll
124 1.1 skrll
125 1.1 skrll static int
126 1.1 skrll apple_mbox_intr(void *arg)
127 1.1 skrll {
128 1.1 skrll struct apple_mbox_softc const *sc = arg;
129 1.1 skrll const uint32_t ctrl = MBOX_READ4(sc, MBOX_I2A_CTRL);
130 1.1 skrll
131 1.1 skrll if (ctrl & MBOX_I2A_CTRL_EMPTY)
132 1.1 skrll return 0;
133 1.1 skrll
134 1.1 skrll if (sc->sc_rx_callback) {
135 1.1 skrll sc->sc_rx_callback(sc->sc_rx_arg);
136 1.1 skrll } else {
137 1.1 skrll printf("%s: 0x%016" PRIx64 "0x%016" PRIx64 "\n",
138 1.1 skrll device_xname(sc->sc_dev),
139 1.1 skrll MBOX_READ8(sc, MBOX_I2A_RECV0),
140 1.1 skrll MBOX_READ8(sc, MBOX_I2A_RECV1));
141 1.1 skrll }
142 1.1 skrll
143 1.1 skrll return 1;
144 1.1 skrll }
145 1.1 skrll
146 1.1 skrll static void *
147 1.1 skrll apple_mbox_acquire(device_t dev, const void *cells, size_t len,
148 1.1 skrll void (*cb)(void *), void *arg)
149 1.1 skrll {
150 1.1 skrll struct apple_mbox_softc * const sc = device_private(dev);
151 1.1 skrll
152 1.1 skrll if (sc->sc_rx_callback == NULL && sc->sc_rx_arg == NULL) {
153 1.1 skrll sc->sc_rx_callback = cb;
154 1.1 skrll sc->sc_rx_arg = arg;
155 1.1 skrll
156 1.1 skrll return sc;
157 1.1 skrll }
158 1.1 skrll
159 1.1 skrll return NULL;
160 1.1 skrll }
161 1.1 skrll
162 1.1 skrll static void
163 1.1 skrll apple_mbox_release(device_t dev, void *priv)
164 1.1 skrll {
165 1.1 skrll struct apple_mbox_softc * const sc = device_private(dev);
166 1.1 skrll
167 1.1 skrll KASSERT(sc == priv);
168 1.1 skrll
169 1.1 skrll sc->sc_rx_callback = NULL;
170 1.1 skrll sc->sc_rx_arg = NULL;
171 1.1 skrll }
172 1.1 skrll
173 1.1 skrll static int
174 1.1 skrll apple_mbox_send(device_t dev, void *priv, const void *data, size_t len)
175 1.1 skrll {
176 1.1 skrll struct apple_mbox_softc * const sc = device_private(dev);
177 1.1 skrll const struct apple_mbox_msg *msg = data;
178 1.1 skrll
179 1.1 skrll KASSERT(sc == priv);
180 1.1 skrll
181 1.1 skrll if (len != sizeof(struct apple_mbox_msg))
182 1.1 skrll return EINVAL;
183 1.1 skrll
184 1.1 skrll
185 1.1 skrll uint32_t ctrl = MBOX_READ4(sc, MBOX_A2I_CTRL);
186 1.1 skrll if (ctrl & MBOX_A2I_CTRL_FULL)
187 1.1 skrll return EBUSY;
188 1.1 skrll
189 1.1 skrll MBOX_WRITE8(sc, MBOX_A2I_SEND0, msg->data0);
190 1.1 skrll MBOX_WRITE8(sc, MBOX_A2I_SEND1, msg->data1);
191 1.1 skrll
192 1.1 skrll return 0;
193 1.1 skrll }
194 1.1 skrll
195 1.1 skrll static int
196 1.1 skrll apple_mbox_recv(device_t dev, void *priv, void *data, size_t len)
197 1.1 skrll {
198 1.1 skrll struct apple_mbox_softc * const sc = device_private(dev);
199 1.1 skrll struct apple_mbox_msg *msg = data;
200 1.1 skrll
201 1.1 skrll KASSERT(sc == priv);
202 1.1 skrll if (len != sizeof(struct apple_mbox_msg))
203 1.1 skrll return EINVAL;
204 1.1 skrll
205 1.1 skrll uint32_t ctrl = MBOX_READ4(sc, MBOX_I2A_CTRL);
206 1.1 skrll if (ctrl & MBOX_I2A_CTRL_EMPTY)
207 1.1 skrll return EAGAIN;
208 1.1 skrll
209 1.1 skrll msg->data0 = MBOX_READ8(sc, MBOX_I2A_RECV0);
210 1.1 skrll msg->data1 = MBOX_READ8(sc, MBOX_I2A_RECV1);
211 1.1 skrll
212 1.1 skrll return 0;
213 1.1 skrll }
214 1.1 skrll
215 1.1 skrll
216 1.1 skrll static int
217 1.1 skrll apple_mbox_match(device_t parent, cfdata_t cf, void *aux)
218 1.1 skrll {
219 1.1 skrll struct fdt_attach_args * const faa = aux;
220 1.1 skrll
221 1.1 skrll return of_compatible_match(faa->faa_phandle, compat_data);
222 1.1 skrll }
223 1.1 skrll
224 1.1 skrll static void
225 1.1 skrll apple_mbox_attach(device_t parent, device_t self, void *aux)
226 1.1 skrll {
227 1.1 skrll struct apple_mbox_softc * const sc = device_private(self);
228 1.1 skrll struct fdt_attach_args * const faa = aux;
229 1.1 skrll const int phandle = faa->faa_phandle;
230 1.1 skrll bus_addr_t addr;
231 1.1 skrll bus_size_t size;
232 1.1 skrll
233 1.1 skrll if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
234 1.1 skrll aprint_error(": couldn't get registers\n");
235 1.1 skrll return;
236 1.1 skrll }
237 1.1 skrll
238 1.1 skrll sc->sc_dev = self;
239 1.1 skrll sc->sc_rx_callback = NULL;
240 1.1 skrll sc->sc_rx_arg = NULL;
241 1.1 skrll sc->sc_bst = faa->faa_bst;
242 1.1 skrll if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
243 1.1 skrll aprint_error(": couldn't map registers\n");
244 1.1 skrll return;
245 1.1 skrll }
246 1.1 skrll
247 1.1 skrll aprint_naive("\n");
248 1.1 skrll aprint_normal(": Apple Mailbox\n");
249 1.1 skrll
250 1.1 skrll for (size_t i = 0; i < __arraycount(mbox_interrupts); i++) {
251 1.1 skrll struct mbox_interrupt *mi = &mbox_interrupts[i];
252 1.1 skrll
253 1.1 skrll if (!mi->mi_claim)
254 1.1 skrll continue;
255 1.1 skrll
256 1.1 skrll int index;
257 1.1 skrll int err = fdtbus_get_index(phandle, "interrupt-names",
258 1.1 skrll mi->mi_name, &index);
259 1.1 skrll if (err != 0) {
260 1.1 skrll aprint_error_dev(self,
261 1.1 skrll "couldn't get %s interrupt index\n", mi->mi_name);
262 1.1 skrll continue;
263 1.1 skrll }
264 1.1 skrll
265 1.1 skrll char istr[128];
266 1.1 skrll if (!fdtbus_intr_str(phandle, index, istr, sizeof(istr))) {
267 1.1 skrll aprint_error_dev(self,
268 1.1 skrll "couldn't decode %s interrupt\n", mi->mi_name);
269 1.1 skrll continue;
270 1.1 skrll }
271 1.1 skrll
272 1.1 skrll sc->sc_intr[i] = fdtbus_intr_establish_xname(phandle, index,
273 1.1 skrll IPL_VM, FDT_INTR_MPSAFE, mi->mi_handler, sc,
274 1.1 skrll device_xname(self));
275 1.1 skrll if (sc->sc_intr[i] == NULL) {
276 1.1 skrll aprint_error_dev(self,
277 1.1 skrll "couldn't establish %s interrupt\n", mi->mi_name);
278 1.1 skrll continue;
279 1.1 skrll }
280 1.1 skrll
281 1.1 skrll aprint_normal_dev(self, "'%s' interrupting on %s\n",
282 1.1 skrll mi->mi_name, istr);
283 1.1 skrll }
284 1.1 skrll
285 1.1 skrll static struct fdtbus_mbox_controller_func funcs = {
286 1.1 skrll .mc_acquire = apple_mbox_acquire,
287 1.1 skrll .mc_release = apple_mbox_release,
288 1.1 skrll .mc_send = apple_mbox_send,
289 1.1 skrll .mc_recv = apple_mbox_recv,
290 1.1 skrll };
291 1.1 skrll
292 1.1 skrll int error = fdtbus_register_mbox_controller(self, phandle, &funcs);
293 1.1 skrll if (error) {
294 1.1 skrll aprint_error_dev(self, "couldn't register mailbox\n");
295 1.1 skrll goto fail_register;
296 1.1 skrll }
297 1.1 skrll return;
298 1.1 skrll
299 1.1 skrll fail_register:
300 1.1 skrll for (size_t i = 0; i < __arraycount(mbox_interrupts); i++) {
301 1.1 skrll if (sc->sc_intr[i] != NULL) {
302 1.1 skrll fdtbus_intr_disestablish(phandle, sc->sc_intr[i]);
303 1.1 skrll }
304 1.1 skrll }
305 1.1 skrll
306 1.1 skrll return;
307 1.1 skrll }
308 1.1 skrll
309 1.1 skrll CFATTACH_DECL_NEW(apple_mbox, sizeof(struct apple_mbox_softc),
310 1.1 skrll apple_mbox_match, apple_mbox_attach, NULL, NULL);
311