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