xref: /netbsd-src/sys/arch/arm/apple/apple_nvme.c (revision e24a9df7237c4ed793f8823d70fe5b3f33a21742)
1*e24a9df7Sskrll /*	$NetBSD: apple_nvme.c,v 1.1 2022/05/07 08:20:03 skrll Exp $	*/
2*e24a9df7Sskrll /*	$OpenBSD: aplns.c,v 1.5 2021/08/29 11:23:29 kettenis Exp $ */
3*e24a9df7Sskrll 
4*e24a9df7Sskrll /*-
5*e24a9df7Sskrll  * Copyright (c) 2022 The NetBSD Foundation, Inc.
6*e24a9df7Sskrll  * All rights reserved.
7*e24a9df7Sskrll  *
8*e24a9df7Sskrll  * This code is derived from software contributed to The NetBSD Foundation
9*e24a9df7Sskrll  * by Nick Hudson
10*e24a9df7Sskrll  *
11*e24a9df7Sskrll  * Redistribution and use in source and binary forms, with or without
12*e24a9df7Sskrll  * modification, are permitted provided that the following conditions
13*e24a9df7Sskrll  * are met:
14*e24a9df7Sskrll  * 1. Redistributions of source code must retain the above copyright
15*e24a9df7Sskrll  *    notice, this list of conditions and the following disclaimer.
16*e24a9df7Sskrll  * 2. Redistributions in binary form must reproduce the above copyright
17*e24a9df7Sskrll  *    notice, this list of conditions and the following disclaimer in the
18*e24a9df7Sskrll  *    documentation and/or other materials provided with the distribution.
19*e24a9df7Sskrll  *
20*e24a9df7Sskrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21*e24a9df7Sskrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22*e24a9df7Sskrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23*e24a9df7Sskrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24*e24a9df7Sskrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*e24a9df7Sskrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*e24a9df7Sskrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*e24a9df7Sskrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*e24a9df7Sskrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*e24a9df7Sskrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30*e24a9df7Sskrll  * POSSIBILITY OF SUCH DAMAGE.
31*e24a9df7Sskrll  */
32*e24a9df7Sskrll 
33*e24a9df7Sskrll /*
34*e24a9df7Sskrll  * Copyright (c) 2014, 2021 David Gwynne <dlg@openbsd.org>
35*e24a9df7Sskrll  *
36*e24a9df7Sskrll  * Permission to use, copy, modify, and distribute this software for any
37*e24a9df7Sskrll  * purpose with or without fee is hereby granted, provided that the above
38*e24a9df7Sskrll  * copyright notice and this permission notice appear in all copies.
39*e24a9df7Sskrll  *
40*e24a9df7Sskrll  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
41*e24a9df7Sskrll  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
42*e24a9df7Sskrll  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
43*e24a9df7Sskrll  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44*e24a9df7Sskrll  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
45*e24a9df7Sskrll  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
46*e24a9df7Sskrll  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47*e24a9df7Sskrll  */
48*e24a9df7Sskrll 
49*e24a9df7Sskrll #include <sys/cdefs.h>
50*e24a9df7Sskrll __KERNEL_RCSID(0, "$NetBSD: apple_nvme.c,v 1.1 2022/05/07 08:20:03 skrll Exp $");
51*e24a9df7Sskrll 
52*e24a9df7Sskrll #include <sys/param.h>
53*e24a9df7Sskrll 
54*e24a9df7Sskrll #include <sys/bus.h>
55*e24a9df7Sskrll #include <sys/device.h>
56*e24a9df7Sskrll #include <sys/kmem.h>
57*e24a9df7Sskrll #include <sys/intr.h>
58*e24a9df7Sskrll 
59*e24a9df7Sskrll #include <dev/ic/nvmereg.h>
60*e24a9df7Sskrll #include <dev/ic/nvmevar.h>
61*e24a9df7Sskrll 
62*e24a9df7Sskrll #include <dev/fdt/fdtvar.h>
63*e24a9df7Sskrll 
64*e24a9df7Sskrll #include <arm/apple/apple_rtkit.h>
65*e24a9df7Sskrll 
66*e24a9df7Sskrll int apple_nvme_mpsafe = 1;
67*e24a9df7Sskrll 
68*e24a9df7Sskrll #define NVME_IO_Q 1
69*e24a9df7Sskrll 
70*e24a9df7Sskrll #define ANS_CPU_CTRL		0x0044
71*e24a9df7Sskrll #define ANS_CPU_CTRL_RUN		__BIT(4)
72*e24a9df7Sskrll 
73*e24a9df7Sskrll #define ANS_MAX_PEND_CMDS_CTRL	0x01210
74*e24a9df7Sskrll #define  ANS_MAX_QUEUE_DEPTH		64
75*e24a9df7Sskrll #define ANS_BOOT_STATUS		0x01300
76*e24a9df7Sskrll #define  ANS_BOOT_STATUS_OK		0xde71ce55
77*e24a9df7Sskrll 
78*e24a9df7Sskrll #define ANS_MODESEL_REG		0x01304
79*e24a9df7Sskrll #define ANS_UNKNOWN_CTRL	0x24008
80*e24a9df7Sskrll #define  ANS_PRP_NULL_CHECK		__BIT(11)
81*e24a9df7Sskrll #define ANS_LINEAR_SQ_CTRL	0x24908
82*e24a9df7Sskrll #define  ANS_LINEAR_SQ_CTRL_EN		__BIT(0)
83*e24a9df7Sskrll #define ANS_LINEAR_ASQ_DB	0x2490c
84*e24a9df7Sskrll #define ANS_LINEAR_IOSQ_DB	0x24910
85*e24a9df7Sskrll 
86*e24a9df7Sskrll #define ANS_NVMMU_NUM		0x28100
87*e24a9df7Sskrll #define ANS_NVMMU_BASE_ASQ	0x28108
88*e24a9df7Sskrll #define ANS_NVMMU_BASE_IOSQ	0x28110
89*e24a9df7Sskrll #define ANS_NVMMU_TCB_INVAL	0x28118
90*e24a9df7Sskrll #define ANS_NVMMU_TCB_STAT	0x28120
91*e24a9df7Sskrll 
92*e24a9df7Sskrll #define ANS_NVMMU_TCB_SIZE	0x4000
93*e24a9df7Sskrll #define ANS_NVMMU_TCB_PITCH	0x80
94*e24a9df7Sskrll 
95*e24a9df7Sskrll struct ans_nvmmu_tcb {
96*e24a9df7Sskrll 	uint8_t		tcb_opcode;
97*e24a9df7Sskrll 	uint8_t		tcb_flags;
98*e24a9df7Sskrll #define ANS_NVMMU_TCB_WRITE		__BIT(0)
99*e24a9df7Sskrll #define ANS_NVMMU_TCB_READ		__BIT(1)
100*e24a9df7Sskrll 	uint8_t		tcb_cid;
101*e24a9df7Sskrll 	uint8_t		tcb_pad0[1];
102*e24a9df7Sskrll 
103*e24a9df7Sskrll 	uint32_t	tcb_prpl_len;
104*e24a9df7Sskrll 	uint8_t		tcb_pad1[16];
105*e24a9df7Sskrll 
106*e24a9df7Sskrll 	uint64_t	tcb_prp[2];
107*e24a9df7Sskrll };
108*e24a9df7Sskrll 
109*e24a9df7Sskrll void	nvme_ans_enable(struct nvme_softc *);
110*e24a9df7Sskrll 
111*e24a9df7Sskrll int	nvme_ans_q_alloc(struct nvme_softc *, struct nvme_queue *);
112*e24a9df7Sskrll void	nvme_ans_q_free(struct nvme_softc *, struct nvme_queue *);
113*e24a9df7Sskrll 
114*e24a9df7Sskrll uint32_t
115*e24a9df7Sskrll 	nvme_ans_sq_enter(struct nvme_softc *, struct nvme_queue *,
116*e24a9df7Sskrll 			  struct nvme_ccb *);
117*e24a9df7Sskrll void	nvme_ans_sq_leave(struct nvme_softc *,
118*e24a9df7Sskrll 			  struct nvme_queue *, struct nvme_ccb *);
119*e24a9df7Sskrll 
120*e24a9df7Sskrll void	nvme_ans_cq_done(struct nvme_softc *,
121*e24a9df7Sskrll 			 struct nvme_queue *, struct nvme_ccb *);
122*e24a9df7Sskrll 
123*e24a9df7Sskrll static const struct nvme_ops nvme_ans_ops = {
124*e24a9df7Sskrll 	.op_enable		= nvme_ans_enable,
125*e24a9df7Sskrll 
126*e24a9df7Sskrll 	.op_q_alloc		= nvme_ans_q_alloc,
127*e24a9df7Sskrll 	.op_q_free		= nvme_ans_q_free,
128*e24a9df7Sskrll 
129*e24a9df7Sskrll 	.op_sq_enter		= nvme_ans_sq_enter,
130*e24a9df7Sskrll 	.op_sq_leave		= nvme_ans_sq_leave,
131*e24a9df7Sskrll 	.op_sq_enter_locked	= nvme_ans_sq_enter,
132*e24a9df7Sskrll 	.op_sq_leave_locked	= nvme_ans_sq_leave,
133*e24a9df7Sskrll 
134*e24a9df7Sskrll 	.op_cq_done		= nvme_ans_cq_done,
135*e24a9df7Sskrll };
136*e24a9df7Sskrll 
137*e24a9df7Sskrll static const struct device_compatible_entry compat_data[] = {
138*e24a9df7Sskrll 	{ .compat = "apple,nvme-m1" },
139*e24a9df7Sskrll 	{ .compat = "apple,nvme-ans2" },
140*e24a9df7Sskrll 	DEVICE_COMPAT_EOL
141*e24a9df7Sskrll };
142*e24a9df7Sskrll 
143*e24a9df7Sskrll struct apple_nvme_softc {
144*e24a9df7Sskrll 	struct nvme_softc asc_nvme;
145*e24a9df7Sskrll 	int asc_phandle;
146*e24a9df7Sskrll 
147*e24a9df7Sskrll 	bus_space_tag_t	asc_iot;
148*e24a9df7Sskrll 	bus_space_handle_t asc_ioh;
149*e24a9df7Sskrll 	bus_size_t asc_size;
150*e24a9df7Sskrll 
151*e24a9df7Sskrll 	struct rtkit_state *asc_rtkit;
152*e24a9df7Sskrll 
153*e24a9df7Sskrll 	size_t asc_nintrs;
154*e24a9df7Sskrll 	void *asc_ihs;
155*e24a9df7Sskrll };
156*e24a9df7Sskrll 
157*e24a9df7Sskrll void
nvme_ans_enable(struct nvme_softc * sc)158*e24a9df7Sskrll nvme_ans_enable(struct nvme_softc *sc)
159*e24a9df7Sskrll {
160*e24a9df7Sskrll 	nvme_write4(sc, ANS_NVMMU_NUM,
161*e24a9df7Sskrll 	    (ANS_NVMMU_TCB_SIZE / ANS_NVMMU_TCB_PITCH) - 1);
162*e24a9df7Sskrll 	nvme_write4(sc, ANS_MODESEL_REG, 0);
163*e24a9df7Sskrll }
164*e24a9df7Sskrll 
165*e24a9df7Sskrll 
166*e24a9df7Sskrll int
nvme_ans_q_alloc(struct nvme_softc * sc,struct nvme_queue * q)167*e24a9df7Sskrll nvme_ans_q_alloc(struct nvme_softc *sc, struct nvme_queue *q)
168*e24a9df7Sskrll {
169*e24a9df7Sskrll 	bus_size_t db, base;
170*e24a9df7Sskrll 
171*e24a9df7Sskrll 	KASSERT(q->q_entries <= (ANS_NVMMU_TCB_SIZE / ANS_NVMMU_TCB_PITCH));
172*e24a9df7Sskrll 
173*e24a9df7Sskrll 	q->q_nvmmu_dmamem = nvme_dmamem_alloc(sc, ANS_NVMMU_TCB_SIZE);
174*e24a9df7Sskrll 	if (q->q_nvmmu_dmamem == NULL)
175*e24a9df7Sskrll 		return -1;
176*e24a9df7Sskrll 
177*e24a9df7Sskrll 	memset(NVME_DMA_KVA(q->q_nvmmu_dmamem), 0,
178*e24a9df7Sskrll 	    NVME_DMA_LEN(q->q_nvmmu_dmamem));
179*e24a9df7Sskrll 
180*e24a9df7Sskrll 	switch (q->q_id) {
181*e24a9df7Sskrll 	case NVME_IO_Q:
182*e24a9df7Sskrll 		db = ANS_LINEAR_IOSQ_DB;
183*e24a9df7Sskrll 		base = ANS_NVMMU_BASE_IOSQ;
184*e24a9df7Sskrll 		break;
185*e24a9df7Sskrll 	case NVME_ADMIN_Q:
186*e24a9df7Sskrll 		db = ANS_LINEAR_ASQ_DB;
187*e24a9df7Sskrll 		base = ANS_NVMMU_BASE_ASQ;
188*e24a9df7Sskrll 		break;
189*e24a9df7Sskrll 	default:
190*e24a9df7Sskrll 		panic("unsupported queue id %u", q->q_id);
191*e24a9df7Sskrll 		/* NOTREACHED */
192*e24a9df7Sskrll 	}
193*e24a9df7Sskrll 
194*e24a9df7Sskrll 	q->q_sqtdbl = db;
195*e24a9df7Sskrll 
196*e24a9df7Sskrll 	nvme_dmamem_sync(sc, q->q_nvmmu_dmamem, BUS_DMASYNC_PREWRITE);
197*e24a9df7Sskrll 	nvme_write8(sc, base, NVME_DMA_DVA(q->q_nvmmu_dmamem));
198*e24a9df7Sskrll 
199*e24a9df7Sskrll 	return 0;
200*e24a9df7Sskrll }
201*e24a9df7Sskrll 
202*e24a9df7Sskrll void
nvme_ans_q_free(struct nvme_softc * sc,struct nvme_queue * q)203*e24a9df7Sskrll nvme_ans_q_free(struct nvme_softc *sc,
204*e24a9df7Sskrll     struct nvme_queue *q)
205*e24a9df7Sskrll {
206*e24a9df7Sskrll 	nvme_dmamem_sync(sc, q->q_nvmmu_dmamem, BUS_DMASYNC_POSTWRITE);
207*e24a9df7Sskrll 	nvme_dmamem_free(sc, q->q_nvmmu_dmamem);
208*e24a9df7Sskrll }
209*e24a9df7Sskrll 
210*e24a9df7Sskrll uint32_t
nvme_ans_sq_enter(struct nvme_softc * sc,struct nvme_queue * q,struct nvme_ccb * ccb)211*e24a9df7Sskrll nvme_ans_sq_enter(struct nvme_softc *sc,
212*e24a9df7Sskrll     struct nvme_queue *q, struct nvme_ccb *ccb)
213*e24a9df7Sskrll {
214*e24a9df7Sskrll 	return ccb->ccb_id;
215*e24a9df7Sskrll }
216*e24a9df7Sskrll 
217*e24a9df7Sskrll static inline struct ans_nvmmu_tcb *
nvme_ans_tcb(struct nvme_queue * q,unsigned int qid)218*e24a9df7Sskrll nvme_ans_tcb(struct nvme_queue *q, unsigned int qid)
219*e24a9df7Sskrll {
220*e24a9df7Sskrll 	uint8_t *ptr = NVME_DMA_KVA(q->q_nvmmu_dmamem);
221*e24a9df7Sskrll 	ptr += qid * ANS_NVMMU_TCB_PITCH;
222*e24a9df7Sskrll 
223*e24a9df7Sskrll 	return (struct ans_nvmmu_tcb *)ptr;
224*e24a9df7Sskrll }
225*e24a9df7Sskrll 
226*e24a9df7Sskrll void
nvme_ans_sq_leave(struct nvme_softc * sc,struct nvme_queue * q,struct nvme_ccb * ccb)227*e24a9df7Sskrll nvme_ans_sq_leave(struct nvme_softc *sc,
228*e24a9df7Sskrll     struct nvme_queue *q, struct nvme_ccb *ccb)
229*e24a9df7Sskrll {
230*e24a9df7Sskrll 	unsigned int id = ccb->ccb_id;
231*e24a9df7Sskrll 	struct ans_nvmmu_tcb *tcb = nvme_ans_tcb(q, id);
232*e24a9df7Sskrll 	struct nvme_sqe_io *sqe = NVME_DMA_KVA(q->q_sq_dmamem);
233*e24a9df7Sskrll 	sqe += id;
234*e24a9df7Sskrll 
235*e24a9df7Sskrll 	bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(q->q_nvmmu_dmamem),
236*e24a9df7Sskrll 	    ANS_NVMMU_TCB_PITCH * id, sizeof(*tcb), BUS_DMASYNC_POSTWRITE);
237*e24a9df7Sskrll 
238*e24a9df7Sskrll 	memset(tcb, 0, sizeof(*tcb));
239*e24a9df7Sskrll 	tcb->tcb_opcode = sqe->opcode;
240*e24a9df7Sskrll 	tcb->tcb_flags = ANS_NVMMU_TCB_WRITE | ANS_NVMMU_TCB_READ;
241*e24a9df7Sskrll 	tcb->tcb_cid = id;
242*e24a9df7Sskrll 	tcb->tcb_prpl_len = sqe->nlb;
243*e24a9df7Sskrll 	tcb->tcb_prp[0] = sqe->entry.prp[0];
244*e24a9df7Sskrll 	tcb->tcb_prp[1] = sqe->entry.prp[1];
245*e24a9df7Sskrll 
246*e24a9df7Sskrll 	bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(q->q_nvmmu_dmamem),
247*e24a9df7Sskrll 	    ANS_NVMMU_TCB_PITCH * id, sizeof(*tcb), BUS_DMASYNC_PREWRITE);
248*e24a9df7Sskrll 	nvme_write4(sc, q->q_sqtdbl, id);
249*e24a9df7Sskrll }
250*e24a9df7Sskrll 
251*e24a9df7Sskrll void
nvme_ans_cq_done(struct nvme_softc * sc,struct nvme_queue * q,struct nvme_ccb * ccb)252*e24a9df7Sskrll nvme_ans_cq_done(struct nvme_softc *sc,
253*e24a9df7Sskrll     struct nvme_queue *q, struct nvme_ccb *ccb)
254*e24a9df7Sskrll {
255*e24a9df7Sskrll 	unsigned int id = ccb->ccb_id;
256*e24a9df7Sskrll 	struct ans_nvmmu_tcb *tcb = nvme_ans_tcb(q, id);
257*e24a9df7Sskrll 
258*e24a9df7Sskrll 	bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(q->q_nvmmu_dmamem),
259*e24a9df7Sskrll 	    ANS_NVMMU_TCB_PITCH * id, sizeof(*tcb), BUS_DMASYNC_POSTWRITE);
260*e24a9df7Sskrll 	memset(tcb, 0, sizeof(*tcb));
261*e24a9df7Sskrll 	bus_dmamap_sync(sc->sc_dmat, NVME_DMA_MAP(q->q_nvmmu_dmamem),
262*e24a9df7Sskrll 	    ANS_NVMMU_TCB_PITCH * id, sizeof(*tcb), BUS_DMASYNC_PREWRITE);
263*e24a9df7Sskrll 
264*e24a9df7Sskrll 	nvme_write4(sc, ANS_NVMMU_TCB_INVAL, id);
265*e24a9df7Sskrll 	uint32_t stat = nvme_read4(sc, ANS_NVMMU_TCB_STAT);
266*e24a9df7Sskrll 	if (stat != 0) {
267*e24a9df7Sskrll 		printf("%s: nvmmu tcp stat is non-zero: 0x%08x\n",
268*e24a9df7Sskrll 		    device_xname(sc->sc_dev), stat);
269*e24a9df7Sskrll 	}
270*e24a9df7Sskrll }
271*e24a9df7Sskrll 
272*e24a9df7Sskrll 
273*e24a9df7Sskrll static int
apple_nvme_intr_establish(struct nvme_softc * sc,uint16_t qid,struct nvme_queue * q)274*e24a9df7Sskrll apple_nvme_intr_establish(struct nvme_softc *sc, uint16_t qid,
275*e24a9df7Sskrll     struct nvme_queue *q)
276*e24a9df7Sskrll {
277*e24a9df7Sskrll 	struct apple_nvme_softc * const asc =
278*e24a9df7Sskrll 	    container_of(sc, struct apple_nvme_softc, asc_nvme);
279*e24a9df7Sskrll 	const int phandle = asc->asc_phandle;
280*e24a9df7Sskrll 	char intr_xname[INTRDEVNAMEBUF];
281*e24a9df7Sskrll 	char intrstr[128];
282*e24a9df7Sskrll 	const device_t self = sc->sc_dev;
283*e24a9df7Sskrll 
284*e24a9df7Sskrll 	KASSERT(sc->sc_use_mq || qid == NVME_ADMIN_Q);
285*e24a9df7Sskrll 	KASSERT(sc->sc_ih[qid] == NULL);
286*e24a9df7Sskrll 
287*e24a9df7Sskrll 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
288*e24a9df7Sskrll 		aprint_error(": couldn't decode interrupt\n");
289*e24a9df7Sskrll 		return 1;
290*e24a9df7Sskrll 	}
291*e24a9df7Sskrll 	sc->sc_ih[qid] = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO,
292*e24a9df7Sskrll 	    FDT_INTR_MPSAFE, nvme_intr, sc, device_xname(sc->sc_dev));
293*e24a9df7Sskrll 	if (sc->sc_ih[qid] == NULL) {
294*e24a9df7Sskrll 		aprint_error_dev(self, "couldn't establish interrupt on %s\n",
295*e24a9df7Sskrll 		    intrstr);
296*e24a9df7Sskrll 		return 1;
297*e24a9df7Sskrll 	}
298*e24a9df7Sskrll 
299*e24a9df7Sskrll 	/* establish also the software interrupt */
300*e24a9df7Sskrll 	sc->sc_softih[qid] = softint_establish(
301*e24a9df7Sskrll 	    SOFTINT_BIO|(apple_nvme_mpsafe ? SOFTINT_MPSAFE : 0),
302*e24a9df7Sskrll 	    nvme_softintr_intx, q);
303*e24a9df7Sskrll 	if (sc->sc_softih[qid] == NULL) {
304*e24a9df7Sskrll 		fdtbus_intr_disestablish(phandle, sc->sc_ih[qid]);
305*e24a9df7Sskrll 		sc->sc_ih[qid] = NULL;
306*e24a9df7Sskrll 
307*e24a9df7Sskrll 		aprint_error_dev(sc->sc_dev,
308*e24a9df7Sskrll 		    "unable to establish %s soft interrupt\n",
309*e24a9df7Sskrll 		    intr_xname);
310*e24a9df7Sskrll 		return 1;
311*e24a9df7Sskrll 	}
312*e24a9df7Sskrll 
313*e24a9df7Sskrll 	if (!sc->sc_use_mq) {
314*e24a9df7Sskrll 		aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr);
315*e24a9df7Sskrll 	} else if (qid == NVME_ADMIN_Q) {
316*e24a9df7Sskrll 		aprint_normal_dev(sc->sc_dev,
317*e24a9df7Sskrll 		    "for admin queue interrupting on %s\n", intrstr);
318*e24a9df7Sskrll 	} else {
319*e24a9df7Sskrll 		aprint_normal_dev(sc->sc_dev,
320*e24a9df7Sskrll 		    "for io queue %d interrupting on %s\n", qid, intrstr);
321*e24a9df7Sskrll 	}
322*e24a9df7Sskrll 	return 0;
323*e24a9df7Sskrll }
324*e24a9df7Sskrll 
325*e24a9df7Sskrll static int
apple_nvme_intr_disestablish(struct nvme_softc * sc,uint16_t qid)326*e24a9df7Sskrll apple_nvme_intr_disestablish(struct nvme_softc *sc, uint16_t qid)
327*e24a9df7Sskrll {
328*e24a9df7Sskrll 	struct apple_nvme_softc * const asc =
329*e24a9df7Sskrll 	   container_of(sc, struct apple_nvme_softc, asc_nvme);
330*e24a9df7Sskrll 
331*e24a9df7Sskrll 	KASSERT(sc->sc_use_mq || qid == NVME_ADMIN_Q);
332*e24a9df7Sskrll 	KASSERT(sc->sc_ih[qid] != NULL);
333*e24a9df7Sskrll 
334*e24a9df7Sskrll 	if (sc->sc_softih) {
335*e24a9df7Sskrll 		softint_disestablish(sc->sc_softih[qid]);
336*e24a9df7Sskrll 		sc->sc_softih[qid] = NULL;
337*e24a9df7Sskrll 	}
338*e24a9df7Sskrll 
339*e24a9df7Sskrll 	fdtbus_intr_disestablish(asc->asc_phandle, sc->sc_ih[qid]);
340*e24a9df7Sskrll 	sc->sc_ih[qid] = NULL;
341*e24a9df7Sskrll 
342*e24a9df7Sskrll 	return 0;
343*e24a9df7Sskrll }
344*e24a9df7Sskrll 
345*e24a9df7Sskrll 
346*e24a9df7Sskrll static int
apple_nvme_setup_intr(struct fdt_attach_args * const faa,struct apple_nvme_softc * const asc)347*e24a9df7Sskrll apple_nvme_setup_intr(struct fdt_attach_args * const faa,
348*e24a9df7Sskrll     struct apple_nvme_softc * const asc)
349*e24a9df7Sskrll {
350*e24a9df7Sskrll 	struct nvme_softc * const sc = &asc->asc_nvme;
351*e24a9df7Sskrll 
352*e24a9df7Sskrll 	asc->asc_nintrs = 1;
353*e24a9df7Sskrll 	asc->asc_phandle = faa->faa_phandle;
354*e24a9df7Sskrll 
355*e24a9df7Sskrll 	sc->sc_use_mq = asc->asc_nintrs > 1;
356*e24a9df7Sskrll 	sc->sc_nq = 1;	/* sc_use_mq */
357*e24a9df7Sskrll 
358*e24a9df7Sskrll 	return 0;
359*e24a9df7Sskrll }
360*e24a9df7Sskrll 
361*e24a9df7Sskrll 
362*e24a9df7Sskrll static int
apple_nvme_match(device_t parent,cfdata_t cf,void * aux)363*e24a9df7Sskrll apple_nvme_match(device_t parent, cfdata_t cf, void *aux)
364*e24a9df7Sskrll {
365*e24a9df7Sskrll 	struct fdt_attach_args * const faa = aux;
366*e24a9df7Sskrll 
367*e24a9df7Sskrll 	return of_compatible_match(faa->faa_phandle, compat_data);
368*e24a9df7Sskrll }
369*e24a9df7Sskrll 
370*e24a9df7Sskrll static void
apple_nvme_attach(device_t parent,device_t self,void * aux)371*e24a9df7Sskrll apple_nvme_attach(device_t parent, device_t self, void *aux)
372*e24a9df7Sskrll {
373*e24a9df7Sskrll 	struct apple_nvme_softc * const asc = device_private(self);
374*e24a9df7Sskrll 	struct nvme_softc *sc = &asc->asc_nvme;
375*e24a9df7Sskrll 	struct fdt_attach_args * const faa = aux;
376*e24a9df7Sskrll 	const int phandle = faa->faa_phandle;
377*e24a9df7Sskrll 	bus_addr_t addr, ans_addr;
378*e24a9df7Sskrll 	bus_size_t size, ans_size;
379*e24a9df7Sskrll 	uint32_t ctrl, status;
380*e24a9df7Sskrll 
381*e24a9df7Sskrll 
382*e24a9df7Sskrll 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
383*e24a9df7Sskrll 		aprint_error(": couldn't get NVME registers\n");
384*e24a9df7Sskrll 		return;
385*e24a9df7Sskrll 	}
386*e24a9df7Sskrll 
387*e24a9df7Sskrll 	if (fdtbus_get_reg(phandle, 1, &ans_addr, &ans_size) != 0) {
388*e24a9df7Sskrll 		aprint_error(": couldn't get ANS registers\n");
389*e24a9df7Sskrll 		return;
390*e24a9df7Sskrll 	}
391*e24a9df7Sskrll 
392*e24a9df7Sskrll 	sc->sc_dev = self;
393*e24a9df7Sskrll 	sc->sc_iot = asc->asc_iot = faa->faa_bst;
394*e24a9df7Sskrll 	sc->sc_ios = size;
395*e24a9df7Sskrll 
396*e24a9df7Sskrll 	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) {
397*e24a9df7Sskrll 		aprint_error(": couldn't map NVME registers\n");
398*e24a9df7Sskrll 		return;
399*e24a9df7Sskrll 	}
400*e24a9df7Sskrll 
401*e24a9df7Sskrll 	if (bus_space_map(asc->asc_iot, ans_addr, ans_size, 0, &asc->asc_ioh) != 0) {
402*e24a9df7Sskrll 		aprint_error(": couldn't map ANS registers\n");
403*e24a9df7Sskrll 		goto fail_ansmap;
404*e24a9df7Sskrll 	}
405*e24a9df7Sskrll 
406*e24a9df7Sskrll 	sc->sc_dmat = faa->faa_dmat;
407*e24a9df7Sskrll 	sc->sc_ops = &nvme_ans_ops;
408*e24a9df7Sskrll 	aprint_naive("\n");
409*e24a9df7Sskrll 	aprint_normal(": Apple NVME\n");
410*e24a9df7Sskrll 
411*e24a9df7Sskrll 	apple_nvme_setup_intr(faa, asc);
412*e24a9df7Sskrll 
413*e24a9df7Sskrll 	sc->sc_intr_establish = apple_nvme_intr_establish;
414*e24a9df7Sskrll 	sc->sc_intr_disestablish = apple_nvme_intr_disestablish;
415*e24a9df7Sskrll 
416*e24a9df7Sskrll 	sc->sc_ih = kmem_zalloc(sizeof(*sc->sc_ih) * asc->asc_nintrs, KM_SLEEP);
417*e24a9df7Sskrll 	sc->sc_softih = kmem_zalloc(sizeof(*sc->sc_softih) * asc->asc_nintrs,
418*e24a9df7Sskrll 	    KM_SLEEP);
419*e24a9df7Sskrll 
420*e24a9df7Sskrll 	asc->asc_rtkit = rtkit_init(phandle, NULL);
421*e24a9df7Sskrll 	if (asc->asc_rtkit == NULL) {
422*e24a9df7Sskrll 		aprint_error("can't map mailbox channel\n");
423*e24a9df7Sskrll 		goto fail_rtkit;
424*e24a9df7Sskrll 	}
425*e24a9df7Sskrll 
426*e24a9df7Sskrll 	ctrl = bus_space_read_4(asc->asc_iot, asc->asc_ioh, ANS_CPU_CTRL);
427*e24a9df7Sskrll 	bus_space_write_4(asc->asc_iot, asc->asc_ioh, ANS_CPU_CTRL,
428*e24a9df7Sskrll 	    ctrl | ANS_CPU_CTRL_RUN);
429*e24a9df7Sskrll 
430*e24a9df7Sskrll 	status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ANS_BOOT_STATUS);
431*e24a9df7Sskrll 	if (status != ANS_BOOT_STATUS_OK)
432*e24a9df7Sskrll 		rtkit_boot(asc->asc_rtkit);
433*e24a9df7Sskrll 
434*e24a9df7Sskrll 	status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ANS_BOOT_STATUS);
435*e24a9df7Sskrll 	if (status != ANS_BOOT_STATUS_OK) {
436*e24a9df7Sskrll 		aprint_error("firmware not ready\n");
437*e24a9df7Sskrll 		goto fail_ansnotready;
438*e24a9df7Sskrll 	}
439*e24a9df7Sskrll 
440*e24a9df7Sskrll 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ANS_LINEAR_SQ_CTRL,
441*e24a9df7Sskrll 	    ANS_LINEAR_SQ_CTRL_EN);
442*e24a9df7Sskrll 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ANS_MAX_PEND_CMDS_CTRL,
443*e24a9df7Sskrll 	    (ANS_MAX_QUEUE_DEPTH << 16) | ANS_MAX_QUEUE_DEPTH);
444*e24a9df7Sskrll 
445*e24a9df7Sskrll 	ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ANS_UNKNOWN_CTRL);
446*e24a9df7Sskrll 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ANS_UNKNOWN_CTRL,
447*e24a9df7Sskrll 	    ctrl & ~ANS_PRP_NULL_CHECK);
448*e24a9df7Sskrll 
449*e24a9df7Sskrll 	if (nvme_attach(sc) != 0) {
450*e24a9df7Sskrll 		/* error printed by nvme_attach() */
451*e24a9df7Sskrll 		return;
452*e24a9df7Sskrll 	}
453*e24a9df7Sskrll 
454*e24a9df7Sskrll 	SET(sc->sc_flags, NVME_F_ATTACHED);
455*e24a9df7Sskrll 	return;
456*e24a9df7Sskrll fail_ansnotready:
457*e24a9df7Sskrll 
458*e24a9df7Sskrll fail_rtkit:
459*e24a9df7Sskrll 
460*e24a9df7Sskrll fail_ansmap:
461*e24a9df7Sskrll 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
462*e24a9df7Sskrll }
463*e24a9df7Sskrll 
464*e24a9df7Sskrll CFATTACH_DECL_NEW(apple_nvme, sizeof(struct apple_nvme_softc),
465*e24a9df7Sskrll 	apple_nvme_match, apple_nvme_attach, NULL, NULL);
466