1 1.1 nisimura /*- 2 1.1 nisimura * Copyright (c) 2012 The NetBSD Foundation, Inc. 3 1.1 nisimura * All rights reserved. 4 1.1 nisimura * 5 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation 6 1.1 nisimura * by Paul Fleischer <paul (at) xpg.dk> 7 1.1 nisimura * 8 1.1 nisimura * Redistribution and use in source and binary forms, with or without 9 1.1 nisimura * modification, are permitted provided that the following conditions 10 1.1 nisimura * are met: 11 1.1 nisimura * 1. Redistributions of source code must retain the above copyright 12 1.1 nisimura * notice, this list of conditions and the following disclaimer. 13 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 nisimura * notice, this list of conditions and the following disclaimer in the 15 1.1 nisimura * documentation and/or other materials provided with the distribution. 16 1.1 nisimura * 17 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE. 28 1.1 nisimura */ 29 1.1 nisimura #include "s3csdi.h" 30 1.1 nisimura 31 1.1 nisimura #include <arm/s3c2xx0/s3c2440reg.h> 32 1.1 nisimura 33 1.1 nisimura #include <lib/libsa/stand.h> 34 1.1 nisimura 35 1.2 matt #include <machine/int_mwgwtypes.h> 36 1.1 nisimura #include <machine/limits.h> 37 1.1 nisimura 38 1.1 nisimura #include <dev/sdmmc/sdmmcreg.h> 39 1.1 nisimura 40 1.1 nisimura #define SDI_REG(reg) (*(volatile uint32_t*)(S3C2440_SDI_BASE+reg)) 41 1.1 nisimura 42 1.1 nisimura //#define SSSDI_DEBUG 43 1.1 nisimura #ifdef SSSDI_DEBUG 44 1.1 nisimura #define DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0) 45 1.1 nisimura #else 46 1.1 nisimura #define DPRINTF(s) do {} while (/*CONSTCOND*/0) 47 1.1 nisimura #endif 48 1.1 nisimura 49 1.1 nisimura struct s3csdi_softc { 50 1.1 nisimura int width; 51 1.1 nisimura }; 52 1.1 nisimura 53 1.1 nisimura extern int pclk; 54 1.1 nisimura 55 1.1 nisimura static void sssdi_perform_pio_read(struct sdmmc_command *cmd); 56 1.1 nisimura //static void sssdi_perform_pio_write(struct sdmmc_command *cmd); 57 1.1 nisimura 58 1.1 nisimura static struct s3csdi_softc s3csdi_softc; 59 1.1 nisimura 60 1.1 nisimura int 61 1.1 nisimura s3csd_match(unsigned int tag) 62 1.1 nisimura { 63 1.1 nisimura printf("Found S3C2440 SD/MMC\n"); 64 1.1 nisimura return 1; 65 1.1 nisimura } 66 1.1 nisimura 67 1.1 nisimura void* 68 1.1 nisimura s3csd_init(unsigned int tag, uint32_t *caps) 69 1.1 nisimura { 70 1.1 nisimura uint32_t data; 71 1.1 nisimura 72 1.1 nisimura *caps = SMC_CAPS_4BIT_MODE; 73 1.1 nisimura 74 1.1 nisimura DPRINTF(("CLKCON: 0x%X\n", *(volatile uint32_t*)(S3C2440_CLKMAN_BASE + CLKMAN_CLKCON))); 75 1.1 nisimura 76 1.1 nisimura DPRINTF(("SDI_INT_MASK: 0x%X\n", SDI_REG(SDI_INT_MASK))); 77 1.1 nisimura 78 1.1 nisimura SDI_REG(SDI_INT_MASK) = 0x0; 79 1.1 nisimura SDI_REG(SDI_DTIMER) = 0x007FFFFF; 80 1.1 nisimura 81 1.1 nisimura SDI_REG(SDI_CON) &= ~SDICON_ENCLK; 82 1.1 nisimura 83 1.1 nisimura SDI_REG(SDI_CON) = SDICON_SD_RESET | SDICON_CTYP_SD; 84 1.1 nisimura 85 1.1 nisimura /* Set GPG8 to input such that we can check if there is a card present 86 1.1 nisimura */ 87 1.1 nisimura data = *(volatile uint32_t*)(S3C2440_GPIO_BASE+GPIO_PGCON); 88 1.1 nisimura data = GPIO_SET_FUNC(data, 8, 0x00); 89 1.1 nisimura *(volatile uint32_t*)(S3C2440_GPIO_BASE+GPIO_PGCON) = data; 90 1.1 nisimura 91 1.1 nisimura /* Check if a card is present */ 92 1.1 nisimura data = *(volatile uint32_t*)(S3C2440_GPIO_BASE+GPIO_PGDAT); 93 1.4 christos if ( (data & (1<<8)) == (1<<8)) { 94 1.1 nisimura printf("No card detected\n"); 95 1.1 nisimura /* Pin 8 is low when no card is inserted */ 96 1.1 nisimura return 0; 97 1.1 nisimura } 98 1.1 nisimura printf("Card detected\n"); 99 1.1 nisimura 100 1.1 nisimura s3csdi_softc.width = 1; 101 1.1 nisimura 102 1.1 nisimura /* We have no private data to return, but 0 signals error */ 103 1.1 nisimura return (void*)0x01; 104 1.1 nisimura } 105 1.1 nisimura 106 1.1 nisimura int 107 1.1 nisimura s3csd_bus_clock(void *priv, int freq) 108 1.1 nisimura { 109 1.1 nisimura int div; 110 1.1 nisimura int clock_set = 0; 111 1.1 nisimura int control; 112 1.1 nisimura int clk = pclk/1000; /*Peripheral bus clock in KHz*/ 113 1.1 nisimura 114 1.1 nisimura /* Round peripheral bus clock down to nearest MHz */ 115 1.1 nisimura clk = (clk / 1000) * 1000; 116 1.1 nisimura 117 1.1 nisimura control = SDI_REG(SDI_CON); 118 1.1 nisimura SDI_REG(SDI_CON) = control & ~SDICON_ENCLK; 119 1.1 nisimura 120 1.1 nisimura 121 1.1 nisimura /* If the frequency is zero just keep the clock disabled */ 122 1.1 nisimura if (freq == 0) 123 1.1 nisimura return 0; 124 1.1 nisimura 125 1.1 nisimura for (div = 1; div <= 256; div++) { 126 1.1 nisimura if ( clk / div <= freq) { 127 1.1 nisimura DPRINTF(("Using divisor %d: %d/%d = %d\n", div, clk, 128 1.1 nisimura div, clk/div)); 129 1.1 nisimura clock_set = 1; 130 1.1 nisimura SDI_REG(SDI_PRE) = div-1; 131 1.1 nisimura break; 132 1.1 nisimura } 133 1.1 nisimura } 134 1.1 nisimura 135 1.1 nisimura if (clock_set) { 136 1.1 nisimura SDI_REG(SDI_CON) = control | SDICON_ENCLK; 137 1.1 nisimura if (div-1 != SDI_REG(SDI_PRE)) { 138 1.1 nisimura return 1; 139 1.1 nisimura } 140 1.1 nisimura 141 1.1 nisimura sdmmc_delay(74000/freq); 142 1.1 nisimura /* Wait for 74 SDCLK */ 143 1.1 nisimura /* 1/freq is the length of a clock cycle, 144 1.1 nisimura so we have to wait 1/freq * 74 . 145 1.1 nisimura 74000 / freq should express the delay in us. 146 1.1 nisimura */ 147 1.1 nisimura return 0; 148 1.1 nisimura } else { 149 1.1 nisimura return 1; 150 1.1 nisimura } 151 1.1 nisimura } 152 1.1 nisimura 153 1.1 nisimura #define SSSDI_TRANSFER_NONE 0 154 1.1 nisimura #define SSSDI_TRANSFER_READ 1 155 1.1 nisimura #define SSSDI_TRANSFER_WRITE 2 156 1.1 nisimura 157 1.1 nisimura void 158 1.1 nisimura s3csd_exec_cmd(void *priv, struct sdmmc_command *cmd) 159 1.1 nisimura { 160 1.1 nisimura uint32_t cmd_control; 161 1.1 nisimura int status = 0; 162 1.1 nisimura uint32_t data_status; 163 1.1 nisimura int transfer = SSSDI_TRANSFER_NONE; 164 1.1 nisimura 165 1.1 nisimura DPRINTF(("s3csd_exec_cmd\n")); 166 1.1 nisimura 167 1.1 nisimura SDI_REG(SDI_DAT_FSTA) = 0xFFFFFFFF; 168 1.1 nisimura SDI_REG(SDI_DAT_STA) = 0xFFFFFFFF; 169 1.1 nisimura SDI_REG(SDI_CMD_STA) = 0xFFFFFFFF; 170 1.1 nisimura 171 1.1 nisimura SDI_REG(SDI_CMD_ARG) = cmd->c_arg; 172 1.1 nisimura 173 1.1 nisimura cmd_control = (cmd->c_opcode & SDICMDCON_CMD_MASK) | 174 1.1 nisimura SDICMDCON_HOST_CMD | SDICMDCON_CMST; 175 1.1 nisimura if (cmd->c_flags & SCF_RSP_PRESENT) 176 1.1 nisimura cmd_control |= SDICMDCON_WAIT_RSP; 177 1.1 nisimura if (cmd->c_flags & SCF_RSP_136) 178 1.1 nisimura cmd_control |= SDICMDCON_LONG_RSP; 179 1.1 nisimura 180 1.1 nisimura if (cmd->c_datalen > 0 && cmd->c_data != NULL) { 181 1.1 nisimura /* TODO: Ensure that the above condition matches the semantics 182 1.1 nisimura of SDICMDCON_WITH_DATA*/ 183 1.1 nisimura DPRINTF(("DATA, datalen: %d, blk_size: %d, offset: %d\n", cmd->c_datalen, 184 1.1 nisimura cmd->c_blklen, cmd->c_arg)); 185 1.1 nisimura cmd_control |= SDICMDCON_WITH_DATA; 186 1.1 nisimura } 187 1.1 nisimura 188 1.1 nisimura if (cmd->c_opcode == MMC_STOP_TRANSMISSION) { 189 1.1 nisimura cmd_control |= SDICMDCON_ABORT_CMD; 190 1.1 nisimura } 191 1.1 nisimura 192 1.1 nisimura SDI_REG(SDI_DTIMER) = 0x007FFFFF; 193 1.1 nisimura SDI_REG(SDI_BSIZE) = cmd->c_blklen; 194 1.1 nisimura 195 1.1 nisimura if ( (cmd->c_flags & SCF_CMD_READ) && 196 1.1 nisimura (cmd_control & SDICMDCON_WITH_DATA)) { 197 1.1 nisimura uint32_t data_control; 198 1.1 nisimura DPRINTF(("Reading %d bytes\n", cmd->c_datalen)); 199 1.1 nisimura transfer = SSSDI_TRANSFER_READ; 200 1.1 nisimura 201 1.1 nisimura data_control = SDIDATCON_DATMODE_RECEIVE | SDIDATCON_RACMD | 202 1.1 nisimura SDIDATCON_DTST | SDIDATCON_BLKMODE | 203 1.1 nisimura ((cmd->c_datalen / cmd->c_blklen) & SDIDATCON_BLKNUM_MASK) | 204 1.1 nisimura SDIDATCON_DATA_WORD; 205 1.1 nisimura 206 1.1 nisimura 207 1.1 nisimura if (s3csdi_softc.width == 4) { 208 1.1 nisimura data_control |= SDIDATCON_WIDEBUS; 209 1.1 nisimura } 210 1.1 nisimura 211 1.1 nisimura SDI_REG(SDI_DAT_CON) = data_control; 212 1.1 nisimura } else if (cmd_control & SDICMDCON_WITH_DATA) { 213 1.1 nisimura /* Write data */ 214 1.1 nisimura 215 1.1 nisimura uint32_t data_control; 216 1.1 nisimura DPRINTF(("Writing %d bytes\n", cmd->c_datalen)); 217 1.1 nisimura DPRINTF(("Requesting %d blocks\n", 218 1.1 nisimura cmd->c_datalen / cmd->c_blklen)); 219 1.1 nisimura transfer = SSSDI_TRANSFER_WRITE; 220 1.1 nisimura data_control = SDIDATCON_DATMODE_TRANSMIT | SDIDATCON_BLKMODE | 221 1.1 nisimura SDIDATCON_TARSP | SDIDATCON_DTST | 222 1.1 nisimura ((cmd->c_datalen / cmd->c_blklen) & SDIDATCON_BLKNUM_MASK) | 223 1.1 nisimura SDIDATCON_DATA_WORD; 224 1.1 nisimura 225 1.1 nisimura /* if (sc->width == 4) { 226 1.1 nisimura data_control |= SDIDATCON_WIDEBUS; 227 1.1 nisimura }*/ 228 1.1 nisimura 229 1.1 nisimura SDI_REG(SDI_DAT_CON) = data_control; 230 1.1 nisimura } 231 1.1 nisimura 232 1.1 nisimura DPRINTF(("SID_CMD_CON: 0x%X\n", cmd_control)); 233 1.1 nisimura /* Send command to SDI */ 234 1.1 nisimura SDI_REG(SDI_CMD_CON) = cmd_control; 235 1.1 nisimura DPRINTF(("Status before cmd sent: 0x%X\n", SDI_REG(SDI_CMD_STA))); 236 1.1 nisimura DPRINTF(("Waiting for command being sent\n")); 237 1.1 nisimura while( !(SDI_REG(SDI_CMD_STA) & SDICMDSTA_CMD_SENT)); 238 1.1 nisimura DPRINTF(("Command has been sent\n")); 239 1.1 nisimura 240 1.1 nisimura //SDI_REG(SDI_CMD_STA) |= SDICMDSTA_CMD_SENT; 241 1.1 nisimura 242 1.1 nisimura if (!(cmd_control & SDICMDCON_WAIT_RSP)) { 243 1.1 nisimura SDI_REG(SDI_CMD_STA) |= SDICMDSTA_CMD_SENT; 244 1.1 nisimura cmd->c_flags |= SCF_ITSDONE; 245 1.1 nisimura goto out; 246 1.1 nisimura } 247 1.1 nisimura 248 1.1 nisimura DPRINTF(("waiting for response\n")); 249 1.1 nisimura while(1) { 250 1.1 nisimura status = SDI_REG(SDI_CMD_STA); 251 1.1 nisimura if (status & SDICMDSTA_RSP_FIN) { 252 1.1 nisimura break; 253 1.1 nisimura } 254 1.1 nisimura if (status & SDICMDSTA_CMD_TIMEOUT) { 255 1.1 nisimura break; 256 1.1 nisimura } 257 1.1 nisimura } 258 1.1 nisimura 259 1.1 nisimura DPRINTF(("Status: 0x%X\n", status)); 260 1.1 nisimura if (status & SDICMDSTA_CMD_TIMEOUT) { 261 1.1 nisimura cmd->c_error = ETIMEDOUT; 262 1.1 nisimura DPRINTF(("Timeout waiting for response\n")); 263 1.1 nisimura goto out; 264 1.1 nisimura } 265 1.1 nisimura DPRINTF(("Got Response\n")); 266 1.1 nisimura 267 1.1 nisimura if (cmd->c_flags & SCF_RSP_136 ) { 268 1.1 nisimura uint32_t w[4]; 269 1.1 nisimura 270 1.1 nisimura /* We store the response least significant word first */ 271 1.1 nisimura w[0] = SDI_REG(SDI_RSP3); 272 1.1 nisimura w[1] = SDI_REG(SDI_RSP2); 273 1.1 nisimura w[2] = SDI_REG(SDI_RSP1); 274 1.1 nisimura w[3] = SDI_REG(SDI_RSP0); 275 1.1 nisimura 276 1.1 nisimura /* The sdmmc subsystem expects that the response is delivered 277 1.1 nisimura without the lower 8 bits (CRC + '1' bit) */ 278 1.1 nisimura cmd->c_resp[0] = (w[0] >> 8) | ((w[1] & 0xFF) << 24); 279 1.1 nisimura cmd->c_resp[1] = (w[1] >> 8) | ((w[2] & 0XFF) << 24); 280 1.1 nisimura cmd->c_resp[2] = (w[2] >> 8) | ((w[3] & 0XFF) << 24); 281 1.1 nisimura cmd->c_resp[3] = (w[3] >> 8); 282 1.1 nisimura 283 1.1 nisimura } else { 284 1.1 nisimura cmd->c_resp[0] = SDI_REG(SDI_RSP0); 285 1.1 nisimura cmd->c_resp[1] = SDI_REG(SDI_RSP1); 286 1.1 nisimura } 287 1.1 nisimura 288 1.1 nisimura DPRINTF(("Response: %X %X %X %X\n", 289 1.1 nisimura cmd->c_resp[0], 290 1.1 nisimura cmd->c_resp[1], 291 1.1 nisimura cmd->c_resp[2], 292 1.1 nisimura cmd->c_resp[3])); 293 1.1 nisimura 294 1.1 nisimura status = SDI_REG(SDI_DAT_CNT); 295 1.1 nisimura 296 1.1 nisimura DPRINTF(("Remaining bytes of current block: %d\n", 297 1.1 nisimura SDIDATCNT_BLK_CNT(status))); 298 1.1 nisimura DPRINTF(("Remaining Block Number : %d\n", 299 1.1 nisimura SDIDATCNT_BLK_NUM_CNT(status))); 300 1.1 nisimura 301 1.1 nisimura data_status = SDI_REG(SDI_DAT_STA); 302 1.1 nisimura 303 1.1 nisimura DPRINTF(("SDI Data Status Register Before xfer: 0x%X\n", data_status)); 304 1.1 nisimura 305 1.1 nisimura if (data_status & SDIDATSTA_DATA_TIMEOUT) { 306 1.1 nisimura cmd->c_error = ETIMEDOUT; 307 1.1 nisimura DPRINTF(("Timeout waiting for data\n")); 308 1.1 nisimura goto out; 309 1.1 nisimura } 310 1.1 nisimura 311 1.1 nisimura 312 1.1 nisimura if (transfer == SSSDI_TRANSFER_READ) { 313 1.1 nisimura DPRINTF(("Waiting for transfer to complete\n")); 314 1.1 nisimura 315 1.1 nisimura sssdi_perform_pio_read(cmd); 316 1.1 nisimura } else if (transfer == SSSDI_TRANSFER_WRITE) { 317 1.1 nisimura 318 1.1 nisimura /* DPRINTF(("PIO WRITE\n")); 319 1.1 nisimura sssdi_perform_pio_write(sc, cmd); 320 1.1 nisimura 321 1.1 nisimura if (cmd->c_error == ETIMEDOUT) 322 1.1 nisimura goto out;*/ 323 1.1 nisimura } 324 1.1 nisimura 325 1.1 nisimura 326 1.1 nisimura /* Response has been received, and any data transfer needed has been 327 1.1 nisimura performed */ 328 1.1 nisimura cmd->c_flags |= SCF_ITSDONE; 329 1.1 nisimura 330 1.1 nisimura out: 331 1.1 nisimura 332 1.1 nisimura data_status = SDI_REG(SDI_DAT_STA); 333 1.1 nisimura DPRINTF(("SDI Data Status Register after execute: 0x%X\n", data_status)); 334 1.1 nisimura 335 1.1 nisimura /* Clear status register. Their are cleared on the 336 1.1 nisimura next sssdi_exec_command */ 337 1.1 nisimura SDI_REG(SDI_CMD_STA) = 0xFFFFFFFF; 338 1.1 nisimura SDI_REG(SDI_DAT_CON) = 0x0; 339 1.1 nisimura } 340 1.1 nisimura 341 1.1 nisimura void 342 1.1 nisimura sssdi_perform_pio_read(struct sdmmc_command *cmd) 343 1.1 nisimura { 344 1.1 nisimura uint32_t status; 345 1.1 nisimura uint32_t fifo_status; 346 1.1 nisimura int count; 347 1.1 nisimura uint32_t written; 348 1.1 nisimura uint8_t *dest = (uint8_t*)cmd->c_data; 349 1.1 nisimura int i; 350 1.1 nisimura 351 1.1 nisimura written = 0; 352 1.1 nisimura 353 1.1 nisimura while (written < cmd->c_datalen ) { 354 1.1 nisimura /* Wait until the FIFO is full or has the final data. 355 1.1 nisimura In the latter case it might not get filled. */ 356 1.1 nisimura //status = sssdi_wait_intr(sc, SDI_FIFO_RX_FULL | SDI_FIFO_RX_LAST, 1000); 357 1.1 nisimura //printf("Waiting for FIFO (got %d / %d)\n", written, cmd->c_datalen); 358 1.1 nisimura do { 359 1.1 nisimura status = SDI_REG(SDI_DAT_FSTA); 360 1.1 nisimura } while( !(status & SDIDATFSTA_RF_FULL) && !(status & SDIDATFSTA_RF_LAST)); 361 1.1 nisimura //printf("Done\n"); 362 1.1 nisimura 363 1.1 nisimura fifo_status = SDI_REG(SDI_DAT_FSTA); 364 1.1 nisimura count = SDIDATFSTA_FFCNT(fifo_status); 365 1.1 nisimura 366 1.1 nisimura //printf("Writing %d bytes to %p\n", count, dest); 367 1.1 nisimura for(i=0; i<count; i+=4) { 368 1.1 nisimura uint32_t buf; 369 1.1 nisimura 370 1.1 nisimura buf = SDI_REG(SDI_DAT_LI_W); 371 1.1 nisimura *dest = (buf & 0xFF); dest++; 372 1.1 nisimura *dest = (buf >> 8) & 0xFF; dest++; 373 1.1 nisimura *dest = (buf >> 16) & 0xFF; dest++; 374 1.1 nisimura *dest = (buf >> 24) & 0xFF; dest++; 375 1.1 nisimura written += 4; 376 1.1 nisimura } 377 1.1 nisimura } 378 1.1 nisimura } 379 1.1 nisimura 380 1.1 nisimura #if 0 381 1.1 nisimura void 382 1.1 nisimura sssdi_perform_pio_write(struct sdmmc_command *cmd) 383 1.1 nisimura { 384 1.1 nisimura uint32_t status; 385 1.1 nisimura uint32_t fifo_status; 386 1.1 nisimura int count; 387 1.1 nisimura uint32_t written; 388 1.1 nisimura uint32_t *dest = (uint32_t*)cmd->c_data; 389 1.1 nisimura 390 1.1 nisimura written = 0; 391 1.1 nisimura 392 1.1 nisimura while (written < cmd->c_datalen ) { 393 1.1 nisimura /* Wait until the FIFO is full or has the final data. 394 1.1 nisimura In the latter case it might not get filled. */ 395 1.1 nisimura DPRINTF(("Waiting for FIFO to become empty\n")); 396 1.1 nisimura status = sssdi_wait_intr(sc, SDI_FIFO_TX_EMPTY, 1000); 397 1.1 nisimura 398 1.1 nisimura fifo_status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_FSTA); 399 1.1 nisimura DPRINTF(("PIO Write FIFO Status: 0x%X\n", fifo_status)); 400 1.1 nisimura count = 64-SDIDATFSTA_FFCNT(fifo_status); 401 1.1 nisimura 402 1.1 nisimura status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_CNT); 403 1.1 nisimura DPRINTF(("Remaining bytes of current block: %d\n", 404 1.1 nisimura SDIDATCNT_BLK_CNT(status))); 405 1.1 nisimura DPRINTF(("Remaining Block Number : %d\n", 406 1.1 nisimura SDIDATCNT_BLK_NUM_CNT(status))); 407 1.1 nisimura 408 1.1 nisimura 409 1.1 nisimura status = bus_space_read_4(sc->iot,sc->ioh, SDI_DAT_STA); 410 1.1 nisimura DPRINTF(("PIO Write Data Status: 0x%X\n", status)); 411 1.1 nisimura 412 1.1 nisimura if (status & SDIDATSTA_DATA_TIMEOUT) { 413 1.1 nisimura cmd->c_error = ETIMEDOUT; 414 1.1 nisimura /* Acknowledge the timeout*/ 415 1.1 nisimura bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_STA, 416 1.1 nisimura SDIDATSTA_DATA_TIMEOUT); 417 1.3 chs printf("%s: Data timeout\n", device_xname(sc->dev)); 418 1.1 nisimura break; 419 1.1 nisimura } 420 1.1 nisimura 421 1.1 nisimura DPRINTF(("Filling FIFO with %d bytes\n", count)); 422 1.1 nisimura for(int i=0; i<count; i+=4) { 423 1.1 nisimura bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_LI_W, *dest); 424 1.1 nisimura written += 4; 425 1.1 nisimura dest++; 426 1.1 nisimura } 427 1.1 nisimura } 428 1.1 nisimura } 429 1.1 nisimura #endif 430 1.1 nisimura 431 1.1 nisimura int 432 1.1 nisimura s3csd_host_ocr(void *priv) 433 1.1 nisimura { 434 1.1 nisimura return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V; 435 1.1 nisimura } 436 1.1 nisimura 437 1.1 nisimura int 438 1.1 nisimura s3csd_bus_power(void *priv, int ocr) 439 1.1 nisimura { 440 1.1 nisimura return 0; 441 1.1 nisimura } 442 1.1 nisimura 443 1.1 nisimura int 444 1.1 nisimura s3csd_bus_width(void *priv, int width) 445 1.1 nisimura { 446 1.1 nisimura s3csdi_softc.width = width; 447 1.1 nisimura return 0; 448 1.1 nisimura } 449 1.1 nisimura 450 1.1 nisimura int 451 1.1 nisimura s3csd_get_max_bus_clock(void *priv) 452 1.1 nisimura { 453 1.1 nisimura return pclk / 1; 454 1.1 nisimura } 455