1/* $OpenBSD: sximmc.c,v 1.15 2024/05/13 01:15:50 jsg 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
189struct 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
208int	sximmc_match(struct device *, void *, void *);
209void	sximmc_attach(struct device *, struct device *, void *);
210
211int	sximmc_intr(void *);
212
213int	sximmc_host_reset(sdmmc_chipset_handle_t);
214uint32_t sximmc_host_ocr(sdmmc_chipset_handle_t);
215int	sximmc_host_maxblklen(sdmmc_chipset_handle_t);
216int	sximmc_card_detect(sdmmc_chipset_handle_t);
217int	sximmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
218int	sximmc_bus_clock(sdmmc_chipset_handle_t, int, int);
219int	sximmc_bus_width(sdmmc_chipset_handle_t, int);
220void	sximmc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
221void	sximmc_card_intr_mask(sdmmc_chipset_handle_t, int);
222void	sximmc_card_intr_ack(sdmmc_chipset_handle_t);
223
224void	sximmc_pwrseq_pre(uint32_t);
225void	sximmc_pwrseq_post(uint32_t);
226
227struct sdmmc_chip_functions sximmc_chip_functions = {
228	.host_reset = sximmc_host_reset,
229	.host_ocr = sximmc_host_ocr,
230	.host_maxblklen = sximmc_host_maxblklen,
231	.card_detect = sximmc_card_detect,
232	.bus_power = sximmc_bus_power,
233	.bus_clock = sximmc_bus_clock,
234	.bus_width = sximmc_bus_width,
235	.exec_command = sximmc_exec_command,
236	.card_intr_mask = sximmc_card_intr_mask,
237	.card_intr_ack = sximmc_card_intr_ack,
238};
239
240struct sximmc_softc {
241	struct device sc_dev;
242	bus_space_tag_t sc_bst;
243	bus_space_handle_t sc_bsh;
244	bus_space_handle_t sc_clk_bsh;
245	bus_dma_tag_t sc_dmat;
246	int sc_node;
247
248	int sc_use_dma;
249
250	void *sc_ih;
251
252	struct device *sc_sdmmc_dev;
253
254	uint32_t sc_fifo_reg;
255	uint32_t sc_dma_ftrglevel;
256
257	bus_dma_segment_t sc_idma_segs[1];
258	int sc_idma_nsegs;
259	bus_size_t sc_idma_size;
260	bus_dmamap_t sc_idma_map;
261	int sc_idma_ndesc;
262	char *sc_idma_desc;
263	int sc_idma_shift;
264
265	uint32_t sc_intr_rint;
266	uint32_t sc_intr_mint;
267	uint32_t sc_idma_idst;
268
269	uint32_t sc_gpio[4];
270	uint32_t sc_vmmc;
271	uint32_t sc_vqmmc;
272	uint32_t sc_pwrseq;
273	uint32_t sc_vdd;
274};
275
276struct cfdriver sximmc_cd = {
277	NULL, "sximmc", DV_DULL
278};
279
280const struct cfattach sximmc_ca = {
281	sizeof(struct sximmc_softc), sximmc_match, sximmc_attach
282};
283
284#define MMC_WRITE(sc, reg, val)	\
285	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
286#define MMC_READ(sc, reg) \
287	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
288
289int	sximmc_set_clock(struct sximmc_softc *sc, u_int);
290
291int
292sximmc_match(struct device *parent, void *match, void *aux)
293{
294	struct fdt_attach_args *faa = aux;
295
296	return (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-mmc") ||
297	    OF_is_compatible(faa->fa_node, "allwinner,sun5i-a13-mmc") ||
298	    OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-mmc") ||
299	    OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-mmc") ||
300	    OF_is_compatible(faa->fa_node, "allwinner,sun20i-d1-mmc") ||
301	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-mmc") ||
302	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-emmc") ||
303	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a100-mmc") ||
304	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a100-emmc"));
305}
306
307int
308sximmc_idma_setup(struct sximmc_softc *sc)
309{
310	int error;
311
312	sc->sc_idma_ndesc = SXIMMC_NDESC;
313	sc->sc_idma_size = sizeof(struct sximmc_idma_descriptor) *
314	    sc->sc_idma_ndesc;
315	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0,
316	    sc->sc_idma_size, sc->sc_idma_segs, 1,
317	    &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
318	if (error)
319		return error;
320	error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
321	    sc->sc_idma_nsegs, sc->sc_idma_size,
322	    &sc->sc_idma_desc, BUS_DMA_WAITOK);
323	if (error)
324		goto free;
325	error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
326	    sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
327	if (error)
328		goto unmap;
329	error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
330	    sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
331	if (error)
332		goto destroy;
333	return 0;
334
335destroy:
336	bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
337unmap:
338	bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
339free:
340	bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
341	return error;
342}
343
344void
345sximmc_attach(struct device *parent, struct device *self, void *aux)
346{
347	struct sximmc_softc *sc = (struct sximmc_softc *)self;
348	struct fdt_attach_args *faa = aux;
349	struct sdmmcbus_attach_args saa;
350	int node, width;
351
352	if (faa->fa_nreg < 1)
353		return;
354
355	sc->sc_node = faa->fa_node;
356	sc->sc_bst = faa->fa_iot;
357	sc->sc_dmat = faa->fa_dmat;
358
359	if (bus_space_map(sc->sc_bst, faa->fa_reg[0].addr,
360	    faa->fa_reg[0].size, 0, &sc->sc_bsh)) {
361		printf(": can't map registers\n");
362		return;
363	}
364
365	sc->sc_use_dma = 1;
366
367	printf("\n");
368
369	pinctrl_byname(faa->fa_node, "default");
370
371	/* enable clock */
372	clock_enable(faa->fa_node, NULL);
373	delay(5000);
374
375	reset_deassert_all(faa->fa_node);
376
377	/*
378	 * The FIFO register is in a different location on the
379	 * Allwinner A31 and later generations.  Unfortunately the
380	 * compatible string wasn't changed, so we need to look at the
381	 * root node to pick the right register.
382	 *
383	 * XXX Should we always use DMA (like Linux does) to avoid
384	 * this issue?
385	 */
386	node = OF_finddevice("/");
387	if (OF_is_compatible(node, "allwinner,sun4i-a10") ||
388	    OF_is_compatible(node, "allwinner,sun5i-a10s") ||
389	    OF_is_compatible(node, "allwinner,sun5i-a13") ||
390	    OF_is_compatible(node, "allwinner,sun7i-a20"))
391		sc->sc_fifo_reg = SXIMMC_FIFO_A10;
392	else
393		sc->sc_fifo_reg = SXIMMC_FIFO_A31;
394
395	if (OF_is_compatible(sc->sc_node, "allwinner,sun9i-a80-mmc"))
396		sc->sc_dma_ftrglevel = SXIMMC_DMA_FTRGLEVEL_A80;
397	else
398		sc->sc_dma_ftrglevel = SXIMMC_DMA_FTRGLEVEL_A20;
399
400	if (OF_is_compatible(faa->fa_node, "allwinner,sun20i-d1-mmc") ||
401	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a100-mmc") ||
402	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a100-emmc"))
403		sc->sc_idma_shift = 2;
404
405	if (sc->sc_use_dma) {
406		if (sximmc_idma_setup(sc) != 0) {
407			printf("%s: failed to setup DMA\n", self->dv_xname);
408			return;
409		}
410	}
411
412	OF_getpropintarray(sc->sc_node, "cd-gpios", sc->sc_gpio,
413	    sizeof(sc->sc_gpio));
414	gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT);
415
416	sc->sc_vmmc = OF_getpropint(sc->sc_node, "vmmc-supply", 0);
417	sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0);
418	sc->sc_pwrseq = OF_getpropint(sc->sc_node, "mmc-pwrseq", 0);
419
420	sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_BIO,
421	    sximmc_intr, sc, sc->sc_dev.dv_xname);
422	if (sc->sc_ih == NULL) {
423		printf(": can't establish interrupt\n");
424		return;
425	}
426
427	sximmc_bus_width(sc, 1);
428	sximmc_set_clock(sc, 400);
429	sximmc_host_reset(sc);
430
431	memset(&saa, 0, sizeof(saa));
432	saa.saa_busname = "sdmmc";
433	saa.sct = &sximmc_chip_functions;
434	saa.sch = sc;
435#if 0
436	saa.saa_clkmin = 400;
437	saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000;
438#endif
439
440	saa.caps = SMC_CAPS_SD_HIGHSPEED | SMC_CAPS_MMC_HIGHSPEED;
441
442	width = OF_getpropint(sc->sc_node, "bus-width", 1);
443	if (width >= 8)
444		saa.caps |= SMC_CAPS_8BIT_MODE;
445	if (width >= 4)
446		saa.caps |= SMC_CAPS_4BIT_MODE;
447
448	if (sc->sc_use_dma) {
449		saa.dmat = sc->sc_dmat;
450		saa.caps |= SMC_CAPS_DMA;
451	}
452
453	if (OF_is_compatible(sc->sc_node, "allwinner,sun4i-a10-mmc") ||
454	    OF_is_compatible(sc->sc_node, "allwinner,sun20i-d1-mmc") ||
455	    OF_is_compatible(sc->sc_node, "allwinner,sun50i-a64-emmc") ||
456	    OF_is_compatible(sc->sc_node, "allwinner,sun50i-a100-emmc")) {
457		saa.max_seg = 0x2000;
458	} else {
459		saa.max_seg = 0x10000;
460	}
461
462	sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
463}
464
465int
466sximmc_set_clock(struct sximmc_softc *sc, u_int freq)
467{
468	if (freq > 0) {
469		if (clock_set_frequency(sc->sc_node, "mmc", freq * 1000))
470			return EIO;
471		clock_enable(sc->sc_node, "mmc");
472		delay(20000);
473	} else
474		clock_disable(sc->sc_node, "mmc");
475
476	return 0;
477}
478
479
480int
481sximmc_intr(void *priv)
482{
483	struct sximmc_softc *sc = priv;
484	uint32_t idst, rint, mint;
485
486	idst = MMC_READ(sc, SXIMMC_IDST);
487	rint = MMC_READ(sc, SXIMMC_RINT);
488	mint = MMC_READ(sc, SXIMMC_MINT);
489	if (!idst && !rint && !mint)
490		return 0;
491
492	MMC_WRITE(sc, SXIMMC_IDST, idst);
493	MMC_WRITE(sc, SXIMMC_RINT, rint);
494	MMC_WRITE(sc, SXIMMC_MINT, mint);
495
496#ifdef SXIMMC_DEBUG
497	printf("%s: mmc intr idst=%08X rint=%08X mint=%08X\n",
498	    sc->sc_dev.dv_xname, idst, rint, mint);
499#endif
500
501	if (idst) {
502		sc->sc_idma_idst |= idst;
503		wakeup(&sc->sc_idma_idst);
504	}
505
506	if (rint) {
507		sc->sc_intr_rint |= rint;
508		wakeup(&sc->sc_intr_rint);
509
510		if (rint & SXIMMC_INT_SDIO_INT) {
511			uint32_t imask;
512
513			imask = MMC_READ(sc, SXIMMC_IMASK);
514			imask &= ~SXIMMC_INT_SDIO_INT;
515			MMC_WRITE(sc, SXIMMC_IMASK, imask);
516			sdmmc_card_intr(sc->sc_sdmmc_dev);
517		}
518	}
519
520	return 1;
521}
522
523void
524sximmc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable)
525{
526	struct sximmc_softc *sc = sch;
527	uint32_t imask;
528
529	imask = MMC_READ(sc, SXIMMC_IMASK);
530	if (enable)
531		imask |= SXIMMC_INT_SDIO_INT;
532	else
533		imask &= ~SXIMMC_INT_SDIO_INT;
534	MMC_WRITE(sc, SXIMMC_IMASK, imask);
535}
536
537void
538sximmc_card_intr_ack(sdmmc_chipset_handle_t sch)
539{
540	struct sximmc_softc *sc = sch;
541	uint32_t imask;
542
543	MMC_WRITE(sc, SXIMMC_RINT, SXIMMC_INT_SDIO_INT);
544	imask = MMC_READ(sc, SXIMMC_IMASK);
545	imask |= SXIMMC_INT_SDIO_INT;
546	MMC_WRITE(sc, SXIMMC_IMASK, imask);
547}
548
549int
550sximmc_wait_rint(struct sximmc_softc *sc, uint32_t mask, int timeout)
551{
552	int retry;
553	int error;
554
555	splassert(IPL_BIO);
556
557	if (sc->sc_intr_rint & mask)
558		return 0;
559
560	retry = sc->sc_use_dma ? (timeout / hz) : 10000;
561
562	while (retry > 0) {
563		if (sc->sc_use_dma) {
564			error = tsleep_nsec(&sc->sc_intr_rint, PWAIT, "rint",
565			    SEC_TO_NSEC(1));
566			if (error && error != EWOULDBLOCK)
567				return error;
568			if (sc->sc_intr_rint & mask)
569				return 0;
570		} else {
571			sc->sc_intr_rint |= MMC_READ(sc, SXIMMC_RINT);
572			if (sc->sc_intr_rint & mask)
573				return 0;
574			delay(1000);
575		}
576		--retry;
577	}
578
579	return ETIMEDOUT;
580}
581
582void
583sximmc_led(struct sximmc_softc *sc, int on)
584{
585}
586
587int
588sximmc_host_reset(sdmmc_chipset_handle_t sch)
589{
590	struct sximmc_softc *sc = sch;
591	int retry = 1000;
592
593#if 0
594	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
595		if (sc->sc_mmc_port == 2 || sc->sc_mmc_port == 3) {
596			MMC_WRITE(sc, SXIMMC_HWRST, 0);
597			delay(10);
598			MMC_WRITE(sc, SXIMMC_HWRST, 1);
599			delay(300);
600		}
601	}
602#endif
603
604	MMC_WRITE(sc, SXIMMC_GCTRL,
605	    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_RESET);
606	while (--retry > 0) {
607		if (!(MMC_READ(sc, SXIMMC_GCTRL) & SXIMMC_GCTRL_RESET))
608			break;
609		delay(100);
610	}
611#ifdef SXIMMC_DEBUG
612	if (retry == 0)
613		printf("%s: host reset failed\n", sc->sc_dev.dv_xname);
614	else
615		printf("%s: host reset succeeded\n", sc->sc_dev.dv_xname);
616#endif
617
618	/* Allow access to the FIFO by the CPU. */
619	MMC_WRITE(sc, SXIMMC_GCTRL,
620	    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_ACCESS_BY_AHB);
621
622	MMC_WRITE(sc, SXIMMC_TIMEOUT, 0xffffffff);
623
624	MMC_WRITE(sc, SXIMMC_IMASK,
625	    SXIMMC_INT_CMD_DONE | SXIMMC_INT_ERROR |
626	    SXIMMC_INT_DATA_OVER | SXIMMC_INT_AUTO_CMD_DONE);
627
628	MMC_WRITE(sc, SXIMMC_GCTRL,
629	    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_INTEN);
630
631	return 0;
632}
633
634uint32_t
635sximmc_host_ocr(sdmmc_chipset_handle_t sch)
636{
637#if 0
638	return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
639#else
640	return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
641#endif
642}
643
644int
645sximmc_host_maxblklen(sdmmc_chipset_handle_t sch)
646{
647#if 0
648	return 8192;
649#else
650	return 512;
651#endif
652}
653
654int
655sximmc_card_detect(sdmmc_chipset_handle_t sch)
656{
657	struct sximmc_softc *sc = sch;
658	int inverted, val;
659
660	/* XXX treat broken-cd as non-removable */
661	if (OF_getproplen(sc->sc_node, "non-removable") == 0 ||
662	    OF_getproplen(sc->sc_node, "broken-cd") == 0)
663		return 1;
664
665	val = gpio_controller_get_pin(sc->sc_gpio);
666
667	inverted = (OF_getproplen(sc->sc_node, "cd-inverted") == 0);
668	return inverted ? !val : val;
669}
670
671int
672sximmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
673{
674	struct sximmc_softc *sc = sch;
675	uint32_t vdd = 0;
676
677	if (ISSET(ocr, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V))
678		vdd = 3300000;
679
680	if (sc->sc_vdd == 0 && vdd > 0)
681		sximmc_pwrseq_pre(sc->sc_pwrseq);
682
683	/* enable mmc power */
684	if (sc->sc_vmmc && vdd > 0)
685		regulator_enable(sc->sc_vmmc);
686
687	if (sc->sc_vqmmc && vdd > 0)
688		regulator_enable(sc->sc_vqmmc);
689
690	delay(10000);
691
692	if (sc->sc_vdd == 0 && vdd > 0)
693		sximmc_pwrseq_post(sc->sc_pwrseq);
694
695	sc->sc_vdd = vdd;
696	return 0;
697}
698
699int
700sximmc_update_clock(struct sximmc_softc *sc)
701{
702	uint32_t cmd;
703	int retry;
704
705#ifdef SXIMMC_DEBUG
706	printf("%s: update clock\n", sc->sc_dev.dv_xname);
707#endif
708
709	cmd = SXIMMC_CMD_START |
710	      SXIMMC_CMD_UPCLK_ONLY |
711	      SXIMMC_CMD_WAIT_PRE_OVER;
712	MMC_WRITE(sc, SXIMMC_CMD, cmd);
713	retry = 0xfffff;
714	while (--retry > 0) {
715		if (!(MMC_READ(sc, SXIMMC_CMD) & SXIMMC_CMD_START))
716			break;
717		delay(10);
718	}
719
720	if (retry == 0) {
721		printf("%s: timeout updating clock\n", sc->sc_dev.dv_xname);
722#ifdef SXIMMC_DEBUG
723		printf("GCTRL: 0x%08x\n", MMC_READ(sc, SXIMMC_GCTRL));
724		printf("CLKCR: 0x%08x\n", MMC_READ(sc, SXIMMC_CLKCR));
725		printf("TIMEOUT: 0x%08x\n", MMC_READ(sc, SXIMMC_TIMEOUT));
726		printf("WIDTH: 0x%08x\n", MMC_READ(sc, SXIMMC_WIDTH));
727		printf("CMD: 0x%08x\n", MMC_READ(sc, SXIMMC_CMD));
728		printf("MINT: 0x%08x\n", MMC_READ(sc, SXIMMC_MINT));
729		printf("RINT: 0x%08x\n", MMC_READ(sc, SXIMMC_RINT));
730		printf("STATUS: 0x%08x\n", MMC_READ(sc, SXIMMC_STATUS));
731#endif
732		return ETIMEDOUT;
733	}
734
735	return 0;
736}
737
738int
739sximmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing)
740{
741	struct sximmc_softc *sc = sch;
742	uint32_t clkcr;
743
744	clkcr = MMC_READ(sc, SXIMMC_CLKCR);
745	if (clkcr & SXIMMC_CLKCR_CARDCLKON) {
746		clkcr &= ~SXIMMC_CLKCR_CARDCLKON;
747		MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
748		if (sximmc_update_clock(sc) != 0)
749			return 1;
750	}
751
752	if (freq) {
753		clkcr &= ~SXIMMC_CLKCR_DIV;
754		MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
755		if (sximmc_update_clock(sc) != 0)
756			return 1;
757
758		if (sximmc_set_clock(sc, freq) != 0)
759			return 1;
760
761		clkcr |= SXIMMC_CLKCR_CARDCLKON;
762		MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
763		if (sximmc_update_clock(sc) != 0)
764			return 1;
765	}
766
767	return 0;
768}
769
770int
771sximmc_bus_width(sdmmc_chipset_handle_t sch, int width)
772{
773	struct sximmc_softc *sc = sch;
774
775#ifdef SXIMMC_DEBUG
776	printf("%s: width = %d\n", sc->sc_dev.dv_xname, width);
777#endif
778
779	switch (width) {
780	case 1:
781		MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_1);
782		break;
783	case 4:
784		MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_4);
785		break;
786	case 8:
787		MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_8);
788		break;
789	default:
790		return 1;
791	}
792
793	return 0;
794}
795
796int
797sximmc_pio_wait(struct sximmc_softc *sc, struct sdmmc_command *cmd)
798{
799	int retry = 0xfffff;
800	uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
801	    SXIMMC_STATUS_FIFO_EMPTY : SXIMMC_STATUS_FIFO_FULL;
802
803	while (--retry > 0) {
804		uint32_t status = MMC_READ(sc, SXIMMC_STATUS);
805		if (!(status & bit))
806			return 0;
807		delay(10);
808	}
809
810	return ETIMEDOUT;
811}
812
813int
814sximmc_pio_transfer(struct sximmc_softc *sc, struct sdmmc_command *cmd)
815{
816	u_char *datap = cmd->c_data;
817	int datalen = cmd->c_resid;
818
819	while (datalen > 3) {
820		if (sximmc_pio_wait(sc, cmd))
821			return ETIMEDOUT;
822		if (cmd->c_flags & SCF_CMD_READ) {
823			*(uint32_t *)datap = MMC_READ(sc, sc->sc_fifo_reg);
824		} else {
825			MMC_WRITE(sc, sc->sc_fifo_reg, *(uint32_t *)datap);
826		}
827		datap += 4;
828		datalen -= 4;
829	}
830
831	if (datalen > 0 && cmd->c_flags & SCF_CMD_READ) {
832		uint32_t rv = MMC_READ(sc, sc->sc_fifo_reg);
833		do {
834			*datap++ = rv & 0xff;
835			rv = rv >> 8;
836		} while(--datalen > 0);
837	} else if (datalen > 0) {
838		uint32_t rv = *datap++;
839		if (datalen > 1)
840			rv |= *datap++ << 8;
841		if (datalen > 2)
842			rv |= *datap++ << 16;
843		MMC_WRITE(sc, sc->sc_fifo_reg, rv);
844	}
845
846	return 0;
847}
848
849int
850sximmc_dma_prepare(struct sximmc_softc *sc, struct sdmmc_command *cmd)
851{
852	struct sximmc_idma_descriptor *dma = (void *)sc->sc_idma_desc;
853	bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr;
854	uint32_t val;
855	int seg;
856
857	if (sc->sc_idma_ndesc < cmd->c_dmamap->dm_nsegs) {
858		printf("%s: not enough descriptors for %d byte transfer!\n",
859		    sc->sc_dev.dv_xname, cmd->c_datalen);
860		return EIO;
861	}
862
863	for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
864		bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr;
865		bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len;
866
867		desc_paddr += sizeof(struct sximmc_idma_descriptor);
868		dma[seg].dma_buf_size = htole32(len);
869		dma[seg].dma_buf_addr = htole32(paddr >> sc->sc_idma_shift);
870		dma[seg].dma_config = htole32(SXIMMC_IDMA_CONFIG_CH |
871		    SXIMMC_IDMA_CONFIG_OWN);
872		if (seg == 0) {
873			dma[seg].dma_config |=
874			    htole32(SXIMMC_IDMA_CONFIG_FD);
875		}
876		if (seg == cmd->c_dmamap->dm_nsegs - 1) {
877			dma[seg].dma_config |=
878			    htole32(SXIMMC_IDMA_CONFIG_LD);
879			dma[seg].dma_config |=
880			    htole32(SXIMMC_IDMA_CONFIG_ER);
881			dma[seg].dma_next = 0;
882		} else {
883			dma[seg].dma_config |=
884			    htole32(SXIMMC_IDMA_CONFIG_DIC);
885			dma[seg].dma_next =
886			    htole32(desc_paddr >> sc->sc_idma_shift);
887		}
888	}
889
890	bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
891	    sc->sc_idma_size, BUS_DMASYNC_PREWRITE);
892
893	sc->sc_idma_idst = 0;
894
895	val = MMC_READ(sc, SXIMMC_GCTRL);
896	val |= SXIMMC_GCTRL_DMAEN;
897	val |= SXIMMC_GCTRL_INTEN;
898	MMC_WRITE(sc, SXIMMC_GCTRL, val);
899	val |= SXIMMC_GCTRL_DMARESET;
900	MMC_WRITE(sc, SXIMMC_GCTRL, val);
901	MMC_WRITE(sc, SXIMMC_DMAC, SXIMMC_DMAC_SOFTRESET);
902	MMC_WRITE(sc, SXIMMC_DMAC,
903	    SXIMMC_DMAC_IDMA_ON|SXIMMC_DMAC_FIX_BURST);
904	val = MMC_READ(sc, SXIMMC_IDIE);
905	val &= ~(SXIMMC_IDST_RECEIVE_INT|SXIMMC_IDST_TRANSMIT_INT);
906	if (cmd->c_flags & SCF_CMD_READ)
907		val |= SXIMMC_IDST_RECEIVE_INT;
908	else
909		val |= SXIMMC_IDST_TRANSMIT_INT;
910	MMC_WRITE(sc, SXIMMC_IDIE, val);
911	MMC_WRITE(sc, SXIMMC_DLBA,
912	    sc->sc_idma_map->dm_segs[0].ds_addr >> sc->sc_idma_shift);
913	MMC_WRITE(sc, SXIMMC_FTRGLEVEL, sc->sc_dma_ftrglevel);
914
915	return 0;
916}
917
918void
919sximmc_dma_complete(struct sximmc_softc *sc)
920{
921	bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
922	    sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
923}
924
925void
926sximmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
927{
928	struct sximmc_softc *sc = sch;
929	uint32_t cmdval = SXIMMC_CMD_START;
930	int retry;
931	int s;
932
933#ifdef SXIMMC_DEBUG
934	printf("%s: opcode %d flags 0x%x data %p datalen %d blklen %d\n",
935	    sc->sc_dev.dv_xname, cmd->c_opcode, cmd->c_flags,
936	    cmd->c_data, cmd->c_datalen, cmd->c_blklen);
937#endif
938
939	s = splbio();
940
941	if (cmd->c_opcode == 0)
942		cmdval |= SXIMMC_CMD_SEND_INIT_SEQ;
943	if (cmd->c_flags & SCF_RSP_PRESENT)
944		cmdval |= SXIMMC_CMD_RSP_EXP;
945	if (cmd->c_flags & SCF_RSP_136)
946		cmdval |= SXIMMC_CMD_LONG_RSP;
947	if (cmd->c_flags & SCF_RSP_CRC)
948		cmdval |= SXIMMC_CMD_CHECK_RSP_CRC;
949
950	if (cmd->c_datalen > 0) {
951		uint16_t blksize;
952		uint16_t blkcount;
953
954		cmdval |= SXIMMC_CMD_DATA_EXP | SXIMMC_CMD_WAIT_PRE_OVER;
955		if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
956			cmdval |= SXIMMC_CMD_WRITE;
957		}
958
959		blksize = MIN(cmd->c_datalen, cmd->c_blklen);
960		blkcount = cmd->c_datalen / blksize;
961		if (blkcount > 1 && cmd->c_opcode != SD_IO_RW_EXTENDED) {
962			cmdval |= SXIMMC_CMD_SEND_AUTO_STOP;
963		}
964
965		MMC_WRITE(sc, SXIMMC_BLKSZ, blksize);
966		MMC_WRITE(sc, SXIMMC_BYTECNT, blkcount * blksize);
967	}
968
969	sc->sc_intr_rint = 0;
970
971#if 0
972	if (awin_chip_id() == AWIN_CHIP_ID_A80) {
973		MMC_WRITE(sc, SXIMMC_A12A,
974		    (cmdval & SXIMMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff);
975	}
976#endif
977
978	MMC_WRITE(sc, SXIMMC_ARG, cmd->c_arg);
979
980#ifdef SXIMMC_DEBUG
981	printf("%s: cmdval = %08x\n", sc->sc_dev.dv_xname, cmdval);
982#endif
983
984	if (cmd->c_datalen == 0) {
985		MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
986	} else {
987		cmd->c_resid = cmd->c_datalen;
988		sximmc_led(sc, 0);
989		if (cmd->c_dmamap && sc->sc_use_dma) {
990			cmd->c_error = sximmc_dma_prepare(sc, cmd);
991			MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
992			if (cmd->c_error == 0) {
993				cmd->c_error = tsleep_nsec(&sc->sc_idma_idst,
994				    PWAIT, "idma", SEC_TO_NSEC(10));
995			}
996			sximmc_dma_complete(sc);
997			if (sc->sc_idma_idst & SXIMMC_IDST_ERROR) {
998				cmd->c_error = EIO;
999			} else if (!(sc->sc_idma_idst & SXIMMC_IDST_COMPLETE)) {
1000				cmd->c_error = ETIMEDOUT;
1001			}
1002		} else {
1003			splx(s);
1004			MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
1005			cmd->c_error = sximmc_pio_transfer(sc, cmd);
1006			s = splbio();
1007		}
1008		sximmc_led(sc, 1);
1009		if (cmd->c_error) {
1010#ifdef SXIMMC_DEBUG
1011			printf("%s: xfer failed, error %d\n",
1012			    sc->sc_dev.dv_xname, cmd->c_error);
1013#endif
1014			goto done;
1015		}
1016	}
1017
1018	cmd->c_error = sximmc_wait_rint(sc,
1019	    SXIMMC_INT_ERROR|SXIMMC_INT_CMD_DONE, hz * 10);
1020	if (cmd->c_error == 0 && (sc->sc_intr_rint & SXIMMC_INT_ERROR)) {
1021		if (sc->sc_intr_rint & SXIMMC_INT_RESP_TIMEOUT) {
1022			cmd->c_error = ETIMEDOUT;
1023		} else {
1024			cmd->c_error = EIO;
1025		}
1026	}
1027	if (cmd->c_error) {
1028#ifdef SXIMMC_DEBUG
1029		printf("%s: cmd failed, error %d\n",
1030		    sc->sc_dev.dv_xname,  cmd->c_error);
1031#endif
1032		goto done;
1033	}
1034
1035	if (cmd->c_datalen > 0) {
1036		cmd->c_error = sximmc_wait_rint(sc,
1037		    SXIMMC_INT_ERROR|
1038		    SXIMMC_INT_AUTO_CMD_DONE|
1039		    SXIMMC_INT_DATA_OVER,
1040		    hz*10);
1041		if (cmd->c_error == 0 &&
1042		    (sc->sc_intr_rint & SXIMMC_INT_ERROR)) {
1043			cmd->c_error = ETIMEDOUT;
1044		}
1045		if (cmd->c_error) {
1046#ifdef SXIMMC_DEBUG
1047			printf("%s: data timeout, rint = %08x\n",
1048			    sc->sc_dev.dv_xname, sc->sc_intr_rint);
1049#endif
1050			cmd->c_error = ETIMEDOUT;
1051			goto done;
1052		}
1053	}
1054
1055	if (cmd->c_flags & SCF_RSP_PRESENT) {
1056		if (cmd->c_flags & SCF_RSP_136) {
1057			cmd->c_resp[0] = MMC_READ(sc, SXIMMC_RESP0);
1058			cmd->c_resp[1] = MMC_READ(sc, SXIMMC_RESP1);
1059			cmd->c_resp[2] = MMC_READ(sc, SXIMMC_RESP2);
1060			cmd->c_resp[3] = MMC_READ(sc, SXIMMC_RESP3);
1061			if (cmd->c_flags & SCF_RSP_CRC) {
1062				cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
1063				    (cmd->c_resp[1] << 24);
1064				cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
1065				    (cmd->c_resp[2] << 24);
1066				cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
1067				    (cmd->c_resp[3] << 24);
1068				cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
1069			}
1070		} else {
1071			cmd->c_resp[0] = MMC_READ(sc, SXIMMC_RESP0);
1072		}
1073	}
1074
1075done:
1076	cmd->c_flags |= SCF_ITSDONE;
1077	splx(s);
1078
1079	if (cmd->c_error) {
1080#ifdef SXIMMC_DEBUG
1081		printf("%s: i/o error %d\n", sc->sc_dev.dv_xname,
1082		    cmd->c_error);
1083#endif
1084		MMC_WRITE(sc, SXIMMC_GCTRL,
1085		    MMC_READ(sc, SXIMMC_GCTRL) |
1086		      SXIMMC_GCTRL_DMARESET | SXIMMC_GCTRL_FIFORESET);
1087		for (retry = 0; retry < 1000; retry++) {
1088			if (!(MMC_READ(sc, SXIMMC_GCTRL) & SXIMMC_GCTRL_RESET))
1089				break;
1090			delay(10);
1091		}
1092		sximmc_host_reset(sc);
1093		sximmc_update_clock(sc);
1094	}
1095
1096	if (!cmd->c_dmamap || !sc->sc_use_dma) {
1097		MMC_WRITE(sc, SXIMMC_GCTRL,
1098		    MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_FIFORESET);
1099	}
1100}
1101
1102void
1103sximmc_pwrseq_pre(uint32_t phandle)
1104{
1105	uint32_t *gpios, *gpio;
1106	int node;
1107	int len;
1108
1109	node = OF_getnodebyphandle(phandle);
1110	if (node == 0)
1111		return;
1112
1113	if (!OF_is_compatible(node, "mmc-pwrseq-simple"))
1114		return;
1115
1116	pinctrl_byname(node, "default");
1117
1118	clock_enable(node, "ext_clock");
1119
1120	len = OF_getproplen(node, "reset-gpios");
1121	if (len <= 0)
1122		return;
1123
1124	gpios = malloc(len, M_TEMP, M_WAITOK);
1125	OF_getpropintarray(node, "reset-gpios", gpios, len);
1126
1127	gpio = gpios;
1128	while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
1129		gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
1130		gpio_controller_set_pin(gpio, 1);
1131		gpio = gpio_controller_next_pin(gpio);
1132	}
1133
1134	free(gpios, M_TEMP, len);
1135}
1136
1137void
1138sximmc_pwrseq_post(uint32_t phandle)
1139{
1140	uint32_t *gpios, *gpio;
1141	int node;
1142	int len;
1143
1144	node = OF_getnodebyphandle(phandle);
1145	if (node == 0)
1146		return;
1147
1148	if (!OF_is_compatible(node, "mmc-pwrseq-simple"))
1149		return;
1150
1151	len = OF_getproplen(node, "reset-gpios");
1152	if (len <= 0)
1153		return;
1154
1155	gpios = malloc(len, M_TEMP, M_WAITOK);
1156	OF_getpropintarray(node, "reset-gpios", gpios, len);
1157
1158	gpio = gpios;
1159	while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
1160		gpio_controller_set_pin(gpio, 0);
1161		gpio = gpio_controller_next_pin(gpio);
1162	}
1163
1164	free(gpios, M_TEMP, len);
1165}
1166