Home | History | Annotate | Line # | Download | only in imx
      1 /* $NetBSD: imx23_mmc.c,v 1.7 2026/07/07 04:54:34 skrll Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Petri Laakso.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 #include <sys/types.h>
     34 #include <sys/bus.h>
     35 #include <sys/cdefs.h>
     36 #include <sys/condvar.h>
     37 #include <sys/device.h>
     38 #include <sys/errno.h>
     39 #include <sys/mutex.h>
     40 #include <sys/systm.h>
     41 
     42 #include <dev/fdt/fdtvar.h>
     43 #include <dev/sdmmc/sdmmcchip.h>
     44 #include <dev/sdmmc/sdmmcreg.h>
     45 #include <dev/sdmmc/sdmmcvar.h>
     46 
     47 #include <arm/imx/imx23_icollreg.h>
     48 #include <arm/imx/imx23_mmcreg.h>
     49 #include <arm/imx/imx23var.h>
     50 #include <arm/pic/picvar.h>
     51 
     52 /*
     53  * SD/MMC host controller driver for i.MX23.
     54  *
     55  * TODO:
     56  *
     57  * - Add support for SMC_CAPS_AUTO_STOP.
     58  * - Uset GPIO for SD card detection.
     59  */
     60 
     61 struct imx23_mmc_softc {
     62 	device_t sc_dev;
     63 	struct fdtbus_dma *dma_channel;
     64 	bus_space_handle_t sc_hdl;
     65 	bus_space_tag_t sc_iot;
     66 	device_t sc_sdmmc;
     67 	kmutex_t sc_lock;
     68 	struct kcondvar sc_intr_cv;
     69 	uint32_t sc_irq_error;
     70 	uint8_t sc_state;
     71 	uint8_t sc_bus_width;
     72 	uint32_t pio_words[3];
     73 };
     74 
     75 
     76 static int	imx23_mmc_match(device_t, cfdata_t, void *);
     77 static void	imx23_mmc_attach(device_t, device_t, void *);
     78 
     79 static void	imx23_mmc_reset(struct imx23_mmc_softc *);
     80 static void	imx23_mmc_init(struct imx23_mmc_softc *);
     81 static uint32_t	imx23_mmc_set_sck(struct imx23_mmc_softc *, uint32_t);
     82 static void	imx23_mmc_dma_intr(void *);
     83 static int	imx23_mmc_error_intr(void *);
     84 static void 	imx23_mmc_prepare_data_command(struct imx23_mmc_softc *,
     85 			       struct fdtbus_dma_req *, struct sdmmc_command *);
     86 static void 	imx23_mmc_prepare_command(struct imx23_mmc_softc *,
     87 			  struct fdtbus_dma_req *, struct sdmmc_command *);
     88 
     89 /* sdmmc(4) driver chip function prototypes. */
     90 static int	imx23_mmc_host_reset(sdmmc_chipset_handle_t);
     91 static uint32_t	imx23_mmc_host_ocr(sdmmc_chipset_handle_t);
     92 static int	imx23_mmc_host_maxblklen(sdmmc_chipset_handle_t);
     93 static int	imx23_mmc_card_detect(sdmmc_chipset_handle_t);
     94 static int	imx23_mmc_write_protect(sdmmc_chipset_handle_t);
     95 static int	imx23_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
     96 static int	imx23_mmc_bus_clock(sdmmc_chipset_handle_t, int);
     97 static int	imx23_mmc_bus_width(sdmmc_chipset_handle_t, int);
     98 static int	imx23_mmc_bus_rod(sdmmc_chipset_handle_t, int);
     99 static void	imx23_mmc_exec_command(sdmmc_chipset_handle_t,
    100 		struct sdmmc_command *);
    101 static void	imx23_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
    102 static void	imx23_mmc_card_intr_ack(sdmmc_chipset_handle_t);
    103 
    104 static struct sdmmc_chip_functions imx23_mmc_functions = {
    105 	.host_reset	= imx23_mmc_host_reset,
    106 	.host_ocr	= imx23_mmc_host_ocr,
    107 	.host_maxblklen	= imx23_mmc_host_maxblklen,
    108 	.card_detect	= imx23_mmc_card_detect,
    109 	.write_protect	= imx23_mmc_write_protect,
    110 	.bus_power	= imx23_mmc_bus_power,
    111 	.bus_clock	= imx23_mmc_bus_clock,
    112 	.bus_width	= imx23_mmc_bus_width,
    113 	.bus_rod	= imx23_mmc_bus_rod,
    114 	.exec_command	= imx23_mmc_exec_command,
    115 	.card_enable_intr = imx23_mmc_card_enable_intr,
    116 	.card_intr_ack	= imx23_mmc_card_intr_ack
    117 };
    118 
    119 CFATTACH_DECL_NEW(imx23mmc, sizeof(struct imx23_mmc_softc), imx23_mmc_match,
    120 		  imx23_mmc_attach, NULL, NULL);
    121 
    122 #define SSP_SOFT_RST_LOOP 455	/* At least 1 us ... */
    123 
    124 #define SSP_RD(sc, reg)							\
    125 	bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
    126 #define SSP_WR(sc, reg, val)						\
    127 	bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
    128 
    129 #define SSP_CLK		160000000	/* CLK_SSP from PLL in Hz */
    130 #define SSP_CLK_MIN	400		/* 400 kHz */
    131 #define SSP_CLK_MAX	48000		/* 48 MHz */
    132 
    133 /* DATA_TIMEOUT is calculated as: * (1 / SSP_CLK) * (DATA_TIMEOUT * 4096) */
    134 #define DATA_TIMEOUT 0x4240
    135 
    136 #define BUS_WIDTH_1_BIT 0x0
    137 #define BUS_WIDTH_4_BIT 0x1
    138 #define BUS_WIDTH_8_BIT 0x2
    139 
    140 /* Flags for sc_state. */
    141 #define SSP_STATE_IDLE	0
    142 #define SSP_STATE_DMA	1
    143 
    144 #define HW_SSP_CTRL1_IRQ_MASK (						\
    145     HW_SSP_CTRL1_SDIO_IRQ |						\
    146     HW_SSP_CTRL1_RESP_ERR_IRQ |						\
    147     HW_SSP_CTRL1_RESP_TIMEOUT_IRQ |					\
    148     HW_SSP_CTRL1_DATA_TIMEOUT_IRQ |					\
    149     HW_SSP_CTRL1_DATA_CRC_IRQ |						\
    150     HW_SSP_CTRL1_FIFO_UNDERRUN_IRQ |					\
    151     HW_SSP_CTRL1_RECV_TIMEOUT_IRQ |					\
    152     HW_SSP_CTRL1_FIFO_OVERRUN_IRQ)
    153 
    154 /* SSP does not support over 64k transfer size. */
    155 #define MAX_TRANSFER_SIZE 65536
    156 
    157 /* Offsets of pio words in pio array */
    158 #define PIO_WORD_CTRL0	0
    159 #define PIO_WORD_CMD0	1
    160 #define PIO_WORD_CMD1	2
    161 
    162 static const struct device_compatible_entry compat_data[] = {
    163 	{ .compat = "fsl,imx23-mmc" },
    164 	DEVICE_COMPAT_EOL
    165 };
    166 
    167 static int
    168 imx23_mmc_match(device_t parent, cfdata_t match, void *aux)
    169 {
    170 	struct fdt_attach_args *const faa = aux;
    171 
    172 	return of_compatible_match(faa->faa_phandle, compat_data);
    173 }
    174 
    175 static void
    176 imx23_mmc_attach(device_t parent, device_t self, void *aux)
    177 {
    178 	struct imx23_mmc_softc *const sc = device_private(self);
    179 	struct fdt_attach_args *const faa = aux;
    180 	const int phandle = faa->faa_phandle;
    181 	struct sdmmcbus_attach_args saa;
    182 	char intrstr[128];
    183 
    184 	sc->sc_dev = self;
    185 	sc->sc_iot = faa->faa_bst;
    186 
    187 	/* map ssp control registers */
    188 	bus_addr_t addr;
    189 	bus_size_t size;
    190 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
    191 		aprint_error(": couldn't get register address\n");
    192 		return;
    193 	}
    194 	if (bus_space_map(faa->faa_bst, addr, size, 0, &sc->sc_hdl)) {
    195 		aprint_error(": couldn't map registers\n");
    196 		return;
    197 	}
    198 
    199 	/* Initialize lock. */
    200 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED);
    201 
    202 	/* Condvar to wait interrupt complete. */
    203 	cv_init(&sc->sc_intr_cv, "ssp_intr");
    204 
    205 	/* acquire DMA channel */
    206 	sc->dma_channel = fdtbus_dma_get(phandle,"rx-tx", imx23_mmc_dma_intr,
    207 					 sc);
    208 	if(sc->dma_channel == NULL) {
    209 		aprint_error(": couldn't map registers\n");
    210 		return;
    211 	}
    212 
    213 	/* establish error interrupt */
    214 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
    215 		aprint_error(": failed to decode interrupt\n");
    216 		return;
    217 	}
    218 	void *ih = fdtbus_intr_establish_xname(phandle, 0, IPL_SDMMC, IST_LEVEL,
    219 					       imx23_mmc_error_intr, sc,
    220 					 device_xname(self));
    221 	if (ih == NULL) {
    222 		aprint_error_dev(self, "couldn't establish error interrupt\n");
    223 		return;
    224 	}
    225 
    226 	imx23_mmc_reset(sc);
    227 	imx23_mmc_init(sc);
    228 
    229 	uint32_t imx23_mmc_vers = SSP_RD(sc, HW_SSP_VERSION);
    230 	aprint_normal(": SSP Block v%" __PRIuBIT ".%" __PRIuBIT "\n",
    231 	    __SHIFTOUT(imx23_mmc_vers, HW_SSP_VERSION_MAJOR),
    232 	    __SHIFTOUT(imx23_mmc_vers, HW_SSP_VERSION_MINOR));
    233 
    234 	/* Attach sdmmc to ssp bus. */
    235 	memset(&saa, 0, sizeof(saa));
    236 	saa.saa_busname = "sdmmc";
    237 	saa.saa_sct	= &imx23_mmc_functions;
    238 	saa.saa_spi_sct	= NULL;
    239 	saa.saa_sch	= sc;
    240 	saa.saa_dmat	= faa->faa_dmat;
    241 	saa.saa_clkmin	= SSP_CLK_MIN;
    242 	saa.saa_clkmax	= SSP_CLK_MAX;
    243 	saa.saa_caps	= SMC_CAPS_DMA | SMC_CAPS_4BIT_MODE |
    244 		          SMC_CAPS_MULTI_SEG_DMA;
    245 
    246 	sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL, CFARGS_NONE);
    247 	if (sc->sc_sdmmc == NULL) {
    248 		aprint_error_dev(sc->sc_dev, "unable to attach sdmmc\n");
    249 		return;
    250 	}
    251 }
    252 
    253 /*
    254  * sdmmc chip functions.
    255  */
    256 static int
    257 imx23_mmc_host_reset(sdmmc_chipset_handle_t sch)
    258 {
    259 	struct imx23_mmc_softc *sc = sch;
    260 	imx23_mmc_reset(sc);
    261 	return 0;
    262 }
    263 
    264 static uint32_t
    265 imx23_mmc_host_ocr(sdmmc_chipset_handle_t sch)
    266 {
    267 	/* SSP supports at least 3.2 - 3.3v */
    268 	return MMC_OCR_3_2V_3_3V;
    269 }
    270 
    271 static int
    272 imx23_mmc_host_maxblklen(sdmmc_chipset_handle_t sch)
    273 {
    274 	return 512;
    275 }
    276 
    277 /*
    278  * Called at the beginning of sdmmc_task_thread to detect the presence
    279  * of the SD card.
    280  */
    281 static int
    282 imx23_mmc_card_detect(sdmmc_chipset_handle_t sch)
    283 {
    284 	return 1; /* the olinuxino has no card detection */
    285 }
    286 
    287 static int
    288 imx23_mmc_write_protect(sdmmc_chipset_handle_t sch)
    289 {
    290 	/* The device is not write protected. */
    291 	return 0;
    292 }
    293 
    294 static int
    295 imx23_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
    296 {
    297 	/* i.MX23 SSP does not support setting bus power. */
    298 	return 0;
    299 }
    300 
    301 static int
    302 imx23_mmc_bus_clock(sdmmc_chipset_handle_t sch, int clock)
    303 {
    304 	struct imx23_mmc_softc *sc = sch;
    305 	uint32_t sck;
    306 
    307 	if (clock < SSP_CLK_MIN)
    308 		sck = imx23_mmc_set_sck(sc, SSP_CLK_MIN * 1000);
    309 	else
    310 		sck = imx23_mmc_set_sck(sc, clock * 1000);
    311 
    312 	/*
    313 	 * Notify user if we didn't get the exact clock rate from SSP that was
    314 	 * requested from the SDMMC subsystem.
    315 	 */
    316 	if (sck != clock * 1000) {
    317 		sck = sck / 1000;
    318 		if (((sck) / 1000) != 0)
    319 			aprint_normal_dev(sc->sc_dev, "bus clock @ %u.%03u "
    320 			    "MHz\n", sck / 1000, sck % 1000);
    321 		else
    322 			aprint_normal_dev(sc->sc_dev, "bus clock @ %u KHz\n",
    323 			    sck % 1000);
    324 	}
    325 
    326 	return 0;
    327 }
    328 
    329 static int
    330 imx23_mmc_bus_width(sdmmc_chipset_handle_t sch, int width)
    331 {
    332 	struct imx23_mmc_softc *sc = sch;
    333 
    334 	switch(width) {
    335 	case(1):
    336 		sc->sc_bus_width = BUS_WIDTH_1_BIT;
    337 		break;
    338 	case(4):
    339 		sc->sc_bus_width = BUS_WIDTH_4_BIT;
    340 		break;
    341 	case(8):
    342 		sc->sc_bus_width = BUS_WIDTH_8_BIT;
    343 		break;
    344 	default:
    345 		return 1;
    346 	}
    347 
    348 	return 0;
    349 }
    350 
    351 static int
    352 imx23_mmc_bus_rod(sdmmc_chipset_handle_t sch, int rod)
    353 {
    354 	/* Go to data transfer mode. */
    355 	return 0;
    356 }
    357 
    358 static void
    359 imx23_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
    360 {
    361 	struct imx23_mmc_softc *sc = sch;
    362 	struct fdtbus_dma_req req;
    363 
    364 	/* SSP does not support over 64k transfer size. */
    365 	if (cmd->c_data != NULL && cmd->c_datalen > MAX_TRANSFER_SIZE) {
    366 		aprint_error_dev(sc->sc_dev, "transfer size over %d: %d\n",
    367 		    MAX_TRANSFER_SIZE, cmd->c_datalen);
    368 		cmd->c_error = ENODEV;
    369 		return;
    370 	}
    371 
    372 	mutex_enter(&sc->sc_lock);
    373 
    374 	/* Setup DMA command chain.*/
    375 	if (cmd->c_data != NULL && cmd->c_datalen) {
    376 		/* command with data */
    377 		imx23_mmc_prepare_data_command(sc, &req, cmd);
    378 	} else {
    379 		/* Only command, no data. */
    380 		imx23_mmc_prepare_command(sc, &req, cmd);
    381 	}
    382 
    383 
    384 	sc->sc_state = SSP_STATE_DMA;
    385 	sc->sc_irq_error = 0;
    386 	cmd->c_error = 0;
    387 
    388 	/* Run DMA */
    389 	if(fdtbus_dma_transfer(sc->dma_channel, &req)) {
    390 		aprint_error_dev(sc->sc_dev, "dma transfer error\n");
    391 		goto out;
    392 	}
    393 
    394 	/* Wait DMA to complete. */
    395 	while (sc->sc_state == SSP_STATE_DMA)
    396 		cv_wait(&sc->sc_intr_cv, &sc->sc_lock);
    397 
    398 	if (sc->sc_irq_error) {
    399 		/*
    400 		 * Do not log RESP_TIMEOUT_IRQ error if bus width is 0 as it is
    401 		 * expected during SD card initialization phase.
    402 		 */
    403 		if (sc->sc_bus_width) {
    404 			aprint_error_dev(sc->sc_dev, "SSP_ERROR_IRQ: %d\n",
    405 			    sc->sc_irq_error);
    406 		}
    407 		else if(!(sc->sc_irq_error & HW_SSP_CTRL1_RESP_TIMEOUT_IRQ)) {
    408 			aprint_error_dev(sc->sc_dev, "SSP_ERROR_IRQ: %d\n",
    409 			    sc->sc_irq_error);
    410 		}
    411 
    412 		/* Shift unsigned error code so it fits nicely to signed int. */
    413 		cmd->c_error = sc->sc_irq_error >> 8;
    414 	}
    415 
    416 	/* Check response from the card if such was requested. */
    417 	if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
    418 		cmd->c_resp[0] = SSP_RD(sc, HW_SSP_SDRESP0);
    419 		if (ISSET(cmd->c_flags, SCF_RSP_136)) {
    420 			cmd->c_resp[1] = SSP_RD(sc, HW_SSP_SDRESP1);
    421 			cmd->c_resp[2] = SSP_RD(sc, HW_SSP_SDRESP2);
    422 			cmd->c_resp[3] = SSP_RD(sc, HW_SSP_SDRESP3);
    423 			/*
    424 			 * Remove CRC7 + LSB by rotating all bits right by 8 to
    425 			 * make sdmmc __bitfield() happy.
    426 			 */
    427 			cmd->c_resp[0] >>= 8; /* Remove CRC7 + LSB. */
    428 			cmd->c_resp[0] |= (0x000000FF & cmd->c_resp[1]) << 24;
    429 			cmd->c_resp[1] >>= 8;
    430 			cmd->c_resp[1] |= (0x000000FF & cmd->c_resp[2]) << 24;
    431 			cmd->c_resp[2] >>= 8;
    432 			cmd->c_resp[2] |= (0x000000FF & cmd->c_resp[3]) << 24;
    433 			cmd->c_resp[3] >>= 8;
    434 		}
    435 	}
    436 
    437 out:
    438 	mutex_exit(&sc->sc_lock);
    439 }
    440 
    441 static void
    442 imx23_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int irq)
    443 {
    444 	struct imx23_mmc_softc *sc = sch;
    445 	aprint_error_dev(sc->sc_dev, "issp_card_enable_intr not implemented\n");
    446 }
    447 
    448 static void
    449 imx23_mmc_card_intr_ack(sdmmc_chipset_handle_t sch)
    450 {
    451 	struct imx23_mmc_softc *sc = sch;
    452 	aprint_error_dev(sc->sc_dev, "issp_card_intr_ack not implemented\n");
    453 }
    454 
    455 /*
    456  * Reset the SSP block.
    457  *
    458  * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
    459  */
    460 static void
    461 imx23_mmc_reset(struct imx23_mmc_softc *sc)
    462 {
    463 	unsigned int loop;
    464 
    465 	/*
    466 	 * Prepare for soft-reset by making sure that SFTRST is not currently
    467 	 * asserted. Also clear CLKGATE so we can wait for its assertion below.
    468 	 */
    469 	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
    470 
    471 	/* Wait at least a microsecond for SFTRST to deassert. */
    472 	loop = 0;
    473 	while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
    474 	    (loop < SSP_SOFT_RST_LOOP))
    475 		loop++;
    476 
    477 	/* Clear CLKGATE so we can wait for its assertion below. */
    478 	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
    479 
    480 	/* Soft-reset the block. */
    481 	SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_SFTRST);
    482 
    483 	/* Wait until clock is in the gated state. */
    484 	while (!(SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE))
    485 		continue;
    486 
    487 	/* Bring block out of reset. */
    488 	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
    489 
    490 	loop = 0;
    491 	while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
    492 	    (loop < SSP_SOFT_RST_LOOP))
    493 		loop++;
    494 
    495 	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
    496 
    497 	/* Wait until clock is in the NON-gated state. */
    498 	while (SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE)
    499 		continue;
    500 }
    501 
    502 /*
    503  * Initialize SSP controller to SD/MMC mode.
    504  */
    505 static void
    506 imx23_mmc_init(struct imx23_mmc_softc *sc)
    507 {
    508 	uint32_t reg;
    509 
    510 	reg = SSP_RD(sc, HW_SSP_CTRL0);
    511 	reg |= HW_SSP_CTRL0_ENABLE;
    512 
    513 	/* Initial data bus width is 1-bit. */
    514 	reg &= ~(HW_SSP_CTRL0_BUS_WIDTH);
    515 	reg |= __SHIFTIN(BUS_WIDTH_1_BIT, HW_SSP_CTRL0_BUS_WIDTH) |
    516 	    HW_SSP_CTRL0_WAIT_FOR_IRQ | HW_SSP_CTRL0_ENABLE;
    517 	SSP_WR(sc, HW_SSP_CTRL0, reg);
    518 	sc->sc_bus_width = BUS_WIDTH_1_BIT;
    519 
    520 	/* Set data timeout. */
    521 	reg = SSP_RD(sc, HW_SSP_TIMING);
    522 	reg &= ~(HW_SSP_TIMING_TIMEOUT);
    523 	reg |= __SHIFTIN(DATA_TIMEOUT, HW_SSP_TIMING_TIMEOUT);
    524 	SSP_WR(sc, HW_SSP_TIMING, reg);
    525 
    526 	/* Set initial clock rate to minimum. */
    527 	imx23_mmc_set_sck(sc, SSP_CLK_MIN * 1000);
    528 
    529 	reg = SSP_RD(sc, HW_SSP_CTRL1);
    530 	/* Enable all but SDIO IRQ's. */
    531 	reg |= HW_SSP_CTRL1_RESP_ERR_IRQ_EN |
    532 	    HW_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
    533 	    HW_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
    534 	    HW_SSP_CTRL1_DATA_CRC_IRQ_EN |
    535 	    HW_SSP_CTRL1_FIFO_UNDERRUN_EN |
    536 	    HW_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
    537 	    HW_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN;
    538 	reg |= HW_SSP_CTRL1_DMA_ENABLE;
    539 	reg |= HW_SSP_CTRL1_POLARITY;
    540 	/* Set SD/MMC mode and use use 8-bits per word. */
    541 	reg &= ~(HW_SSP_CTRL1_WORD_LENGTH | HW_SSP_CTRL1_SSP_MODE);
    542 	reg |= __SHIFTIN(0x7, HW_SSP_CTRL1_WORD_LENGTH) |
    543 	    __SHIFTIN(0x3, HW_SSP_CTRL1_SSP_MODE);
    544 	SSP_WR(sc, HW_SSP_CTRL1, reg);
    545 }
    546 
    547 /*
    548  * Set SSP_SCK clock rate to the value specified in target.
    549  *
    550  * SSP_SCK is calculated as: SSP_CLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE))
    551  *
    552  * imx23_mmc_set_sck finds the most suitable CLOCK_DIVIDE and CLOCK_RATE
    553  * register values for the target clock rate by iterating through all possible
    554  * register values.
    555  */
    556 static uint32_t
    557 imx23_mmc_set_sck(struct imx23_mmc_softc *sc, uint32_t target)
    558 {
    559 	uint32_t newclk, found, reg;
    560 	uint8_t div, rate, d, r;
    561 
    562 	found = div = rate = 0;
    563 
    564 	for (d = 2; d < 254; d++) {
    565 		for (r = 0; r < 255; r++) {
    566 			newclk = SSP_CLK / (d * (1 + r));
    567 			if (newclk == target) {
    568 				found = newclk;
    569 				div = d;
    570 				rate = r;
    571 				goto out;
    572 			}
    573 			if (newclk < target && newclk > found) {
    574 				found = newclk;
    575 				div = d;
    576 				rate = r;
    577 			}
    578 		}
    579 	}
    580 out:
    581 	reg = SSP_RD(sc, HW_SSP_TIMING);
    582 	reg &= ~(HW_SSP_TIMING_CLOCK_DIVIDE | HW_SSP_TIMING_CLOCK_RATE);
    583 	reg |= __SHIFTIN(div, HW_SSP_TIMING_CLOCK_DIVIDE) |
    584 	    __SHIFTIN(rate, HW_SSP_TIMING_CLOCK_RATE);
    585 	SSP_WR(sc, HW_SSP_TIMING, reg);
    586 
    587 	return SSP_CLK / (div * (1 + rate));
    588 }
    589 
    590 /*
    591  * IRQ from DMA.
    592  */
    593 static void
    594 imx23_mmc_dma_intr(void *arg)
    595 {
    596 	struct imx23_mmc_softc *sc = arg;
    597 
    598 	mutex_enter(&sc->sc_lock);
    599 
    600 	sc->sc_state = SSP_STATE_IDLE;
    601 
    602 	/* Signal thread that interrupt was handled. */
    603 	cv_signal(&sc->sc_intr_cv);
    604 
    605 	mutex_exit(&sc->sc_lock);
    606 }
    607 
    608 /*
    609  * IRQ from SSP block.
    610  *
    611  * When SSP receives IRQ it terminates ongoing DMA transfer by issuing DMATERM
    612  * signal to DMA block.
    613  */
    614 static int
    615 imx23_mmc_error_intr(void *arg)
    616 {
    617 	struct imx23_mmc_softc *sc = arg;
    618 
    619 	mutex_enter(&sc->sc_lock);
    620 
    621 	sc->sc_irq_error =
    622 	    SSP_RD(sc, HW_SSP_CTRL1) & HW_SSP_CTRL1_IRQ_MASK;
    623 
    624 	/* Acknowledge all IRQ's. */
    625 	SSP_WR(sc, HW_SSP_CTRL1_CLR, HW_SSP_CTRL1_IRQ_MASK);
    626 
    627 	mutex_exit(&sc->sc_lock);
    628 
    629 	/* Return 1 to acknowledge IRQ. */
    630 	return 1;
    631 }
    632 
    633 /*
    634  * Set up a dma transfer for a block with data.
    635  */
    636 static void
    637 imx23_mmc_prepare_data_command(struct imx23_mmc_softc *sc,
    638 	struct fdtbus_dma_req *req, struct sdmmc_command *cmd)
    639 {
    640 	int block_count = cmd->c_datalen / cmd->c_blklen;
    641 
    642 	/* prepare DMA request */
    643 	req->dreq_segs = cmd->c_dmamap->dm_segs;
    644 	req->dreq_nsegs = cmd->c_dmamap->dm_nsegs;
    645 	req->dreq_block_irq = 1;
    646 	req->dreq_block_multi = 0;
    647 	req->dreq_datalen = 3;
    648 	req->dreq_data = sc->pio_words;
    649 
    650 	/* prepare CTRL0 register*/
    651 	sc->pio_words[PIO_WORD_CTRL0] =
    652 	    HW_SSP_CTRL0_DATA_XFER |
    653 	    __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) |
    654 	    HW_SSP_CTRL0_WAIT_FOR_IRQ |
    655 	    __SHIFTIN(cmd->c_datalen, HW_SSP_CTRL0_XFER_COUNT) |
    656 	    HW_SSP_CTRL0_ENABLE;
    657 	if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
    658 		req->dreq_dir = FDT_DMA_READ;
    659 		sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_READ;
    660 	} else {
    661 		req->dreq_dir = FDT_DMA_WRITE;
    662 	}
    663 	if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) {
    664 		sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_IGNORE_CRC;
    665 	}
    666 	if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
    667 		sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_GET_RESP;
    668 		if (ISSET(cmd->c_flags, SCF_RSP_136)) {
    669 			sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_LONG_RESP;
    670 		}
    671 	}
    672 
    673 	/* prepare CMD0 register */
    674 	sc->pio_words[PIO_WORD_CMD0] =
    675 	    HW_SSP_CMD0_APPEND_8CYC |
    676 	    __SHIFTIN(ffs(cmd->c_blklen) - 1, HW_SSP_CMD0_BLOCK_SIZE) |
    677 	    __SHIFTIN(block_count - 1, HW_SSP_CMD0_BLOCK_COUNT) |
    678 	    __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD);
    679 
    680 	/* prepare CMD1 register */
    681 	sc->pio_words[PIO_WORD_CMD1] = cmd->c_arg;
    682 }
    683 
    684 /*
    685  * Setup a dma transfer for a command without data (PIO only)
    686  */
    687 static void
    688 imx23_mmc_prepare_command(struct imx23_mmc_softc *sc,
    689 	struct fdtbus_dma_req *req, struct sdmmc_command *cmd)
    690 {
    691 	/* prepare DMA */
    692 	req->dreq_nsegs = 0;
    693 	req->dreq_block_irq = 1;
    694 	req->dreq_block_multi = 0;
    695 	req->dreq_dir = FDT_DMA_NO_XFER;
    696 	req->dreq_datalen = 3;
    697 	req->dreq_data = sc->pio_words;
    698 
    699 	/* prepare CTRL0 register*/
    700 	sc->pio_words[PIO_WORD_CTRL0] =
    701 	    __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) |
    702 	    HW_SSP_CTRL0_WAIT_FOR_IRQ | HW_SSP_CTRL0_ENABLE;
    703 	if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) {
    704 		sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_IGNORE_CRC;
    705 	}
    706 	if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
    707 		sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_GET_RESP;
    708 		if (ISSET(cmd->c_flags, SCF_RSP_136)) {
    709 			sc->pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_LONG_RESP;
    710 		}
    711 	}
    712 
    713 	/* prepare CMD0 register */
    714 	sc->pio_words[PIO_WORD_CMD0] =
    715 	    __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD);
    716 
    717 	/* prepare CMD1 register */
    718 	sc->pio_words[PIO_WORD_CMD1] = cmd->c_arg;
    719 }
    720