kernel: vm kernel call can't suspend
[minix.git] / drivers / mmc / mmchost_mmchs.c
blobcbf5a838479f4f4460757a804673d7ad68232680
1 /* kernel headers */
2 #include <minix/blockdriver.h>
3 #include <minix/com.h>
4 #include <minix/vm.h>
5 #include <sys/mman.h>
7 /* usr headers */
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <inttypes.h>
14 #include <limits.h>
16 /* local headers */
17 #include "mmclog.h"
18 #include "mmchost.h"
20 /* header imported from netbsd */
21 #include "sdmmcreg.h"
22 #include "sdmmcreg.h"
23 #include "sdhcreg.h"
25 /* omap /hardware related */
26 #include "omap_mmc.h"
29 * Define a structure to be used for logging
31 static struct mmclog log = {
32 .name = "mmc_host_mmchs",
33 .log_level = LEVEL_INFO,
34 .log_func = default_log
37 #define REG(x)(*((volatile uint32_t *)(x)))
38 #define BIT(x)(0x1 << x)
40 /* Write a uint32_t value to a memory address. */
41 inline void
42 write32(uint32_t address, uint32_t value)
44 REG(address) = value;
47 /* Read an uint32_t from a memory address */
48 inline uint32_t
49 read32(uint32_t address)
52 return REG(address);
55 /* Set a 32 bits value depending on a mask */
56 inline void
57 set32(uint32_t address, uint32_t mask, uint32_t value)
59 uint32_t val;
60 val = read32(address);
61 /* clear the bits */
62 val &= ~(mask);
63 /* apply the value using the mask */
64 val |= (value & mask);
65 write32(address, val);
68 static uint32_t base_address;
71 * Initialize the MMC controller given a certain
72 * instance. this driver only handles a single
73 * mmchs controller at a given time.
75 int
76 mmchs_init(uint32_t instance)
78 int counter;
79 uint32_t value;
81 counter = 0;
82 value = 0;
84 struct minix_mem_range mr;
86 mr.mr_base = MMCHS1_REG_BASE;
87 mr.mr_limit = MMCHS1_REG_BASE + 0x400;
89 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
90 panic("Unable to request permission to map memory");
93 /* Set the base address to use */
94 base_address =
95 (uint32_t) vm_map_phys(SELF, (void *) MMCHS1_REG_BASE, 0x400);
96 if (base_address == (uint32_t) MAP_FAILED)
97 panic("Unable to map MMC memory");
99 base_address = (unsigned long) base_address - 0x100;
101 /* Soft reset of the controller. This section is documented in the TRM
104 /* Write 1 to sysconfig[0] to trigger a reset */
105 set32(base_address + MMCHS_SD_SYSCONFIG, MMCHS_SD_SYSCONFIG_SOFTRESET,
106 MMCHS_SD_SYSCONFIG_SOFTRESET);
108 /* Read sysstatus to know when it's done */
109 while (!(read32(base_address + MMCHS_SD_SYSSTATUS)
110 & MMCHS_SD_SYSSTATUS_RESETDONE)) {
111 /* TODO:Add proper delay and escape route */
113 counter++;
116 /* Set SD default capabilities */
117 set32(base_address + MMCHS_SD_CAPA, MMCHS_SD_CAPA_VS_MASK,
118 MMCHS_SD_CAPA_VS18 | MMCHS_SD_CAPA_VS30);
120 /* TRM mentions MMCHS_SD_CUR_CAPA but does not describe how to limit
121 * the current */
123 uint32_t mask =
124 MMCHS_SD_SYSCONFIG_AUTOIDLE | MMCHS_SD_SYSCONFIG_ENAWAKEUP |
125 MMCHS_SD_SYSCONFIG_STANDBYMODE | MMCHS_SD_SYSCONFIG_CLOCKACTIVITY |
126 MMCHS_SD_SYSCONFIG_SIDLEMODE;
128 /* Automatic clock gating strategy */
129 value = MMCHS_SD_SYSCONFIG_AUTOIDLE_EN;
130 /* Enable wake-up capability */
131 value |= MMCHS_SD_SYSCONFIG_ENAWAKEUP_EN;
132 /* Smart-idle */
133 value |= MMCHS_SD_SYSCONFIG_SIDLEMODE_IDLE;
134 /* Booth the interface and functional can be switched off */
135 value |= MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_OFF;
136 /* Go into wake-up mode when possible */
137 value |= MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_INTERNAL;
140 * wake-up configuration
142 set32(base_address + MMCHS_SD_SYSCONFIG, mask, value);
144 /* Wake-up on sd interrupt for SDIO */
145 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_IWE,
146 MMCHS_SD_HCTL_IWE_EN);
149 * MMC host and bus configuration
152 /* Configure data and command transfer (1 bit mode) */
153 set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_DW8,
154 MMCHS_SD_CON_DW8_1BIT);
155 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_DTW,
156 MMCHS_SD_HCTL_DTW_1BIT);
158 /* Configure card voltage to 3.0 volt */
159 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDVS,
160 MMCHS_SD_HCTL_SDVS_VS30);
162 /* Power on the host controller and wait for the
163 * MMCHS_SD_HCTL_SDBP_POWER_ON to be set */
164 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDBP,
165 MMCHS_SD_HCTL_SDBP_ON);
167 /* TODO: Add padconf stuff here as documented in the TRM */
169 while ((read32(base_address + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP)
170 != MMCHS_SD_HCTL_SDBP_ON) {
171 /* TODO:Add proper delay and escape route */
172 counter++;
175 /* Enable internal clock and clock to the card */
176 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_ICE,
177 MMCHS_SD_SYSCTL_ICE_EN);
179 // @TODO Fix external clock enable , this one is very slow
180 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
181 (0x3ff << 6));
182 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CEN,
183 MMCHS_SD_SYSCTL_CEN_EN);
184 counter = 0;
186 while ((read32(base_address + MMCHS_SD_SYSCTL) & MMCHS_SD_SYSCTL_ICS)
187 != MMCHS_SD_SYSCTL_ICS_STABLE) {
188 /* TODO:Add proper delay and escape route */
189 counter++;
193 * See spruh73e page 3576 Card Detection, Identification, and Selection
196 /* Enable command interrupt */
197 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_CC_ENABLE,
198 MMCHS_SD_IE_CC_ENABLE_ENABLE);
199 /* Enable transfer complete interrupt */
200 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_TC_ENABLE,
201 MMCHS_SD_IE_TC_ENABLE_ENABLE);
203 /* enable error interrupts */
204 /* NOTE: We are currently skipping the BADA interrupt it does get
205 * raised for unknown reasons */
206 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_ERROR_MASK, 0x0fffffffu);
208 /* clean the error interrupts */
209 set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
210 0xffffffffu);
212 /* send a init signal to the host controller. This does not actually
213 * send a command to a card manner */
214 set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
215 MMCHS_SD_CON_INIT_INIT);
216 /* command 0 , type other commands not response etc) */
217 write32(base_address + MMCHS_SD_CMD, 0x00);
219 counter = 0;
220 while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_STAT_CC)
221 != MMCHS_SD_STAT_CC_RAISED) {
222 if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
223 mmc_log_warn(&log, "%s, error stat %x\n",
224 __FUNCTION__,
225 read32(base_address + MMCHS_SD_STAT));
226 return 1;
228 counter++;
231 /* clear the cc interrupt status */
232 set32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE,
233 MMCHS_SD_IE_CC_ENABLE_ENABLE);
236 * Set Set SD_CON[1] INIT bit to 0x0 to end the initialization sequence
238 set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
239 MMCHS_SD_CON_INIT_NOINIT);
241 /* Clean the MMCHS_SD_STAT register */
242 write32(base_address + MMCHS_SD_STAT, 0xffffffffu);
243 return 0;
247 mmchs_send_cmd(uint32_t command, uint32_t arg)
249 int count = 0;
251 /* Read current interrupt status and fail it an interrupt is already
252 * asserted */
253 if ((read32(base_address + MMCHS_SD_STAT) & 0xffffu)) {
254 mmc_log_warn(&log, "%s, interrupt already raised stat %08x\n",
255 __FUNCTION__, read32(base_address + MMCHS_SD_STAT));
256 write32(base_address + MMCHS_SD_STAT,
257 MMCHS_SD_IE_CC_ENABLE_CLEAR);
258 // return 1;
261 /* Set arguments */
262 write32(base_address + MMCHS_SD_ARG, arg);
263 /* Set command */
264 set32(base_address + MMCHS_SD_CMD, MMCHS_SD_CMD_MASK, command);
266 /* Wait for completion */
267 while ((read32(base_address + MMCHS_SD_STAT) & 0xffffu) == 0x0) {
268 count++;
271 if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
272 mmc_log_warn(&log, "%s, error stat %08x\n", __FUNCTION__,
273 read32(base_address + MMCHS_SD_STAT));
274 set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
275 0xffffffffu);
276 return 1;
279 if ((command & MMCHS_SD_CMD_RSP_TYPE) ==
280 MMCHS_SD_CMD_RSP_TYPE_48B_BUSY) {
282 * Command with busy response *CAN* also set the TC bit if they exit busy
284 while ((read32(base_address + MMCHS_SD_STAT)
285 & MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) {
286 count++;
288 write32(base_address + MMCHS_SD_STAT,
289 MMCHS_SD_IE_TC_ENABLE_CLEAR);
292 /* clear the cc status */
293 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR);
294 return 0;
298 mmc_send_cmd(struct mmc_command *c)
301 /* convert the command to a hsmmc command */
302 int ret;
303 uint32_t cmd, arg;
304 cmd = MMCHS_SD_CMD_INDX_CMD(c->cmd);
305 arg = c->args;
307 switch (c->resp_type) {
308 case RESP_LEN_48_CHK_BUSY:
309 cmd |= MMCHS_SD_CMD_RSP_TYPE_48B_BUSY;
310 break;
311 case RESP_LEN_48:
312 cmd |= MMCHS_SD_CMD_RSP_TYPE_48B;
313 break;
314 case RESP_LEN_136:
315 cmd |= MMCHS_SD_CMD_RSP_TYPE_136B;
316 break;
317 case NO_RESPONSE:
318 cmd |= MMCHS_SD_CMD_RSP_TYPE_NO_RESP;
319 break;
320 default:
321 return 1;
324 ret = mmchs_send_cmd(cmd, arg);
326 /* copy response into cmd->resp */
327 switch (c->resp_type) {
328 case RESP_LEN_48_CHK_BUSY:
329 case RESP_LEN_48:
330 c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
331 break;
332 case RESP_LEN_136:
333 c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
334 c->resp[1] = read32(base_address + MMCHS_SD_RSP32);
335 c->resp[2] = read32(base_address + MMCHS_SD_RSP54);
336 c->resp[3] = read32(base_address + MMCHS_SD_RSP76);
337 break;
338 case NO_RESPONSE:
339 break;
340 default:
341 return 1;
344 return ret;
347 static struct mmc_command command;
350 card_goto_idle_state()
352 command.cmd = MMC_GO_IDLE_STATE;
353 command.resp_type = NO_RESPONSE;
354 command.args = 0x00;
355 if (mmc_send_cmd(&command)) {
356 // Failure
357 return 1;
359 return 0;
363 card_identification()
365 command.cmd = MMC_SEND_EXT_CSD;
366 command.resp_type = RESP_LEN_48;
367 command.args = MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN;
369 if (mmc_send_cmd(&command)) {
370 // We currently only support 2.0,
371 return 1;
374 if (!(command.resp[0]
375 == (MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN))) {
376 mmc_log_warn(&log, "%s, check pattern check failed %08x\n",
377 __FUNCTION__, command.resp[0]);
378 return 1;
380 return 0;
384 card_query_voltage_and_type(struct sd_card_regs *card)
387 command.cmd = MMC_APP_CMD;
388 command.resp_type = RESP_LEN_48;
389 command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
390 if (mmc_send_cmd(&command)) {
391 return 1;
394 command.cmd = SD_APP_OP_COND;
395 command.resp_type = RESP_LEN_48;
397 /* 0x1 << 30 == send HCS (Host capacity support) and get OCR register */
398 command.args =
399 MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V | MMC_OCR_3_1V_3_2V |
400 MMC_OCR_3_0V_3_1V | MMC_OCR_2_9V_3_0V | MMC_OCR_2_8V_2_9V |
401 MMC_OCR_2_7V_2_8V;
402 command.args |= MMC_OCR_HCS; /* RCA=0000 */
404 if (mmc_send_cmd(&command)) {
405 return 1;
407 /* @todo wait for max 1 ms */
408 while (!(command.resp[0] & MMC_OCR_MEM_READY)) {
409 command.cmd = MMC_APP_CMD;
410 command.resp_type = RESP_LEN_48;
411 command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
412 if (mmc_send_cmd(&command)) {
413 return 1;
416 /* Send ADMD41 */
417 /* 0x1 << 30 == send HCS (Host capacity support) and get OCR
418 * register */
419 command.cmd = SD_APP_OP_COND;
420 command.resp_type = RESP_LEN_48;
421 /* 0x1 << 30 == send HCS (Host capacity support) */
422 command.args = MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V
423 | MMC_OCR_3_1V_3_2V | MMC_OCR_3_0V_3_1V | MMC_OCR_2_9V_3_0V
424 | MMC_OCR_2_8V_2_9V | MMC_OCR_2_7V_2_8V;
425 command.args |= MMC_OCR_HCS; /* RCA=0000 */
427 if (mmc_send_cmd(&command)) {
428 return 1;
431 /* if bit 31 is set the response is valid */
432 if ((command.resp[0] & MMC_OCR_MEM_READY)) {
433 break;
437 card->ocr = command.resp[3];
438 return 0;
442 card_identify(struct sd_card_regs *card)
445 /* Send cmd 2 (all_send_cid) and expect 136 bits response */
446 command.cmd = MMC_ALL_SEND_CID;
447 command.resp_type = RESP_LEN_136;
448 command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
450 if (mmc_send_cmd(&command)) {
451 return 1;
454 card->cid[0] = command.resp[0];
455 card->cid[1] = command.resp[1];
456 card->cid[2] = command.resp[2];
457 card->cid[3] = command.resp[3];
459 command.cmd = MMC_SET_RELATIVE_ADDR;
460 command.resp_type = RESP_LEN_48;
461 command.args = 0x0; /* RCA=0000 */
463 /* R6 response */
464 if (mmc_send_cmd(&command)) {
465 return 1;
468 card->rca = SD_R6_RCA(command.resp);
469 /* MMHCS only supports a single card so sending MMCHS_SD_CMD_CMD2 is
470 * useless Still we should make it possible in the API to support
471 * multiple cards */
473 return 0;
477 card_csd(struct sd_card_regs *card)
479 /* send_csd -> r2 response */
480 command.cmd = MMC_SEND_CSD;
481 command.resp_type = RESP_LEN_136;
482 command.args = MMC_ARG_RCA(card->rca); /* card rca */
484 if (mmc_send_cmd(&command)) {
485 return 1;
488 card->csd[0] = command.resp[0];
489 card->csd[1] = command.resp[1];
490 card->csd[2] = command.resp[2];
491 card->csd[3] = command.resp[3];
493 if (SD_CSD_CSDVER(card->csd) != SD_CSD_CSDVER_2_0) {
494 mmc_log_warn(&log, "Version 2.0 of CSD register expected\n");
495 return 1;
498 /* sanity check */
499 // mmc_log_warn(&log,"size = %llu bytes\n", (long long
500 // unsigned)SD_CSD_V2_CAPACITY( card->csd) * 512);
501 return 0;
505 select_card(struct sd_card_regs *card)
508 command.cmd = MMC_SELECT_CARD;
509 command.resp_type = RESP_LEN_48_CHK_BUSY;
510 command.args = MMC_ARG_RCA(card->rca); /* card rca */
512 if (mmc_send_cmd(&command)) {
513 return 1;
515 return 0;
519 read_single_block(struct sd_card_regs *card,
520 uint32_t blknr, unsigned char *buf)
522 uint32_t count;
523 uint32_t value;
525 count = 0;
527 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
528 MMCHS_SD_IE_BRR_ENABLE_ENABLE);
530 set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
532 /* read single block */
533 if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_READ_BLOCK_SINGLE)
534 | MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
535 | MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1) */
536 | MMCHS_SD_CMD_MSBS_SINGLE /* single block */
537 | MMCHS_SD_CMD_DDIR_READ /* read data from card */
538 , blknr)) {
539 return 1;
542 while ((read32(base_address + MMCHS_SD_STAT)
543 & MMCHS_SD_IE_BRR_ENABLE_ENABLE) == 0) {
544 count++;
547 if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN)) {
548 return 1; /* We are not allowed to read data from the
549 * data buffer */
552 for (count = 0; count < 512; count += 4) {
553 value = read32(base_address + MMCHS_SD_DATA);
554 buf[count] = *((char *) &value);
555 buf[count + 1] = *((char *) &value + 1);
556 buf[count + 2] = *((char *) &value + 2);
557 buf[count + 3] = *((char *) &value + 3);
560 /* Wait for TC */
561 while ((read32(base_address +
562 MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE)
563 == 0) {
564 count++;
566 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
568 /* clear and disable the bbr interrupt */
569 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_BRR_ENABLE_CLEAR);
570 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
571 MMCHS_SD_IE_BRR_ENABLE_DISABLE);
572 return 0;
576 write_single_block(struct sd_card_regs *card,
577 uint32_t blknr, unsigned char *buf)
579 uint32_t count;
580 uint32_t value;
582 count = 0;
584 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE,
585 MMCHS_SD_IE_BWR_ENABLE_ENABLE);
586 // set32(base_address + MMCHS_SD_IE, 0xfff , 0xfff);
587 set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
589 /* Set timeout */
590 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO,
591 MMCHS_SD_SYSCTL_DTO_2POW27);
593 /* write single block */
594 if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_WRITE_BLOCK_SINGLE)
595 | MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
596 | MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1b) */
597 | MMCHS_SD_CMD_MSBS_SINGLE /* single block */
598 | MMCHS_SD_CMD_DDIR_WRITE /* write to the card */
599 , blknr)) {
600 return 1;
603 /* Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt */
604 while ((read32(base_address +
605 MMCHS_SD_STAT) & MMCHS_SD_IE_BWR_ENABLE) == 0) {
606 count++;
609 if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)) {
610 return 1; /* not ready to write data */
612 for (count = 0; count < 512; count += 4) {
613 *((char *) &value) = buf[count];
614 *((char *) &value + 1) = buf[count + 1];
615 *((char *) &value + 2) = buf[count + 2];
616 *((char *) &value + 3) = buf[count + 3];
617 write32(base_address + MMCHS_SD_DATA, value);
620 /* Wait for TC */
621 while ((read32(base_address +
622 MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE)
623 == 0) {
624 count++;
626 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
627 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR); /* finished.
629 /* clear the bwr interrupt FIXME is this right when writing? */
630 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_BWR_ENABLE_CLEAR);
631 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE,
632 MMCHS_SD_IE_BWR_ENABLE_DISABLE);
633 return 0;
637 mmchs_host_init(struct mmc_host *host)
639 mmchs_init(1);
640 return 0;
643 void
644 mmchs_set_log_level(int level)
646 if (level >= 0 && level <= 4) {
647 log.log_level = level;
652 mmchs_host_set_instance(struct mmc_host *host, int instance)
654 mmc_log_info(&log, "Using instance number %d\n", instance);
655 if (instance != 0) {
656 return EIO;
658 return OK;
662 mmchs_host_reset(struct mmc_host *host)
664 mmchs_init(1);
665 return 0;
669 mmchs_card_detect(struct sd_slot *slot)
671 /* @TODO implement proper card detect */
672 return 1;
675 struct sd_card *
676 mmchs_card_initialize(struct sd_slot *slot)
678 mmchs_init(1);
680 struct sd_card *card;
681 card = &slot->card;
682 memset(card, 0, sizeof(struct sd_card));
683 card->slot = slot;
685 if (card_goto_idle_state()) {
686 mmc_log_warn(&log, "Failed to go idle state\n");
687 return NULL;
690 if (card_identification()) {
691 mmc_log_warn(&log, "Failed to do card_identification\n");
692 return NULL;
695 if (card_query_voltage_and_type(&slot->card.regs)) {
696 mmc_log_warn(&log,
697 "Failed to do card_query_voltage_and_type\n");
698 return NULL;
700 if (card_identify(&slot->card.regs)) {
701 mmc_log_warn(&log, "Failed to identify card\n");
702 return NULL;
704 /* We have now initialized the hardware identified the card */
705 if (card_csd(&slot->card.regs)) {
706 mmc_log_warn(&log,
707 "failed to read csd (card specific data)\n");
708 return NULL;
711 if (select_card(&slot->card.regs)) {
712 mmc_log_warn(&log, "Failed to select card\n");
713 return NULL;
716 if (SD_CSD_READ_BL_LEN(slot->card.regs.csd) != 0x09) {
717 /* for CSD version 2.0 the value is fixed to 0x09 and means a
718 * block size of 512 */
719 mmc_log_warn(&log, "Block size expect to be 512\n");
720 return NULL;
723 slot->card.blk_size = 512; /* HARDCODED value */
724 slot->card.blk_count = SD_CSD_V2_CAPACITY(slot->card.regs.csd);
725 slot->card.state = SD_MODE_DATA_TRANSFER_MODE;
727 memset(slot->card.part, 0, sizeof(slot->card.part));
728 memset(slot->card.subpart, 0, sizeof(slot->card.subpart));
729 slot->card.part[0].dv_base = 0;
730 slot->card.part[0].dv_size =
731 (unsigned long long) SD_CSD_V2_CAPACITY(slot->card.regs.csd) * 512;
732 return &slot->card;
735 /* read count blocks into existing buf */
736 static int
737 mmchs_host_read(struct sd_card *card,
738 uint32_t blknr, uint32_t count, unsigned char *buf)
740 uint32_t i;
741 i = count;
742 for (i = 0; i < count; i++) {
743 read_single_block(&card->regs, blknr + i,
744 buf + (i * card->blk_size));
746 return OK;
749 /* write count blocks */
750 static int
751 mmchs_host_write(struct sd_card *card,
752 uint32_t blknr, uint32_t count, unsigned char *buf)
754 uint32_t i;
756 i = count;
757 for (i = 0; i < count; i++) {
758 write_single_block(&card->regs, blknr + i,
759 buf + (i * card->blk_size));
762 return OK;
766 mmchs_card_release(struct sd_card *card)
768 assert(card->open_ct == 1);
769 card->open_ct--;
770 card->state = SD_MODE_UNINITIALIZED;
771 /* TODO:Set card state */
772 return OK;
775 void
776 host_initialize_host_structure_mmchs(struct mmc_host *host)
778 /* Initialize the basic data structures host slots and cards */
779 int i;
781 host->host_set_instance = mmchs_host_set_instance;
782 host->host_init = mmchs_host_init;
783 host->set_log_level = mmchs_set_log_level;
784 host->host_reset = mmchs_host_reset;
785 host->card_detect = mmchs_card_detect;
786 host->card_initialize = mmchs_card_initialize;
787 host->card_release = mmchs_card_release;
788 host->read = mmchs_host_read;
789 host->write = mmchs_host_write;
791 /* initialize data structures */
792 for (i = 0; i < sizeof(host->slot) / sizeof(host->slot[0]); i++) {
793 // @TODO set initial card and slot state
794 host->slot[i].host = host;
795 host->slot[i].card.slot = &host->slot[i];