s3c2440_sdi.c revision 1.5 1 /* $NetBSD: s3c2440_sdi.c,v 1.5 2019/11/10 21:16:24 chs Exp $ */
2 /*-
3 * Copyright (c) 2012 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Paul Fleischer <paul (at) xpg.dk>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: s3c2440_sdi.c,v 1.5 2019/11/10 21:16:24 chs Exp $");
32
33 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/malloc.h> /* For M_NOWAIT*/
38
39 #include <sys/mutex.h>
40 #include <sys/condvar.h>
41
42 #include <sys/bus.h>
43 #include <machine/cpu.h>
44
45 #include <arm/s3c2xx0/s3c24x0var.h>
46 #include <arm/s3c2xx0/s3c2440var.h>
47 #include <arm/s3c2xx0/s3c24x0reg.h>
48 #include <arm/s3c2xx0/s3c2440reg.h>
49 #include <arm/s3c2xx0/s3c2440_dma.h>
50
51 //#include <arm/s3c2xx0/s3c2440_sdi.h>
52
53 #include <dev/sdmmc/sdmmcchip.h>
54 #include <dev/sdmmc/sdmmcvar.h>
55
56 #include <uvm/uvm_extern.h>
57 /*#define SSSDI_DEBUG*/
58 #ifdef SSSDI_DEBUG
59 #define DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
60 #else
61 #define DPRINTF(s) do {} while (/*CONSTCOND*/0)
62 #endif
63
64 struct sssdi_softc {
65 device_t dev;
66
67 bus_space_tag_t iot;
68
69 bus_space_handle_t ioh;
70 bus_space_handle_t card_ioh; /* Card detect I/O*/
71
72 device_t sdmmc;
73
74 uint32_t caps;
75
76 int width; /* Transfer width */
77 void *sc_ih; /* SSSDI Interrupt handler */
78
79 struct kmutex intr_mtx;
80 struct kcondvar intr_cv;
81 uint32_t intr_status; /* Set by the interrupt handler */
82
83 dmac_xfer_t sc_xfer;
84
85 bus_dma_segment_t sc_dr;
86 };
87
88 /* Basic driver stuff */
89 static int sssdi_match(device_t, cfdata_t, void *);
90 static void sssdi_attach(device_t, device_t, void *);
91
92 CFATTACH_DECL_NEW(sssdi, sizeof(struct sssdi_softc), sssdi_match, sssdi_attach,
93 NULL, NULL);
94
95 /* SD/MMC chip functions */
96 static int sssdi_host_reset(sdmmc_chipset_handle_t);
97 static uint32_t sssdi_host_ocr(sdmmc_chipset_handle_t);
98 static int sssdi_maxblklen(sdmmc_chipset_handle_t);
99 static int sssdi_card_detect(sdmmc_chipset_handle_t);
100 static int sssdi_write_protect(sdmmc_chipset_handle_t);
101 static int sssdi_bus_power(sdmmc_chipset_handle_t, uint32_t);
102 static int sssdi_bus_clock(sdmmc_chipset_handle_t, int);
103 static int sssdi_bus_width(sdmmc_chipset_handle_t, int);
104 static int sssdi_bus_rod(sdmmc_chipset_handle_t, int);
105 static void sssdi_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
106 static void sssdi_card_enable_intr(sdmmc_chipset_handle_t, int);
107 static void sssdi_card_intr_ack(sdmmc_chipset_handle_t);
108
109 /* Interrupt Handlers */
110 int sssdi_intr(void *arg);
111 int sssdi_intr_card(void *arg);
112
113 /* Interrupt helper functions */
114 static void sssdi_enable_intr(struct sssdi_softc *, uint32_t );
115 void sssdi_disable_intr(struct sssdi_softc *sc, uint32_t i);
116 void sssdi_clear_intr(struct sssdi_softc *sc);
117 static int sssdi_wait_intr(struct sssdi_softc *sc, uint32_t mask, int timeout);
118
119 /* Programmed I/O transfer helpers */
120 void sssdi_perform_pio_read(struct sssdi_softc *sc, struct sdmmc_command *cmd);
121 void sssdi_perform_pio_write(struct sssdi_softc *sc, struct sdmmc_command *cmd);
122
123 /* Interrupt helper defines */
124 #define SDI_CMD_SENT SDIINTMASK_CMD_SENT
125 #define SDI_CMD_TIMEOUT SDIINTMASK_CMD_TIMEOUT
126 #define SDI_RESP_FIN SDIINTMASK_RESP
127 #define SDI_FIFO_RX_FULL SDIINTMASK_RF_FULL
128 #define SDI_FIFO_RX_LAST SDIINTMASK_RF_LAST
129 #define SDI_FIFO_TX_EMPTY SDIINTMASK_TF_EMPTY
130 #define SDI_DATA_FIN SDIINTMASK_DATA_FIN
131 #define SDI_DATA_TIMEOUT SDIINTMASK_DATA_TIMEOUT
132
133 /* Constants */
134 #define SDI_DMA_WAIT_TIME 5000 /* ms */
135 #define SDI_CMD_WAIT_TIME 5000 /* ms */
136
137 /* SDMMC function structure */
138 struct sdmmc_chip_functions sssdi_functions = {
139 /* host controller reset */
140 .host_reset = sssdi_host_reset,
141
142 /* host capabilities */
143 .host_ocr = sssdi_host_ocr,
144 .host_maxblklen = sssdi_maxblklen,
145
146 /* card detection */
147 .card_detect = sssdi_card_detect,
148
149 /* write protect */
150 .write_protect = sssdi_write_protect,
151
152 /* bus power, clock frequency and width */
153 .bus_power = sssdi_bus_power,
154 .bus_clock = sssdi_bus_clock,
155 .bus_width = sssdi_bus_width,
156 .bus_rod = sssdi_bus_rod,
157
158 /* command execution */
159 .exec_command = sssdi_exec_command,
160
161 /* card interrupt */
162 .card_enable_intr = sssdi_card_enable_intr,
163 .card_intr_ack = sssdi_card_intr_ack,
164 };
165
166 int
167 sssdi_match(device_t parent, cfdata_t match, void *aux)
168 {
169 /* struct s3c2xx0_attach_args *sa = aux;*/
170
171 /* Not sure how to match here, maybe CPU type? */
172 return 1;
173 }
174
175 void
176 sssdi_attach(device_t parent, device_t self, void *aux)
177 {
178 struct sssdi_softc *sc = device_private(self);
179 struct s3c2xx0_attach_args *sa = (struct s3c2xx0_attach_args *)aux;
180 struct sdmmcbus_attach_args saa;
181 bus_space_tag_t iot = sa->sa_iot;
182 uint32_t data;
183
184 sc->dev = self;
185 sc->iot = iot;
186
187 if (bus_space_map(iot, S3C2440_SDI_BASE, S3C2440_SDI_SIZE, 0, &sc->ioh) ) {
188 printf(": failed to map registers");
189 return;
190 }
191
192 if (bus_space_map(iot, S3C2440_GPIO_BASE, S3C2440_GPIO_SIZE, 0, &sc->card_ioh) ) {
193 printf(": failed to map GPIO memory for card detection");
194 return;
195 }
196
197 /* Set GPG8 to EINT[16], as it is the card detect line. */
198 data = bus_space_read_4(sc->iot, sc->card_ioh, GPIO_PGCON);
199 data = GPIO_SET_FUNC(data, 8, 0x2);
200 bus_space_write_4(sc->iot, sc->card_ioh, GPIO_PGCON, data);
201
202 /* Set GPH8 to input, as it is used to detect write protection. */
203 data = bus_space_read_4(sc->iot, sc->card_ioh, GPIO_PHCON);
204 data = GPIO_SET_FUNC(data, 8, 0x00);
205 bus_space_write_4(sc->iot, sc->card_ioh, GPIO_PHCON, data);
206
207 mutex_init(&sc->intr_mtx, MUTEX_DEFAULT, IPL_SDMMC);
208
209 cv_init(&sc->intr_cv, "s3c2440_sdiintr");
210 sc->intr_status = 0;
211 sc->caps = SMC_CAPS_4BIT_MODE | SMC_CAPS_DMA | SMC_CAPS_MULTI_SEG_DMA;
212
213 memset(&saa, 0, sizeof(saa));
214 saa.saa_busname = "sdmmc";
215 saa.saa_sct = &sssdi_functions;
216 saa.saa_sch = sc;
217 saa.saa_dmat = sa->sa_dmat;
218 saa.saa_clkmin = s3c2xx0_softc->sc_pclk / 256;
219 saa.saa_clkmax = s3c2xx0_softc->sc_pclk / 1; /* PCLK/1 or PCLK/2 depending on how the spec is read */
220 saa.saa_caps = sc->caps;
221
222 /* Attach our interrupt handler */
223 sc->sc_ih = s3c24x0_intr_establish(S3C2410_INT_SDI, IPL_SDMMC, IST_EDGE_RISING, sssdi_intr, sc);
224
225 /* Attach interrupt handler to detect change in card status */
226 s3c2440_extint_establish(16, IPL_SDMMC, IST_EDGE_BOTH, sssdi_intr_card, sc);
227
228 data = bus_space_read_4(s3c2xx0_softc->sc_iot, s3c2xx0_softc->sc_clkman_ioh, CLKMAN_CLKCON);
229 bus_space_write_4(s3c2xx0_softc->sc_iot, s3c2xx0_softc->sc_clkman_ioh, CLKMAN_CLKCON, data | CLKCON_SDI);
230
231 (void) sssdi_host_reset(sc);
232
233 printf("\n");
234
235 /* Attach to the generic SD/MMC bus */
236 /* Is it a good idea to get the private parts of sdmmc ? */
237 sc->sdmmc = config_found(sc->dev, &saa, NULL);
238
239 sc->sc_xfer = s3c2440_dmac_allocate_xfer();
240 sc->sc_dr.ds_addr = S3C2440_SDI_BASE+SDI_DAT_LI_W;
241 sc->sc_dr.ds_len = 4;
242 }
243
244 int
245 sssdi_host_reset(sdmmc_chipset_handle_t sch)
246 {
247 struct sssdi_softc *sc = (struct sssdi_softc*)sch;
248
249 /* Note that we do not enable the clock just yet. */
250 bus_space_write_4(sc->iot, sc->ioh, SDI_CON, SDICON_SD_RESET |
251 SDICON_CTYP_SD | SDICON_RCV_IO_INT);
252 /* bus_space_write_4(sc->iot, sc->ioh, SDI_CMD_STA, SDICMDSTA_RSP_CRC | SDICMDSTA_CMD_SENT |
253 SDICMDSTA_CMD_TIMEOUT | SDICMDSTA_RSP_FIN);*/
254
255 sssdi_clear_intr(sc);
256 sssdi_enable_intr(sc, SDI_CMD_SENT | SDI_CMD_TIMEOUT | SDI_DATA_TIMEOUT
257 | SDI_RESP_FIN);
258
259 return 0;
260 }
261
262 uint32_t
263 sssdi_host_ocr(sdmmc_chipset_handle_t sch)
264 {
265 /* This really ought to be made configurable, I guess... */
266 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
267 }
268
269 int
270 sssdi_maxblklen(sdmmc_chipset_handle_t sch)
271 {
272 /* The S3C2440 user's manual mentions 4095 as a maximum */
273 return 4095;
274 }
275
276 int
277 sssdi_card_detect(sdmmc_chipset_handle_t sch)
278 {
279 struct sssdi_softc *sc = (struct sssdi_softc*)sch;
280 uint32_t data;
281
282 DPRINTF(("sssdi_card_detect\n"));
283
284 data = bus_space_read_4(sc->iot, sc->card_ioh, GPIO_PGDAT);
285
286 /* GPIO Port G, pin 8 is high when card is inserted. */
287 if ( (data & (1<<8)) == 0) {
288 return 1; /* Card Present */
289 } else {
290 return 0; /* No Card */
291 }
292 }
293
294 int
295 sssdi_write_protect(sdmmc_chipset_handle_t sch)
296 {
297 struct sssdi_softc *sc = (struct sssdi_softc*)sch;
298 uint32_t data;
299
300 data = bus_space_read_4(sc->iot, sc->card_ioh, GPIO_PHDAT);
301
302
303 /* If GPIO Port H Pin 8 is high, the card is write protected. */
304 if ( (data & (1<<8)) ) {
305 return 1; /* Write protected */
306 } else {
307 return 0; /* Writable */
308 }
309 }
310
311 int
312 sssdi_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
313 {
314 /* Do nothing, we can't adjust the bus power */
315 return 0;
316 }
317
318 int
319 sssdi_bus_clock(sdmmc_chipset_handle_t sch, int freq)
320 {
321 struct sssdi_softc *sc = (struct sssdi_softc*)sch;
322 int div;
323 int clock_set = 0;
324 int control;
325 int pclk = s3c2xx0_softc->sc_pclk/1000; /*Peripheral bus clock in KHz*/
326
327 /* Round peripheral bus clock down to nearest MHz */
328 pclk = (pclk / 1000) * 1000;
329
330 control = bus_space_read_4(sc->iot, sc->ioh, SDI_CON);
331 bus_space_write_4(sc->iot, sc->ioh, SDI_CON, control & ~SDICON_ENCLK);
332
333 DPRINTF(("sssdi_bus_clock (freq: %d KHz)\n", freq));
334
335 /* If the frequency is zero just keep the clock disabled */
336 if (freq == 0)
337 return 0;
338
339 for (div = 1; div <= 256; div++) {
340 if ( pclk / div <= freq) {
341 DPRINTF(("Using divisor %d: %d/%d = %d\n", div, pclk,
342 div, pclk/div));
343 clock_set = 1;
344 bus_space_write_1(sc->iot, sc->ioh, SDI_PRE, div-1);
345 break;
346 }
347 }
348
349 if (clock_set) {
350 bus_space_write_4(sc->iot, sc->ioh,
351 SDI_CON, control | SDICON_ENCLK);
352 if (div-1 == bus_space_read_4(sc->iot, sc->ioh, SDI_PRE)) {
353 /* Clock successfully set, TODO: how do we fail?! */
354 }
355
356 /* We do not need to wait here, as the sdmmc code will do that
357 for us. */
358 return 0;
359 } else {
360 return 1;
361 }
362 }
363
364 int
365 sssdi_bus_width(sdmmc_chipset_handle_t sch, int width)
366 {
367 struct sssdi_softc *sc = (struct sssdi_softc*)sch;
368
369 sc->width = width;
370 return 0;
371 }
372
373 int
374 sssdi_bus_rod(sdmmc_chipset_handle_t sch, int on)
375 {
376 return -1;
377 }
378
379 #define SSSDI_TRANSFER_NONE 0
380 #define SSSDI_TRANSFER_READ 1
381 #define SSSDI_TRANSFER_WRITE 2
382
383 void
384 sssdi_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
385 {
386 struct sssdi_softc *sc = (struct sssdi_softc*)sch;
387 uint32_t cmd_control;
388 int status = 0;
389 #ifdef SSSDI_DEBUG
390 uint32_t data_status;
391 #endif
392 int transfer = SSSDI_TRANSFER_NONE;
393 dmac_xfer_t xfer;
394
395 /* Reset all status registers prior to sending a command */
396 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_FSTA, 0xFFFFFFFF);
397 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_STA, 0xFFFFFFFF);
398 bus_space_write_4(sc->iot, sc->ioh, SDI_CMD_STA, 0xFFFFFFFF);
399
400 /* Set the argument */
401 bus_space_write_4(sc->iot, sc->ioh, SDI_CMD_ARG, cmd->c_arg);
402
403 /* Prepare the value for the command control register */
404 cmd_control = (cmd->c_opcode & SDICMDCON_CMD_MASK) |
405 SDICMDCON_HOST_CMD | SDICMDCON_CMST;
406 if (cmd->c_flags & SCF_RSP_PRESENT)
407 cmd_control |= SDICMDCON_WAIT_RSP;
408 if (cmd->c_flags & SCF_RSP_136)
409 cmd_control |= SDICMDCON_LONG_RSP;
410
411 if (cmd->c_datalen > 0 && cmd->c_data != NULL) {
412 /* TODO: Ensure that the above condition matches the semantics
413 of SDICMDCON_WITH_DATA*/
414 DPRINTF(("DATA, datalen: %d, blk_size: %d\n", cmd->c_datalen,
415 cmd->c_blklen));
416 cmd_control |= SDICMDCON_WITH_DATA;
417 }
418
419 /* Unfortunately we have to set the ABORT_CMD bit when using CMD12 and
420 CMD52.
421 CMD12 is MMC_STOP_TRANSMISSION. I currently do not know what CMD52
422 is, but it is related to SDIO.
423 */
424 if (cmd->c_opcode == MMC_STOP_TRANSMISSION) {
425 cmd_control |= SDICMDCON_ABORT_CMD;
426 }
427
428 /* Prepare SDI for data transfer */
429 bus_space_write_4(sc->iot, sc->ioh, SDI_BSIZE, cmd->c_blklen);
430
431 /* Set maximum transfer timeout */
432 bus_space_write_4(sc->iot, sc->ioh, SDI_DTIMER, 0x007FFFFF);
433
434 /* Set the timeout as low as possible to trigger timeouts for debugging purposes */
435 /*bus_space_write_4(sc->iot, sc->ioh, SDI_DTIMER, 0x00005000);*/
436
437 if ( (cmd->c_flags & SCF_CMD_READ) &&
438 (cmd_control & SDICMDCON_WITH_DATA)) {
439 uint32_t data_control;
440 DPRINTF(("Reading %d bytes\n", cmd->c_datalen));
441 transfer = SSSDI_TRANSFER_READ;
442
443 data_control = SDIDATCON_DATMODE_RECEIVE | SDIDATCON_RACMD |
444 SDIDATCON_DTST | SDIDATCON_BLKMODE |
445 ((cmd->c_datalen / cmd->c_blklen) & SDIDATCON_BLKNUM_MASK) |
446 SDIDATCON_DATA_WORD;
447
448 if (sc->caps & SMC_CAPS_DMA) {
449 data_control |= SDIDATCON_ENDMA;
450 xfer = sc->sc_xfer;
451 xfer->dx_desc[DMAC_DESC_SRC].xd_bus_type = DMAC_BUS_TYPE_PERIPHERAL;
452 xfer->dx_desc[DMAC_DESC_SRC].xd_increment = FALSE;
453 xfer->dx_desc[DMAC_DESC_SRC].xd_nsegs = 1;
454 xfer->dx_desc[DMAC_DESC_SRC].xd_dma_segs = &sc->sc_dr;
455
456 xfer->dx_desc[DMAC_DESC_DST].xd_bus_type = DMAC_BUS_TYPE_SYSTEM;
457 xfer->dx_desc[DMAC_DESC_DST].xd_increment = TRUE;
458 xfer->dx_desc[DMAC_DESC_DST].xd_nsegs = cmd->c_dmamap->dm_nsegs;
459 xfer->dx_desc[DMAC_DESC_DST].xd_dma_segs = cmd->c_dmamap->dm_segs;
460
461 /* Let the SD/MMC peripheral control the DMA transfer */
462 xfer->dx_peripheral = DMAC_PERIPH_SDI;
463 xfer->dx_xfer_width = DMAC_XFER_WIDTH_32BIT;
464 }
465 if (sc->width == 4) {
466 data_control |= SDIDATCON_WIDEBUS;
467 }
468
469 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_CON, data_control);
470 } else if (cmd_control & SDICMDCON_WITH_DATA) {
471 /* Write data */
472
473 uint32_t data_control;
474 DPRINTF(("Writing %d bytes\n", cmd->c_datalen));
475 DPRINTF(("Requesting %d blocks\n",
476 cmd->c_datalen / cmd->c_blklen));
477 transfer = SSSDI_TRANSFER_WRITE;
478 data_control = SDIDATCON_DATMODE_TRANSMIT | SDIDATCON_BLKMODE |
479 SDIDATCON_TARSP | SDIDATCON_DTST |
480 ((cmd->c_datalen / cmd->c_blklen) & SDIDATCON_BLKNUM_MASK) |
481 SDIDATCON_DATA_WORD;
482
483 if (sc->caps & SMC_CAPS_DMA) {
484 data_control |= SDIDATCON_ENDMA;
485 xfer = sc->sc_xfer;
486
487 xfer->dx_desc[DMAC_DESC_DST].xd_bus_type = DMAC_BUS_TYPE_PERIPHERAL;
488 xfer->dx_desc[DMAC_DESC_DST].xd_increment = FALSE;
489 xfer->dx_desc[DMAC_DESC_DST].xd_nsegs = 1;
490 xfer->dx_desc[DMAC_DESC_DST].xd_dma_segs = &sc->sc_dr;
491
492 xfer->dx_desc[DMAC_DESC_SRC].xd_bus_type = DMAC_BUS_TYPE_SYSTEM;
493 xfer->dx_desc[DMAC_DESC_SRC].xd_increment = TRUE;
494 xfer->dx_desc[DMAC_DESC_SRC].xd_nsegs = cmd->c_dmamap->dm_nsegs;
495 xfer->dx_desc[DMAC_DESC_SRC].xd_dma_segs = cmd->c_dmamap->dm_segs;
496
497 /* Let the SD/MMC peripheral control the DMA transfer */
498 xfer->dx_peripheral = DMAC_PERIPH_SDI;
499 xfer->dx_xfer_width = DMAC_XFER_WIDTH_32BIT;
500 }
501 if (sc->width == 4) {
502 data_control |= SDIDATCON_WIDEBUS;
503 }
504
505 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_CON, data_control);
506 }
507
508 /* Send command to SDI */
509 bus_space_write_4(sc->iot, sc->ioh, SDI_CMD_CON, cmd_control);
510
511 /* Wait for command sent acknowledgement, timeout set to 5000ms */
512 status = sssdi_wait_intr(sc, SDI_CMD_SENT | SDI_CMD_TIMEOUT, mstohz(SDI_CMD_WAIT_TIME));
513
514 if (status & SDI_CMD_TIMEOUT) {
515 DPRINTF(("Timeout waiting for command acknowledgement\n"));
516 cmd->c_error = ETIMEDOUT;
517 goto out;
518 } else if (status & SDICMDSTA_CMD_SENT) {
519 /* Interrupt handler has acknowledged already, we do not need
520 to do anything further here */
521 }
522
523 if (!(cmd_control & SDICMDCON_WAIT_RSP)) {
524 cmd->c_flags |= SCF_ITSDONE;
525 goto out;
526 }
527
528 DPRINTF(("waiting for response\n"));
529
530 status = sssdi_wait_intr(sc, SDI_RESP_FIN | SDI_DATA_TIMEOUT, 100);
531 if (status & SDI_CMD_TIMEOUT || status & SDI_DATA_TIMEOUT) {
532 cmd->c_error = ETIMEDOUT;
533 DPRINTF(("Timeout waiting for response\n"));
534 goto out;
535 }
536 DPRINTF(("Got Response\n"));
537
538
539 if (cmd->c_flags & SCF_RSP_136 ) {
540 uint32_t w[4];
541
542 /* We store the response least significant word first */
543 w[0] = bus_space_read_4(sc->iot, sc->ioh, SDI_RSP3);
544 w[1] = bus_space_read_4(sc->iot, sc->ioh, SDI_RSP2);
545 w[2] = bus_space_read_4(sc->iot, sc->ioh, SDI_RSP1);
546 w[3] = bus_space_read_4(sc->iot, sc->ioh, SDI_RSP0);
547
548 /* The sdmmc subsystem expects that the response is delivered
549 without the lower 8 bits (CRC + '1' bit) */
550 cmd->c_resp[0] = (w[0] >> 8) | ((w[1] & 0xFF) << 24);
551 cmd->c_resp[1] = (w[1] >> 8) | ((w[2] & 0XFF) << 24);
552 cmd->c_resp[2] = (w[2] >> 8) | ((w[3] & 0XFF) << 24);
553 cmd->c_resp[3] = (w[3] >> 8);
554
555 } else {
556 cmd->c_resp[0] = bus_space_read_4(sc->iot, sc->ioh, SDI_RSP0);
557 cmd->c_resp[1] = bus_space_read_4(sc->iot, sc->ioh, SDI_RSP1);
558 }
559
560 DPRINTF(("Response: %X %X %X %X\n",
561 cmd->c_resp[0],
562 cmd->c_resp[1],
563 cmd->c_resp[2],
564 cmd->c_resp[3]));
565
566 status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_CNT);
567
568 DPRINTF(("Remaining bytes of current block: %d\n",
569 SDIDATCNT_BLK_CNT(status)));
570 DPRINTF(("Remaining Block Number : %d\n",
571 SDIDATCNT_BLK_NUM_CNT(status)));
572
573 #ifdef SSSDI_DEBUG
574 data_status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_STA);
575 printf("SDI Data Status Register Before xfer: 0x%X\n", data_status);
576 #endif
577 if (transfer == SSSDI_TRANSFER_READ) {
578 DPRINTF(("Waiting for transfer to complete\n"));
579
580 if (sc->sc_xfer != NULL ) {
581 int dma_error = 0;
582 /* It might not be very efficient to delay the start of
583 the DMA transfer until now, but it works :-).
584 */
585 s3c2440_dmac_start_xfer(sc->sc_xfer);
586
587 /* Wait until the transfer has completed, timeout is
588 500ms */
589 dma_error = s3c2440_dmac_wait_xfer(sc->sc_xfer, mstohz(SDI_DMA_WAIT_TIME));
590 if (dma_error != 0) {
591 //s3c2440_dma_xfer_abort(sc->dma_xfer, mstohz(100)); /* XXX: Handle timeout during abort */
592 cmd->c_error = dma_error;
593 DPRINTF(("DMA xfer failed: %d\n", dma_error));
594 goto out;
595 }
596 } else {
597 DPRINTF(("PIO READ\n"));
598 sssdi_perform_pio_read(sc, cmd);
599 }
600 } else if (transfer == SSSDI_TRANSFER_WRITE) {
601 DPRINTF(("Waiting for WRITE transfer to complete\n"));
602
603 if (sc->sc_xfer != NULL) {
604 int dma_error = 0;
605 s3c2440_dmac_start_xfer(sc->sc_xfer);
606
607 dma_error = s3c2440_dmac_wait_xfer(sc->sc_xfer, mstohz(SDI_DMA_WAIT_TIME));
608 if (dma_error != 0) {
609 //s3c2440_dma_xfer_abort(sc->dma_xfer, mstohz(100)); /* XXX: Handle timeout during abort*/
610 cmd->c_error = dma_error;
611 DPRINTF(("DMA xfer failed: %d\n", dma_error));
612 goto out;
613 }
614 } else {
615 DPRINTF(("PIO WRITE\n"));
616 sssdi_perform_pio_write(sc, cmd);
617 }
618
619 if (cmd->c_error == ETIMEDOUT)
620 goto out;
621
622 DPRINTF(("Waiting for transfer to complete\n"));
623 status = sssdi_wait_intr(sc, SDI_DATA_FIN | SDI_DATA_TIMEOUT, 1000);
624 if (status & SDI_CMD_TIMEOUT || status & SDI_DATA_TIMEOUT) {
625 cmd->c_error = ETIMEDOUT;
626 DPRINTF(("Timeout waiting for data to complete\n"));
627 goto out;
628 }
629 DPRINTF(("Done\n"));
630
631 }
632
633
634 /* Response has been received, and any data transfer needed has been
635 performed */
636 cmd->c_flags |= SCF_ITSDONE;
637
638 out:
639
640 #ifdef SSSDI_DEBUG
641 data_status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_STA);
642 printf("SDI Data Status Register after execute: 0x%X\n", data_status);
643 #endif
644
645 /* Clear status register. Their are cleared on the
646 next sssdi_exec_command */
647 bus_space_write_4(sc->iot, sc->ioh, SDI_CMD_STA, 0xFFFFFFFF);
648 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_CON, 0x0);
649 }
650
651 void sssdi_perform_pio_read(struct sssdi_softc *sc, struct sdmmc_command *cmd)
652 {
653 uint32_t fifo_status;
654 int count;
655 uint32_t written;
656 uint32_t *dest = (uint32_t*)cmd->c_data;
657
658 written = 0;
659
660 while (written < cmd->c_datalen ) {
661 /* Wait until the FIFO is full or has the final data.
662 In the latter case it might not get filled. */
663 sssdi_wait_intr(sc, SDI_FIFO_RX_FULL | SDI_FIFO_RX_LAST, 1000);
664
665 fifo_status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_FSTA);
666 count = SDIDATFSTA_FFCNT(fifo_status);
667
668 for(int i=0; i<count; i+=4) {
669 uint32_t buf;
670
671 buf = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_LI_W);
672 *dest = buf;
673 written += 4;
674 dest++;
675 }
676 }
677 }
678
679 void
680 sssdi_perform_pio_write(struct sssdi_softc *sc, struct sdmmc_command *cmd)
681 {
682 uint32_t status;
683 uint32_t fifo_status;
684 int count;
685 uint32_t written;
686 uint32_t *dest = (uint32_t*)cmd->c_data;
687
688 written = 0;
689
690 while (written < cmd->c_datalen ) {
691 /* Wait until the FIFO is full or has the final data.
692 In the latter case it might not get filled. */
693 DPRINTF(("Waiting for FIFO to become empty\n"));
694 status = sssdi_wait_intr(sc, SDI_FIFO_TX_EMPTY, 1000);
695
696 fifo_status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_FSTA);
697 DPRINTF(("PIO Write FIFO Status: 0x%X\n", fifo_status));
698 count = 64-SDIDATFSTA_FFCNT(fifo_status);
699
700 status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_CNT);
701 DPRINTF(("Remaining bytes of current block: %d\n",
702 SDIDATCNT_BLK_CNT(status)));
703 DPRINTF(("Remaining Block Number : %d\n",
704 SDIDATCNT_BLK_NUM_CNT(status)));
705
706
707 status = bus_space_read_4(sc->iot,sc->ioh, SDI_DAT_STA);
708 DPRINTF(("PIO Write Data Status: 0x%X\n", status));
709
710 if (status & SDIDATSTA_DATA_TIMEOUT) {
711 cmd->c_error = ETIMEDOUT;
712 /* Acknowledge the timeout*/
713 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_STA,
714 SDIDATSTA_DATA_TIMEOUT);
715 printf("%s: Data timeout\n", device_xname(sc->dev));
716 break;
717 }
718
719 DPRINTF(("Filling FIFO with %d bytes\n", count));
720 for(int i=0; i<count; i+=4) {
721 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_LI_W, *dest);
722 written += 4;
723 dest++;
724 }
725 }
726 }
727
728
729 void
730 sssdi_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
731 {
732 printf("sssdi_card_enable_intr not implemented\n");
733 }
734
735 void
736 sssdi_card_intr_ack(sdmmc_chipset_handle_t sch)
737 {
738 printf("sssdi_card_intr_ack not implemented\n");
739 }
740
741 int
742 sssdi_intr(void *arg)
743 {
744 struct sssdi_softc *sc = (struct sssdi_softc*)arg;
745 uint32_t status;
746 uint32_t ack_status;
747
748 /* Start by dealing with Command Status */
749 ack_status = 0;
750 status = bus_space_read_4(sc->iot, sc->ioh, SDI_CMD_STA);
751
752 if (status & SDICMDSTA_CMD_TIMEOUT) {
753 ack_status |= SDICMDSTA_CMD_TIMEOUT;
754 sc->intr_status |= SDI_CMD_TIMEOUT;
755 /*sssdi_disable_intr(sc, SDI_CMD_TIMEOUT);*/
756 }
757 if (status & SDICMDSTA_CMD_SENT) {
758 ack_status |= SDICMDSTA_CMD_SENT;
759 sc->intr_status |= SDI_CMD_SENT;
760 /* sssdi_disable_intr(sc, SDI_CMD_SENT);*/
761 }
762 if (status & SDICMDSTA_RSP_FIN) {
763 ack_status |= SDICMDSTA_RSP_FIN;
764 sc->intr_status |= SDI_RESP_FIN;
765 /* sssdi_disable_intr(sc, SDI_RESP_FIN);*/
766 }
767 bus_space_write_4(sc->iot, sc->ioh, SDI_CMD_STA, ack_status);
768
769 /* Next: FIFO Status */
770 ack_status = 0;
771 status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_FSTA);
772 if (status & SDIDATFSTA_RF_FULL) {
773 ack_status |= SDIDATFSTA_RF_FULL;
774 sc->intr_status |= SDI_FIFO_RX_FULL;
775 sssdi_disable_intr(sc, SDI_FIFO_RX_FULL);
776 }
777 if (status & SDIDATFSTA_RF_LAST) {
778 ack_status |= SDIDATFSTA_RF_LAST | SDIDATFSTA_RESET;
779 sc->intr_status |= SDI_FIFO_RX_LAST;
780 sssdi_disable_intr(sc, SDI_FIFO_RX_LAST);
781 }
782 if (status & SDIDATFSTA_TF_EMPTY) {
783 ack_status |= SDIDATFSTA_TF_EMPTY;
784 sc->intr_status |= SDI_FIFO_TX_EMPTY;
785 sssdi_disable_intr(sc, SDI_FIFO_TX_EMPTY);
786 }
787 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_FSTA, ack_status);
788
789 ack_status = 0;
790 status = bus_space_read_4(sc->iot, sc->ioh, SDI_DAT_STA);
791 if (status & SDIDATSTA_DATA_FIN) {
792 DPRINTF(("sssdi_intr: DATA FINISHED\n"));
793 ack_status |= SDIDATSTA_DATA_FIN;
794 sc->intr_status |= SDI_DATA_FIN;
795 sssdi_disable_intr(sc, SDI_DATA_FIN);
796 }
797 if (status & SDIDATSTA_DATA_TIMEOUT) {
798 printf("sssdi_intr: DATA TIMEOUT\n");
799 ack_status |= SDIDATSTA_DATA_TIMEOUT;
800 sc->intr_status |= SDI_DATA_TIMEOUT;
801 /* Data timeout interrupt is always enabled, thus
802 we do not disable it when we have received one. */
803 /*sssdi_disable_intr(sc, SDI_DATA_TIMEOUT);*/
804
805 if (sc->sc_xfer != NULL) {
806 s3c2440_dmac_abort_xfer(sc->sc_xfer);
807 }
808 }
809 bus_space_write_4(sc->iot, sc->ioh, SDI_DAT_STA, ack_status);
810
811 mutex_enter(&sc->intr_mtx);
812 cv_broadcast(&sc->intr_cv);
813 mutex_exit(&sc->intr_mtx);
814
815 return 1;
816 }
817
818 int
819 sssdi_intr_card(void *arg)
820 {
821 struct sssdi_softc *sc = (struct sssdi_softc*)arg;
822
823 /* TODO: If card was removed then abort any current command */
824
825 sdmmc_needs_discover(sc->sdmmc);
826
827 return 1; /* handled */
828 }
829
830 static void
831 sssdi_enable_intr(struct sssdi_softc *sc, uint32_t i)
832 {
833 uint32_t v = bus_space_read_4(sc->iot, sc->ioh, SDI_INT_MASK);
834 bus_space_write_4(sc->iot, sc->ioh, SDI_INT_MASK, v | i );
835 }
836
837 void
838 sssdi_disable_intr(struct sssdi_softc *sc, uint32_t i)
839 {
840 uint32_t v = bus_space_read_4(sc->iot, sc->ioh, SDI_INT_MASK);
841 bus_space_write_4(sc->iot, sc->ioh, SDI_INT_MASK, v & ~i );
842 }
843
844 void
845 sssdi_clear_intr(struct sssdi_softc *sc)
846 {
847 bus_space_write_4(sc->iot, sc->ioh, SDI_INT_MASK, 0x0);
848 }
849
850 static int
851 sssdi_wait_intr(struct sssdi_softc *sc, uint32_t mask, int timeout)
852 {
853 uint32_t status;
854
855 /* Wait until the command has been sent */
856 mutex_enter(&sc->intr_mtx);
857 sssdi_enable_intr(sc, mask);
858 status = sc->intr_status & mask;
859 while(status == 0) {
860
861 if (cv_timedwait(&sc->intr_cv, &sc->intr_mtx, timeout) ==
862 EWOULDBLOCK ) {
863 DPRINTF(("Timed out waiting for interrupt from SDI controller\n"));
864 status |= SDI_CMD_TIMEOUT;
865 break;
866 }
867
868 status = sc->intr_status & mask;
869 }
870
871 sc->intr_status &= ~status;
872 mutex_exit(&sc->intr_mtx);
873
874 return status;
875 }
876