xref: /netbsd-src/sys/arch/arm/amlogic/mesongx_mmc.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1 /* $NetBSD: mesongx_mmc.c,v 1.5 2019/04/21 13:08:48 jmcneill Exp $ */
2 
3 /*-
4  * Copyright (c) 2019 Jared McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: mesongx_mmc.c,v 1.5 2019/04/21 13:08:48 jmcneill Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/intr.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/bitops.h>
39 #include <sys/gpio.h>
40 
41 #include <dev/sdmmc/sdmmcvar.h>
42 #include <dev/sdmmc/sdmmcchip.h>
43 #include <dev/sdmmc/sdmmc_ioreg.h>
44 
45 #include <dev/fdt/fdtvar.h>
46 
47 #define	SD_EMMC_CLOCK			0x00
48 #define	 CLOCK_CFG_IRQ_SDIO_SLEEP		__BIT(25)
49 #define	 CLOCK_CFG_ALWAYS_ON			__BIT(24)
50 #define	 CLOCK_CFG_RX_DELAY			__BITS(23,20)
51 #define	 CLOCK_CFG_TX_DELAY			__BITS(19,16)
52 #define	 CLOCK_CFG_SRAM_PD			__BITS(15,14)
53 #define	 CLOCK_CFG_RX_PHASE			__BITS(13,12)
54 #define	 CLOCK_CFG_TX_PHASE			__BITS(11,10)
55 #define	 CLOCK_CFG_CO_PHASE			__BITS(9,8)
56 #define	 CLOCK_CFG_SRC				__BITS(7,6)
57 #define	 CLOCK_CFG_DIV				__BITS(5,0)
58 #define	SD_EMMC_DELAY			0x04
59 #define	SD_EMMC_ADJUST			0x08
60 #define	 ADJUST_ADJ_DELAY			__BITS(21,16)
61 #define	 ADJUST_CALI_RISE			__BIT(14)
62 #define	 ADJUST_ADJ_ENABLE			__BIT(13)
63 #define	 ADJUST_CALI_ENABLE			__BIT(12)
64 #define	 ADJUST_CALI_SEL			__BITS(11,8)
65 #define	SD_EMMC_CALOUT			0x10
66 #define	 CALOUT_CALI_SETUP			__BITS(15,8)
67 #define	 CALOUT_CALI_VLD			__BIT(7)
68 #define	 CALOUT_CALI_IDX			__BITS(5,0)
69 #define	SD_EMMC_START			0x40
70 #define	 START_DESC_ADDR			__BITS(31,2)
71 #define	 START_DESC_BUSY			__BIT(1)
72 #define	 START_DESC_INT				__BIT(0)
73 #define	SD_EMMC_CFG			0x44
74 #define	 CFG_IP_TXD_ADJ				__BITS(31,28)
75 #define	 CFG_ERR_ABORT				__BIT(27)
76 #define	 CFG_IRQ_DS				__BIT(26)
77 #define	 CFG_TXD_RETRY				__BIT(25)
78 #define	 CFG_TXD_ADD_ERR			__BIT(24)
79 #define	 CFG_AUTO_CLK				__BIT(23)
80 #define	 CFG_STOP_CLK				__BIT(22)
81 #define	 CFG_CMD_LOW				__BIT(21)
82 #define	 CFG_CHK_DS				__BIT(20)
83 #define	 CFG_IGNORE_OWNER			__BIT(19)
84 #define	 CFG_SDCLK_ALWAYS_ON			__BIT(18)
85 #define	 CFG_BLK_GAP_IP				__BIT(17)
86 #define	 CFG_OUT_FALL				__BIT(16)
87 #define	 CFG_RC_CC				__BITS(15,12)
88 #define	 CFG_RESP_TIMEOUT			__BIT(11,8)
89 #define	 CFG_BL_LEN				__BITS(7,4)
90 #define	 CFG_DC_UGT				__BIT(3)
91 #define	 CFG_DDR				__BIT(2)
92 #define	 CFG_BUS_WIDTH				__BITS(1,0)
93 #define	  CFG_BUS_WIDTH_1			0
94 #define	  CFG_BUS_WIDTH_4			1
95 #define	  CFG_BUS_WIDTH_8			2
96 #define	SD_EMMC_STATUS			0x48
97 #define	 STATUS_CORE_BUSY			__BIT(31)
98 #define	 STATUS_DESC_BUSY			__BIT(30)
99 #define	 STATUS_BUS_FSM				__BIT(29,26)
100 #define	 STATUS_DS				__BIT(25)
101 #define	 STATUS_CMD_I				__BIT(24)
102 #define	 STATUS_DAT_I				__BITS(23,16)
103 #define	 STATUS_IRQ_SDIO			__BIT(15)
104 #define	 STATUS_RESP_STATUS			__BIT(14)
105 #define	 STATUS_END_OF_CHAIN			__BIT(13)
106 #define	 STATUS_DESC_TIMEOUT			__BIT(12)
107 #define	 STATUS_RESP_TIMEOUT			__BIT(11)
108 #define	 STATUS_RESP_ERR			__BIT(10)
109 #define	 STATUS_DESC_ERR			__BIT(9)
110 #define	 STATUS_TXD_ERR				__BIT(8)
111 #define	 STATUS_RXD_ERR				__BITS(7,0)
112 #define	 STATUS_TIMEOUT				(STATUS_DESC_TIMEOUT | STATUS_RESP_TIMEOUT)
113 #define	 STATUS_ERROR				(STATUS_RESP_ERR | STATUS_DESC_ERR | STATUS_RXD_ERR | STATUS_TXD_ERR)
114 #define	SD_EMMC_IRQ_EN			0x4c
115 #define	 IRQ_EN_CFG_SECURE			__BIT(16)
116 #define	 IRQ_EN_IRQ_SDIO			__BIT(15)
117 #define	 IRQ_EN_RESP_STATUS			__BIT(14)
118 #define	 IRQ_EN_END_OF_CHAIN			__BIT(13)
119 #define	 IRQ_EN_DESC_TIMEOUT			__BIT(12)
120 #define	 IRQ_EN_RESP_TIMEOUT			__BIT(11)
121 #define	 IRQ_EN_RESP_ERR			__BIT(10)
122 #define	 IRQ_EN_DESC_ERR			__BIT(9)
123 #define	 IRQ_EN_TXD_ERR				__BIT(8)
124 #define	 IRQ_EN_RXD_ERR				__BITS(7,0)
125 #define	SD_EMMC_CMD_CFG			0x50
126 #define	SD_EMMC_CMD_ARG			0x54
127 #define	SD_EMMC_CMD_DAT			0x58
128 #define	SD_EMMC_CMD_RSP			0x5c
129 #define	SD_EMMC_CMD_RSP1		0x60
130 #define	SD_EMMC_CMD_RSP2		0x64
131 #define	SD_EMMC_CMD_RSP3		0x68
132 
133 struct mesongx_mmc_desc {
134 	uint32_t		flags;
135 #define	MESONGX_MMC_FLAGS_OWNER		__BIT(31)
136 #define	MESONGX_MMC_FLAGS_ERROR		__BIT(30)
137 #define	MESONGX_MMC_FLAGS_CMD_INDEX	__BITS(29,24)
138 #define	MESONGX_MMC_FLAGS_DATA_NUM	__BIT(23)
139 #define	MESONGX_MMC_FLAGS_RESP_NUM	__BIT(22)
140 #define	MESONGX_MMC_FLAGS_RESP_128	__BIT(21)
141 #define	MESONGX_MMC_FLAGS_RESP_NOCRC	__BIT(20)
142 #define	MESONGX_MMC_FLAGS_DATA_WR	__BIT(19)
143 #define	MESONGX_MMC_FLAGS_DATA_IO	__BIT(18)
144 #define	MESONGX_MMC_FLAGS_NO_CMD	__BIT(17)
145 #define	MESONGX_MMC_FLAGS_NO_RESP	__BIT(16)
146 #define	MESONGX_MMC_FLAGS_TIMEOUT	__BITS(15,12)
147 #define	MESONGX_MMC_FLAGS_END_OF_CHAIN	__BIT(11)
148 #define	MESONGX_MMC_FLAGS_R1B		__BIT(10)
149 #define	MESONGX_MMC_FLAGS_BLOCK_MODE	__BIT(9)
150 #define	MESONGX_MMC_FLAGS_LENGTH	__BITS(8,0)
151 	uint32_t		arg;
152 	uint32_t		data;
153 #define	MESONGX_MMC_DATA_BIG_ENDIAN	__BIT(1)
154 #define	MESONGX_MMC_DATA_SRAM		__BIT(0)
155 	uint32_t		resp;
156 #define	MESONGX_MMC_RESP_SRAM		__BIT(0)
157 } __packed;
158 
159 #define MESONGX_MMC_NDESC		256
160 
161 struct mesongx_mmc_softc;
162 
163 static int	mesongx_mmc_match(device_t, cfdata_t, void *);
164 static void	mesongx_mmc_attach(device_t, device_t, void *);
165 static void	mesongx_mmc_attach_i(device_t);
166 
167 static int	mesongx_mmc_intr(void *);
168 static int	mesongx_mmc_dma_setup(struct mesongx_mmc_softc *);
169 static int	mesongx_mmc_dmabounce_setup(struct mesongx_mmc_softc *);
170 
171 static int	mesongx_mmc_host_reset(sdmmc_chipset_handle_t);
172 static uint32_t	mesongx_mmc_host_ocr(sdmmc_chipset_handle_t);
173 static int	mesongx_mmc_host_maxblklen(sdmmc_chipset_handle_t);
174 static int	mesongx_mmc_card_detect(sdmmc_chipset_handle_t);
175 static int	mesongx_mmc_write_protect(sdmmc_chipset_handle_t);
176 static int	mesongx_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
177 static int	mesongx_mmc_bus_clock(sdmmc_chipset_handle_t, int, bool);
178 static int	mesongx_mmc_bus_width(sdmmc_chipset_handle_t, int);
179 static int	mesongx_mmc_bus_rod(sdmmc_chipset_handle_t, int);
180 static int	mesongx_mmc_signal_voltage(sdmmc_chipset_handle_t, int);
181 static int	mesongx_mmc_execute_tuning(sdmmc_chipset_handle_t, int);
182 static void	mesongx_mmc_exec_command(sdmmc_chipset_handle_t,
183 				      struct sdmmc_command *);
184 static void	mesongx_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
185 static void	mesongx_mmc_card_intr_ack(sdmmc_chipset_handle_t);
186 
187 static struct sdmmc_chip_functions mesongx_mmc_chip_functions = {
188 	.host_reset = mesongx_mmc_host_reset,
189 	.host_ocr = mesongx_mmc_host_ocr,
190 	.host_maxblklen = mesongx_mmc_host_maxblklen,
191 	.card_detect = mesongx_mmc_card_detect,
192 	.write_protect = mesongx_mmc_write_protect,
193 	.bus_power = mesongx_mmc_bus_power,
194 	.bus_clock_ddr = mesongx_mmc_bus_clock,
195 	.bus_width = mesongx_mmc_bus_width,
196 	.bus_rod = mesongx_mmc_bus_rod,
197 	.signal_voltage = mesongx_mmc_signal_voltage,
198 	.execute_tuning = mesongx_mmc_execute_tuning,
199 	.exec_command = mesongx_mmc_exec_command,
200 	.card_enable_intr = mesongx_mmc_card_enable_intr,
201 	.card_intr_ack = mesongx_mmc_card_intr_ack,
202 };
203 
204 struct mesongx_mmc_softc {
205 	device_t		sc_dev;
206 	bus_space_tag_t		sc_bst;
207 	bus_space_handle_t	sc_bsh;
208 	bus_dma_tag_t		sc_dmat;
209 	int			sc_phandle;
210 
211 	void			*sc_ih;
212 	kmutex_t		sc_intr_lock;
213 	kcondvar_t		sc_intr_cv;
214 
215 	device_t		sc_sdmmc_dev;
216 	uint32_t		sc_host_ocr;
217 
218 	struct sdmmc_command	*sc_cmd;
219 
220 	bus_dma_segment_t	sc_desc_segs[1];
221 	int			sc_desc_nsegs;
222 	bus_size_t		sc_desc_size;
223 	bus_dmamap_t		sc_desc_map;
224 	int			sc_desc_ndesc;
225 	void			*sc_desc_desc;
226 
227 	bus_dmamap_t		sc_dmabounce_map;
228 	void			*sc_dmabounce_buf;
229 	size_t			sc_dmabounce_buflen;
230 
231 	struct clk		*sc_clk_core;
232 	struct clk		*sc_clk_clkin[2];
233 
234 	struct fdtbus_reset	*sc_rst;
235 
236 	struct fdtbus_gpio_pin	*sc_gpio_cd;
237 	int			sc_gpio_cd_inverted;
238 	struct fdtbus_gpio_pin	*sc_gpio_wp;
239 	int			sc_gpio_wp_inverted;
240 
241 	struct fdtbus_regulator	*sc_reg_vmmc;
242 	struct fdtbus_regulator	*sc_reg_vqmmc;
243 
244 	struct fdtbus_mmc_pwrseq *sc_pwrseq;
245 
246 	u_int			sc_max_frequency;
247 	bool			sc_non_removable;
248 	bool			sc_broken_cd;
249 };
250 
251 CFATTACH_DECL_NEW(mesongx_mmc, sizeof(struct mesongx_mmc_softc),
252 	mesongx_mmc_match, mesongx_mmc_attach, NULL, NULL);
253 
254 #define MMC_WRITE(sc, reg, val)	\
255 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
256 #define MMC_READ(sc, reg) \
257 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
258 
259 static const struct of_compat_data compat_data[] = {
260 	{ "amlogic,meson-gx-mmc",	1 },
261 	{ "amlogic,meson-gxbb-mmc",	1 },
262 	{ NULL }
263 };
264 
265 static int
266 mesongx_mmc_match(device_t parent, cfdata_t cf, void *aux)
267 {
268 	struct fdt_attach_args * const faa = aux;
269 
270 	return of_match_compat_data(faa->faa_phandle, compat_data);
271 }
272 
273 static void
274 mesongx_mmc_attach(device_t parent, device_t self, void *aux)
275 {
276 	struct mesongx_mmc_softc * const sc = device_private(self);
277 	struct fdt_attach_args * const faa = aux;
278 	const int phandle = faa->faa_phandle;
279 	char intrstr[128];
280 	bus_addr_t addr;
281 	bus_size_t size;
282 
283 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
284 		aprint_error(": couldn't get registers\n");
285 		return;
286 	}
287 
288 	sc->sc_clk_core = fdtbus_clock_get(phandle, "core");
289 	sc->sc_clk_clkin[0] = fdtbus_clock_get(phandle, "clkin0");
290 	sc->sc_clk_clkin[1] = fdtbus_clock_get(phandle, "clkin1");
291 
292 	if (sc->sc_clk_core == NULL || sc->sc_clk_clkin[0] == NULL ||
293 	    sc->sc_clk_clkin[1] == NULL) {
294 		aprint_error(": couldn't get clocks\n");
295 		return;
296 	}
297 
298 	sc->sc_rst = fdtbus_reset_get_index(phandle, 0);
299 	if (sc->sc_rst == NULL) {
300 		aprint_error(": couldn't get reset\n");
301 		return;
302 	}
303 
304 	sc->sc_pwrseq = fdtbus_mmc_pwrseq_get(phandle);
305 
306 	if (clk_enable(sc->sc_clk_core) != 0) {
307 		aprint_error(": couldn't enable core clock\n");
308 		return;
309 	}
310 	if (clk_enable(sc->sc_clk_clkin[0]) != 0 ||
311 	    clk_enable(sc->sc_clk_clkin[1]) != 0) {
312 		aprint_error(": couldn't enable clkin clocks\n");
313 		return;
314 	}
315 
316 	if (fdtbus_reset_deassert(sc->sc_rst) != 0) {
317 		aprint_error(": couldn't de-assert reset\n");
318 		return;
319 	}
320 
321 	sc->sc_dev = self;
322 	sc->sc_phandle = phandle;
323 	sc->sc_bst = faa->faa_bst;
324 	sc->sc_dmat = faa->faa_dmat;
325 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
326 	cv_init(&sc->sc_intr_cv, "gxmmcirq");
327 
328 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
329 		aprint_error(": couldn't map registers\n");
330 		return;
331 	}
332 
333 	aprint_naive("\n");
334 	aprint_normal(": eMMC/SD/SDIO controller\n");
335 
336 	sc->sc_reg_vmmc = fdtbus_regulator_acquire(phandle, "vmmc-supply");
337 	sc->sc_reg_vqmmc = fdtbus_regulator_acquire(phandle, "vqmmc-supply");
338 
339 	sc->sc_gpio_cd = fdtbus_gpio_acquire(phandle, "cd-gpios",
340 	    GPIO_PIN_INPUT);
341 	sc->sc_gpio_wp = fdtbus_gpio_acquire(phandle, "wp-gpios",
342 	    GPIO_PIN_INPUT);
343 
344 	sc->sc_gpio_cd_inverted = of_hasprop(phandle, "cd-inverted") ? 1 : 0;
345 	sc->sc_gpio_wp_inverted = of_hasprop(phandle, "wp-inverted") ? 1 : 0;
346 
347 	sc->sc_non_removable = of_hasprop(phandle, "non-removable");
348 	sc->sc_broken_cd = of_hasprop(phandle, "broken-cd");
349 
350 	if (of_getprop_uint32(phandle, "max-frequency", &sc->sc_max_frequency))
351 		sc->sc_max_frequency = 52000000;
352 
353 	if (mesongx_mmc_dma_setup(sc) != 0 ||
354 	    mesongx_mmc_dmabounce_setup(sc) != 0) {
355 		aprint_error_dev(self, "failed to setup DMA\n");
356 		return;
357 	}
358 
359 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
360 		aprint_error_dev(self, "failed to decode interrupt\n");
361 		return;
362 	}
363 
364 	sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, FDT_INTR_MPSAFE,
365 	    mesongx_mmc_intr, sc);
366 	if (sc->sc_ih == NULL) {
367 		aprint_error_dev(self, "failed to establish interrupt on %s\n",
368 		    intrstr);
369 		return;
370 	}
371 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
372 
373 	if (sc->sc_pwrseq)
374 		fdtbus_mmc_pwrseq_reset(sc->sc_pwrseq);
375 
376 	config_interrupts(self, mesongx_mmc_attach_i);
377 }
378 
379 static int
380 mesongx_mmc_dma_setup(struct mesongx_mmc_softc *sc)
381 {
382 	int error;
383 
384 	sc->sc_desc_ndesc = MESONGX_MMC_NDESC;
385 	sc->sc_desc_size = sizeof(struct mesongx_mmc_desc) *
386 	    sc->sc_desc_ndesc;
387 	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_desc_size,
388 	    sizeof(struct mesongx_mmc_desc),
389 	    sc->sc_desc_size, sc->sc_desc_segs, 1,
390 	    &sc->sc_desc_nsegs, BUS_DMA_WAITOK);
391 	if (error)
392 		return error;
393 	error = bus_dmamem_map(sc->sc_dmat, sc->sc_desc_segs,
394 	    sc->sc_desc_nsegs, sc->sc_desc_size,
395 	    &sc->sc_desc_desc, BUS_DMA_WAITOK);
396 	if (error)
397 		goto free;
398 	error = bus_dmamap_create(sc->sc_dmat, sc->sc_desc_size, 1,
399 	    sc->sc_desc_size, 0, BUS_DMA_WAITOK, &sc->sc_desc_map);
400 	if (error)
401 		goto unmap;
402 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_desc_map,
403 	    sc->sc_desc_desc, sc->sc_desc_size, NULL, BUS_DMA_WAITOK);
404 	if (error)
405 		goto destroy;
406 	return 0;
407 
408 destroy:
409 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_desc_map);
410 unmap:
411 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_desc_desc, sc->sc_desc_size);
412 free:
413 	bus_dmamem_free(sc->sc_dmat, sc->sc_desc_segs, sc->sc_desc_nsegs);
414 	return error;
415 }
416 
417 static int
418 mesongx_mmc_dmabounce_setup(struct mesongx_mmc_softc *sc)
419 {
420 	bus_dma_segment_t ds[1];
421 	int error, rseg;
422 
423 	sc->sc_dmabounce_buflen = MAXPHYS;
424 	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmabounce_buflen, 0,
425 	    sc->sc_dmabounce_buflen, ds, 1, &rseg, BUS_DMA_WAITOK);
426 	if (error)
427 		return error;
428 	error = bus_dmamem_map(sc->sc_dmat, ds, 1, sc->sc_dmabounce_buflen,
429 	    &sc->sc_dmabounce_buf, BUS_DMA_WAITOK);
430 	if (error)
431 		goto free;
432 	error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmabounce_buflen, 1,
433 	    sc->sc_dmabounce_buflen, 0, BUS_DMA_WAITOK, &sc->sc_dmabounce_map);
434 	if (error)
435 		goto unmap;
436 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmabounce_map,
437 	    sc->sc_dmabounce_buf, sc->sc_dmabounce_buflen, NULL,
438 	    BUS_DMA_WAITOK);
439 	if (error)
440 		goto destroy;
441 	return 0;
442 
443 destroy:
444 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmabounce_map);
445 unmap:
446 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmabounce_buf,
447 	    sc->sc_dmabounce_buflen);
448 free:
449 	bus_dmamem_free(sc->sc_dmat, ds, rseg);
450 	return error;
451 }
452 
453 static int
454 mesongx_mmc_set_clock(struct mesongx_mmc_softc *sc, u_int freq, bool ddr)
455 {
456 	int best_diff, best_sel, best_div, sel, div;
457 	uint32_t val;
458 
459 	if (freq == 0)
460 		freq = SDMMC_SDCLK_400K;
461 
462 	best_diff = INT_MAX;
463 	best_sel = 0;
464 	best_div = 0;
465 
466 	const u_int target_rate = (freq * 1000) << ddr;
467 	for (sel = 0; sel <= 1; sel++) {
468 		const u_int parent_rate = clk_get_rate(sc->sc_clk_clkin[sel]);
469 		for (div = 1; div <= 63; div++) {
470 			const u_int rate = parent_rate / div;
471 			if (rate > target_rate)
472 				continue;
473 			const int diff = target_rate - rate;
474 			if (diff < best_diff) {
475 				best_diff = diff;
476 				best_sel = sel;
477 				best_div = div;
478 			}
479 		}
480 	}
481 
482 	if (best_diff == INT_MAX)
483 		return ERANGE;
484 
485 	val = MMC_READ(sc, SD_EMMC_CLOCK);
486 	val |= CLOCK_CFG_ALWAYS_ON;
487 	val &= ~CLOCK_CFG_RX_PHASE;
488 	val |= __SHIFTIN(0, CLOCK_CFG_RX_PHASE);
489 	val &= ~CLOCK_CFG_TX_PHASE;
490 	val |= __SHIFTIN(2, CLOCK_CFG_TX_PHASE);
491 	val &= ~CLOCK_CFG_CO_PHASE;
492 	val |= __SHIFTIN(3, CLOCK_CFG_CO_PHASE);
493 	val &= ~CLOCK_CFG_SRC;
494 	val |= __SHIFTIN(best_sel, CLOCK_CFG_SRC);
495 	val &= ~CLOCK_CFG_DIV;
496 	val |= __SHIFTIN(best_div, CLOCK_CFG_DIV);
497 	MMC_WRITE(sc, SD_EMMC_CLOCK, val);
498 
499 	return 0;
500 }
501 
502 static void
503 mesongx_mmc_attach_i(device_t self)
504 {
505 	struct mesongx_mmc_softc * const sc = device_private(self);
506 	struct sdmmcbus_attach_args saa;
507 	uint32_t width;
508 
509 	if (sc->sc_pwrseq)
510 		fdtbus_mmc_pwrseq_pre_power_on(sc->sc_pwrseq);
511 
512 	mesongx_mmc_bus_clock(sc, SDMMC_SDCLK_400K, false);
513 	mesongx_mmc_host_reset(sc);
514 	mesongx_mmc_bus_width(sc, 1);
515 
516 	if (sc->sc_pwrseq)
517 		fdtbus_mmc_pwrseq_post_power_on(sc->sc_pwrseq);
518 
519 	if (of_getprop_uint32(sc->sc_phandle, "bus-width", &width) != 0)
520 		width = 4;
521 
522 	memset(&saa, 0, sizeof(saa));
523 	saa.saa_busname = "sdmmc";
524 	saa.saa_sct = &mesongx_mmc_chip_functions;
525 	saa.saa_sch = sc;
526 	saa.saa_dmat = sc->sc_dmat;
527 	saa.saa_clkmin = SDMMC_SDCLK_400K;
528 	saa.saa_clkmax = sc->sc_max_frequency / 1000;
529 	saa.saa_caps = SMC_CAPS_DMA;
530 #if notyet
531 	/* XXX causes init to die when using root on eMMC with ODROID-C2 */
532 	saa.saa_caps |= SMC_CAPS_MULTI_SEG_DMA;
533 #endif
534 
535 	sc->sc_host_ocr = MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
536 
537 	if (of_getprop_bool(sc->sc_phandle, "cap-sd-highspeed")) {
538 		saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED;
539 		sc->sc_host_ocr |= MMC_OCR_HCS;
540 	}
541 	if (of_getprop_bool(sc->sc_phandle, "cap-mmc-highspeed"))
542 		saa.saa_caps |= SMC_CAPS_MMC_HIGHSPEED;
543 
544 	if (of_getprop_bool(sc->sc_phandle, "mmc-ddr-3_3v")) {
545 		saa.saa_caps |= SMC_CAPS_MMC_DDR52;
546 	}
547 
548 	if (of_getprop_bool(sc->sc_phandle, "mmc-ddr-1_8v")) {
549 		saa.saa_caps |= SMC_CAPS_MMC_DDR52;
550 		sc->sc_host_ocr |= MMC_OCR_1_65V_1_95V;
551 	}
552 	if (of_getprop_bool(sc->sc_phandle, "mmc-hs200-1_8v")) {
553 		saa.saa_caps |= SMC_CAPS_MMC_HS200;
554 		sc->sc_host_ocr |= MMC_OCR_1_65V_1_95V;
555 	}
556 
557 	if (width == 4)
558 		saa.saa_caps |= SMC_CAPS_4BIT_MODE;
559 	if (width == 8)
560 		saa.saa_caps |= SMC_CAPS_8BIT_MODE;
561 
562 	if (sc->sc_gpio_cd)
563 		saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
564 
565 	sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
566 }
567 
568 static int
569 mesongx_mmc_intr(void *priv)
570 {
571 	struct mesongx_mmc_softc * const sc = priv;
572 	struct sdmmc_command *cmd;
573 	int rv = 0;
574 
575 	mutex_enter(&sc->sc_intr_lock);
576 
577 	const uint32_t irq_en = MMC_READ(sc, SD_EMMC_IRQ_EN);
578 	const uint32_t status = MMC_READ(sc, SD_EMMC_STATUS) & irq_en;
579 
580 	if ((status & STATUS_IRQ_SDIO) != 0) {
581 		rv = 1;
582 		sdmmc_card_intr(sc->sc_sdmmc_dev);
583 	}
584 
585 	cmd = sc->sc_cmd;
586 	if (cmd == NULL) {
587 		device_printf(sc->sc_dev, "WARNING: IRQ with no active command, status %#x\n", status);
588 		goto done;
589 	}
590 
591 	if ((status & STATUS_TIMEOUT) != 0) {
592 		rv = 1;
593 		cmd->c_error = ETIMEDOUT;
594 		goto done;
595 	}
596 
597 	if ((status & STATUS_ERROR) != 0) {
598 		rv = 1;
599 		cmd->c_error = EIO;
600 		goto done;
601 	}
602 
603 	if ((status & STATUS_END_OF_CHAIN) != 0 && (cmd->c_flags & SCF_ITSDONE) == 0) {
604 		rv = 1;
605 		if ((cmd->c_flags & SCF_RSP_PRESENT) != 0) {
606 			if (cmd->c_flags & SCF_RSP_136) {
607 				cmd->c_resp[0] = MMC_READ(sc, SD_EMMC_CMD_RSP);
608 				cmd->c_resp[1] = MMC_READ(sc, SD_EMMC_CMD_RSP1);
609 				cmd->c_resp[2] = MMC_READ(sc, SD_EMMC_CMD_RSP2);
610 				cmd->c_resp[3] = MMC_READ(sc, SD_EMMC_CMD_RSP3);
611 				if (cmd->c_flags & SCF_RSP_CRC) {
612 					cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
613 					    (cmd->c_resp[1] << 24);
614 					cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
615 					    (cmd->c_resp[2] << 24);
616 					cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
617 					    (cmd->c_resp[3] << 24);
618 					cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
619 				}
620 			} else {
621 				cmd->c_resp[0] = MMC_READ(sc, SD_EMMC_CMD_RSP);
622 			}
623 		}
624 		cmd->c_flags |= SCF_ITSDONE;
625 		cmd->c_error = 0;
626 		goto done;
627 	}
628 
629 done:
630 	if (rv) {
631 		cv_broadcast(&sc->sc_intr_cv);
632 		MMC_WRITE(sc, SD_EMMC_STATUS, irq_en);
633 	}
634 
635 	mutex_exit(&sc->sc_intr_lock);
636 
637 	return rv;
638 }
639 
640 static int
641 mesongx_mmc_host_reset(sdmmc_chipset_handle_t sch)
642 {
643 	struct mesongx_mmc_softc * const sc = sch;
644 	uint32_t val;
645 
646 	MMC_WRITE(sc, SD_EMMC_START, 0);
647 
648 	val = MMC_READ(sc, SD_EMMC_CFG);
649 	val &= ~CFG_RC_CC;
650 	val |= __SHIFTIN(ilog2(16), CFG_RC_CC);
651 	val |= CFG_SDCLK_ALWAYS_ON;
652 	MMC_WRITE(sc, SD_EMMC_CFG, val);
653 
654 	return 0;
655 }
656 
657 static uint32_t
658 mesongx_mmc_host_ocr(sdmmc_chipset_handle_t sch)
659 {
660 	struct mesongx_mmc_softc * const sc = sch;
661 
662 	return sc->sc_host_ocr;
663 }
664 
665 static int
666 mesongx_mmc_host_maxblklen(sdmmc_chipset_handle_t sch)
667 {
668 	return 512;
669 }
670 
671 static int
672 mesongx_mmc_card_detect(sdmmc_chipset_handle_t sch)
673 {
674 	struct mesongx_mmc_softc * const sc = sch;
675 	int val;
676 
677 	if (sc->sc_non_removable || sc->sc_broken_cd) {
678 		/*
679 		 * Non-removable or broken card detect flag set in
680 		 * DT, assume always present
681 		 */
682 		return 1;
683 	} else if (sc->sc_gpio_cd != NULL) {
684 		val = fdtbus_gpio_read(sc->sc_gpio_cd);
685 		if (sc->sc_gpio_cd_inverted)
686 			val = !val;
687 		return val;
688 	} else {
689 		return 1;
690 	}
691 }
692 
693 static int
694 mesongx_mmc_write_protect(sdmmc_chipset_handle_t sch)
695 {
696 	struct mesongx_mmc_softc * const sc = sch;
697 	int val;
698 
699 	if (sc->sc_gpio_wp != NULL) {
700 		val = fdtbus_gpio_read(sc->sc_gpio_wp);
701 		if (sc->sc_gpio_wp_inverted)
702 			val = !val;
703 		return val;
704 	}
705 
706 	return 0;
707 }
708 
709 static int
710 mesongx_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
711 {
712 	return 0;
713 }
714 
715 static int
716 mesongx_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, bool ddr)
717 {
718 	struct mesongx_mmc_softc * const sc = sch;
719 	uint32_t val;
720 	int error;
721 
722 	error = mesongx_mmc_set_clock(sc, freq, ddr);
723 	if (error != 0)
724 		return error;
725 
726 	val = MMC_READ(sc, SD_EMMC_CFG);
727 	if (ddr)
728 		val |= CFG_DDR;
729 	else
730 		val &= ~CFG_DDR;
731 	MMC_WRITE(sc, SD_EMMC_CFG, val);
732 
733 	return 0;
734 }
735 
736 static int
737 mesongx_mmc_bus_width(sdmmc_chipset_handle_t sch, int width)
738 {
739 	struct mesongx_mmc_softc *sc = sch;
740 	uint32_t val;
741 
742 	val = MMC_READ(sc, SD_EMMC_CFG);
743 	val &= ~CFG_BUS_WIDTH;
744 
745 	switch (width) {
746 	case 1:
747 		val |= __SHIFTIN(CFG_BUS_WIDTH_1, CFG_BUS_WIDTH);
748 		break;
749 	case 4:
750 		val |= __SHIFTIN(CFG_BUS_WIDTH_4, CFG_BUS_WIDTH);
751 		break;
752 	case 8:
753 		val |= __SHIFTIN(CFG_BUS_WIDTH_8, CFG_BUS_WIDTH);
754 		break;
755 	default:
756 		return EINVAL;
757 	}
758 
759 	MMC_WRITE(sc, SD_EMMC_CFG, val);
760 
761 	return 0;
762 }
763 
764 static int
765 mesongx_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
766 {
767 	return -1;
768 }
769 
770 static int
771 mesongx_mmc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
772 {
773 	struct mesongx_mmc_softc *sc = sch;
774 	u_int uvol;
775 	int error;
776 
777 	if (sc->sc_reg_vqmmc == NULL)
778 		return 0;
779 
780 	switch (signal_voltage) {
781 	case SDMMC_SIGNAL_VOLTAGE_330:
782 		uvol = 3300000;
783 		break;
784 	case SDMMC_SIGNAL_VOLTAGE_180:
785 		uvol = 1800000;
786 		break;
787 	default:
788 		return EINVAL;
789 	}
790 
791 	error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol);
792 	if (error != 0)
793 		return 0;
794 
795 	error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol);
796 	if (error != 0)
797 		return error;
798 
799 	return fdtbus_regulator_enable(sc->sc_reg_vqmmc);
800 }
801 
802 static int
803 mesongx_mmc_execute_tuning(sdmmc_chipset_handle_t sch, int timing)
804 {
805 	switch (timing) {
806 	case SDMMC_TIMING_MMC_HS200:
807 		break;
808 	default:
809 		return EINVAL;
810 	}
811 
812 	return 0;
813 }
814 
815 static int
816 mesongx_mmc_dma_prepare(struct mesongx_mmc_softc *sc, struct sdmmc_command *cmd, uint32_t cmdflags)
817 {
818 	struct mesongx_mmc_desc *dma = sc->sc_desc_desc;
819 	bus_dmamap_t map = cmd->c_dmamap;
820 	u_int xferlen, blen, resid;
821 	bus_size_t off;
822 	uint32_t flags;
823 	int desc, seg;
824 
825 	if (cmd->c_blklen > 512) {
826 		device_printf(sc->sc_dev, "block length %d not supported\n", cmd->c_blklen);
827 		return EINVAL;
828 	}
829 
830 	for (seg = 0; seg < map->dm_nsegs; seg++) {
831 		if (map->dm_segs[seg].ds_len % cmd->c_blklen != 0) {
832 			/* Force DMA bounce for unaligned transfers */
833 			map = NULL;
834 			break;
835 		}
836 	}
837 
838 	if (map == NULL) {
839 		map = sc->sc_dmabounce_map;
840 		cmd->c_flags |= SCF_NEED_BOUNCE;
841 
842 		if ((cmd->c_flags & SCF_CMD_READ) != 0) {
843 			memset(sc->sc_dmabounce_buf, 0, cmd->c_datalen);
844 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
845 			    0, cmd->c_datalen, BUS_DMASYNC_PREREAD);
846 		} else {
847 			memcpy(sc->sc_dmabounce_buf, cmd->c_data, cmd->c_datalen);
848 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
849 			    0, cmd->c_datalen, BUS_DMASYNC_PREWRITE);
850 		}
851 	}
852 
853 	desc = 0;
854 	for (seg = 0; seg < map->dm_nsegs; seg++) {
855 		bus_addr_t paddr = map->dm_segs[seg].ds_addr;
856 		bus_size_t len = map->dm_segs[seg].ds_len;
857 		resid = uimin(len, cmd->c_resid);
858 		off = 0;
859 		while (resid > 0) {
860 			if (desc == sc->sc_desc_ndesc)
861 				break;
862 
863 			flags = cmdflags;
864 
865 			if (resid >= cmd->c_blklen) {
866 				xferlen = (resid / cmd->c_blklen) * cmd->c_blklen;
867 				blen = xferlen / cmd->c_blklen;
868 				flags |= MESONGX_MMC_FLAGS_BLOCK_MODE;
869 			} else {
870 				blen = xferlen = resid;
871 			}
872 			KASSERT(xferlen > 0);
873 			KASSERT(blen <= 512);
874 
875 			flags |= __SHIFTIN(blen % 512, MESONGX_MMC_FLAGS_LENGTH);
876 			if (desc > 0)
877 				flags |= MESONGX_MMC_FLAGS_NO_CMD;
878 			if (cmd->c_resid == xferlen)
879 				flags |= MESONGX_MMC_FLAGS_END_OF_CHAIN;
880 
881 			dma[desc].flags = htole32(flags);
882 			dma[desc].arg = htole32(cmd->c_arg);
883 			dma[desc].data = htole32(paddr + off);
884 			dma[desc].resp = 0;
885 
886 			cmd->c_resid -= xferlen;
887 			resid -= xferlen;
888 			off += xferlen;
889 
890 			if (cmd->c_resid == 0)
891 				break;
892 
893 			++desc;
894 		}
895 	}
896 	if (desc == sc->sc_desc_ndesc) {
897 		device_printf(sc->sc_dev,
898 		    "not enough descriptors for %d byte transfer (%d segs)!\n",
899 		    cmd->c_datalen, map->dm_nsegs);
900 		return EIO;
901 	}
902 
903 	bus_dmamap_sync(sc->sc_dmat, sc->sc_desc_map, 0,
904 	    sc->sc_desc_size, BUS_DMASYNC_PREWRITE);
905 
906 	return 0;
907 }
908 
909 static void
910 mesongx_mmc_dma_complete(struct mesongx_mmc_softc *sc, struct sdmmc_command *cmd)
911 {
912 	bus_dmamap_sync(sc->sc_dmat, sc->sc_desc_map, 0,
913 	    sc->sc_desc_size, BUS_DMASYNC_POSTWRITE);
914 
915 	if ((cmd->c_flags & SCF_NEED_BOUNCE) != 0) {
916 		if ((cmd->c_flags & SCF_CMD_READ) != 0) {
917 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
918 			    0, cmd->c_datalen, BUS_DMASYNC_POSTREAD);
919 			memcpy(cmd->c_data, sc->sc_dmabounce_buf, cmd->c_datalen);
920 		} else {
921 			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
922 			    0, cmd->c_datalen, BUS_DMASYNC_POSTWRITE);
923 		}
924 	}
925 }
926 
927 static void
928 mesongx_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
929 {
930 	struct mesongx_mmc_softc *sc = sch;
931 	uint32_t cmdflags, val;
932 	int error;
933 
934 	const uint32_t irq_mask = IRQ_EN_RESP_STATUS |
935 				  IRQ_EN_END_OF_CHAIN |
936 				  IRQ_EN_DESC_TIMEOUT |
937 				  IRQ_EN_RESP_TIMEOUT |
938 				  IRQ_EN_RESP_ERR |
939 				  IRQ_EN_DESC_ERR |
940 				  IRQ_EN_TXD_ERR |
941 				  IRQ_EN_RXD_ERR;
942 
943 	mutex_enter(&sc->sc_intr_lock);
944 
945 	while (sc->sc_cmd != NULL)
946 		cv_wait(&sc->sc_intr_cv, &sc->sc_intr_lock);
947 	sc->sc_cmd = cmd;
948 
949 	MMC_WRITE(sc, SD_EMMC_START, 0);
950 	MMC_WRITE(sc, SD_EMMC_STATUS, MMC_READ(sc, SD_EMMC_STATUS));
951 
952 	val = MMC_READ(sc, SD_EMMC_IRQ_EN);
953 	MMC_WRITE(sc, SD_EMMC_IRQ_EN, val | irq_mask);
954 
955 	cmdflags = MESONGX_MMC_FLAGS_OWNER;
956 	cmdflags |= __SHIFTIN(12, MESONGX_MMC_FLAGS_TIMEOUT);	/* 2^12 = 4096 ms timeout */
957 	cmdflags |= __SHIFTIN(cmd->c_opcode, MESONGX_MMC_FLAGS_CMD_INDEX);
958 
959 	if ((cmd->c_flags & SCF_RSP_PRESENT) == 0) {
960 		cmdflags |= MESONGX_MMC_FLAGS_NO_RESP;
961 	} else {
962 		cmdflags |= MESONGX_MMC_FLAGS_RESP_NUM;
963 		if ((cmd->c_flags & SCF_RSP_136) != 0)
964 			cmdflags |= MESONGX_MMC_FLAGS_RESP_128;
965 		if ((cmd->c_flags & SCF_RSP_CRC) == 0)
966 			cmdflags |= MESONGX_MMC_FLAGS_RESP_NOCRC;
967 		if ((cmd->c_flags & SCF_RSP_MASK) == SCF_RSP_R1B)
968 			cmdflags |= MESONGX_MMC_FLAGS_R1B;
969 	}
970 
971 	if (cmd->c_datalen > 0) {
972 		cmdflags |= MESONGX_MMC_FLAGS_DATA_IO;
973 		if ((cmd->c_flags & SCF_CMD_READ) == 0)
974 			cmdflags |= MESONGX_MMC_FLAGS_DATA_WR;
975 
976 		val = MMC_READ(sc, SD_EMMC_CFG);
977 		val &= ~CFG_BL_LEN;
978 		val |= __SHIFTIN(ilog2(cmd->c_blklen), CFG_BL_LEN);
979 		MMC_WRITE(sc, SD_EMMC_CFG, val);
980 
981 		cmd->c_resid = cmd->c_datalen;
982 		cmd->c_error = mesongx_mmc_dma_prepare(sc, cmd, cmdflags);
983 		if (cmd->c_error != 0)
984 			goto done;
985 
986 		const bus_addr_t desc_paddr = sc->sc_desc_map->dm_segs[0].ds_addr;
987 		MMC_WRITE(sc, SD_EMMC_START, desc_paddr | START_DESC_BUSY);	/* starts transfer */
988 	} else {
989 		MMC_WRITE(sc, SD_EMMC_CMD_CFG, cmdflags | MESONGX_MMC_FLAGS_END_OF_CHAIN);
990 		MMC_WRITE(sc, SD_EMMC_CMD_DAT, 0);
991 		MMC_WRITE(sc, SD_EMMC_CMD_ARG, cmd->c_arg);			/* starts transfer */
992 	}
993 
994 	struct bintime timeout = { .sec = 5, .frac = 0 };
995 	const struct bintime epsilon = { .sec = 1, .frac = 0 };
996 
997 	while ((cmd->c_flags & SCF_ITSDONE) == 0 && cmd->c_error == 0) {
998 		error = cv_timedwaitbt(&sc->sc_intr_cv, &sc->sc_intr_lock, &timeout, &epsilon);
999 		if (error != 0) {
1000 			cmd->c_error = error;
1001 			goto done;
1002 		}
1003 	}
1004 
1005 	if (cmd->c_error == 0 && cmd->c_datalen > 0)
1006 		mesongx_mmc_dma_complete(sc, cmd);
1007 
1008 done:
1009 	MMC_WRITE(sc, SD_EMMC_START, 0);
1010 
1011 	val = MMC_READ(sc, SD_EMMC_IRQ_EN);
1012 	MMC_WRITE(sc, SD_EMMC_IRQ_EN, val & ~irq_mask);
1013 
1014 	sc->sc_cmd = NULL;
1015 	cv_broadcast(&sc->sc_intr_cv);
1016 
1017 #ifdef MESONGX_MMC_DEBUG
1018 	if (cmd->c_error != 0) {
1019 		for (u_int reg = 0x00; reg < 0x100; reg += 0x10) {
1020 			device_printf(sc->sc_dev, "      %02x: %08x %08x %08x %08x\n", reg,
1021 			    MMC_READ(sc, reg + 0),
1022 			    MMC_READ(sc, reg + 4),
1023 			    MMC_READ(sc, reg + 8),
1024 			    MMC_READ(sc, reg + 12));
1025 		}
1026 	}
1027 #endif
1028 
1029 	mutex_exit(&sc->sc_intr_lock);
1030 }
1031 
1032 static void
1033 mesongx_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
1034 {
1035 	struct mesongx_mmc_softc * const sc = sch;
1036 	uint32_t val;
1037 
1038 	mutex_enter(&sc->sc_intr_lock);
1039 
1040 	val = MMC_READ(sc, SD_EMMC_IRQ_EN);
1041 	MMC_WRITE(sc, SD_EMMC_IRQ_EN, val | IRQ_EN_IRQ_SDIO);
1042 
1043 	mutex_exit(&sc->sc_intr_lock);
1044 }
1045 
1046 static void
1047 mesongx_mmc_card_intr_ack(sdmmc_chipset_handle_t sch)
1048 {
1049 	struct mesongx_mmc_softc *sc = sch;
1050 
1051 	MMC_WRITE(sc, SD_EMMC_STATUS, STATUS_IRQ_SDIO);
1052 }
1053