ldivmod, uldivmod: fix qdivrem calls
[minix.git] / drivers / mmc / mmchost_mmchs.c
blob1797febaeb3c058ef0ce08cadcc5ac5928fdedae
1 /* kernel headers */
2 #include <minix/blockdriver.h>
3 #include <minix/com.h>
4 #include <minix/vm.h>
5 #include <minix/spin.h>
6 #include <sys/mman.h>
7 #include <sys/time.h>
9 /* usr headers */
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <string.h>
15 #include <inttypes.h>
16 #include <limits.h>
17 #include <unistd.h>
19 /* local headers */
20 #include "mmclog.h"
21 #include "mmchost.h"
23 /* header imported from netbsd */
24 #include "sdmmcreg.h"
25 #include "sdmmcreg.h"
26 #include "sdhcreg.h"
28 /* omap /hardware related */
29 #include "omap_mmc.h"
31 #define USE_INTR
33 #ifdef USE_INTR
34 static int hook_id = 1;
35 #define OMAP3_MMC1_IRQ 83 /* MMC/SD module 1 */
36 #endif
38 #define SANE_TIMEOUT 500000 /* 500 MS */
40 * Define a structure to be used for logging
42 static struct mmclog log = {
43 .name = "mmc_host_mmchs",
44 .log_level = LEVEL_INFO,
45 .log_func = default_log
48 #define REG(x)(*((volatile uint32_t *)(x)))
49 #define BIT(x)(0x1 << x)
51 /* Write a uint32_t value to a memory address. */
52 static inline void
53 write32(uint32_t address, uint32_t value)
55 REG(address) = value;
58 /* Read an uint32_t from a memory address */
59 static inline uint32_t
60 read32(uint32_t address)
63 return REG(address);
66 /* Set a 32 bits value depending on a mask */
67 static inline void
68 set32(uint32_t address, uint32_t mask, uint32_t value)
70 uint32_t val;
71 val = read32(address);
72 /* clear the bits */
73 val &= ~(mask);
74 /* apply the value using the mask */
75 val |= (value & mask);
76 write32(address, val);
79 static uint32_t base_address;
82 * Initialize the MMC controller given a certain
83 * instance. this driver only handles a single
84 * mmchs controller at a given time.
86 int
87 mmchs_init(uint32_t instance)
90 uint32_t value;
91 value = 0;
92 struct minix_mem_range mr;
93 spin_t spin;
95 mr.mr_base = MMCHS1_REG_BASE;
96 mr.mr_limit = MMCHS1_REG_BASE + 0x400;
98 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
99 panic("Unable to request permission to map memory");
102 /* Set the base address to use */
103 base_address =
104 (uint32_t) vm_map_phys(SELF, (void *) MMCHS1_REG_BASE, 0x400);
105 if (base_address == (uint32_t) MAP_FAILED)
106 panic("Unable to map MMC memory");
108 base_address = (unsigned long) base_address - 0x100;
110 /* Soft reset of the controller. This section is documented in the TRM
113 /* Write 1 to sysconfig[0] to trigger a reset */
114 set32(base_address + MMCHS_SD_SYSCONFIG, MMCHS_SD_SYSCONFIG_SOFTRESET,
115 MMCHS_SD_SYSCONFIG_SOFTRESET);
117 /* Read sysstatus to know when it's done */
119 spin_init(&spin, SANE_TIMEOUT);
120 while (!(read32(base_address + MMCHS_SD_SYSSTATUS)
121 & MMCHS_SD_SYSSTATUS_RESETDONE)) {
122 if (spin_check(&spin) == FALSE) {
123 mmc_log_warn(&log, "mmc init timeout\n");
124 return 1;
128 /* Set SD default capabilities */
129 set32(base_address + MMCHS_SD_CAPA, MMCHS_SD_CAPA_VS_MASK,
130 MMCHS_SD_CAPA_VS18 | MMCHS_SD_CAPA_VS30);
132 /* TRM mentions MMCHS_SD_CUR_CAPA but does not describe how to limit
133 * the current */
135 uint32_t mask =
136 MMCHS_SD_SYSCONFIG_AUTOIDLE | MMCHS_SD_SYSCONFIG_ENAWAKEUP |
137 MMCHS_SD_SYSCONFIG_STANDBYMODE | MMCHS_SD_SYSCONFIG_CLOCKACTIVITY |
138 MMCHS_SD_SYSCONFIG_SIDLEMODE;
140 /* Automatic clock gating strategy */
141 value = MMCHS_SD_SYSCONFIG_AUTOIDLE_EN;
142 /* Enable wake-up capability */
143 value |= MMCHS_SD_SYSCONFIG_ENAWAKEUP_EN;
144 /* Smart-idle */
145 value |= MMCHS_SD_SYSCONFIG_SIDLEMODE_IDLE;
146 /* Booth the interface and functional can be switched off */
147 value |= MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_OFF;
148 /* Go into wake-up mode when possible */
149 value |= MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_INTERNAL;
152 * wake-up configuration
154 set32(base_address + MMCHS_SD_SYSCONFIG, mask, value);
156 /* Wake-up on sd interrupt for SDIO */
157 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_IWE,
158 MMCHS_SD_HCTL_IWE_EN);
161 * MMC host and bus configuration
164 /* Configure data and command transfer (1 bit mode) */
165 set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_DW8,
166 MMCHS_SD_CON_DW8_1BIT);
167 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_DTW,
168 MMCHS_SD_HCTL_DTW_1BIT);
170 /* Configure card voltage to 3.0 volt */
171 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDVS,
172 MMCHS_SD_HCTL_SDVS_VS30);
174 /* Power on the host controller and wait for the
175 * MMCHS_SD_HCTL_SDBP_POWER_ON to be set */
176 set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDBP,
177 MMCHS_SD_HCTL_SDBP_ON);
179 // /* TODO: Add padconf/pinmux stuff here as documented in the TRM */
180 spin_init(&spin, SANE_TIMEOUT);
181 while ((read32(base_address + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP)
182 != MMCHS_SD_HCTL_SDBP_ON) {
183 if (spin_check(&spin) == FALSE) {
184 mmc_log_warn(&log, "mmc init timeout SDBP not set\n");
185 return 1;
189 /* Enable internal clock and clock to the card */
190 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_ICE,
191 MMCHS_SD_SYSCTL_ICE_EN);
193 // @TODO Fix external clock enable , this one is very slow
194 // but we first need faster context switching
195 //set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
196 // (0x20 << 6));
197 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
198 (0x5 << 6));
200 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CEN,
201 MMCHS_SD_SYSCTL_CEN_EN);
203 spin_init(&spin, SANE_TIMEOUT);
204 while ((read32(base_address + MMCHS_SD_SYSCTL) & MMCHS_SD_SYSCTL_ICS)
205 != MMCHS_SD_SYSCTL_ICS_STABLE) {
207 if (spin_check(&spin) == FALSE) {
208 mmc_log_warn(&log, "clock not stable\n");
209 return 1;
214 * See spruh73e page 3576 Card Detection, Identification, and Selection
217 /* Enable command interrupt */
218 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_CC_ENABLE,
219 MMCHS_SD_IE_CC_ENABLE_ENABLE);
220 /* Enable transfer complete interrupt */
221 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_TC_ENABLE,
222 MMCHS_SD_IE_TC_ENABLE_ENABLE);
224 /* enable error interrupts */
225 /* NOTE: We are currently skipping the BADA interrupt it does get
226 * raised for unknown reasons */
227 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_ERROR_MASK, 0x0fffffffu);
229 /* clean the error interrupts */
230 set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
231 0xffffffffu);
233 /* send a init signal to the host controller. This does not actually
234 * send a command to a card manner */
235 set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
236 MMCHS_SD_CON_INIT_INIT);
237 /* command 0 , type other commands not response etc) */
238 write32(base_address + MMCHS_SD_CMD, 0x00);
240 spin_init(&spin, SANE_TIMEOUT);
241 while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_STAT_CC)
242 != MMCHS_SD_STAT_CC_RAISED) {
243 if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
244 mmc_log_warn(&log, "%s, error stat %x\n",
245 __FUNCTION__,
246 read32(base_address + MMCHS_SD_STAT));
247 return 1;
250 if (spin_check(&spin) == FALSE) {
251 mmc_log_warn(&log,
252 "Interrupt not raised during init\n");
253 return 1;
257 /* clear the cc interrupt status */
258 set32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE,
259 MMCHS_SD_IE_CC_ENABLE_ENABLE);
262 * Set Set SD_CON[1] INIT bit to 0x0 to end the initialization sequence
264 set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
265 MMCHS_SD_CON_INIT_NOINIT);
267 /* Set timeout */
268 set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO,
269 MMCHS_SD_SYSCTL_DTO_2POW27);
271 /* Clean the MMCHS_SD_STAT register */
272 write32(base_address + MMCHS_SD_STAT, 0xffffffffu);
273 #ifdef USE_INTR
274 hook_id = 1;
275 if (sys_irqsetpolicy(OMAP3_MMC1_IRQ, 0, &hook_id) != OK) {
276 printf("mmc: couldn't set IRQ policy %d\n", OMAP3_MMC1_IRQ);
277 return 1;
279 /* enable signaling from MMC controller towards interrupt controller */
280 write32(base_address + MMCHS_SD_ISE, 0xffffffffu);
281 #endif
283 return 0;
286 static void
287 mmchs_hw_intr(unsigned int irqs)
289 mmc_log_warn(&log, "Hardware interrupt left over\n");
291 #ifdef USE_INTR
292 if (sys_irqenable(&hook_id) != OK)
293 printf("couldn't re-enable interrupt \n");
294 #endif
295 /* Leftover interrupt(s) received; ack it/them. */
298 /*===========================================================================*
299 * w_intr_wait *
300 *===========================================================================*/
301 static int
302 intr_wait(int mask)
304 long v;
305 #ifdef USE_INTR
306 if (sys_irqenable(&hook_id) != OK)
307 printf("Failed to enable irqenable irq\n");
308 /* Wait for a task completion interrupt. */
309 message m;
310 int ipc_status;
311 int ticks = SANE_TIMEOUT * sys_hz() / 1000000;
313 if (ticks <= 0) ticks =1;
314 while (1) {
315 int rr;
316 sys_setalarm(ticks, 0);
317 if ((rr = driver_receive(ANY, &m, &ipc_status)) != OK) {
318 panic("driver_receive failed: %d", rr);
320 if (is_ipc_notify(ipc_status)) {
321 switch (_ENDPOINT_P(m.m_source)) {
322 case CLOCK:
323 /* Timeout. */
324 // w_timeout(); /* a.o. set w_status */
325 mmc_log_warn(&log, "TIMEOUT\n");
326 return 1;
327 break;
328 case HARDWARE:
329 v = read32(base_address + MMCHS_SD_STAT);
330 if (v & mask) {
331 sys_setalarm(0, 0);
332 return 0;
333 } else if (v & (1 << 15)){
334 return 1; /* error */
335 } else {
336 mmc_log_debug(&log, "unexpected HW interrupt 0x%08x mask 0X%08x\n", v, mask);
337 if (sys_irqenable(&hook_id) != OK)
338 printf
339 ("Failed to re-enable irqenable irq\n");
340 continue;
341 // return 1;
343 default:
345 * unhandled message. queue it and
346 * handle it in the blockdriver loop.
348 blockdriver_mq_queue(&m, ipc_status);
350 } else {
351 mmc_log_debug(&log, "Other\n");
353 * unhandled message. queue it and handle it in the
354 * blockdriver loop.
356 blockdriver_mq_queue(&m, ipc_status);
359 sys_setalarm(0, 0); /* cancel the alarm */
361 #else
362 spin_t spin;
363 spin_init(&spin, SANE_TIMEOUT);
364 /* Wait for completion */
365 int counter =0;
366 while (1 == 1) {
367 counter ++;
368 v = read32(base_address + MMCHS_SD_STAT);
369 if (spin_check(&spin) == FALSE) {
370 mmc_log_warn(&log, "Timeout waiting for interrupt (%d) value 0x%08x mask 0x%08x\n",counter, v,mask);
371 return 1;
373 if (v & mask) {
374 return 0;
375 } else if (v & 0xFF00) {
376 mmc_log_debug(&log, "unexpected HW interrupt (%d) 0x%08x mask 0x%08x\n", v, mask);
377 return 1;
380 return 1; /* unreached */
381 #endif /* USE_INTR */
384 void
385 intr_assert(int mask)
387 if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
388 mmc_log_debug(&log, "%s, error stat %08x\n", __FUNCTION__,
389 read32(base_address + MMCHS_SD_STAT));
390 set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
391 0xffffffffu);
392 } else {
393 write32(base_address + MMCHS_SD_STAT, mask);
398 mmchs_send_cmd(uint32_t command, uint32_t arg)
401 /* Read current interrupt status and fail it an interrupt is already
402 * asserted */
404 /* Set arguments */
405 write32(base_address + MMCHS_SD_ARG, arg);
406 /* Set command */
407 set32(base_address + MMCHS_SD_CMD, MMCHS_SD_CMD_MASK, command);
409 if (intr_wait(MMCHS_SD_STAT_CC | MMCHS_SD_IE_TC_ENABLE_CLEAR)) {
410 intr_assert(MMCHS_SD_STAT_CC);
411 mmc_log_warn(&log, "Failure waiting for interrupt\n");
412 return 1;
415 if ((command & MMCHS_SD_CMD_RSP_TYPE) ==
416 MMCHS_SD_CMD_RSP_TYPE_48B_BUSY) {
418 * Command with busy response *CAN* also set the TC bit if they exit busy
420 if ((read32(base_address + MMCHS_SD_STAT)
421 & MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) {
422 mmc_log_warn(&log, "TC should be raised\n");
424 write32(base_address + MMCHS_SD_STAT,
425 MMCHS_SD_IE_TC_ENABLE_CLEAR);
427 if (intr_wait(MMCHS_SD_STAT_CC | MMCHS_SD_IE_TC_ENABLE_CLEAR)) {
428 intr_assert(MMCHS_SD_STAT_CC);
429 mmc_log_warn(&log, "Failure waiting for clear\n");
430 return 1;
433 intr_assert(MMCHS_SD_STAT_CC);
434 return 0;
438 mmc_send_cmd(struct mmc_command *c)
441 /* convert the command to a hsmmc command */
442 int ret;
443 uint32_t cmd, arg;
444 cmd = MMCHS_SD_CMD_INDX_CMD(c->cmd);
445 arg = c->args;
447 switch (c->resp_type) {
448 case RESP_LEN_48_CHK_BUSY:
449 cmd |= MMCHS_SD_CMD_RSP_TYPE_48B_BUSY;
450 break;
451 case RESP_LEN_48:
452 cmd |= MMCHS_SD_CMD_RSP_TYPE_48B;
453 break;
454 case RESP_LEN_136:
455 cmd |= MMCHS_SD_CMD_RSP_TYPE_136B;
456 break;
457 case NO_RESPONSE:
458 cmd |= MMCHS_SD_CMD_RSP_TYPE_NO_RESP;
459 break;
460 default:
461 return 1;
464 ret = mmchs_send_cmd(cmd, arg);
466 /* copy response into cmd->resp */
467 switch (c->resp_type) {
468 case RESP_LEN_48_CHK_BUSY:
469 case RESP_LEN_48:
470 c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
471 break;
472 case RESP_LEN_136:
473 c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
474 c->resp[1] = read32(base_address + MMCHS_SD_RSP32);
475 c->resp[2] = read32(base_address + MMCHS_SD_RSP54);
476 c->resp[3] = read32(base_address + MMCHS_SD_RSP76);
477 break;
478 case NO_RESPONSE:
479 break;
480 default:
481 return 1;
484 return ret;
487 static struct mmc_command command;
490 card_goto_idle_state()
492 command.cmd = MMC_GO_IDLE_STATE;
493 command.resp_type = NO_RESPONSE;
494 command.args = 0x00;
495 if (mmc_send_cmd(&command)) {
496 // Failure
497 return 1;
499 return 0;
503 card_identification()
505 command.cmd = MMC_SEND_EXT_CSD;
506 command.resp_type = RESP_LEN_48;
507 command.args = MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN;
509 if (mmc_send_cmd(&command)) {
510 // We currently only support 2.0,
511 return 1;
514 if (!(command.resp[0]
515 == (MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN))) {
516 mmc_log_warn(&log, "%s, check pattern check failed %08x\n",
517 __FUNCTION__, command.resp[0]);
518 return 1;
520 return 0;
524 card_query_voltage_and_type(struct sd_card_regs *card)
526 spin_t spin;
527 command.cmd = MMC_APP_CMD;
528 command.resp_type = RESP_LEN_48;
529 command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
531 if (mmc_send_cmd(&command)) {
532 return 1;
535 command.cmd = SD_APP_OP_COND;
536 command.resp_type = RESP_LEN_48;
538 /* 0x1 << 30 == send HCS (Host capacity support) and get OCR register */
539 command.args =
540 MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V | MMC_OCR_3_1V_3_2V |
541 MMC_OCR_3_0V_3_1V | MMC_OCR_2_9V_3_0V | MMC_OCR_2_8V_2_9V |
542 MMC_OCR_2_7V_2_8V;
543 command.args |= MMC_OCR_HCS; /* RCA=0000 */
545 if (mmc_send_cmd(&command)) {
546 return 1;
548 /* @todo wait for max 1 ms */
549 spin_init(&spin, SANE_TIMEOUT);
550 while (!(command.resp[0] & MMC_OCR_MEM_READY)) {
551 command.cmd = MMC_APP_CMD;
552 command.resp_type = RESP_LEN_48;
553 command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
554 if (mmc_send_cmd(&command)) {
555 return 1;
558 /* Send ADMD41 */
559 /* 0x1 << 30 == send HCS (Host capacity support) and get OCR
560 * register */
561 command.cmd = SD_APP_OP_COND;
562 command.resp_type = RESP_LEN_48;
563 /* 0x1 << 30 == send HCS (Host capacity support) */
564 command.args = MMC_OCR_3_3V_3_4V | MMC_OCR_3_2V_3_3V
565 | MMC_OCR_3_1V_3_2V | MMC_OCR_3_0V_3_1V | MMC_OCR_2_9V_3_0V
566 | MMC_OCR_2_8V_2_9V | MMC_OCR_2_7V_2_8V;
567 command.args |= MMC_OCR_HCS; /* RCA=0000 */
569 if (mmc_send_cmd(&command)) {
570 return 1;
573 /* if bit 31 is set the response is valid */
574 if ((command.resp[0] & MMC_OCR_MEM_READY)) {
575 break;
577 if (spin_check(&spin) == FALSE) {
578 mmc_log_warn(&log,
579 "TIMEOUT waiting for the SD card\n");
583 card->ocr = command.resp[3];
584 return 0;
588 card_identify(struct sd_card_regs *card)
591 /* Send cmd 2 (all_send_cid) and expect 136 bits response */
592 command.cmd = MMC_ALL_SEND_CID;
593 command.resp_type = RESP_LEN_136;
594 command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
596 if (mmc_send_cmd(&command)) {
597 return 1;
600 card->cid[0] = command.resp[0];
601 card->cid[1] = command.resp[1];
602 card->cid[2] = command.resp[2];
603 card->cid[3] = command.resp[3];
605 command.cmd = MMC_SET_RELATIVE_ADDR;
606 command.resp_type = RESP_LEN_48;
607 command.args = 0x0; /* RCA=0000 */
609 /* R6 response */
610 if (mmc_send_cmd(&command)) {
611 return 1;
614 card->rca = SD_R6_RCA(command.resp);
615 /* MMHCS only supports a single card so sending MMCHS_SD_CMD_CMD2 is
616 * useless Still we should make it possible in the API to support
617 * multiple cards */
619 return 0;
623 card_csd(struct sd_card_regs *card)
625 /* send_csd -> r2 response */
626 command.cmd = MMC_SEND_CSD;
627 command.resp_type = RESP_LEN_136;
628 command.args = MMC_ARG_RCA(card->rca); /* card rca */
630 if (mmc_send_cmd(&command)) {
631 return 1;
634 card->csd[0] = command.resp[0];
635 card->csd[1] = command.resp[1];
636 card->csd[2] = command.resp[2];
637 card->csd[3] = command.resp[3];
639 if (SD_CSD_CSDVER(card->csd) != SD_CSD_CSDVER_2_0) {
640 mmc_log_warn(&log, "Version 2.0 of CSD register expected\n");
641 return 1;
644 /* sanity check */
645 // mmc_log_warn(&log,"size = %llu bytes\n", (long long
646 // unsigned)SD_CSD_V2_CAPACITY( card->csd) * 512);
647 return 0;
651 select_card(struct sd_card_regs *card)
654 command.cmd = MMC_SELECT_CARD;
655 command.resp_type = RESP_LEN_48_CHK_BUSY;
656 command.args = MMC_ARG_RCA(card->rca); /* card rca */
658 if (mmc_send_cmd(&command)) {
659 return 1;
661 return 0;
665 read_single_block(struct sd_card_regs *card,
666 uint32_t blknr, unsigned char *buf)
668 uint32_t count;
669 uint32_t value;
671 count = 0;
673 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
674 MMCHS_SD_IE_BRR_ENABLE_ENABLE);
676 set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
678 /* read single block */
679 if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_READ_BLOCK_SINGLE)
680 | MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
681 | MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1) */
682 | MMCHS_SD_CMD_MSBS_SINGLE /* single block */
683 | MMCHS_SD_CMD_DDIR_READ /* read data from card */
684 , blknr)) {
685 mmc_log_warn(&log, "Error sending command\n");
686 return 1;
689 if (intr_wait(MMCHS_SD_IE_BRR_ENABLE_ENABLE)) {
690 intr_assert(MMCHS_SD_IE_BRR_ENABLE_ENABLE);
691 mmc_log_warn(&log, "Timeout waiting for interrupt\n");
692 return 1;
695 if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN)) {
696 mmc_log_warn(&log, "Problem BRE should be true\n");
697 return 1; /* We are not allowed to read data from the
698 * data buffer */
701 for (count = 0; count < 512; count += 4) {
702 value = read32(base_address + MMCHS_SD_DATA);
703 buf[count] = *((char *) &value);
704 buf[count + 1] = *((char *) &value + 1);
705 buf[count + 2] = *((char *) &value + 2);
706 buf[count + 3] = *((char *) &value + 3);
709 /* Wait for TC */
710 if (intr_wait(MMCHS_SD_IE_TC_ENABLE_ENABLE)) {
711 intr_assert(MMCHS_SD_IE_TC_ENABLE_ENABLE);
712 mmc_log_warn(&log, "Timeout waiting for interrupt\n");
713 return 1;
716 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
718 /* clear and disable the bbr interrupt */
719 write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_BRR_ENABLE_CLEAR);
720 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
721 MMCHS_SD_IE_BRR_ENABLE_DISABLE);
722 return 0;
726 write_single_block(struct sd_card_regs *card,
727 uint32_t blknr, unsigned char *buf)
729 uint32_t count;
730 uint32_t value;
732 if ((read32(base_address + MMCHS_SD_STAT) & 0xffffu)) {
733 mmc_log_warn(&log, "%s, interrupt already raised stat %08x\n",
734 __FUNCTION__, read32(base_address + MMCHS_SD_STAT));
735 write32(base_address + MMCHS_SD_STAT,
736 MMCHS_SD_IE_CC_ENABLE_CLEAR);
737 // return 1;
740 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE,
741 MMCHS_SD_IE_BWR_ENABLE_ENABLE);
742 count = 0;
744 // set32(base_address + MMCHS_SD_IE, 0xfff , 0xfff);
745 set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
747 /* write single block */
748 if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_WRITE_BLOCK_SINGLE)
749 | MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
750 | MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1b) */
751 | MMCHS_SD_CMD_MSBS_SINGLE /* single block */
752 | MMCHS_SD_CMD_DDIR_WRITE /* write to the card */
753 , blknr)) {
754 mmc_log_warn(&log, "Write single block command failed\n");
755 mmc_log_trace(&log, "STAT=(0x%08x)\n",
756 read32(base_address + MMCHS_SD_STAT));
757 return 1;
760 /* Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt */
761 if (intr_wait(MMCHS_SD_IE_BWR_ENABLE)) {
762 intr_assert(MMCHS_SD_IE_BWR_ENABLE);
763 mmc_log_warn(&log, "WFI failed\n");
764 return 1;
766 /* clear the interrupt directly */
767 intr_assert(MMCHS_SD_IE_BWR_ENABLE);
769 if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)) {
770 mmc_log_warn(&log,
771 "Error expected Buffer to be write enabled\n");
772 return 1; /* not ready to write data */
776 for (count = 0; count < 512; count += 4) {
777 while (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)){
778 mmc_log_trace(&log, "Error expected Buffer to be write enabled(%d)\n", count);
780 *((char *) &value) = buf[count];
781 *((char *) &value + 1) = buf[count + 1];
782 *((char *) &value + 2) = buf[count + 2];
783 *((char *) &value + 3) = buf[count + 3];
784 write32(base_address + MMCHS_SD_DATA, value);
788 /* Wait for TC */
789 if (intr_wait(MMCHS_SD_IE_TC_ENABLE_CLEAR)) {
790 intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
791 mmc_log_warn(&log, "(Write) Timeout waiting for transfer complete\n");
792 return 1;
794 intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
795 set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE,
796 MMCHS_SD_IE_BWR_ENABLE_DISABLE);
797 return 0;
801 mmchs_host_init(struct mmc_host *host)
803 mmchs_init(1);
804 return 0;
807 void
808 mmchs_set_log_level(int level)
810 if (level >= 0 && level <= 4) {
811 log.log_level = level;
816 mmchs_host_set_instance(struct mmc_host *host, int instance)
818 mmc_log_info(&log, "Using instance number %d\n", instance);
819 if (instance != 0) {
820 return EIO;
822 return OK;
826 mmchs_host_reset(struct mmc_host *host)
828 // mmchs_init(1);
829 return 0;
833 mmchs_card_detect(struct sd_slot *slot)
835 /* @TODO implement proper card detect */
836 return 1;
839 struct sd_card *
840 mmchs_card_initialize(struct sd_slot *slot)
842 // mmchs_init(1);
844 struct sd_card *card;
845 card = &slot->card;
846 memset(card, 0, sizeof(struct sd_card));
847 card->slot = slot;
849 if (card_goto_idle_state()) {
850 mmc_log_warn(&log, "Failed to go idle state\n");
851 return NULL;
854 if (card_identification()) {
855 mmc_log_warn(&log, "Failed to do card_identification\n");
856 return NULL;
859 if (card_query_voltage_and_type(&slot->card.regs)) {
860 mmc_log_warn(&log,
861 "Failed to do card_query_voltage_and_type\n");
862 return NULL;
864 if (card_identify(&slot->card.regs)) {
865 mmc_log_warn(&log, "Failed to identify card\n");
866 return NULL;
868 /* We have now initialized the hardware identified the card */
869 if (card_csd(&slot->card.regs)) {
870 mmc_log_warn(&log,
871 "failed to read csd (card specific data)\n");
872 return NULL;
875 if (select_card(&slot->card.regs)) {
876 mmc_log_warn(&log, "Failed to select card\n");
877 return NULL;
880 if (SD_CSD_READ_BL_LEN(slot->card.regs.csd) != 0x09) {
881 /* for CSD version 2.0 the value is fixed to 0x09 and means a
882 * block size of 512 */
883 mmc_log_warn(&log, "Block size expect to be 512\n");
884 return NULL;
887 slot->card.blk_size = 512; /* HARDCODED value */
888 slot->card.blk_count = SD_CSD_V2_CAPACITY(slot->card.regs.csd);
889 slot->card.state = SD_MODE_DATA_TRANSFER_MODE;
891 memset(slot->card.part, 0, sizeof(slot->card.part));
892 memset(slot->card.subpart, 0, sizeof(slot->card.subpart));
893 slot->card.part[0].dv_base = 0;
894 slot->card.part[0].dv_size =
895 (unsigned long long) SD_CSD_V2_CAPACITY(slot->card.regs.csd) * 512;
896 return &slot->card;
899 /* read count blocks into existing buf */
900 static int
901 mmchs_host_read(struct sd_card *card,
902 uint32_t blknr, uint32_t count, unsigned char *buf)
904 uint32_t i;
905 i = count;
906 for (i = 0; i < count; i++) {
907 read_single_block(&card->regs, blknr + i,
908 buf + (i * card->blk_size));
910 return OK;
913 /* write count blocks */
914 static int
915 mmchs_host_write(struct sd_card *card,
916 uint32_t blknr, uint32_t count, unsigned char *buf)
918 uint32_t i;
920 i = count;
921 for (i = 0; i < count; i++) {
922 write_single_block(&card->regs, blknr + i,
923 buf + (i * card->blk_size));
926 return OK;
930 mmchs_card_release(struct sd_card *card)
932 assert(card->open_ct == 1);
933 card->open_ct--;
934 card->state = SD_MODE_UNINITIALIZED;
935 /* TODO:Set card state */
936 return OK;
939 void
940 host_initialize_host_structure_mmchs(struct mmc_host *host)
942 /* Initialize the basic data structures host slots and cards */
943 int i;
945 host->host_set_instance = mmchs_host_set_instance;
946 host->host_init = mmchs_host_init;
947 host->set_log_level = mmchs_set_log_level;
948 host->host_reset = mmchs_host_reset;
949 host->card_detect = mmchs_card_detect;
950 host->card_initialize = mmchs_card_initialize;
951 host->card_release = mmchs_card_release;
952 host->hw_intr = mmchs_hw_intr;
953 host->read = mmchs_host_read;
954 host->write = mmchs_host_write;
956 /* initialize data structures */
957 for (i = 0; i < sizeof(host->slot) / sizeof(host->slot[0]); i++) {
958 // @TODO set initial card and slot state
959 host->slot[i].host = host;
960 host->slot[i].card.slot = &host->slot[i];