xref: /openbsd/sys/dev/fdt/sximmc.c (revision 0ea1c705)
1 /* $OpenBSD: sximmc.c,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
2 /* $NetBSD: awin_mmc.c,v 1.23 2015/11/14 10:32:40 bouyer Exp $ */
3 
4 /*-
5  * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/device.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 
36 #include <machine/intr.h>
37 #include <machine/bus.h>
38 #include <machine/fdt.h>
39 
40 #include <dev/sdmmc/sdmmcvar.h>
41 #include <dev/sdmmc/sdmmcchip.h>
42 #include <dev/sdmmc/sdmmc_ioreg.h>
43 
44 #include <dev/ofw/openfirm.h>
45 #include <dev/ofw/ofw_clock.h>
46 #include <dev/ofw/ofw_gpio.h>
47 #include <dev/ofw/ofw_pinctrl.h>
48 #include <dev/ofw/ofw_regulator.h>
49 #include <dev/ofw/fdt.h>
50 
51 //#define SXIMMC_DEBUG
52 
53 #define SXIMMC_GCTRL			0x0000
54 #define SXIMMC_CLKCR			0x0004
55 #define SXIMMC_TIMEOUT			0x0008
56 #define SXIMMC_WIDTH			0x000C
57 #define SXIMMC_BLKSZ			0x0010
58 #define SXIMMC_BYTECNT			0x0014
59 #define SXIMMC_CMD			0x0018
60 #define SXIMMC_ARG			0x001C
61 #define SXIMMC_RESP0			0x0020
62 #define SXIMMC_RESP1			0x0024
63 #define SXIMMC_RESP2			0x0028
64 #define SXIMMC_RESP3			0x002C
65 #define SXIMMC_IMASK			0x0030
66 #define SXIMMC_MINT			0x0034
67 #define SXIMMC_RINT			0x0038
68 #define SXIMMC_STATUS			0x003C
69 #define SXIMMC_FTRGLEVEL		0x0040
70 #define SXIMMC_FUNCSEL			0x0044
71 #define SXIMMC_CBCR			0x0048
72 #define SXIMMC_BBCR			0x004C
73 #define SXIMMC_DBGC			0x0050
74 #define SXIMMC_A12A			0x0058		/* A80 */
75 #define SXIMMC_HWRST			0x0078		/* A80 */
76 #define SXIMMC_DMAC			0x0080
77 #define SXIMMC_DLBA			0x0084
78 #define SXIMMC_IDST			0x0088
79 #define SXIMMC_IDIE			0x008C
80 #define SXIMMC_CHDA			0x0090
81 #define SXIMMC_CBDA			0x0094
82 #define SXIMMC_FIFO_A10			0x0100
83 #define SXIMMC_FIFO_A31			0x0200
84 
85 #define SXIMMC_GCTRL_ACCESS_BY_AHB	(1U << 31)
86 #define SXIMMC_GCTRL_WAIT_MEM_ACCESS_DONE (1U << 30)
87 #define SXIMMC_GCTRL_DDR_MODE		(1U << 10)
88 #define SXIMMC_GCTRL_DEBOUNCEEN		(1U << 8)
89 #define SXIMMC_GCTRL_DMAEN		(1U << 5)
90 #define SXIMMC_GCTRL_INTEN		(1U << 4)
91 #define SXIMMC_GCTRL_DMARESET		(1U << 2)
92 #define SXIMMC_GCTRL_FIFORESET		(1U << 1)
93 #define SXIMMC_GCTRL_SOFTRESET		(1U << 0)
94 #define SXIMMC_GCTRL_RESET \
95 	(SXIMMC_GCTRL_SOFTRESET | SXIMMC_GCTRL_FIFORESET | \
96 	 SXIMMC_GCTRL_DMARESET)
97 
98 #define SXIMMC_CLKCR_LOWPOWERON		(1U << 17)
99 #define SXIMMC_CLKCR_CARDCLKON		(1U << 16)
100 #define SXIMMC_CLKCR_DIV		0x0000ffff
101 
102 #define SXIMMC_WIDTH_1			0
103 #define SXIMMC_WIDTH_4			1
104 #define SXIMMC_WIDTH_8			2
105 
106 #define SXIMMC_CMD_START		(1U << 31)
107 #define SXIMMC_CMD_USE_HOLD_REG		(1U << 29)
108 #define SXIMMC_CMD_VOL_SWITCH		(1U << 28)
109 #define SXIMMC_CMD_BOOT_ABORT		(1U << 27)
110 #define SXIMMC_CMD_BOOT_ACK_EXP		(1U << 26)
111 #define SXIMMC_CMD_ALT_BOOT_OPT		(1U << 25)
112 #define SXIMMC_CMD_ENBOOT		(1U << 24)
113 #define SXIMMC_CMD_CCS_EXP		(1U << 23)
114 #define SXIMMC_CMD_RD_CEATA_DEV		(1U << 22)
115 #define SXIMMC_CMD_UPCLK_ONLY		(1U << 21)
116 #define SXIMMC_CMD_SEND_INIT_SEQ	(1U << 15)
117 #define SXIMMC_CMD_STOP_ABORT_CMD	(1U << 14)
118 #define SXIMMC_CMD_WAIT_PRE_OVER	(1U << 13)
119 #define SXIMMC_CMD_SEND_AUTO_STOP	(1U << 12)
120 #define SXIMMC_CMD_SEQMOD		(1U << 11)
121 #define SXIMMC_CMD_WRITE		(1U << 10)
122 #define SXIMMC_CMD_DATA_EXP		(1U << 9)
123 #define SXIMMC_CMD_CHECK_RSP_CRC	(1U << 8)
124 #define SXIMMC_CMD_LONG_RSP		(1U << 7)
125 #define SXIMMC_CMD_RSP_EXP		(1U << 6)
126 
127 #define SXIMMC_INT_CARD_REMOVE		(1U << 31)
128 #define SXIMMC_INT_CARD_INSERT		(1U << 30)
129 #define SXIMMC_INT_SDIO_INT		(1U << 16)
130 #define SXIMMC_INT_END_BIT_ERR		(1U << 15)
131 #define SXIMMC_INT_AUTO_CMD_DONE	(1U << 14)
132 #define SXIMMC_INT_START_BIT_ERR	(1U << 13)
133 #define SXIMMC_INT_HW_LOCKED		(1U << 12)
134 #define SXIMMC_INT_FIFO_RUN_ERR		(1U << 11)
135 #define SXIMMC_INT_VOL_CHG_DONE		(1U << 10)
136 #define SXIMMC_INT_DATA_STARVE		(1U << 10)
137 #define SXIMMC_INT_BOOT_START		(1U << 9)
138 #define SXIMMC_INT_DATA_TIMEOUT		(1U << 9)
139 #define SXIMMC_INT_ACK_RCV		(1U << 8)
140 #define SXIMMC_INT_RESP_TIMEOUT		(1U << 8)
141 #define SXIMMC_INT_DATA_CRC_ERR		(1U << 7)
142 #define SXIMMC_INT_RESP_CRC_ERR		(1U << 6)
143 #define SXIMMC_INT_RX_DATA_REQ		(1U << 5)
144 #define SXIMMC_INT_TX_DATA_REQ		(1U << 4)
145 #define SXIMMC_INT_DATA_OVER		(1U << 3)
146 #define SXIMMC_INT_CMD_DONE		(1U << 2)
147 #define SXIMMC_INT_RESP_ERR		(1U << 1)
148 #define SXIMMC_INT_ERROR \
149 	(SXIMMC_INT_RESP_ERR | SXIMMC_INT_RESP_CRC_ERR | \
150 	 SXIMMC_INT_DATA_CRC_ERR | SXIMMC_INT_RESP_TIMEOUT | \
151 	 SXIMMC_INT_FIFO_RUN_ERR | SXIMMC_INT_HW_LOCKED | \
152 	 SXIMMC_INT_START_BIT_ERR  | SXIMMC_INT_END_BIT_ERR)
153 
154 #define SXIMMC_STATUS_DMAREQ		(1U << 31)
155 #define SXIMMC_STATUS_DATA_FSM_BUSY	(1U << 10)
156 #define SXIMMC_STATUS_CARD_DATA_BUSY	(1U << 9)
157 #define SXIMMC_STATUS_CARD_PRESENT	(1U << 8)
158 #define SXIMMC_STATUS_FIFO_FULL		(1U << 3)
159 #define SXIMMC_STATUS_FIFO_EMPTY	(1U << 2)
160 #define SXIMMC_STATUS_TXWL_FLAG		(1U << 1)
161 #define SXIMMC_STATUS_RXWL_FLAG		(1U << 0)
162 
163 #define SXIMMC_FUNCSEL_CEATA_DEV_INTEN (1U << 10)
164 #define SXIMMC_FUNCSEL_SEND_AUTO_STOP_CCSD (1U << 9)
165 #define SXIMMC_FUNCSEL_SEND_CCSD	(1U << 8)
166 #define SXIMMC_FUNCSEL_ABT_RD_DATA	(1U << 2)
167 #define SXIMMC_FUNCSEL_SDIO_RD_WAIT	(1U << 1)
168 #define SXIMMC_FUNCSEL_SEND_IRQ_RSP	(1U << 0)
169 
170 #define SXIMMC_DMAC_REFETCH_DES		(1U << 31)
171 #define SXIMMC_DMAC_IDMA_ON		(1U << 7)
172 #define SXIMMC_DMAC_FIX_BURST		(1U << 1)
173 #define SXIMMC_DMAC_SOFTRESET		(1U << 0)
174 
175 #define SXIMMC_IDST_HOST_ABT		(1U << 10)
176 #define SXIMMC_IDST_ABNORMAL_INT_SUM	(1U << 9)
177 #define SXIMMC_IDST_NORMAL_INT_SUM	(1U << 8)
178 #define SXIMMC_IDST_CARD_ERR_SUM	(1U << 5)
179 #define SXIMMC_IDST_DES_INVALID		(1U << 4)
180 #define SXIMMC_IDST_FATAL_BUS_ERR	(1U << 2)
181 #define SXIMMC_IDST_RECEIVE_INT		(1U << 1)
182 #define SXIMMC_IDST_TRANSMIT_INT	(1U << 0)
183 #define SXIMMC_IDST_ERROR \
184 	(SXIMMC_IDST_ABNORMAL_INT_SUM | SXIMMC_IDST_CARD_ERR_SUM | \
185 	 SXIMMC_IDST_DES_INVALID | SXIMMC_IDST_FATAL_BUS_ERR)
186 #define SXIMMC_IDST_COMPLETE \
187 	(SXIMMC_IDST_RECEIVE_INT | SXIMMC_IDST_TRANSMIT_INT)
188 
189 struct sximmc_idma_descriptor {
190 	uint32_t	dma_config;
191 #define SXIMMC_IDMA_CONFIG_DIC	(1U << 1)
192 #define SXIMMC_IDMA_CONFIG_LD	(1U << 2)
193 #define SXIMMC_IDMA_CONFIG_FD	(1U << 3)
194 #define SXIMMC_IDMA_CONFIG_CH	(1U << 4)
195 #define SXIMMC_IDMA_CONFIG_ER	(1U << 5)
196 #define SXIMMC_IDMA_CONFIG_CES	(1U << 30)
197 #define SXIMMC_IDMA_CONFIG_OWN	(1U << 31)
198 	uint32_t	dma_buf_size;
199 	uint32_t	dma_buf_addr;
200 	uint32_t	dma_next;
201 } __packed;
202 
203 #define SXIMMC_NDESC		32
204 
205 #define SXIMMC_DMA_FTRGLEVEL_A20	0x20070008
206 #define SXIMMC_DMA_FTRGLEVEL_A80	0x200f0010
207 
208 int	sximmc_match(struct device *, void *, void *);
209 void	sximmc_attach(struct device *, struct device *, void *);
210 
211 int	sximmc_intr(void *);
212 
213 int	sximmc_host_reset(sdmmc_chipset_handle_t);
214 uint32_t sximmc_host_ocr(sdmmc_chipset_handle_t);
215 int	sximmc_host_maxblklen(sdmmc_chipset_handle_t);
216 int	sximmc_card_detect(sdmmc_chipset_handle_t);
217 int	sximmc_write_protect(sdmmc_chipset_handle_t);
218 int	sximmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
219 int	sximmc_bus_clock(sdmmc_chipset_handle_t, int, int);
220 int	sximmc_bus_width(sdmmc_chipset_handle_t, int);
221 void	sximmc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
222 
223 void	sximmc_pwrseq_pre(uint32_t);
224 void	sximmc_pwrseq_post(uint32_t);
225 
226 struct sdmmc_chip_functions sximmc_chip_functions = {
227 	.host_reset = sximmc_host_reset,
228 	.host_ocr = sximmc_host_ocr,
229 	.host_maxblklen = sximmc_host_maxblklen,
230 	.card_detect = sximmc_card_detect,
231 	.bus_power = sximmc_bus_power,
232 	.bus_clock = sximmc_bus_clock,
233 	.bus_width = sximmc_bus_width,
234 	.exec_command = sximmc_exec_command,
235 };
236 
237 struct sximmc_softc {
238 	struct device sc_dev;
239 	bus_space_tag_t sc_bst;
240 	bus_space_handle_t sc_bsh;
241 	bus_space_handle_t sc_clk_bsh;
242 	bus_dma_tag_t sc_dmat;
243 	int sc_node;
244 
245 	int sc_use_dma;
246 
247 	void *sc_ih;
248 
249 	struct device *sc_sdmmc_dev;
250 
251 	uint32_t sc_fifo_reg;
252 	uint32_t sc_dma_ftrglevel;
253 
254 	uint32_t sc_idma_xferlen;
255 	bus_dma_segment_t sc_idma_segs[1];
256 	int sc_idma_nsegs;
257 	bus_size_t sc_idma_size;
258 	bus_dmamap_t sc_idma_map;
259 	int sc_idma_ndesc;
260 	char *sc_idma_desc;
261 
262 	uint32_t sc_intr_rint;
263 	uint32_t sc_intr_mint;
264 	uint32_t sc_idma_idst;
265 
266 	uint32_t sc_gpio[4];
267 	uint32_t sc_vmmc;
268 	uint32_t sc_pwrseq;
269 	uint32_t sc_vdd;
270 };
271 
272 struct cfdriver sximmc_cd = {
273 	NULL, "sximmc", DV_DULL
274 };
275 
276 struct cfattach sximmc_ca = {
277 	sizeof(struct sximmc_softc), sximmc_match, sximmc_attach
278 };
279 
280 #define MMC_WRITE(sc, reg, val)	\
281 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
282 #define MMC_READ(sc, reg) \
283 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
284 
285 int	sximmc_set_clock(struct sximmc_softc *sc, u_int);
286 
287 int
288 sximmc_match(struct device *parent, void *match, void *aux)
289 {
290 	struct fdt_attach_args *faa = aux;
291 
292 	if (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-mmc"))
293 		return 1;
294 	if (OF_is_compatible(faa->fa_node, "allwinner,sun5i-a13-mmc"))
295 		return 1;
296 	if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-mmc"))
297 		return 1;
298 	if (OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-mmc"))
299 		return 1;
300 
301 	return 0;
302 }
303 
304 int
305 sximmc_idma_setup(struct sximmc_softc *sc)
306 {
307 	int error;
308 
309 	if (OF_is_compatible(sc->sc_node, "allwinner,sun4i-a10-mmc")) {
310 		sc->sc_idma_xferlen = 0x2000;
311 	} else {
312 		sc->sc_idma_xferlen = 0x10000;
313 	}
314 
315 	sc->sc_idma_ndesc = SXIMMC_NDESC;
316 	sc->sc_idma_size = sizeof(struct sximmc_idma_descriptor) *
317 	    sc->sc_idma_ndesc;
318 	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0,
319 	    sc->sc_idma_size, sc->sc_idma_segs, 1,
320 	    &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
321 	if (error)
322 		return error;
323 	error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
324 	    sc->sc_idma_nsegs, sc->sc_idma_size,
325 	    &sc->sc_idma_desc, BUS_DMA_WAITOK);
326 	if (error)
327 		goto free;
328 	error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
329 	    sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
330 	if (error)
331 		goto unmap;
332 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
333 	    sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
334 	if (error)
335 		goto destroy;
336 	return 0;
337 
338 destroy:
339 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
340 unmap:
341 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
342 free:
343 	bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
344 	return error;
345 }
346 
347 void
348 sximmc_attach(struct device *parent, struct device *self, void *aux)
349 {
350 	struct sximmc_softc *sc = (struct sximmc_softc *)self;
351 	struct fdt_attach_args *faa = aux;
352 	struct sdmmcbus_attach_args saa;
353 	int node, width;
354 
355 	if (faa->fa_nreg < 1)
356 		return;
357 
358 	sc->sc_node = faa->fa_node;
359 	sc->sc_bst = faa->fa_iot;
360 	sc->sc_dmat = faa->fa_dmat;
361 
362 	if (bus_space_map(sc->sc_bst, faa->fa_reg[0].addr,
363 	    faa->fa_reg[0].size, 0, &sc->sc_bsh)) {
364 		printf(": can't map registers\n");
365 		return;
366 	}
367 
368 	sc->sc_use_dma = 1;
369 
370 	printf("\n");
371 
372 	pinctrl_byname(faa->fa_node, "default");
373 
374 	/* enable clock */
375 	clock_enable(faa->fa_node, NULL);
376 	delay(5000);
377 
378 	reset_deassert_all(faa->fa_node);
379 
380 	/*
381 	 * The FIFO register is in a different location on the
382 	 * Allwinner A31 and later generations.  Unfortunately the
383 	 * compatible string wasn't changed, so we need to look at the
384 	 * root node to pick the right register.
385 	 *
386 	 * XXX Should we always use DMA (like Linux does) to avoid
387 	 * this issue?
388 	 */
389 	node = OF_finddevice("/");
390 	if (OF_is_compatible(node, "allwinner,sun4i-a10") ||
391 	    OF_is_compatible(node, "allwinner,sun5i-a10s") ||
392 	    OF_is_compatible(node, "allwinner,sun5i-a13") ||
393 	    OF_is_compatible(node, "allwinner,sun7i-a20"))
394 		sc->sc_fifo_reg = SXIMMC_FIFO_A10;
395 	else
396 		sc->sc_fifo_reg = SXIMMC_FIFO_A31;
397 
398 	if (OF_is_compatible(sc->sc_node, "allwinner,sun9i-a80-mmc"))
399 		sc->sc_dma_ftrglevel = SXIMMC_DMA_FTRGLEVEL_A80;
400 	else
401 		sc->sc_dma_ftrglevel = SXIMMC_DMA_FTRGLEVEL_A20;
402 
403 	if (sc->sc_use_dma) {
404 		if (sximmc_idma_setup(sc) != 0) {
405 			printf("%s: failed to setup DMA\n", self->dv_xname);
406 			return;
407 		}
408 	}
409 
410 	OF_getpropintarray(sc->sc_node, "cd-gpios", sc->sc_gpio,
411 	    sizeof(sc->sc_gpio));
412 	gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT);
413 
414 	sc->sc_vmmc = OF_getpropint(sc->sc_node, "vmmc-supply", 0);
415 	sc->sc_pwrseq = OF_getpropint(sc->sc_node, "mmc-pwrseq", 0);
416 
417 	sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO,
418 	    sximmc_intr, sc, sc->sc_dev.dv_xname);
419 	if (sc->sc_ih == NULL) {
420 		printf(": can't to establish interrupt\n");
421 		return;
422 	}
423 
424 	sximmc_bus_width(sc, 1);
425 	sximmc_set_clock(sc, 400);
426 	sximmc_host_reset(sc);
427 
428 	memset(&saa, 0, sizeof(saa));
429 	saa.saa_busname = "sdmmc";
430 	saa.sct = &sximmc_chip_functions;
431 	saa.sch = sc;
432 #if 0
433 	saa.saa_clkmin = 400;
434 	saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000;
435 #endif
436 
437 	saa.caps = SMC_CAPS_SD_HIGHSPEED | SMC_CAPS_MMC_HIGHSPEED;
438 
439 	width = OF_getpropint(sc->sc_node, "bus-width", 1);
440 	if (width >= 8)
441 		saa.caps |= SMC_CAPS_8BIT_MODE;
442 	if (width >= 4)
443 		saa.caps |= SMC_CAPS_4BIT_MODE;
444 
445 	if (sc->sc_use_dma) {
446 		saa.dmat = sc->sc_dmat;
447 		saa.caps |= SMC_CAPS_DMA;
448 	}
449 
450 	sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
451 }
452 
453 int
454 sximmc_set_clock(struct sximmc_softc *sc, u_int freq)
455 {
456 	if (freq > 0) {
457 		if (clock_set_frequency(sc->sc_node, "mmc", freq * 1000))
458 			return EIO;
459 		clock_enable(sc->sc_node, "mmc");
460 		delay(20000);
461 	} else
462 		clock_disable(sc->sc_node, "mmc");
463 
464 	return 0;
465 }
466 
467 
468 int
469 sximmc_intr(void *priv)
470 {
471 	struct sximmc_softc *sc = priv;
472 	uint32_t idst, rint, mint;
473 
474 	idst = MMC_READ(sc, SXIMMC_IDST);
475 	rint = MMC_READ(sc, SXIMMC_RINT);
476 	mint = MMC_READ(sc, SXIMMC_MINT);
477 	if (!idst && !rint && !mint)
478 		return 0;
479 
480 	MMC_WRITE(sc, SXIMMC_IDST, idst);
481 	MMC_WRITE(sc, SXIMMC_RINT, rint);
482 	MMC_WRITE(sc, SXIMMC_MINT, mint);
483 
484 #ifdef SXIMMC_DEBUG
485 	printf("%s: mmc intr idst=%08X rint=%08X mint=%08X\n",
486 	    sc->sc_dev.dv_xname, idst, rint, mint);
487 #endif
488 
489 	if (idst) {
490 		sc->sc_idma_idst |= idst;
491 		wakeup(&sc->sc_idma_idst);
492 	}
493 
494 	if (rint) {
495 		sc->sc_intr_rint |= rint;
496 		wakeup(&sc->sc_intr_rint);
497 	}
498 
499 	return 1;
500 }
501 
502 int
503 sximmc_wait_rint(struct sximmc_softc *sc, uint32_t mask, int timeout)
504 {
505 	int retry;
506 	int error;
507 
508 	splassert(IPL_BIO);
509 
510 	if (sc->sc_intr_rint & mask)
511 		return 0;
512 
513 	retry = sc->sc_use_dma ? (timeout / hz) : 10000;
514 
515 	while (retry > 0) {
516 		if (sc->sc_use_dma) {
517 			error = tsleep(&sc->sc_intr_rint, PWAIT, "rint", hz);
518 			if (error && error != EWOULDBLOCK)
519 				return error;
520 			if (sc->sc_intr_rint & mask)
521 				return 0;
522 		} else {
523 			sc->sc_intr_rint |= MMC_READ(sc, SXIMMC_RINT);
524 			if (sc->sc_intr_rint & mask)
525 				return 0;
526 			delay(1000);
527 		}
528 		--retry;
529 	}
530 
531 	return ETIMEDOUT;
532 }
533 
534 void
535 sximmc_led(struct sximmc_softc *sc, int on)
536 {
537 }
538 
539 int
540 sximmc_host_reset(sdmmc_chipset_handle_t sch)
541 {
542 	struct sximmc_softc *sc = sch;
543 	int retry = 1000;
544 
545 #if 0
546 	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
547 		if (sc->sc_mmc_port == 2 || sc->sc_mmc_port == 3) {
548 			MMC_WRITE(sc, SXIMMC_HWRST, 0);
549 			delay(10);
550 			MMC_WRITE(sc, SXIMMC_HWRST, 1);
551 			delay(300);
552 		}
553 	}
554 #endif
555 
556 	MMC_WRITE(sc, SXIMMC_GCTRL,
557 	    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_RESET);
558 	while (--retry > 0) {
559 		if (!(MMC_READ(sc, SXIMMC_GCTRL) & SXIMMC_GCTRL_RESET))
560 			break;
561 		delay(100);
562 	}
563 #ifdef SXIMMC_DEBUG
564 	if (retry == 0)
565 		printf("%s: host reset failed\n", sc->sc_dev.dv_xname);
566 	else
567 		printf("%s: host reset succeeded\n", sc->sc_dev.dv_xname);
568 #endif
569 
570 	MMC_WRITE(sc, SXIMMC_TIMEOUT, 0xffffffff);
571 
572 	MMC_WRITE(sc, SXIMMC_IMASK,
573 	    SXIMMC_INT_CMD_DONE | SXIMMC_INT_ERROR |
574 	    SXIMMC_INT_DATA_OVER | SXIMMC_INT_AUTO_CMD_DONE);
575 
576 	MMC_WRITE(sc, SXIMMC_GCTRL,
577 	    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_INTEN);
578 
579 	return 0;
580 }
581 
582 uint32_t
583 sximmc_host_ocr(sdmmc_chipset_handle_t sch)
584 {
585 #if 0
586 	return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
587 #else
588 	return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
589 #endif
590 }
591 
592 int
593 sximmc_host_maxblklen(sdmmc_chipset_handle_t sch)
594 {
595 #if 0
596 	return 8192;
597 #else
598 	return 512;
599 #endif
600 }
601 
602 int
603 sximmc_card_detect(sdmmc_chipset_handle_t sch)
604 {
605 	struct sximmc_softc *sc = sch;
606 	int inverted, val;
607 
608 	if (OF_getproplen(sc->sc_node, "non-removable") == 0)
609 		return 1;
610 
611 	val = gpio_controller_get_pin(sc->sc_gpio);
612 
613 	inverted = (OF_getproplen(sc->sc_node, "cd-inverted") == 0);
614 	return inverted ? !val : val;;
615 }
616 
617 int
618 sximmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
619 {
620 	struct sximmc_softc *sc = sch;
621 	uint32_t vdd = 0;
622 
623 	if (ISSET(ocr, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V))
624 		vdd = 3300000;
625 
626 	if (sc->sc_vdd == 0 && vdd > 0)
627 		sximmc_pwrseq_pre(sc->sc_pwrseq);
628 
629 	/* enable mmc power */
630 	if (sc->sc_vmmc && vdd > 0)
631 		regulator_enable(sc->sc_vmmc);
632 
633 	if (sc->sc_vdd == 0 && vdd > 0)
634 		sximmc_pwrseq_post(sc->sc_pwrseq);
635 
636 	sc->sc_vdd = vdd;
637 	return 0;
638 }
639 
640 int
641 sximmc_update_clock(struct sximmc_softc *sc)
642 {
643 	uint32_t cmd;
644 	int retry;
645 
646 #ifdef SXIMMC_DEBUG
647 	printf("%s: update clock\n", sc->sc_dev.dv_xname);
648 #endif
649 
650 	cmd = SXIMMC_CMD_START |
651 	      SXIMMC_CMD_UPCLK_ONLY |
652 	      SXIMMC_CMD_WAIT_PRE_OVER;
653 	MMC_WRITE(sc, SXIMMC_CMD, cmd);
654 	retry = 0xfffff;
655 	while (--retry > 0) {
656 		if (!(MMC_READ(sc, SXIMMC_CMD) & SXIMMC_CMD_START))
657 			break;
658 		delay(10);
659 	}
660 
661 	if (retry == 0) {
662 		printf("%s: timeout updating clock\n", sc->sc_dev.dv_xname);
663 #ifdef SXIMMC_DEBUG
664 		printf("GCTRL: 0x%08x\n", MMC_READ(sc, SXIMMC_GCTRL));
665 		printf("CLKCR: 0x%08x\n", MMC_READ(sc, SXIMMC_CLKCR));
666 		printf("TIMEOUT: 0x%08x\n", MMC_READ(sc, SXIMMC_TIMEOUT));
667 		printf("WIDTH: 0x%08x\n", MMC_READ(sc, SXIMMC_WIDTH));
668 		printf("CMD: 0x%08x\n", MMC_READ(sc, SXIMMC_CMD));
669 		printf("MINT: 0x%08x\n", MMC_READ(sc, SXIMMC_MINT));
670 		printf("RINT: 0x%08x\n", MMC_READ(sc, SXIMMC_RINT));
671 		printf("STATUS: 0x%08x\n", MMC_READ(sc, SXIMMC_STATUS));
672 #endif
673 		return ETIMEDOUT;
674 	}
675 
676 	return 0;
677 }
678 
679 int
680 sximmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing)
681 {
682 	struct sximmc_softc *sc = sch;
683 	uint32_t clkcr;
684 
685 	clkcr = MMC_READ(sc, SXIMMC_CLKCR);
686 	if (clkcr & SXIMMC_CLKCR_CARDCLKON) {
687 		clkcr &= ~SXIMMC_CLKCR_CARDCLKON;
688 		MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
689 		if (sximmc_update_clock(sc) != 0)
690 			return 1;
691 	}
692 
693 	if (freq) {
694 		clkcr &= ~SXIMMC_CLKCR_DIV;
695 		MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
696 		if (sximmc_update_clock(sc) != 0)
697 			return 1;
698 
699 		if (sximmc_set_clock(sc, freq) != 0)
700 			return 1;
701 
702 		clkcr |= SXIMMC_CLKCR_CARDCLKON;
703 		MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
704 		if (sximmc_update_clock(sc) != 0)
705 			return 1;
706 	}
707 
708 	return 0;
709 }
710 
711 int
712 sximmc_bus_width(sdmmc_chipset_handle_t sch, int width)
713 {
714 	struct sximmc_softc *sc = sch;
715 
716 #ifdef SXIMMC_DEBUG
717 	printf("%s: width = %d\n", sc->sc_dev.dv_xname, width);
718 #endif
719 
720 	switch (width) {
721 	case 1:
722 		MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_1);
723 		break;
724 	case 4:
725 		MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_4);
726 		break;
727 	case 8:
728 		MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_8);
729 		break;
730 	default:
731 		return 1;
732 	}
733 
734 	return 0;
735 }
736 
737 int
738 sximmc_pio_wait(struct sximmc_softc *sc, struct sdmmc_command *cmd)
739 {
740 	int retry = 0xfffff;
741 	uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
742 	    SXIMMC_STATUS_FIFO_EMPTY : SXIMMC_STATUS_FIFO_FULL;
743 
744 	while (--retry > 0) {
745 		uint32_t status = MMC_READ(sc, SXIMMC_STATUS);
746 		if (!(status & bit))
747 			return 0;
748 		delay(10);
749 	}
750 
751 	return ETIMEDOUT;
752 }
753 
754 int
755 sximmc_pio_transfer(struct sximmc_softc *sc, struct sdmmc_command *cmd)
756 {
757 	uint32_t *datap = (uint32_t *)cmd->c_data;
758 	int i;
759 
760 	for (i = 0; i < (cmd->c_resid >> 2); i++) {
761 		if (sximmc_pio_wait(sc, cmd))
762 			return ETIMEDOUT;
763 		if (cmd->c_flags & SCF_CMD_READ) {
764 			datap[i] = MMC_READ(sc, sc->sc_fifo_reg);
765 		} else {
766 			MMC_WRITE(sc, sc->sc_fifo_reg, datap[i]);
767 		}
768 	}
769 
770 	return 0;
771 }
772 
773 int
774 sximmc_dma_prepare(struct sximmc_softc *sc, struct sdmmc_command *cmd)
775 {
776 	struct sximmc_idma_descriptor *dma = (void *)sc->sc_idma_desc;
777 	bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr;
778 	bus_size_t off;
779 	int desc, resid, seg;
780 	uint32_t val;
781 
782 	desc = 0;
783 	for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
784 		bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr;
785 		bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len;
786 		resid = min(len, cmd->c_resid);
787 		off = 0;
788 		while (resid > 0) {
789 			if (desc == sc->sc_idma_ndesc)
790 				break;
791 			len = min(sc->sc_idma_xferlen, resid);
792 			dma[desc].dma_buf_size = htole32(len);
793 			dma[desc].dma_buf_addr = htole32(paddr + off);
794 			dma[desc].dma_config = htole32(SXIMMC_IDMA_CONFIG_CH |
795 					       SXIMMC_IDMA_CONFIG_OWN);
796 			cmd->c_resid -= len;
797 			resid -= len;
798 			off += len;
799 			if (desc == 0) {
800 				dma[desc].dma_config |=
801 				    htole32(SXIMMC_IDMA_CONFIG_FD);
802 			}
803 			if (cmd->c_resid == 0) {
804 				dma[desc].dma_config |=
805 				    htole32(SXIMMC_IDMA_CONFIG_LD);
806 				dma[desc].dma_config |=
807 				    htole32(SXIMMC_IDMA_CONFIG_ER);
808 				dma[desc].dma_next = 0;
809 			} else {
810 				dma[desc].dma_config |=
811 				    htole32(SXIMMC_IDMA_CONFIG_DIC);
812 				dma[desc].dma_next = htole32(
813 				    desc_paddr + ((desc+1) *
814 				    sizeof(struct sximmc_idma_descriptor)));
815 			}
816 			++desc;
817 		}
818 	}
819 	if (desc == sc->sc_idma_ndesc) {
820 		printf("%s: not enough descriptors for %d byte transfer!\n",
821 		    sc->sc_dev.dv_xname, cmd->c_datalen);
822 		return EIO;
823 	}
824 
825 	bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
826 	    sc->sc_idma_size, BUS_DMASYNC_PREWRITE);
827 
828 	sc->sc_idma_idst = 0;
829 
830 	val = MMC_READ(sc, SXIMMC_GCTRL);
831 	val |= SXIMMC_GCTRL_DMAEN;
832 	val |= SXIMMC_GCTRL_INTEN;
833 	MMC_WRITE(sc, SXIMMC_GCTRL, val);
834 	val |= SXIMMC_GCTRL_DMARESET;
835 	MMC_WRITE(sc, SXIMMC_GCTRL, val);
836 	MMC_WRITE(sc, SXIMMC_DMAC, SXIMMC_DMAC_SOFTRESET);
837 	MMC_WRITE(sc, SXIMMC_DMAC,
838 	    SXIMMC_DMAC_IDMA_ON|SXIMMC_DMAC_FIX_BURST);
839 	val = MMC_READ(sc, SXIMMC_IDIE);
840 	val &= ~(SXIMMC_IDST_RECEIVE_INT|SXIMMC_IDST_TRANSMIT_INT);
841 	if (cmd->c_flags & SCF_CMD_READ)
842 		val |= SXIMMC_IDST_RECEIVE_INT;
843 	else
844 		val |= SXIMMC_IDST_TRANSMIT_INT;
845 	MMC_WRITE(sc, SXIMMC_IDIE, val);
846 	MMC_WRITE(sc, SXIMMC_DLBA, desc_paddr);
847 	MMC_WRITE(sc, SXIMMC_FTRGLEVEL, sc->sc_dma_ftrglevel);
848 
849 	return 0;
850 }
851 
852 void
853 sximmc_dma_complete(struct sximmc_softc *sc)
854 {
855 	bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
856 	    sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
857 }
858 
859 void
860 sximmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
861 {
862 	struct sximmc_softc *sc = sch;
863 	uint32_t cmdval = SXIMMC_CMD_START;
864 	int retry;
865 	int s;
866 
867 #ifdef SXIMMC_DEBUG
868 	printf("%s: opcode %d flags 0x%x data %p datalen %d blklen %d\n",
869 	    sc->sc_dev.dv_xname, cmd->c_opcode, cmd->c_flags,
870 	    cmd->c_data, cmd->c_datalen, cmd->c_blklen);
871 #endif
872 
873 	s = splbio();
874 
875 	if (cmd->c_opcode == 0)
876 		cmdval |= SXIMMC_CMD_SEND_INIT_SEQ;
877 	if (cmd->c_flags & SCF_RSP_PRESENT)
878 		cmdval |= SXIMMC_CMD_RSP_EXP;
879 	if (cmd->c_flags & SCF_RSP_136)
880 		cmdval |= SXIMMC_CMD_LONG_RSP;
881 	if (cmd->c_flags & SCF_RSP_CRC)
882 		cmdval |= SXIMMC_CMD_CHECK_RSP_CRC;
883 
884 	if (cmd->c_datalen > 0) {
885 		uint16_t blksize;
886 		uint16_t blkcount;
887 
888 		cmdval |= SXIMMC_CMD_DATA_EXP | SXIMMC_CMD_WAIT_PRE_OVER;
889 		if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
890 			cmdval |= SXIMMC_CMD_WRITE;
891 		}
892 
893 		blksize = MIN(cmd->c_datalen, cmd->c_blklen);
894 		blkcount = cmd->c_datalen / blksize;
895 		if (blkcount > 1) {
896 			cmdval |= SXIMMC_CMD_SEND_AUTO_STOP;
897 		}
898 
899 		MMC_WRITE(sc, SXIMMC_BLKSZ, blksize);
900 		MMC_WRITE(sc, SXIMMC_BYTECNT, blkcount * blksize);
901 	}
902 
903 	sc->sc_intr_rint = 0;
904 
905 #if 0
906 	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
907 		MMC_WRITE(sc, SXIMMC_A12A,
908 		    (cmdval & SXIMMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff);
909 	}
910 #endif
911 
912 	MMC_WRITE(sc, SXIMMC_ARG, cmd->c_arg);
913 
914 #ifdef SXIMMC_DEBUG
915 	printf("%s: cmdval = %08x\n", sc->sc_dev.dv_xname, cmdval);
916 #endif
917 
918 	if (cmd->c_datalen == 0) {
919 		MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
920 	} else {
921 		cmd->c_resid = cmd->c_datalen;
922 		sximmc_led(sc, 0);
923 		if (cmd->c_dmamap && sc->sc_use_dma) {
924 			cmd->c_error = sximmc_dma_prepare(sc, cmd);
925 			MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
926 			if (cmd->c_error == 0) {
927 				cmd->c_error = tsleep(&sc->sc_idma_idst,
928 				    PWAIT, "idma", hz*10);
929 			}
930 			sximmc_dma_complete(sc);
931 			if (sc->sc_idma_idst & SXIMMC_IDST_ERROR) {
932 				cmd->c_error = EIO;
933 			} else if (!(sc->sc_idma_idst & SXIMMC_IDST_COMPLETE)) {
934 				cmd->c_error = ETIMEDOUT;
935 			}
936 		} else {
937 			splx(s);
938 			MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
939 			cmd->c_error = sximmc_pio_transfer(sc, cmd);
940 			s = splbio();
941 		}
942 		sximmc_led(sc, 1);
943 		if (cmd->c_error) {
944 #ifdef SXIMMC_DEBUG
945 			printf("%s: xfer failed, error %d\n",
946 			    sc->sc_dev.dv_xname, cmd->c_error);
947 #endif
948 			goto done;
949 		}
950 	}
951 
952 	cmd->c_error = sximmc_wait_rint(sc,
953 	    SXIMMC_INT_ERROR|SXIMMC_INT_CMD_DONE, hz * 10);
954 	if (cmd->c_error == 0 && (sc->sc_intr_rint & SXIMMC_INT_ERROR)) {
955 		if (sc->sc_intr_rint & SXIMMC_INT_RESP_TIMEOUT) {
956 			cmd->c_error = ETIMEDOUT;
957 		} else {
958 			cmd->c_error = EIO;
959 		}
960 	}
961 	if (cmd->c_error) {
962 #ifdef SXIMMC_DEBUG
963 		printf("%s: cmd failed, error %d\n",
964 		    sc->sc_dev.dv_xname,  cmd->c_error);
965 #endif
966 		goto done;
967 	}
968 
969 	if (cmd->c_datalen > 0) {
970 		cmd->c_error = sximmc_wait_rint(sc,
971 		    SXIMMC_INT_ERROR|
972 		    SXIMMC_INT_AUTO_CMD_DONE|
973 		    SXIMMC_INT_DATA_OVER,
974 		    hz*10);
975 		if (cmd->c_error == 0 &&
976 		    (sc->sc_intr_rint & SXIMMC_INT_ERROR)) {
977 			cmd->c_error = ETIMEDOUT;
978 		}
979 		if (cmd->c_error) {
980 #ifdef SXIMMC_DEBUG
981 			printf("%s: data timeout, rint = %08x\n",
982 			    sc->sc_dev.dv_xname, sc->sc_intr_rint);
983 #endif
984 			cmd->c_error = ETIMEDOUT;
985 			goto done;
986 		}
987 	}
988 
989 	if (cmd->c_flags & SCF_RSP_PRESENT) {
990 		if (cmd->c_flags & SCF_RSP_136) {
991 			cmd->c_resp[0] = MMC_READ(sc, SXIMMC_RESP0);
992 			cmd->c_resp[1] = MMC_READ(sc, SXIMMC_RESP1);
993 			cmd->c_resp[2] = MMC_READ(sc, SXIMMC_RESP2);
994 			cmd->c_resp[3] = MMC_READ(sc, SXIMMC_RESP3);
995 			if (cmd->c_flags & SCF_RSP_CRC) {
996 				cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
997 				    (cmd->c_resp[1] << 24);
998 				cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
999 				    (cmd->c_resp[2] << 24);
1000 				cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
1001 				    (cmd->c_resp[3] << 24);
1002 				cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
1003 			}
1004 		} else {
1005 			cmd->c_resp[0] = MMC_READ(sc, SXIMMC_RESP0);
1006 		}
1007 	}
1008 
1009 done:
1010 	cmd->c_flags |= SCF_ITSDONE;
1011 	splx(s);
1012 
1013 	if (cmd->c_error) {
1014 #ifdef SXIMMC_DEBUG
1015 		printf("%s: i/o error %d\n", sc->sc_dev.dv_xname,
1016 		    cmd->c_error);
1017 #endif
1018 		MMC_WRITE(sc, SXIMMC_GCTRL,
1019 		    MMC_READ(sc, SXIMMC_GCTRL) |
1020 		      SXIMMC_GCTRL_DMARESET | SXIMMC_GCTRL_FIFORESET);
1021 		for (retry = 0; retry < 1000; retry++) {
1022 			if (!(MMC_READ(sc, SXIMMC_GCTRL) & SXIMMC_GCTRL_RESET))
1023 				break;
1024 			delay(10);
1025 		}
1026 		sximmc_host_reset(sc);
1027 		sximmc_update_clock(sc);
1028 	}
1029 
1030 	if (!cmd->c_dmamap || !sc->sc_use_dma) {
1031 		MMC_WRITE(sc, SXIMMC_GCTRL,
1032 		    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_FIFORESET);
1033 	}
1034 }
1035 
1036 void
1037 sximmc_pwrseq_pre(uint32_t phandle)
1038 {
1039 	uint32_t *gpios, *gpio;
1040 	int node;
1041 	int len;
1042 
1043 	node = OF_getnodebyphandle(phandle);
1044 	if (node == 0)
1045 		return;
1046 
1047 	if (!OF_is_compatible(node, "mmc-pwrseq-simple"))
1048 		return;
1049 
1050 	pinctrl_byname(node, "default");
1051 
1052 	clock_enable(node, "ext_clock");
1053 
1054 	len = OF_getproplen(node, "reset-gpios");
1055 	if (len <= 0)
1056 		return;
1057 
1058 	gpios = malloc(len, M_TEMP, M_WAITOK);
1059 	OF_getpropintarray(node, "reset-gpios", gpios, len);
1060 
1061 	gpio = gpios;
1062 	while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
1063 		gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
1064 		gpio_controller_set_pin(gpio, 1);
1065 		gpio = gpio_controller_next_pin(gpio);
1066 	}
1067 
1068 	free(gpios, M_TEMP, len);
1069 }
1070 
1071 void
1072 sximmc_pwrseq_post(uint32_t phandle)
1073 {
1074 	uint32_t *gpios, *gpio;
1075 	int node;
1076 	int len;
1077 
1078 	node = OF_getnodebyphandle(phandle);
1079 	if (node == 0)
1080 		return;
1081 
1082 	if (!OF_is_compatible(node, "mmc-pwrseq-simple"))
1083 		return;
1084 
1085 	len = OF_getproplen(node, "reset-gpios");
1086 	if (len <= 0)
1087 		return;
1088 
1089 	gpios = malloc(len, M_TEMP, M_WAITOK);
1090 	OF_getpropintarray(node, "reset-gpios", gpios, len);
1091 
1092 	gpio = gpios;
1093 	while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
1094 		gpio_controller_set_pin(gpio, 0);
1095 		gpio = gpio_controller_next_pin(gpio);
1096 	}
1097 
1098 	free(gpios, M_TEMP, len);
1099 }
1100