1/**
2 * \file
3 * \brief IMX8x uSDHC Digital Host Controller Driver
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2010, 2011, 2012,2020 ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
13 * Attn: Systems Group.
14 */
15
16/*
17 * In U-boot drivers/mmc/fsl_esdhc.c is talking to the
18 * same controller. This driver follows the i.MX 8DualXPlus/8QuadXPlus
19 * Applications Processor Reference Manual register definitions and
20 * descriptions, except for the vendor specific register, which is
21 * used differently in U-Boot, and that seems the correct way.
22 *
23 * Card detection on Toradex boards:
24 * ===========
25 * The Toradex boards dont break out the SDHC card detection pin, instead
26 * a GPIO (Bank4, Pin22) has to be checked for card present. Currently,
27 * this driver simply assumes a card is present.
28 */
29
30#include <barrelfish/barrelfish.h>
31#include <int_route/int_route_client.h>
32#include <pci/pci.h>
33#include <dev/imx8x/sdhc_dev.h>
34#include <driverkit/driverkit.h>
35#include <barrelfish/deferred.h>
36#include <barrelfish/systime.h>
37
38//#define DEBUG_ON
39
40#if defined(DEBUG_ON) || defined(GLOBAL_DEBUG)
41#    define DEBUG(x...) debug_printf(x)
42#else
43#    define DEBUG(x...) ((void)0)
44#endif
45
46#define MMC_CMD_GO_IDLE_STATE       0
47#define MMC_CMD_SEND_OP_COND        1
48#define MMC_CMD_ALL_SEND_CID        2
49#define MMC_CMD_SET_RELATIVE_ADDR   3
50#define MMC_CMD_SET_DSR         4
51#define MMC_CMD_SWITCH          6
52#define MMC_CMD_SELECT_CARD     7
53#define MMC_CMD_SEND_EXT_CSD        8
54#define MMC_CMD_SEND_CSD        9
55#define MMC_CMD_SEND_CID        10
56#define MMC_CMD_STOP_TRANSMISSION   12
57#define MMC_CMD_SEND_STATUS     13
58#define MMC_CMD_SET_BLOCKLEN        16
59#define MMC_CMD_READ_SINGLE_BLOCK   17
60#define MMC_CMD_READ_MULTIPLE_BLOCK 18
61#define MMC_CMD_SEND_TUNING_BLOCK       19
62#define MMC_CMD_SEND_TUNING_BLOCK_HS200 21
63#define MMC_CMD_SET_BLOCK_COUNT         23
64#define MMC_CMD_WRITE_SINGLE_BLOCK  24
65#define MMC_CMD_WRITE_MULTIPLE_BLOCK    25
66#define MMC_CMD_ERASE_GROUP_START   35
67#define MMC_CMD_ERASE_GROUP_END     36
68#define MMC_CMD_ERASE           38
69#define MMC_CMD_APP_CMD         55
70#define MMC_CMD_SPI_READ_OCR        58
71#define MMC_CMD_SPI_CRC_ON_OFF      59
72#define MMC_CMD_RES_MAN         62
73
74#define SD_CMD_SEND_RELATIVE_ADDR   3
75#define SD_CMD_SWITCH_FUNC      6
76#define SD_CMD_SEND_IF_COND     8
77#define SD_CMD_SWITCH_UHS18V        11
78#define SD_CMD_APP_SET_BUS_WIDTH    6
79#define SD_CMD_APP_SD_STATUS        13
80#define SD_CMD_ERASE_WR_BLK_START   32
81#define SD_CMD_ERASE_WR_BLK_END     33
82#define SD_CMD_APP_SEND_OP_COND     41
83#define SD_CMD_APP_SEND_SCR     51
84
85
86#define MMC_RSP_PRESENT (1 << 0)
87#define MMC_RSP_136 (1 << 1)        /* 136 bit response */
88#define MMC_RSP_CRC (1 << 2)        /* expect valid crc */
89#define MMC_RSP_BUSY    (1 << 3)        /* card may send busy */
90#define MMC_RSP_OPCODE  (1 << 4)        /* response contains opcode */
91
92#define MMC_RSP_NONE    (0)
93#define MMC_RSP_R1  (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
94#define MMC_RSP_R1b (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE| \
95            MMC_RSP_BUSY)
96#define MMC_RSP_R2  (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
97#define MMC_RSP_R3  (MMC_RSP_PRESENT)
98#define MMC_RSP_R4  (MMC_RSP_PRESENT)
99#define MMC_RSP_R5  (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
100#define MMC_RSP_R6  (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
101#define MMC_RSP_R7  (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
102
103#define OCR_BUSY        0x80000000
104#define OCR_HCS         0x40000000
105#define OCR_S18R        0x1000000
106
107#define BLOCK_SIZE 512
108
109struct sdhc {
110    sdhc_t dev;
111    uintptr_t vbase;
112    uint32_t caps;
113
114    // Card properties
115    uint8_t cid[16];
116    uint32_t csd[4];
117    uint16_t rca;
118    int high_capacity;
119
120	uint64_t read_bl_len;
121	uint64_t write_bl_len ;
122	uint64_t capacity_user;
123};
124
125struct cmd {
126    uint16_t     cmdidx;
127    unsigned int cmdarg;
128    unsigned int resp_type;
129    unsigned int response[4]; // The response of the command
130    genpaddr_t   dma_base;    // If a data transfer is necessary, use this
131                              // physical base address for read/write.
132};
133
134#define dump(sd) do {\
135        char buf[1024];\
136        sdhc_int_status_pr(buf, 1024, &sd->dev);\
137        DEBUG("%s:%d: %s\n", __FUNCTION__, __LINE__, buf);\
138    } while(0)
139
140#define dump_all(sd) do {\
141        char buf[16*1024];\
142        sdhc_pr(buf, 16*1024, &sd->dev);\
143        printf("%s\n", buf);\
144    } while(0)
145
146
147static void int_handler(void *arg)
148{
149    DEBUG("%s: enter\n", __FUNCTION__);
150    struct sdhc * sd = (struct sdhc *)arg;
151    dump(sd);
152}
153
154__attribute__((used))
155static errval_t software_reset(struct sdhc *sd){
156    sdhc_sys_ctrl_rsta_wrf(&sd->dev, 1);
157    volatile uint64_t timeout  = 1000000;
158    while(sdhc_sys_ctrl_rsta_rdf(&sd->dev)){
159        timeout--;
160        if(timeout == 0){
161            DEBUG("Reset TIMEOUT!\n");
162            return SDHC_ERR_RESET_TIMEOUT;
163        }
164    }
165
166    // Set sensible defaults
167    sdhc_mmc_boot_rawwr(&sd->dev, 0);
168    sdhc_mix_ctrl_rawwr(&sd->dev, 0);
169    sdhc_clk_tune_ctrl_status_rawwr(&sd->dev, 0);
170    sdhc_dll_rawwr(&sd->dev, 0);
171
172    sdhc_vend_spec_t vs = 0;
173    vs = sdhc_vend_spec_ipgen_insert(vs, 1);
174    vs = sdhc_vend_spec_hcken_insert(vs, 1);
175    sdhc_vend_spec_wr(&sd->dev, vs);
176
177    DEBUG("Reset complete!\n");
178
179    sd->caps = sdhc_host_ctrl_cap_rawrd(&sd->dev);
180
181    //Setting clock to initial 40mhz
182    sdhc_vend_spec_cken_wrf(&sd->dev, 0);
183
184    sdhc_sys_ctrl_t s = 0;
185    s = sdhc_sys_ctrl_dvs_insert(s, 0xf);
186    s = sdhc_sys_ctrl_sdclkfs_insert(s, 0x10);
187    s = sdhc_sys_ctrl_dtocv_insert(s, 0xc);
188    sdhc_sys_ctrl_wr(&sd->dev, s);
189
190    barrelfish_usleep(10000);
191    vs = sdhc_vend_spec_rd(&sd->dev);
192    vs = sdhc_vend_spec_peren_insert(vs, 1);
193    vs = sdhc_vend_spec_cken_insert(vs, 1);
194    sdhc_vend_spec_wr(&sd->dev, vs);
195
196    sdhc_prot_ctrl_dtw_wrf(&sd->dev, 0); // Bus width: 1-bit mode
197    sdhc_prot_ctrl_emode_wrf(&sd->dev, 0x2); // Little endian mode
198    sdhc_sys_ctrl_dtocv_wrf(&sd->dev, 0xe);
199
200    return SYS_ERR_OK;
201}
202
203
204
205__attribute__((used))
206static sdhc_cmd_xfr_typ_t xfr_typ_for_cmd(struct cmd *cmd){
207    sdhc_cmd_xfr_typ_t c = 0;
208
209    if(cmd->cmdidx == MMC_CMD_READ_SINGLE_BLOCK ||
210       cmd->cmdidx == MMC_CMD_WRITE_SINGLE_BLOCK)
211    {
212        c = sdhc_cmd_xfr_typ_dpsel_insert(c, 1);
213    }
214
215    c = sdhc_cmd_xfr_typ_cmdinx_insert(c, cmd->cmdidx);
216    if (cmd->resp_type & MMC_RSP_CRC)
217        c = sdhc_cmd_xfr_typ_cccen_insert(c, 1);
218    if (cmd->resp_type & MMC_RSP_OPCODE)
219        c = sdhc_cmd_xfr_typ_cicen_insert(c, 1);
220
221
222    c = sdhc_cmd_xfr_typ_rsptyp_insert(c, sdhc_rsp_tp_none);
223    if (cmd->resp_type & MMC_RSP_136)
224        c = sdhc_cmd_xfr_typ_rsptyp_insert(c, sdhc_rsp_tp_136);
225    else if (cmd->resp_type & MMC_RSP_BUSY)
226        c = sdhc_cmd_xfr_typ_rsptyp_insert(c, sdhc_rsp_tp_48cb);
227    else if (cmd->resp_type & MMC_RSP_PRESENT)
228        c = sdhc_cmd_xfr_typ_rsptyp_insert(c, sdhc_rsp_tp_48);
229
230    c = sdhc_cmd_xfr_typ_cmdtyp_insert(c, sdhc_cmd_tp_norm);
231    if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
232        c = sdhc_cmd_xfr_typ_cmdtyp_insert(c, sdhc_cmd_tp_abrt);
233
234    return c;
235}
236
237__attribute__((used))
238static errval_t sdhc_send_cmd(struct sdhc * sd, struct cmd * cmd) {
239    DEBUG("sdhc_send_cmd: cmdidx=%d,cmdarg=%d\n", cmd->cmdidx, cmd->cmdarg);
240
241    uint32_t mask; // TODO: in some cases we don't need to wait for all
242    if(cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) {
243       mask = 1;
244    } else {
245       mask = 3;
246    }
247    while(sdhc_pres_state_rawrd(&sd->dev) & mask){
248        DEBUG("Card busy!\n");
249    }
250    DEBUG("Card ready (data & cmd inhibit are clear)!\n");
251    barrelfish_usleep(10000);
252
253    // Clear interrupts
254    sdhc_int_status_rawwr(&sd->dev, ~0x0);
255
256    // Mask interrupts.
257    sdhc_int_signal_en_rawwr(&sd->dev, 0);
258
259    // CMD argument
260    sdhc_cmd_arg_wr(&sd->dev, cmd->cmdarg);
261
262    // Mixer controler
263    int is_read = cmd->cmdidx == MMC_CMD_READ_SINGLE_BLOCK;
264    int is_write = cmd->cmdidx == MMC_CMD_WRITE_SINGLE_BLOCK;
265    sdhc_mix_ctrl_wr(&sd->dev, 0);
266    sdhc_mix_ctrl_dmaen_wrf(&sd->dev, is_read || is_write);
267    sdhc_mix_ctrl_dtdsel_wrf(&sd->dev, is_read);
268
269    if(is_read || is_write){
270        // DMA address setup
271        assert((cmd->dma_base >> 32) == 0);
272        sdhc_vend_spec2_acmd23_argu2_en_wrf(&sd->dev, 0);
273        sdhc_ds_addr_wr(&sd->dev, cmd->dma_base);
274
275        //Set watermark
276        sdhc_wtmk_lvl_rd_wml_wrf(&sd->dev, 16);
277        sdhc_wtmk_lvl_wr_wml_wrf(&sd->dev, 16);
278    }
279
280    sdhc_cmd_xfr_typ_t c = xfr_typ_for_cmd(cmd);
281    sdhc_cmd_xfr_typ_wr(&sd->dev, c);
282
283    //DEBUG("%s:%d: Wait until irq_stat.tc || irq_stat.cc \n", __FUNCTION__, __LINE__);
284    uint32_t tc = 0;
285    uint32_t cc = 0;
286    size_t i = 0;
287    do {
288        uint32_t ctoe = sdhc_int_status_ctoe_rdf(&sd->dev);
289        uint32_t cce = sdhc_int_status_cce_rdf(&sd->dev);
290        tc = sdhc_int_status_tc_rdf(&sd->dev);
291        cc = sdhc_int_status_cc_rdf(&sd->dev);
292
293        if (ctoe == 0x1 && cce == 0x1) {
294            DEBUG("%s:%d: ctoe = 1 ccrc = 1: Conflict on cmd line.\n",
295                    __FUNCTION__, __LINE__);
296            dump(sd);
297            return SDHC_ERR_CMD_CONFLICT;
298        }
299        if (ctoe == 0x1 && cce == 0x0) {
300            DEBUG("%s:%d: cto = 1 ccrc = 0: Abort.\n", __FUNCTION__, __LINE__);
301            dump(sd);
302            return SDHC_ERR_CMD_TIMEOUT;
303        }
304
305        if (i++ > 1000) {
306            dump(sd);
307            USER_PANIC("Command not Ackd?");
308        }
309        barrelfish_usleep(100);
310        if(tc || cc) break;
311    } while (true);
312    DEBUG("Command complete!\n");
313
314    if(cmd->resp_type & MMC_RSP_136){
315        uint32_t r0 = sdhc_cmd_rsp0_rd(&sd->dev);
316        uint32_t r1 = sdhc_cmd_rsp1_rd(&sd->dev);
317        uint32_t r2 = sdhc_cmd_rsp2_rd(&sd->dev);
318        uint32_t r3 = sdhc_cmd_rsp3_rd(&sd->dev);
319        cmd->response[0] = (r3 << 8) | (r2 >> 24);
320        cmd->response[1] = (r2 << 8) | (r1 >> 24);
321        cmd->response[2] = (r1 << 8) | (r0 >> 24);
322        cmd->response[3] = (r0 << 8);
323    } else {
324        cmd->response[0] = sdhc_cmd_rsp0_rd(&sd->dev);
325    }
326    return SYS_ERR_OK;
327}
328
329static errval_t sdhc_go_idle(struct sdhc *sd) {
330    errval_t err;
331    struct cmd init = {
332        .cmdidx = MMC_CMD_GO_IDLE_STATE,
333        .cmdarg = 0,
334        .resp_type = MMC_RSP_NONE
335    };
336    err = sdhc_send_cmd(sd, &init);
337    if(err_is_ok(err)){
338        DEBUG("Successfully sent GO_IDLE transaction\n");
339    }
340    barrelfish_usleep(2000);
341    return err;
342}
343
344static errval_t sdhc_send_if_cond(struct sdhc *sd) {
345    errval_t err;
346    uint32_t pattern = 0xde;
347    struct cmd cmd = {
348        .cmdidx = SD_CMD_SEND_IF_COND,
349        .cmdarg = 0x100 | pattern, // Offer 3V voltage followed by pattern
350        .resp_type = MMC_RSP_R7
351    };
352
353    err = sdhc_send_cmd(sd, &cmd);
354    if(err_is_ok(err)){
355        if(cmd.response[0] == (0x100 | pattern)){
356            DEBUG("IF_COND: Success! Got (at least) SD Version 2\n");
357            return SYS_ERR_OK;
358        } else {
359            DEBUG("IF_COND: Legacy cards not supported!\n");
360            err = SDHC_ERR_CMD_TIMEOUT;
361        }
362    }
363    return err;
364}
365
366/*
367 * This function queries the card to determine operating voltage/standard
368 * etc. It does not perform a card initialization.
369 */
370static errval_t sdhc_get_ocr(struct sdhc *sd){
371    errval_t err;
372    uint32_t ocr=0;
373
374    while(1){
375        struct cmd app_cmd = {
376            .cmdidx = MMC_CMD_APP_CMD,
377            .cmdarg = 0,
378            .resp_type = MMC_RSP_R1
379        };
380
381        err = sdhc_send_cmd(sd, &app_cmd);
382        if(err_is_fail(err)){
383            DEBUG_ERR(err, "send app_cmd");
384            return err;
385        }
386
387        struct cmd op_cond_cmd = {
388            .cmdidx = SD_CMD_APP_SEND_OP_COND,
389            .cmdarg = 0x40300000,  // Have OCS and default voltages
390            .resp_type = MMC_RSP_R3
391        };
392        err = sdhc_send_cmd(sd, &op_cond_cmd);
393        if(err_is_fail(err)) {
394            DEBUG_ERR(err, "send op_cond_cmd");
395            return err;
396        }
397
398        if(op_cond_cmd.response[0] & OCR_BUSY) {
399            ocr = op_cond_cmd.response[0];
400            break;
401        }
402
403        barrelfish_usleep(10000);
404    }
405
406    DEBUG("Received OCR! ocr=0x%"PRIx32"\n", ocr);
407
408    if((ocr & OCR_HCS) == OCR_HCS){
409        DEBUG("High capacity card found!\n");
410        sd->high_capacity = 1;
411    } else {
412        DEBUG("Non high capacity card. NOT TESTED\n");
413        sd->high_capacity = 0;
414    }
415    sd->rca = 0;
416    return SYS_ERR_OK;
417}
418
419
420
421/**
422 * Here we perform the actual card initialization
423 */
424static errval_t sdhc_card_init(struct sdhc* sd){
425    errval_t err;
426    // Put card in identify mode
427    struct cmd cid = {
428        .cmdidx = MMC_CMD_ALL_SEND_CID,
429        .resp_type = MMC_RSP_R2,
430        .cmdarg = 0
431    };
432    err = sdhc_send_cmd(sd, &cid);
433    if(err_is_fail(err)){
434        DEBUG_ERR(err, "cid command");
435    }
436    memcpy(sd->cid, cid.response, 16);
437
438    struct cmd send_addr = {
439        .cmdidx = SD_CMD_SEND_RELATIVE_ADDR,
440        .cmdarg = sd->rca << 16,
441        .resp_type = MMC_RSP_R6
442    };
443
444    err = sdhc_send_cmd(sd, &send_addr);
445    if(err_is_fail(err)){
446        DEBUG_ERR(err, "send addr command");
447    }
448    sd->rca = send_addr.response[0] >> 16 & 0xffff;
449    DEBUG("Determined RCA=0x%"PRIx16".\n", sd->rca);
450
451    struct cmd send_csd = {
452        .cmdidx = MMC_CMD_SEND_CSD,
453        .resp_type = MMC_RSP_R2,
454        .cmdarg = sd->rca << 16
455    };
456    err = sdhc_send_cmd(sd, &send_csd);
457    if(err_is_fail(err)){
458        DEBUG_ERR(err, "send csd command");
459    }
460    sd->csd[0] = send_csd.response[0];
461    sd->csd[1] = send_csd.response[1];
462    sd->csd[2] = send_csd.response[2];
463    sd->csd[3] = send_csd.response[3];
464    DEBUG("CSD: [0]=%"PRIx32", [1]=%"PRIx32", [2]=%"PRIx32", [3]=%"PRIx32"\n",
465            sd->csd[0], sd->csd[1], sd->csd[2], sd->csd[3]);
466	sd->read_bl_len = 1 << ((sd->csd[1]>>16) & 0xf);
467    DEBUG("SD read_bl_len: %"PRIx64"\n", sd->read_bl_len);
468	sd->write_bl_len = sd->read_bl_len;
469
470	if(sd->high_capacity) {
471		unsigned int csize, cmult;
472		csize = (sd->csd[1] & 0x3f) << 16 | (sd->csd[2] & 0xffff0000) >> 16;
473		cmult = 8;
474		sd->capacity_user = ((csize + 1) << (cmult + 2)) * sd->read_bl_len;
475		DEBUG("SD capacity: %"PRIx64"\n", sd->capacity_user);
476	}
477
478	// Select the card, this puts it into the "transfer" state
479    struct cmd select_card = {
480        .cmdidx = MMC_CMD_SELECT_CARD,
481        .resp_type = MMC_RSP_R1,
482        .cmdarg = sd->rca << 16
483    };
484	err = sdhc_send_cmd(sd, &select_card);
485    if(err_is_fail(err)) {
486        DEBUG_ERR(err, "select_card cmd");
487        return err;
488    }
489
490    return SYS_ERR_OK;
491}
492
493/* Read BLOCK_SIZE bytes block index into buffer */
494static errval_t sdhc_read_block(struct sdhc * sd, int index, void **buffer){
495    errval_t err;
496
497    // allocate and map frame for buffer
498    struct capref frame;
499    struct frame_identity frameid;
500    size_t retbytes;
501    err = frame_alloc(&frame, 4096, &retbytes);
502    assert(err_is_ok(err));
503    assert(retbytes == 4096);
504    err = vspace_map_one_frame_attr(buffer, retbytes, frame,
505            VREGION_FLAGS_READ_WRITE_NOCACHE, NULL, NULL);
506    for(int i=0; i<128;i++) ((uint32_t*)*buffer)[i] = 0xdead;
507    assert(err_is_ok(err));
508    err = frame_identify(frame, &frameid);
509    assert(err_is_ok(err));
510
511
512    //Clear interrupts
513    sdhc_int_status_rawwr(&sd->dev, ~0x0);
514
515    struct cmd set_blocklen = {
516        .cmdidx = MMC_CMD_SET_BLOCKLEN,
517        .cmdarg = BLOCK_SIZE,
518        .resp_type = MMC_RSP_R1
519    };
520    err = sdhc_send_cmd(sd, &set_blocklen);
521    if(err_is_fail(err)){
522        DEBUG_ERR(err, "set_blocklen");
523        return err;
524    }
525
526    struct cmd read_block = {
527        .cmdidx = MMC_CMD_READ_SINGLE_BLOCK,
528        .cmdarg = index,
529        .resp_type = MMC_RSP_R1,
530        .dma_base = frameid.base
531
532    };
533    err = sdhc_send_cmd(sd, &read_block);
534    if(err_is_fail(err)){
535        DEBUG_ERR(err, "read_block");
536        return err;
537    }
538
539    return SYS_ERR_OK;
540}
541
542/* Write BLOCK_SIZE bytes to block index from data */
543static errval_t sdhc_write_block(struct sdhc * sd, int index, void *data){
544    errval_t err;
545
546    // allocate and map frame for buffer
547    struct capref frame;
548    struct frame_identity frameid;
549    size_t retbytes;
550    err = frame_alloc(&frame, 4096, &retbytes);
551    assert(err_is_ok(err));
552    assert(retbytes == 4096);
553    void *data_dest;
554    err = vspace_map_one_frame_attr(&data_dest, retbytes, frame,
555            VREGION_FLAGS_READ_WRITE_NOCACHE, NULL, NULL);
556    assert(err_is_ok(err));
557    err = frame_identify(frame, &frameid);
558    assert(err_is_ok(err));
559
560    memcpy(data_dest, data, BLOCK_SIZE);
561
562
563    struct cmd set_blocklen = {
564        .cmdidx = MMC_CMD_SET_BLOCKLEN,
565        .cmdarg = BLOCK_SIZE,
566        .resp_type = MMC_RSP_R1
567    };
568    err = sdhc_send_cmd(sd, &set_blocklen);
569    if(err_is_fail(err)){
570        DEBUG_ERR(err, "set_blocklen");
571        return err;
572    }
573
574    struct cmd write_block = {
575        .cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK,
576        .cmdarg = index,
577        .resp_type = MMC_RSP_R1,
578        .dma_base = frameid.base
579
580    };
581    err = sdhc_send_cmd(sd, &write_block);
582    if(err_is_fail(err)){
583        DEBUG_ERR(err, "read_block");
584        return err;
585    }
586
587    return SYS_ERR_OK;
588}
589
590static errval_t sdhc_init(struct sdhc * sd){
591    //Initialize and identify the card. Roughly following SDHC specification,
592    //3.6 Card Initialization and Identification.
593    errval_t err;
594
595    DEBUG("Sending go idle transaction...\n"); err = sdhc_go_idle(sd);
596    if(err_is_fail(err)) return err;
597
598    DEBUG("Sending if_cond transaction...\n");
599    err = sdhc_send_if_cond(sd);
600    if(err_is_fail(err)) return err;
601
602    DEBUG("Query OCR (CMD 55/41)...\n");
603    err = sdhc_get_ocr(sd);
604    if(err_is_fail(err)) return err;
605
606    DEBUG("Card initialization...\n");
607    err = sdhc_card_init(sd);
608    if(err_is_fail(err)) return err;
609
610    DEBUG("Card in transfer state!");
611
612    return SYS_ERR_OK;
613}
614
615static errval_t sdhc_test(struct sdhc *sd) {
616    errval_t err;
617    DEBUG("... testing read block...\n");
618    void *buf;
619    err = sdhc_read_block(sd, 0, &buf);
620    if(err_is_fail(err)) return err;
621    for(int i=0; i<16;i++){
622        DEBUG("    buf[%d] = %"PRIx32"\n", i, ((uint32_t*)buf)[i]);
623    }
624
625    DEBUG("... testing write block...\n");
626
627    uint32_t data[128];
628    for(int i=0; i<128; i+=4){
629        data[i] = 0xdead;
630        data[i+1] = 0xbeef;
631        data[i+2] = 0xc0c0;
632        data[i+3] = 0xcaca;
633    };
634    err = sdhc_write_block(sd, 20, data);
635
636    DEBUG("...  reading just written data\n");
637    void *buf2t;
638    err = sdhc_read_block(sd, 20, &buf2t);
639    uint32_t *buf2 = (uint32_t*) buf2t;
640    if(err_is_fail(err)) return err;
641    for(int i=0; i<16;i++){
642        DEBUG("    buf2[%d] = %"PRIx32"\n", i, buf2[i]);
643    }
644    if(buf2[0] == 0xdead && buf2[1] ==0xbeef){
645        return SYS_ERR_OK;
646    } else {
647        return SDHC_ERR_TEST_FAILED;
648    }
649}
650
651static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev)
652{
653    DEBUG("sdhc entering init\n");
654    errval_t err;
655    struct sdhc *sd = malloc(sizeof(struct sdhc));
656    bfi->dstate = sd;
657    struct capref devframe_cap = { .slot = DRIVERKIT_ARGCN_SLOT_BAR0,
658                                   .cnode = bfi->argcn };
659    err = map_device_cap(devframe_cap, &sd->vbase);
660    if(err_is_fail(err)){
661        DEBUG_ERR(err, "map devframe");
662        return err;
663    }
664    sdhc_initialize(&sd->dev, (mackerel_addr_t)sd->vbase);
665
666    struct capref irq_src;
667    irq_src.cnode = bfi->argcn;
668    irq_src.slot = PCIARG_SLOT_INT;
669
670    // Register interrupt handler
671    err = int_route_client_route_and_connect(irq_src, 0,
672           get_default_waitset(), int_handler, sd);
673    if (err_is_fail(err)) {
674       USER_PANIC_ERR(err, "interrupt setup failed.");
675    }
676    DEBUG("interrupt setup complete\n");
677
678    err = software_reset(sd);
679    if (err_is_fail(err)) {
680       DEBUG_ERR(err, "software reset failed");
681       return err;
682    }
683    DEBUG("reset done.\n");
684
685    err = sdhc_init(sd);
686    if (err_is_fail(err)) {
687       DEBUG_ERR(err, "mmc init failed (No card present?)");
688       return err;
689    }
690
691    err = sdhc_test(sd);
692    if (err_is_fail(err)) {
693       DEBUG_ERR(err, "mmc test failed");
694       return err;
695    }
696    printf("SHDC test suceeded!\n");
697
698    return SYS_ERR_OK;
699}
700
701static errval_t attach(struct bfdriver_instance *bfi)
702{
703    return SYS_ERR_OK;
704}
705
706static errval_t detach(struct bfdriver_instance *bfi)
707{
708    return SYS_ERR_OK;
709}
710
711static errval_t set_sleep_level(struct bfdriver_instance *bfi, uint32_t level)
712{
713    return SYS_ERR_OK;
714}
715
716static errval_t destroy(struct bfdriver_instance *bfi)
717{
718    struct sdhc *sd = bfi->dstate;
719    free(sd);
720    bfi->dstate = NULL;
721    bfi->device = 0x0;
722    return SYS_ERR_OK;
723}
724
725static errval_t get_ep(struct bfdriver_instance *bfi, bool lmp, struct capref *ret_cap)
726{
727    USER_PANIC("NIY \n");
728    return SYS_ERR_OK;
729}
730
731DEFINE_MODULE(sdhc, init, attach, detach, set_sleep_level, destroy, get_ep);
732