1 1.8 andvar /* $Id: imx23_ssp.c,v 1.8 2021/10/21 13:21:54 andvar Exp $ */ 2 1.1 jkunz 3 1.1 jkunz /* 4 1.1 jkunz * Copyright (c) 2012 The NetBSD Foundation, Inc. 5 1.1 jkunz * All rights reserved. 6 1.1 jkunz * 7 1.1 jkunz * This code is derived from software contributed to The NetBSD Foundation 8 1.1 jkunz * by Petri Laakso. 9 1.1 jkunz * 10 1.1 jkunz * Redistribution and use in source and binary forms, with or without 11 1.1 jkunz * modification, are permitted provided that the following conditions 12 1.1 jkunz * are met: 13 1.1 jkunz * 1. Redistributions of source code must retain the above copyright 14 1.1 jkunz * notice, this list of conditions and the following disclaimer. 15 1.1 jkunz * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jkunz * notice, this list of conditions and the following disclaimer in the 17 1.1 jkunz * documentation and/or other materials provided with the distribution. 18 1.1 jkunz * 19 1.1 jkunz * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 jkunz * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 jkunz * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 jkunz * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 jkunz * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 jkunz * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 jkunz * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 jkunz * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 jkunz * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 jkunz * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 jkunz * POSSIBILITY OF SUCH DAMAGE. 30 1.1 jkunz */ 31 1.1 jkunz 32 1.1 jkunz #include <sys/param.h> 33 1.1 jkunz #include <sys/types.h> 34 1.1 jkunz #include <sys/bus.h> 35 1.1 jkunz #include <sys/cdefs.h> 36 1.3 jkunz #include <sys/condvar.h> 37 1.1 jkunz #include <sys/device.h> 38 1.1 jkunz #include <sys/errno.h> 39 1.3 jkunz #include <sys/mutex.h> 40 1.1 jkunz #include <sys/systm.h> 41 1.1 jkunz 42 1.3 jkunz #include <arm/pic/picvar.h> 43 1.3 jkunz 44 1.3 jkunz #include <arm/imx/imx23_apbdmavar.h> 45 1.3 jkunz #include <arm/imx/imx23_icollreg.h> 46 1.1 jkunz #include <arm/imx/imx23_sspreg.h> 47 1.1 jkunz #include <arm/imx/imx23var.h> 48 1.1 jkunz 49 1.1 jkunz #include <dev/sdmmc/sdmmcchip.h> 50 1.1 jkunz #include <dev/sdmmc/sdmmcreg.h> 51 1.1 jkunz #include <dev/sdmmc/sdmmcvar.h> 52 1.1 jkunz 53 1.1 jkunz /* 54 1.2 jkunz * SD/MMC host controller driver for i.MX23. 55 1.3 jkunz * 56 1.3 jkunz * TODO: 57 1.3 jkunz * 58 1.3 jkunz * - Add support for SMC_CAPS_AUTO_STOP. 59 1.4 matt * - Uset GPIO for SD card detection. 60 1.1 jkunz */ 61 1.1 jkunz 62 1.3 jkunz #define DMA_MAXNSEGS ((MAXPHYS / PAGE_SIZE) + 1) 63 1.3 jkunz 64 1.3 jkunz typedef struct issp_softc { 65 1.1 jkunz device_t sc_dev; 66 1.3 jkunz apbdma_softc_t sc_dmac; 67 1.3 jkunz bus_dma_tag_t sc_dmat; 68 1.3 jkunz bus_dmamap_t sc_dmamp; 69 1.3 jkunz bus_size_t sc_chnsiz; 70 1.3 jkunz bus_dma_segment_t sc_ds[1]; 71 1.3 jkunz int sc_rseg; 72 1.3 jkunz bus_space_handle_t sc_hdl; 73 1.1 jkunz bus_space_tag_t sc_iot; 74 1.1 jkunz device_t sc_sdmmc; 75 1.3 jkunz kmutex_t sc_lock; 76 1.3 jkunz struct kcondvar sc_intr_cv; 77 1.3 jkunz unsigned int dma_channel; 78 1.3 jkunz uint32_t sc_dma_error; 79 1.3 jkunz uint32_t sc_irq_error; 80 1.3 jkunz uint8_t sc_state; 81 1.3 jkunz uint8_t sc_bus_width; 82 1.3 jkunz } *issp_softc_t; 83 1.1 jkunz 84 1.1 jkunz static int issp_match(device_t, cfdata_t, void *); 85 1.1 jkunz static void issp_attach(device_t, device_t, void *); 86 1.1 jkunz static int issp_activate(device_t, enum devact); 87 1.1 jkunz 88 1.2 jkunz static void issp_reset(struct issp_softc *); 89 1.2 jkunz static void issp_init(struct issp_softc *); 90 1.3 jkunz static uint32_t issp_set_sck(struct issp_softc *, uint32_t); 91 1.3 jkunz static int issp_dma_intr(void *); 92 1.3 jkunz static int issp_error_intr(void *); 93 1.3 jkunz static void issp_ack_intr(struct issp_softc *); 94 1.3 jkunz static void issp_create_dma_cmd_list_multi(issp_softc_t, void *, 95 1.3 jkunz struct sdmmc_command *); 96 1.3 jkunz static void issp_create_dma_cmd_list_single(issp_softc_t, void *, 97 1.3 jkunz struct sdmmc_command *); 98 1.3 jkunz static void issp_create_dma_cmd_list(issp_softc_t, void *, 99 1.3 jkunz struct sdmmc_command *); 100 1.2 jkunz 101 1.2 jkunz /* sdmmc(4) driver chip function prototypes. */ 102 1.1 jkunz static int issp_host_reset(sdmmc_chipset_handle_t); 103 1.1 jkunz static uint32_t issp_host_ocr(sdmmc_chipset_handle_t); 104 1.1 jkunz static int issp_host_maxblklen(sdmmc_chipset_handle_t); 105 1.1 jkunz static int issp_card_detect(sdmmc_chipset_handle_t); 106 1.1 jkunz static int issp_write_protect(sdmmc_chipset_handle_t); 107 1.1 jkunz static int issp_bus_power(sdmmc_chipset_handle_t, uint32_t); 108 1.1 jkunz static int issp_bus_clock(sdmmc_chipset_handle_t, int); 109 1.1 jkunz static int issp_bus_width(sdmmc_chipset_handle_t, int); 110 1.1 jkunz static int issp_bus_rod(sdmmc_chipset_handle_t, int); 111 1.1 jkunz static void issp_exec_command(sdmmc_chipset_handle_t, 112 1.3 jkunz struct sdmmc_command *); 113 1.1 jkunz static void issp_card_enable_intr(sdmmc_chipset_handle_t, int); 114 1.1 jkunz static void issp_card_intr_ack(sdmmc_chipset_handle_t); 115 1.1 jkunz 116 1.1 jkunz static struct sdmmc_chip_functions issp_functions = { 117 1.1 jkunz .host_reset = issp_host_reset, 118 1.1 jkunz .host_ocr = issp_host_ocr, 119 1.1 jkunz .host_maxblklen = issp_host_maxblklen, 120 1.1 jkunz .card_detect = issp_card_detect, 121 1.1 jkunz .write_protect = issp_write_protect, 122 1.1 jkunz .bus_power = issp_bus_power, 123 1.1 jkunz .bus_clock = issp_bus_clock, 124 1.1 jkunz .bus_width = issp_bus_width, 125 1.1 jkunz .bus_rod = issp_bus_rod, 126 1.1 jkunz .exec_command = issp_exec_command, 127 1.1 jkunz .card_enable_intr = issp_card_enable_intr, 128 1.1 jkunz .card_intr_ack = issp_card_intr_ack 129 1.1 jkunz }; 130 1.1 jkunz 131 1.2 jkunz CFATTACH_DECL3_NEW(ssp, 132 1.2 jkunz sizeof(struct issp_softc), 133 1.2 jkunz issp_match, 134 1.2 jkunz issp_attach, 135 1.2 jkunz NULL, 136 1.2 jkunz issp_activate, 137 1.2 jkunz NULL, 138 1.2 jkunz NULL, 139 1.3 jkunz 0 140 1.3 jkunz ); 141 1.2 jkunz 142 1.2 jkunz #define SSP_SOFT_RST_LOOP 455 /* At least 1 us ... */ 143 1.2 jkunz 144 1.2 jkunz #define SSP_RD(sc, reg) \ 145 1.1 jkunz bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg)) 146 1.2 jkunz #define SSP_WR(sc, reg, val) \ 147 1.1 jkunz bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val)) 148 1.1 jkunz 149 1.4 matt #define SSP_CLK 160000000 /* CLK_SSP from PLL in Hz */ 150 1.2 jkunz #define SSP_CLK_MIN 400 /* 400 kHz */ 151 1.2 jkunz #define SSP_CLK_MAX 48000 /* 48 MHz */ 152 1.2 jkunz 153 1.3 jkunz /* DATA_TIMEOUT is calculated as: * (1 / SSP_CLK) * (DATA_TIMEOUT * 4096) */ 154 1.4 matt #define DATA_TIMEOUT 0x4240 155 1.2 jkunz 156 1.2 jkunz #define BUS_WIDTH_1_BIT 0x0 157 1.2 jkunz #define BUS_WIDTH_4_BIT 0x1 158 1.2 jkunz #define BUS_WIDTH_8_BIT 0x2 159 1.2 jkunz 160 1.3 jkunz #define SSP1_ATTACHED 1 161 1.3 jkunz #define SSP2_ATTACHED 2 162 1.3 jkunz 163 1.3 jkunz /* Flags for sc_state. */ 164 1.3 jkunz #define SSP_STATE_IDLE 0 165 1.3 jkunz #define SSP_STATE_DMA 1 166 1.3 jkunz 167 1.3 jkunz #define PIO_WORD_CTRL0 0 168 1.3 jkunz #define PIO_WORD_CMD0 1 169 1.3 jkunz #define PIO_WORD_CMD1 2 170 1.3 jkunz 171 1.3 jkunz #define HW_SSP_CTRL1_IRQ_MASK ( \ 172 1.3 jkunz HW_SSP_CTRL1_SDIO_IRQ | \ 173 1.3 jkunz HW_SSP_CTRL1_RESP_ERR_IRQ | \ 174 1.3 jkunz HW_SSP_CTRL1_RESP_TIMEOUT_IRQ | \ 175 1.3 jkunz HW_SSP_CTRL1_DATA_TIMEOUT_IRQ | \ 176 1.3 jkunz HW_SSP_CTRL1_DATA_CRC_IRQ | \ 177 1.3 jkunz HW_SSP_CTRL1_FIFO_UNDERRUN_IRQ | \ 178 1.3 jkunz HW_SSP_CTRL1_RECV_TIMEOUT_IRQ | \ 179 1.3 jkunz HW_SSP_CTRL1_FIFO_OVERRUN_IRQ) 180 1.3 jkunz 181 1.3 jkunz /* SSP does not support over 64k transfer size. */ 182 1.3 jkunz #define MAX_TRANSFER_SIZE 65536 183 1.3 jkunz 184 1.1 jkunz static int 185 1.1 jkunz issp_match(device_t parent, cfdata_t match, void *aux) 186 1.1 jkunz { 187 1.1 jkunz struct apb_attach_args *aa = aux; 188 1.1 jkunz 189 1.1 jkunz if ((aa->aa_addr == HW_SSP1_BASE) && (aa->aa_size == HW_SSP1_SIZE)) 190 1.1 jkunz return 1; 191 1.1 jkunz 192 1.1 jkunz if ((aa->aa_addr == HW_SSP2_BASE) && (aa->aa_size == HW_SSP2_SIZE)) 193 1.1 jkunz return 1; 194 1.1 jkunz 195 1.1 jkunz return 0; 196 1.1 jkunz } 197 1.1 jkunz 198 1.1 jkunz static void 199 1.1 jkunz issp_attach(device_t parent, device_t self, void *aux) 200 1.1 jkunz { 201 1.1 jkunz struct issp_softc *sc = device_private(self); 202 1.2 jkunz struct apb_softc *sc_parent = device_private(parent); 203 1.1 jkunz struct apb_attach_args *aa = aux; 204 1.1 jkunz struct sdmmcbus_attach_args saa; 205 1.3 jkunz static int ssp_attached = 0; 206 1.3 jkunz int error; 207 1.3 jkunz void *intr; 208 1.3 jkunz 209 1.3 jkunz sc->sc_dev = self; 210 1.3 jkunz sc->sc_iot = aa->aa_iot; 211 1.3 jkunz sc->sc_dmat = aa->aa_dmat; 212 1.3 jkunz 213 1.3 jkunz /* Test if device instance is already attached. */ 214 1.3 jkunz if (aa->aa_addr == HW_SSP1_BASE && ISSET(ssp_attached, SSP1_ATTACHED)) { 215 1.3 jkunz aprint_error_dev(sc->sc_dev, "SSP1 already attached\n"); 216 1.3 jkunz return; 217 1.3 jkunz } 218 1.3 jkunz if (aa->aa_addr == HW_SSP2_BASE && ISSET(ssp_attached, SSP2_ATTACHED)) { 219 1.3 jkunz aprint_error_dev(sc->sc_dev, "SSP2 already attached\n"); 220 1.3 jkunz return; 221 1.3 jkunz } 222 1.3 jkunz 223 1.3 jkunz if (aa->aa_addr == HW_SSP1_BASE) { 224 1.3 jkunz sc->dma_channel = APBH_DMA_CHANNEL_SSP1; 225 1.3 jkunz } 226 1.3 jkunz if (aa->aa_addr == HW_SSP2_BASE) { 227 1.3 jkunz sc->dma_channel = APBH_DMA_CHANNEL_SSP2; 228 1.3 jkunz } 229 1.3 jkunz 230 1.3 jkunz /* This driver requires DMA functionality from the bus. 231 1.3 jkunz * Parent bus passes handle to the DMA controller instance. */ 232 1.3 jkunz if (sc_parent->dmac == NULL) { 233 1.3 jkunz aprint_error_dev(sc->sc_dev, "DMA functionality missing\n"); 234 1.3 jkunz return; 235 1.3 jkunz } 236 1.3 jkunz sc->sc_dmac = device_private(sc_parent->dmac); 237 1.3 jkunz 238 1.3 jkunz /* Initialize lock. */ 239 1.3 jkunz mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SDMMC); 240 1.2 jkunz 241 1.3 jkunz /* Condvar to wait interrupt complete. */ 242 1.3 jkunz cv_init(&sc->sc_intr_cv, "ssp_intr"); 243 1.3 jkunz 244 1.3 jkunz /* Establish interrupt handlers for SSP errors and SSP DMA. */ 245 1.3 jkunz if (aa->aa_addr == HW_SSP1_BASE) { 246 1.3 jkunz intr = intr_establish(IRQ_SSP1_DMA, IPL_SDMMC, IST_LEVEL, 247 1.3 jkunz issp_dma_intr, sc); 248 1.3 jkunz if (intr == NULL) { 249 1.3 jkunz aprint_error_dev(sc->sc_dev, "Unable to establish " 250 1.3 jkunz "interrupt for SSP1 DMA\n"); 251 1.3 jkunz return; 252 1.3 jkunz } 253 1.3 jkunz intr = intr_establish(IRQ_SSP1_ERROR, IPL_SDMMC, IST_LEVEL, 254 1.3 jkunz issp_error_intr, sc); 255 1.3 jkunz if (intr == NULL) { 256 1.3 jkunz aprint_error_dev(sc->sc_dev, "Unable to establish " 257 1.3 jkunz "interrupt for SSP1 ERROR\n"); 258 1.3 jkunz return; 259 1.3 jkunz } 260 1.3 jkunz } 261 1.3 jkunz 262 1.3 jkunz if (aa->aa_addr == HW_SSP2_BASE) { 263 1.3 jkunz intr = intr_establish(IRQ_SSP2_DMA, IPL_SDMMC, IST_LEVEL, 264 1.3 jkunz issp_dma_intr, sc); 265 1.3 jkunz if (intr == NULL) { 266 1.3 jkunz aprint_error_dev(sc->sc_dev, "Unable to establish " 267 1.3 jkunz "interrupt for SSP2 DMA\n"); 268 1.3 jkunz return; 269 1.3 jkunz } 270 1.3 jkunz intr = intr_establish(IRQ_SSP2_ERROR, IPL_SDMMC, IST_LEVEL, 271 1.3 jkunz issp_error_intr, sc); 272 1.3 jkunz if (intr == NULL) { 273 1.3 jkunz aprint_error_dev(sc->sc_dev, "Unable to establish " 274 1.3 jkunz "interrupt for SSP2 ERROR\n"); 275 1.3 jkunz return; 276 1.3 jkunz } 277 1.3 jkunz } 278 1.3 jkunz 279 1.3 jkunz /* Allocate DMA handle. */ 280 1.3 jkunz error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 281 1.3 jkunz 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmamp); 282 1.3 jkunz if (error) { 283 1.3 jkunz aprint_error_dev(sc->sc_dev, 284 1.3 jkunz "Unable to allocate DMA handle\n"); 285 1.3 jkunz return; 286 1.3 jkunz } 287 1.3 jkunz 288 1.3 jkunz /* Allocate memory for DMA command chain. */ 289 1.3 jkunz sc->sc_chnsiz = sizeof(struct apbdma_command) * 290 1.3 jkunz (MAX_TRANSFER_SIZE / SDMMC_SECTOR_SIZE); 291 1.3 jkunz 292 1.3 jkunz error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_chnsiz, PAGE_SIZE, 0, 293 1.3 jkunz sc->sc_ds, 1, &sc->sc_rseg, BUS_DMA_NOWAIT); 294 1.3 jkunz if (error) { 295 1.3 jkunz aprint_error_dev(sc->sc_dev, 296 1.3 jkunz "Unable to allocate DMA memory\n"); 297 1.1 jkunz return; 298 1.3 jkunz } 299 1.1 jkunz 300 1.3 jkunz /* Initialize DMA channel. */ 301 1.3 jkunz apbdma_chan_init(sc->sc_dmac, sc->dma_channel); 302 1.1 jkunz 303 1.3 jkunz /* Map SSP bus space. */ 304 1.3 jkunz if (bus_space_map(sc->sc_iot, aa->aa_addr, aa->aa_size, 0, 305 1.3 jkunz &sc->sc_hdl)) { 306 1.3 jkunz aprint_error_dev(sc->sc_dev, "Unable to map SSP bus space\n"); 307 1.1 jkunz return; 308 1.1 jkunz } 309 1.1 jkunz 310 1.1 jkunz issp_reset(sc); 311 1.2 jkunz issp_init(sc); 312 1.1 jkunz 313 1.2 jkunz uint32_t issp_vers = SSP_RD(sc, HW_SSP_VERSION); 314 1.1 jkunz aprint_normal(": SSP Block v%" __PRIuBIT ".%" __PRIuBIT "\n", 315 1.1 jkunz __SHIFTOUT(issp_vers, HW_SSP_VERSION_MAJOR), 316 1.1 jkunz __SHIFTOUT(issp_vers, HW_SSP_VERSION_MINOR)); 317 1.1 jkunz 318 1.3 jkunz /* Attach sdmmc to ssp bus. */ 319 1.1 jkunz saa.saa_busname = "sdmmc"; 320 1.1 jkunz saa.saa_sct = &issp_functions; 321 1.1 jkunz saa.saa_spi_sct = NULL; 322 1.1 jkunz saa.saa_sch = sc; 323 1.1 jkunz saa.saa_dmat = aa->aa_dmat; 324 1.1 jkunz saa.saa_clkmin = SSP_CLK_MIN; 325 1.1 jkunz saa.saa_clkmax = SSP_CLK_MAX; 326 1.3 jkunz saa.saa_caps = SMC_CAPS_DMA | SMC_CAPS_4BIT_MODE | 327 1.3 jkunz SMC_CAPS_MULTI_SEG_DMA; 328 1.1 jkunz 329 1.6 thorpej sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL, CFARGS_NONE); 330 1.1 jkunz if (sc->sc_sdmmc == NULL) { 331 1.1 jkunz aprint_error_dev(sc->sc_dev, "unable to attach sdmmc\n"); 332 1.1 jkunz return; 333 1.1 jkunz } 334 1.1 jkunz 335 1.7 andvar /* Device instance was successfully attached. */ 336 1.3 jkunz if (aa->aa_addr == HW_SSP1_BASE) 337 1.3 jkunz ssp_attached |= SSP1_ATTACHED; 338 1.3 jkunz if (aa->aa_addr == HW_SSP2_BASE) 339 1.3 jkunz ssp_attached |= SSP2_ATTACHED; 340 1.1 jkunz 341 1.1 jkunz return; 342 1.1 jkunz } 343 1.1 jkunz 344 1.1 jkunz static int 345 1.1 jkunz issp_activate(device_t self, enum devact act) 346 1.1 jkunz { 347 1.1 jkunz return EOPNOTSUPP; 348 1.1 jkunz } 349 1.1 jkunz 350 1.1 jkunz /* 351 1.1 jkunz * sdmmc chip functions. 352 1.1 jkunz */ 353 1.1 jkunz static int 354 1.1 jkunz issp_host_reset(sdmmc_chipset_handle_t sch) 355 1.1 jkunz { 356 1.1 jkunz struct issp_softc *sc = sch; 357 1.1 jkunz issp_reset(sc); 358 1.1 jkunz return 0; 359 1.1 jkunz } 360 1.1 jkunz 361 1.1 jkunz static uint32_t 362 1.1 jkunz issp_host_ocr(sdmmc_chipset_handle_t sch) 363 1.1 jkunz { 364 1.3 jkunz /* SSP supports at least 3.2 - 3.3v */ 365 1.1 jkunz return MMC_OCR_3_2V_3_3V; 366 1.1 jkunz } 367 1.1 jkunz 368 1.1 jkunz static int 369 1.1 jkunz issp_host_maxblklen(sdmmc_chipset_handle_t sch) 370 1.1 jkunz { 371 1.1 jkunz return 512; 372 1.1 jkunz } 373 1.1 jkunz 374 1.1 jkunz /* 375 1.1 jkunz * Called at the beginning of sdmmc_task_thread to detect the presence 376 1.1 jkunz * of the SD card. 377 1.1 jkunz */ 378 1.1 jkunz static int 379 1.1 jkunz issp_card_detect(sdmmc_chipset_handle_t sch) 380 1.1 jkunz { 381 1.1 jkunz return 1; 382 1.1 jkunz } 383 1.1 jkunz 384 1.1 jkunz static int 385 1.1 jkunz issp_write_protect(sdmmc_chipset_handle_t sch) 386 1.1 jkunz { 387 1.1 jkunz /* The device is not write protected. */ 388 1.1 jkunz return 0; 389 1.1 jkunz } 390 1.1 jkunz 391 1.1 jkunz static int 392 1.2 jkunz issp_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 393 1.1 jkunz { 394 1.2 jkunz /* i.MX23 SSP does not support setting bus power. */ 395 1.1 jkunz return 0; 396 1.1 jkunz } 397 1.1 jkunz 398 1.1 jkunz static int 399 1.1 jkunz issp_bus_clock(sdmmc_chipset_handle_t sch, int clock) 400 1.1 jkunz { 401 1.1 jkunz struct issp_softc *sc = sch; 402 1.1 jkunz uint32_t sck; 403 1.1 jkunz 404 1.3 jkunz if (clock < SSP_CLK_MIN) 405 1.3 jkunz sck = issp_set_sck(sc, SSP_CLK_MIN * 1000); 406 1.3 jkunz else 407 1.3 jkunz sck = issp_set_sck(sc, clock * 1000); 408 1.2 jkunz 409 1.3 jkunz /* Notify user if we didn't get the exact clock rate from SSP that was 410 1.3 jkunz * requested from the SDMMC subsystem. */ 411 1.3 jkunz if (sck != clock * 1000) { 412 1.3 jkunz sck = sck / 1000; 413 1.3 jkunz if (((sck) / 1000) != 0) 414 1.3 jkunz aprint_normal_dev(sc->sc_dev, "bus clock @ %u.%03u " 415 1.3 jkunz "MHz\n", sck / 1000, sck % 1000); 416 1.3 jkunz else 417 1.3 jkunz aprint_normal_dev(sc->sc_dev, "bus clock @ %u KHz\n", 418 1.3 jkunz sck % 1000); 419 1.3 jkunz } 420 1.1 jkunz 421 1.1 jkunz return 0; 422 1.1 jkunz } 423 1.1 jkunz 424 1.1 jkunz static int 425 1.1 jkunz issp_bus_width(sdmmc_chipset_handle_t sch, int width) 426 1.1 jkunz { 427 1.2 jkunz struct issp_softc *sc = sch; 428 1.2 jkunz 429 1.2 jkunz switch(width) { 430 1.2 jkunz case(1): 431 1.3 jkunz sc->sc_bus_width = BUS_WIDTH_1_BIT; 432 1.2 jkunz break; 433 1.2 jkunz case(4): 434 1.3 jkunz sc->sc_bus_width = BUS_WIDTH_4_BIT; 435 1.2 jkunz break; 436 1.2 jkunz case(8): 437 1.3 jkunz sc->sc_bus_width = BUS_WIDTH_8_BIT; 438 1.2 jkunz break; 439 1.2 jkunz default: 440 1.2 jkunz return 1; 441 1.2 jkunz } 442 1.2 jkunz 443 1.2 jkunz return 0; 444 1.1 jkunz } 445 1.1 jkunz 446 1.1 jkunz static int 447 1.1 jkunz issp_bus_rod(sdmmc_chipset_handle_t sch, int rod) 448 1.1 jkunz { 449 1.1 jkunz /* Go to data transfer mode. */ 450 1.1 jkunz return 0; 451 1.1 jkunz } 452 1.1 jkunz 453 1.1 jkunz static void 454 1.1 jkunz issp_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 455 1.1 jkunz { 456 1.3 jkunz issp_softc_t sc = sch; 457 1.3 jkunz void *dma_chain; 458 1.3 jkunz int error; 459 1.3 jkunz 460 1.3 jkunz /* SSP does not support over 64k transfer size. */ 461 1.3 jkunz if (cmd->c_data != NULL && cmd->c_datalen > MAX_TRANSFER_SIZE) { 462 1.3 jkunz aprint_error_dev(sc->sc_dev, "transfer size over %d: %d\n", 463 1.3 jkunz MAX_TRANSFER_SIZE, cmd->c_datalen); 464 1.3 jkunz cmd->c_error = ENODEV; 465 1.3 jkunz return; 466 1.3 jkunz } 467 1.3 jkunz 468 1.3 jkunz /* Map dma_chain to point allocated previously allocated DMA chain. */ 469 1.3 jkunz error = bus_dmamem_map(sc->sc_dmat, sc->sc_ds, 1, sc->sc_chnsiz, 470 1.3 jkunz &dma_chain, BUS_DMA_NOWAIT); 471 1.3 jkunz if (error) { 472 1.3 jkunz aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error); 473 1.3 jkunz cmd->c_error = error; 474 1.3 jkunz goto out; 475 1.3 jkunz } 476 1.2 jkunz 477 1.3 jkunz error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamp, dma_chain, 478 1.3 jkunz sc->sc_chnsiz, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE); 479 1.3 jkunz if (error) { 480 1.3 jkunz aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error); 481 1.3 jkunz cmd->c_error = error; 482 1.3 jkunz goto dmamem_unmap; 483 1.3 jkunz } 484 1.1 jkunz 485 1.3 jkunz memset(dma_chain, 0, sc->sc_chnsiz); 486 1.1 jkunz 487 1.3 jkunz /* Setup DMA command chain.*/ 488 1.3 jkunz if (cmd->c_data != NULL && (cmd->c_datalen / cmd->c_blklen) > 1) { 489 1.3 jkunz /* Multi block transfer. */ 490 1.3 jkunz issp_create_dma_cmd_list_multi(sc, dma_chain, cmd); 491 1.3 jkunz } else if (cmd->c_data != NULL && cmd->c_datalen) { 492 1.3 jkunz /* Single block transfer. */ 493 1.3 jkunz issp_create_dma_cmd_list_single(sc, dma_chain, cmd); 494 1.3 jkunz } else { 495 1.3 jkunz /* Only command, no data. */ 496 1.3 jkunz issp_create_dma_cmd_list(sc, dma_chain, cmd); 497 1.1 jkunz } 498 1.1 jkunz 499 1.3 jkunz /* Tell DMA controller where it can find just initialized DMA chain. */ 500 1.3 jkunz apbdma_chan_set_chain(sc->sc_dmac, sc->dma_channel, sc->sc_dmamp); 501 1.3 jkunz 502 1.3 jkunz /* Synchronize command chain before DMA controller accesses it. */ 503 1.3 jkunz bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, 0, sc->sc_chnsiz, 504 1.3 jkunz BUS_DMASYNC_PREWRITE); 505 1.3 jkunz 506 1.3 jkunz sc->sc_state = SSP_STATE_DMA; 507 1.3 jkunz sc->sc_irq_error = 0; 508 1.3 jkunz sc->sc_dma_error = 0; 509 1.3 jkunz cmd->c_error = 0; 510 1.3 jkunz 511 1.3 jkunz mutex_enter(&sc->sc_lock); 512 1.1 jkunz 513 1.3 jkunz /* Run DMA command chain. */ 514 1.3 jkunz apbdma_run(sc->sc_dmac, sc->dma_channel); 515 1.2 jkunz 516 1.3 jkunz /* Wait DMA to complete. */ 517 1.3 jkunz while (sc->sc_state == SSP_STATE_DMA) 518 1.3 jkunz cv_wait(&sc->sc_intr_cv, &sc->sc_lock); 519 1.2 jkunz 520 1.3 jkunz mutex_exit(&sc->sc_lock); 521 1.1 jkunz 522 1.3 jkunz bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, 0, sc->sc_chnsiz, 523 1.3 jkunz BUS_DMASYNC_POSTWRITE); 524 1.1 jkunz 525 1.3 jkunz if (sc->sc_dma_error) { 526 1.3 jkunz if (sc->sc_dma_error == DMA_IRQ_TERM) { 527 1.3 jkunz apbdma_chan_reset(sc->sc_dmac, sc->dma_channel); 528 1.3 jkunz cmd->c_error = sc->sc_dma_error; 529 1.2 jkunz } 530 1.3 jkunz else if (sc->sc_dma_error == DMA_IRQ_BUS_ERROR) { 531 1.3 jkunz aprint_error_dev(sc->sc_dev, "DMA_IRQ_BUS_ERROR: %d\n", 532 1.3 jkunz sc->sc_irq_error); 533 1.3 jkunz cmd->c_error = sc->sc_dma_error; 534 1.2 jkunz } 535 1.2 jkunz } 536 1.2 jkunz 537 1.3 jkunz if (sc->sc_irq_error) { 538 1.3 jkunz /* Do not log RESP_TIMEOUT_IRQ error if bus width is 0 as it is 539 1.3 jkunz * expected during SD card initialization phase. */ 540 1.3 jkunz if (sc->sc_bus_width) { 541 1.3 jkunz aprint_error_dev(sc->sc_dev, "SSP_ERROR_IRQ: %d\n", 542 1.3 jkunz sc->sc_irq_error); 543 1.3 jkunz } 544 1.3 jkunz else if(!(sc->sc_irq_error & HW_SSP_CTRL1_RESP_TIMEOUT_IRQ)) { 545 1.3 jkunz aprint_error_dev(sc->sc_dev, "SSP_ERROR_IRQ: %d\n", 546 1.3 jkunz sc->sc_irq_error); 547 1.3 jkunz } 548 1.2 jkunz 549 1.3 jkunz /* Shift unsigned error code so it fits nicely to signed int. */ 550 1.3 jkunz cmd->c_error = sc->sc_irq_error >> 8; 551 1.3 jkunz } 552 1.1 jkunz 553 1.8 andvar /* Check response from the card if such was requested. */ 554 1.1 jkunz if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) { 555 1.2 jkunz cmd->c_resp[0] = SSP_RD(sc, HW_SSP_SDRESP0); 556 1.1 jkunz if (ISSET(cmd->c_flags, SCF_RSP_136)) { 557 1.2 jkunz cmd->c_resp[1] = SSP_RD(sc, HW_SSP_SDRESP1); 558 1.2 jkunz cmd->c_resp[2] = SSP_RD(sc, HW_SSP_SDRESP2); 559 1.2 jkunz cmd->c_resp[3] = SSP_RD(sc, HW_SSP_SDRESP3); 560 1.2 jkunz /* 561 1.2 jkunz * Remove CRC7 + LSB by rotating all bits right by 8 to 562 1.2 jkunz * make sdmmc __bitfield() happy. 563 1.2 jkunz */ 564 1.2 jkunz cmd->c_resp[0] >>= 8; /* Remove CRC7 + LSB. */ 565 1.2 jkunz cmd->c_resp[0] |= (0x000000FF & cmd->c_resp[1]) << 24; 566 1.2 jkunz cmd->c_resp[1] >>= 8; 567 1.2 jkunz cmd->c_resp[1] |= (0x000000FF & cmd->c_resp[2]) << 24; 568 1.2 jkunz cmd->c_resp[2] >>= 8; 569 1.2 jkunz cmd->c_resp[2] |= (0x000000FF & cmd->c_resp[3]) << 24; 570 1.2 jkunz cmd->c_resp[3] >>= 8; 571 1.1 jkunz } 572 1.1 jkunz } 573 1.3 jkunz 574 1.3 jkunz bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamp); 575 1.3 jkunz dmamem_unmap: 576 1.3 jkunz bus_dmamem_unmap(sc->sc_dmat, dma_chain, sc->sc_chnsiz); 577 1.3 jkunz out: 578 1.3 jkunz 579 1.1 jkunz return; 580 1.1 jkunz } 581 1.1 jkunz 582 1.1 jkunz static void 583 1.1 jkunz issp_card_enable_intr(sdmmc_chipset_handle_t sch, int irq) 584 1.1 jkunz { 585 1.1 jkunz struct issp_softc *sc = sch; 586 1.3 jkunz aprint_error_dev(sc->sc_dev, "issp_card_enable_intr not implemented\n"); 587 1.1 jkunz return; 588 1.1 jkunz } 589 1.1 jkunz 590 1.1 jkunz static void 591 1.1 jkunz issp_card_intr_ack(sdmmc_chipset_handle_t sch) 592 1.1 jkunz { 593 1.1 jkunz struct issp_softc *sc = sch; 594 1.3 jkunz aprint_error_dev(sc->sc_dev, "issp_card_intr_ack not implemented\n"); 595 1.1 jkunz return; 596 1.1 jkunz } 597 1.1 jkunz 598 1.1 jkunz /* 599 1.1 jkunz * Reset the SSP block. 600 1.1 jkunz * 601 1.2 jkunz * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block" 602 1.1 jkunz */ 603 1.1 jkunz static void 604 1.1 jkunz issp_reset(struct issp_softc *sc) 605 1.1 jkunz { 606 1.1 jkunz unsigned int loop; 607 1.1 jkunz 608 1.1 jkunz /* Prepare for soft-reset by making sure that SFTRST is not currently 609 1.1 jkunz * asserted. Also clear CLKGATE so we can wait for its assertion below. 610 1.1 jkunz */ 611 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST); 612 1.1 jkunz 613 1.1 jkunz /* Wait at least a microsecond for SFTRST to deassert. */ 614 1.1 jkunz loop = 0; 615 1.2 jkunz while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) || 616 1.1 jkunz (loop < SSP_SOFT_RST_LOOP)) 617 1.1 jkunz loop++; 618 1.1 jkunz 619 1.1 jkunz /* Clear CLKGATE so we can wait for its assertion below. */ 620 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE); 621 1.1 jkunz 622 1.1 jkunz /* Soft-reset the block. */ 623 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_SFTRST); 624 1.1 jkunz 625 1.1 jkunz /* Wait until clock is in the gated state. */ 626 1.2 jkunz while (!(SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE)); 627 1.1 jkunz 628 1.1 jkunz /* Bring block out of reset. */ 629 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST); 630 1.1 jkunz 631 1.1 jkunz loop = 0; 632 1.2 jkunz while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) || 633 1.1 jkunz (loop < SSP_SOFT_RST_LOOP)) 634 1.1 jkunz loop++; 635 1.1 jkunz 636 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE); 637 1.2 jkunz 638 1.1 jkunz /* Wait until clock is in the NON-gated state. */ 639 1.2 jkunz while (SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE); 640 1.1 jkunz 641 1.1 jkunz return; 642 1.1 jkunz } 643 1.1 jkunz 644 1.2 jkunz /* 645 1.2 jkunz * Initialize SSP controller to SD/MMC mode. 646 1.1 jkunz */ 647 1.1 jkunz static void 648 1.1 jkunz issp_init(struct issp_softc *sc) 649 1.1 jkunz { 650 1.1 jkunz uint32_t reg; 651 1.1 jkunz 652 1.3 jkunz reg = SSP_RD(sc, HW_SSP_CTRL0); 653 1.3 jkunz reg |= HW_SSP_CTRL0_ENABLE; 654 1.3 jkunz 655 1.2 jkunz /* Initial data bus width is 1-bit. */ 656 1.1 jkunz reg &= ~(HW_SSP_CTRL0_BUS_WIDTH); 657 1.2 jkunz reg |= __SHIFTIN(BUS_WIDTH_1_BIT, HW_SSP_CTRL0_BUS_WIDTH) | 658 1.2 jkunz HW_SSP_CTRL0_WAIT_FOR_IRQ | HW_SSP_CTRL0_ENABLE; 659 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL0, reg); 660 1.3 jkunz sc->sc_bus_width = BUS_WIDTH_1_BIT; 661 1.1 jkunz 662 1.2 jkunz /* Set data timeout. */ 663 1.2 jkunz reg = SSP_RD(sc, HW_SSP_TIMING); 664 1.2 jkunz reg &= ~(HW_SSP_TIMING_TIMEOUT); 665 1.2 jkunz reg |= __SHIFTIN(DATA_TIMEOUT, HW_SSP_TIMING_TIMEOUT); 666 1.3 jkunz SSP_WR(sc, HW_SSP_TIMING, reg); 667 1.2 jkunz 668 1.2 jkunz /* Set initial clock rate to minimum. */ 669 1.2 jkunz issp_set_sck(sc, SSP_CLK_MIN * 1000); 670 1.2 jkunz 671 1.2 jkunz reg = SSP_RD(sc, HW_SSP_CTRL1); 672 1.3 jkunz /* Enable all but SDIO IRQ's. */ 673 1.3 jkunz reg |= HW_SSP_CTRL1_RESP_ERR_IRQ_EN | 674 1.3 jkunz HW_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN | 675 1.3 jkunz HW_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN | 676 1.3 jkunz HW_SSP_CTRL1_DATA_CRC_IRQ_EN | 677 1.3 jkunz HW_SSP_CTRL1_FIFO_UNDERRUN_EN | 678 1.3 jkunz HW_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN | 679 1.3 jkunz HW_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN; 680 1.3 jkunz reg |= HW_SSP_CTRL1_DMA_ENABLE; 681 1.3 jkunz reg |= HW_SSP_CTRL1_POLARITY; 682 1.3 jkunz /* Set SD/MMC mode and use use 8-bits per word. */ 683 1.1 jkunz reg &= ~(HW_SSP_CTRL1_WORD_LENGTH | HW_SSP_CTRL1_SSP_MODE); 684 1.3 jkunz reg |= __SHIFTIN(0x7, HW_SSP_CTRL1_WORD_LENGTH) | 685 1.1 jkunz __SHIFTIN(0x3, HW_SSP_CTRL1_SSP_MODE); 686 1.2 jkunz SSP_WR(sc, HW_SSP_CTRL1, reg); 687 1.1 jkunz 688 1.1 jkunz return; 689 1.1 jkunz } 690 1.1 jkunz 691 1.1 jkunz /* 692 1.1 jkunz * Set SSP_SCK clock rate to the value specified in target. 693 1.1 jkunz * 694 1.1 jkunz * SSP_SCK is calculated as: SSP_CLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)) 695 1.1 jkunz * 696 1.3 jkunz * issp_set_sck finds the most suitable CLOCK_DIVIDE and CLOCK_RATE register 697 1.1 jkunz * values for the target clock rate by iterating through all possible register 698 1.1 jkunz * values. 699 1.1 jkunz */ 700 1.1 jkunz static uint32_t 701 1.1 jkunz issp_set_sck(struct issp_softc *sc, uint32_t target) 702 1.1 jkunz { 703 1.1 jkunz uint32_t newclk, found, reg; 704 1.1 jkunz uint8_t div, rate, d, r; 705 1.1 jkunz 706 1.1 jkunz found = div = rate = 0; 707 1.1 jkunz 708 1.1 jkunz for (d = 2; d < 254; d++) { 709 1.1 jkunz for (r = 0; r < 255; r++) { 710 1.1 jkunz newclk = SSP_CLK / (d * (1 + r)); 711 1.1 jkunz if (newclk == target) { 712 1.1 jkunz found = newclk; 713 1.1 jkunz div = d; 714 1.1 jkunz rate = r; 715 1.1 jkunz goto out; 716 1.1 jkunz } 717 1.1 jkunz if (newclk < target && newclk > found) { 718 1.1 jkunz found = newclk; 719 1.1 jkunz div = d; 720 1.1 jkunz rate = r; 721 1.1 jkunz } 722 1.1 jkunz } 723 1.1 jkunz } 724 1.1 jkunz out: 725 1.2 jkunz reg = SSP_RD(sc, HW_SSP_TIMING); 726 1.1 jkunz reg &= ~(HW_SSP_TIMING_CLOCK_DIVIDE | HW_SSP_TIMING_CLOCK_RATE); 727 1.1 jkunz reg |= __SHIFTIN(div, HW_SSP_TIMING_CLOCK_DIVIDE) | 728 1.1 jkunz __SHIFTIN(rate, HW_SSP_TIMING_CLOCK_RATE); 729 1.2 jkunz SSP_WR(sc, HW_SSP_TIMING, reg); 730 1.1 jkunz 731 1.2 jkunz return SSP_CLK / (div * (1 + rate)); 732 1.1 jkunz } 733 1.3 jkunz 734 1.3 jkunz /* 735 1.3 jkunz * IRQ from DMA. 736 1.3 jkunz */ 737 1.3 jkunz static int 738 1.3 jkunz issp_dma_intr(void *arg) 739 1.3 jkunz { 740 1.3 jkunz issp_softc_t sc = arg; 741 1.3 jkunz unsigned int dma_err; 742 1.3 jkunz 743 1.3 jkunz dma_err = apbdma_intr_status(sc->sc_dmac, sc->dma_channel); 744 1.3 jkunz 745 1.3 jkunz if (dma_err) { 746 1.3 jkunz apbdma_ack_error_intr(sc->sc_dmac, sc->dma_channel); 747 1.3 jkunz } else { 748 1.3 jkunz apbdma_ack_intr(sc->sc_dmac, sc->dma_channel); 749 1.3 jkunz } 750 1.3 jkunz 751 1.3 jkunz mutex_enter(&sc->sc_lock); 752 1.3 jkunz 753 1.3 jkunz sc->sc_dma_error = dma_err; 754 1.3 jkunz sc->sc_state = SSP_STATE_IDLE; 755 1.3 jkunz 756 1.3 jkunz /* Signal thread that interrupt was handled. */ 757 1.3 jkunz cv_signal(&sc->sc_intr_cv); 758 1.3 jkunz 759 1.3 jkunz mutex_exit(&sc->sc_lock); 760 1.3 jkunz 761 1.3 jkunz /* Return 1 to acknowledge IRQ. */ 762 1.3 jkunz return 1; 763 1.3 jkunz } 764 1.3 jkunz 765 1.3 jkunz /* 766 1.3 jkunz * IRQ from SSP block. 767 1.3 jkunz * 768 1.3 jkunz * When SSP receives IRQ it terminates ongoing DMA transfer by issuing DMATERM 769 1.3 jkunz * signal to DMA block. 770 1.3 jkunz */ 771 1.3 jkunz static int 772 1.3 jkunz issp_error_intr(void *arg) 773 1.3 jkunz { 774 1.3 jkunz issp_softc_t sc = arg; 775 1.3 jkunz 776 1.3 jkunz mutex_enter(&sc->sc_lock); 777 1.3 jkunz 778 1.3 jkunz sc->sc_irq_error = 779 1.3 jkunz SSP_RD(sc, HW_SSP_CTRL1) & HW_SSP_CTRL1_IRQ_MASK; 780 1.3 jkunz 781 1.3 jkunz issp_ack_intr(sc); 782 1.3 jkunz 783 1.3 jkunz mutex_exit(&sc->sc_lock); 784 1.3 jkunz 785 1.3 jkunz /* Return 1 to acknowledge IRQ. */ 786 1.3 jkunz return 1; 787 1.3 jkunz } 788 1.3 jkunz 789 1.3 jkunz /* 790 1.3 jkunz * Acknowledge SSP error IRQ. 791 1.3 jkunz */ 792 1.3 jkunz static void 793 1.3 jkunz issp_ack_intr(struct issp_softc *sc) 794 1.3 jkunz { 795 1.3 jkunz 796 1.3 jkunz /* Acknowledge all IRQ's. */ 797 1.3 jkunz SSP_WR(sc, HW_SSP_CTRL1_CLR, HW_SSP_CTRL1_IRQ_MASK); 798 1.3 jkunz 799 1.3 jkunz return; 800 1.3 jkunz } 801 1.3 jkunz 802 1.3 jkunz /* 803 1.3 jkunz * Set up multi block DMA transfer. 804 1.3 jkunz */ 805 1.3 jkunz static void 806 1.3 jkunz issp_create_dma_cmd_list_multi(issp_softc_t sc, void *dma_chain, 807 1.3 jkunz struct sdmmc_command *cmd) 808 1.3 jkunz { 809 1.3 jkunz apbdma_command_t dma_cmd; 810 1.3 jkunz int blocks; 811 1.3 jkunz int nblk; 812 1.3 jkunz 813 1.3 jkunz blocks = cmd->c_datalen / cmd->c_blklen; 814 1.3 jkunz nblk = 0; 815 1.3 jkunz dma_cmd = dma_chain; 816 1.3 jkunz 817 1.3 jkunz /* HEAD */ 818 1.3 jkunz apbdma_cmd_buf(&dma_cmd[nblk], cmd->c_blklen * nblk, cmd->c_dmamap); 819 1.3 jkunz apbdma_cmd_chain(&dma_cmd[nblk], &dma_cmd[nblk+1], dma_chain, 820 1.3 jkunz sc->sc_dmamp); 821 1.3 jkunz 822 1.3 jkunz dma_cmd[nblk].control = 823 1.3 jkunz __SHIFTIN(cmd->c_blklen, APBDMA_CMD_XFER_COUNT) | 824 1.3 jkunz __SHIFTIN(3, APBDMA_CMD_CMDPIOWORDS) | APBDMA_CMD_HALTONTERMINATE | 825 1.3 jkunz APBDMA_CMD_CHAIN; 826 1.3 jkunz 827 1.3 jkunz if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) { 828 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= 829 1.3 jkunz HW_SSP_CTRL0_IGNORE_CRC; 830 1.3 jkunz } 831 1.3 jkunz 832 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_DATA_XFER | 833 1.3 jkunz __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) | 834 1.3 jkunz HW_SSP_CTRL0_WAIT_FOR_IRQ | 835 1.3 jkunz __SHIFTIN(cmd->c_datalen, HW_SSP_CTRL0_XFER_COUNT); 836 1.3 jkunz 837 1.3 jkunz if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) { 838 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= 839 1.3 jkunz HW_SSP_CTRL0_GET_RESP; 840 1.3 jkunz if (ISSET(cmd->c_flags, SCF_RSP_136)) { 841 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= 842 1.3 jkunz HW_SSP_CTRL0_LONG_RESP; 843 1.3 jkunz } 844 1.3 jkunz } 845 1.3 jkunz 846 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_ENABLE; 847 1.3 jkunz 848 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CMD0] = 849 1.3 jkunz __SHIFTIN(ffs(cmd->c_blklen) - 1, HW_SSP_CMD0_BLOCK_SIZE) | 850 1.3 jkunz __SHIFTIN(blocks - 1, HW_SSP_CMD0_BLOCK_COUNT) | 851 1.3 jkunz __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD); 852 1.3 jkunz 853 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CMD1] = cmd->c_arg; 854 1.3 jkunz 855 1.3 jkunz if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 856 1.3 jkunz dma_cmd[nblk].control |= 857 1.3 jkunz __SHIFTIN(APBDMA_CMD_DMA_WRITE, APBDMA_CMD_COMMAND); 858 1.3 jkunz dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_READ; 859 1.3 jkunz } else { 860 1.3 jkunz dma_cmd[nblk].control |= 861 1.3 jkunz __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND); 862 1.3 jkunz } 863 1.3 jkunz 864 1.3 jkunz nblk++; 865 1.3 jkunz 866 1.3 jkunz /* BODY: Build commands for blocks between head and tail, if any. */ 867 1.3 jkunz for (; nblk < blocks - 1; nblk++) { 868 1.3 jkunz 869 1.3 jkunz apbdma_cmd_buf(&dma_cmd[nblk], cmd->c_blklen * nblk, 870 1.3 jkunz cmd->c_dmamap); 871 1.3 jkunz 872 1.3 jkunz apbdma_cmd_chain(&dma_cmd[nblk], &dma_cmd[nblk+1], dma_chain, 873 1.3 jkunz sc->sc_dmamp); 874 1.3 jkunz 875 1.3 jkunz dma_cmd[nblk].control = 876 1.3 jkunz __SHIFTIN(cmd->c_blklen, APBDMA_CMD_XFER_COUNT) | 877 1.3 jkunz APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_CHAIN; 878 1.3 jkunz 879 1.3 jkunz if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 880 1.3 jkunz dma_cmd[nblk].control |= 881 1.3 jkunz __SHIFTIN(APBDMA_CMD_DMA_WRITE, 882 1.3 jkunz APBDMA_CMD_COMMAND); 883 1.3 jkunz } else { 884 1.3 jkunz dma_cmd[nblk].control |= 885 1.3 jkunz __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND); 886 1.3 jkunz } 887 1.3 jkunz } 888 1.3 jkunz 889 1.3 jkunz /* TAIL 890 1.3 jkunz * 891 1.3 jkunz * TODO: Send CMD12/STOP with last DMA command to support 892 1.3 jkunz * SMC_CAPS_AUTO_STOP. 893 1.3 jkunz */ 894 1.3 jkunz apbdma_cmd_buf(&dma_cmd[nblk], cmd->c_blklen * nblk, cmd->c_dmamap); 895 1.3 jkunz /* next = NULL */ 896 1.3 jkunz dma_cmd[nblk].control = 897 1.3 jkunz __SHIFTIN(cmd->c_blklen, APBDMA_CMD_XFER_COUNT) | 898 1.3 jkunz APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_WAIT4ENDCMD | 899 1.3 jkunz APBDMA_CMD_SEMAPHORE | APBDMA_CMD_IRQONCMPLT; 900 1.3 jkunz 901 1.3 jkunz if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 902 1.3 jkunz dma_cmd[nblk].control |= __SHIFTIN(APBDMA_CMD_DMA_WRITE, 903 1.3 jkunz APBDMA_CMD_COMMAND); 904 1.3 jkunz } else { 905 1.3 jkunz dma_cmd[nblk].control |= __SHIFTIN(APBDMA_CMD_DMA_READ, 906 1.3 jkunz APBDMA_CMD_COMMAND); 907 1.3 jkunz } 908 1.3 jkunz 909 1.3 jkunz return; 910 1.3 jkunz } 911 1.3 jkunz 912 1.3 jkunz /* 913 1.3 jkunz * Set up single block DMA transfer. 914 1.3 jkunz */ 915 1.3 jkunz static void 916 1.3 jkunz issp_create_dma_cmd_list_single(issp_softc_t sc, void *dma_chain, 917 1.3 jkunz struct sdmmc_command *cmd) 918 1.3 jkunz { 919 1.3 jkunz apbdma_command_t dma_cmd; 920 1.3 jkunz 921 1.3 jkunz dma_cmd = dma_chain; 922 1.3 jkunz 923 1.3 jkunz dma_cmd[0].control = __SHIFTIN(cmd->c_datalen, APBDMA_CMD_XFER_COUNT) | 924 1.3 jkunz __SHIFTIN(3, APBDMA_CMD_CMDPIOWORDS) | 925 1.3 jkunz APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_WAIT4ENDCMD | 926 1.3 jkunz APBDMA_CMD_SEMAPHORE | APBDMA_CMD_IRQONCMPLT; 927 1.3 jkunz 928 1.3 jkunz /* Transfer single block to the beginning of the DMA buffer. */ 929 1.3 jkunz apbdma_cmd_buf(&dma_cmd[0], 0, cmd->c_dmamap); 930 1.3 jkunz 931 1.3 jkunz if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) { 932 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= 933 1.3 jkunz HW_SSP_CTRL0_IGNORE_CRC; 934 1.3 jkunz } 935 1.3 jkunz 936 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= 937 1.3 jkunz HW_SSP_CTRL0_DATA_XFER | 938 1.3 jkunz __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) | 939 1.3 jkunz HW_SSP_CTRL0_WAIT_FOR_IRQ | 940 1.3 jkunz __SHIFTIN(cmd->c_datalen, HW_SSP_CTRL0_XFER_COUNT); 941 1.3 jkunz 942 1.3 jkunz if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) { 943 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_GET_RESP; 944 1.3 jkunz if (ISSET(cmd->c_flags, SCF_RSP_136)) { 945 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= 946 1.3 jkunz HW_SSP_CTRL0_LONG_RESP; 947 1.3 jkunz } 948 1.3 jkunz } 949 1.3 jkunz 950 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_ENABLE; 951 1.3 jkunz 952 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CMD0] = 953 1.3 jkunz HW_SSP_CMD0_APPEND_8CYC | 954 1.3 jkunz __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD); 955 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CMD1] = cmd->c_arg; 956 1.3 jkunz 957 1.3 jkunz if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 958 1.3 jkunz dma_cmd[0].control |= 959 1.3 jkunz __SHIFTIN(APBDMA_CMD_DMA_WRITE, APBDMA_CMD_COMMAND); 960 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_READ; 961 1.3 jkunz } else { 962 1.3 jkunz dma_cmd[0].control |= 963 1.3 jkunz __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND); 964 1.3 jkunz } 965 1.3 jkunz 966 1.3 jkunz return; 967 1.3 jkunz } 968 1.3 jkunz 969 1.3 jkunz /* 970 1.3 jkunz * Do DMA PIO (issue CMD). No block transfers. 971 1.3 jkunz */ 972 1.3 jkunz static void 973 1.3 jkunz issp_create_dma_cmd_list(issp_softc_t sc, void *dma_chain, 974 1.3 jkunz struct sdmmc_command *cmd) 975 1.3 jkunz { 976 1.3 jkunz apbdma_command_t dma_cmd; 977 1.3 jkunz 978 1.3 jkunz dma_cmd = dma_chain; 979 1.3 jkunz 980 1.3 jkunz dma_cmd[0].control = __SHIFTIN(3, APBDMA_CMD_CMDPIOWORDS) | 981 1.3 jkunz APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_WAIT4ENDCMD | 982 1.3 jkunz APBDMA_CMD_SEMAPHORE | APBDMA_CMD_IRQONCMPLT | 983 1.3 jkunz __SHIFTIN(APBDMA_CMD_NO_DMA_XFER, APBDMA_CMD_COMMAND); 984 1.3 jkunz 985 1.3 jkunz if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) { 986 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= 987 1.3 jkunz HW_SSP_CTRL0_IGNORE_CRC; 988 1.3 jkunz } 989 1.3 jkunz 990 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= 991 1.3 jkunz __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) | 992 1.3 jkunz HW_SSP_CTRL0_WAIT_FOR_IRQ; 993 1.3 jkunz 994 1.3 jkunz if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) { 995 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_GET_RESP; 996 1.3 jkunz if (ISSET(cmd->c_flags, SCF_RSP_136)) { 997 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= 998 1.3 jkunz HW_SSP_CTRL0_LONG_RESP; 999 1.3 jkunz } 1000 1.3 jkunz } 1001 1.3 jkunz 1002 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_ENABLE; 1003 1.3 jkunz 1004 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CMD0] = 1005 1.3 jkunz __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD); 1006 1.3 jkunz dma_cmd[0].pio_words[PIO_WORD_CMD1] = cmd->c_arg; 1007 1.3 jkunz 1008 1.3 jkunz return; 1009 1.3 jkunz } 1010