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