s3csdi.c revision 1.3 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.1 nisimura if ( (data & (1<<8)) == 1) {
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