Пример #1
0
/* 
 * \brief Identify card
 *
 * Does currently not work! Report all card types being present, 
 * no matter what and if any card is actually inserted!
 *
 * This is according to TI TRM
 */
void mmchs_identify_card(void)
{
    // << OMAP TRM method does not work!

    // send a CMD0 command
    // TRM 24.5.1.2.1.7.1
    mmchs_send_cmd(CMD0, 0);

    // send a CMD5 command
    // XXX don't use the wrapper function    mmchs_send_cmd(CMD5);

    // Wait for CMD line to become available
    while (sdhc_ps_cmdi_rdf(&sdhc)!=0);
    // Unset STAT bits. These bits will reflect completion of command execution
    sdhc_stat_wr(&sdhc, ~0x0);
    assert (sdhc_stat_cc_rdf(&sdhc)==0x0);
    // Issue the command
    sdhc_ctm_index_wrf(&sdhc, 0x5);

    // XXX Does this detect if there is actually a card in the slot or just
    //     if the controller has the capability to read a card of that type?
    uint32_t cc, cto, run = 0;

    // Wait for completion
    do {
        cc = sdhc_stat_cc_rdf(&sdhc); 
        cto = sdhc_stat_cto_rdf(&sdhc); 
        run = 0;

        if (cc==0x1) {
            printf("SDIO card detected .. printing registers ..\n");
            assert (sdhc_stat_bada_rdf(&sdhc)==0x0);
        } else if (cto==0x1) {
            printf("No SDIO card detected .. \n");
        } else {
            run = 1;
        }
    } while(run);

    assert(sdhc_stat_bada_rdf(&sdhc)==0x0);

    // CMD line reset
    mmchs_cmd_line_reset();

    // Send a CMD8 command
    // CC value?          0x1 -> SD card
    // CMD8 needs an argument ..
    mmchs_send_cmd(CMD8, 0);
    do {
        if (sdhc_stat_cc_rdf(&sdhc)) {
            printf("SD card found .. (v 2.0 or higher)\n");        
            return;
        } else {
            printf("No SD card found .. \n");
        }
    } while (sdhc_stat_cto_rdf(&sdhc)!=0x1);

    // We do not check for other cards (i.e. SD v1.x, or unknown cards .. )
    assert(!"There is no SD v2 card in the slot .. \n");
}
Пример #2
0
int write_single_block(struct sd_card *card,
		uint32_t blknr,
		unsigned char * buf)
{
	uint32_t count;
	uint32_t value;

	count = 0;

	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE,
			MMCHS_SD_IE_BWR_ENABLE_ENABLE);
	//set32(base_address + MMCHS_SD_IE, 0xfff , 0xfff);
	set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);

	/* Set timeout */
	set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO,
			MMCHS_SD_SYSCTL_DTO_2POW27);

	if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_WRITE_BLOCK_SINGLE) /* write single block */
	| MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
	| MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1b) */
	| MMCHS_SD_CMD_MSBS_SINGLE /* single block */
	| MMCHS_SD_CMD_DDIR_WRITE /* write to the card */
	, blknr)) {
		return 1;
	}

	/* Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt */
	while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_IE_BWR_ENABLE) == 0) {
		count++;
	}

	if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)) {
		return 1; /* not ready to write data */
	}
	for (count = 0; count < 512; count += 4) {
		*((char*) &value) = buf[count];
		*((char*) &value + 1) = buf[count + 1];
		*((char*) &value + 2) = buf[count + 2];
		*((char*) &value + 3) = buf[count + 3];
		write32(base_address + MMCHS_SD_DATA, value);
	}

	/* Wait for TC */
	while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE)
			== 0) {
		count++;
	}
	write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
	write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR);/* finished.  */
	/* clear the bwr interrupt FIXME is this right when writing?*/
	write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_BWR_ENABLE_CLEAR);
	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE,
			MMCHS_SD_IE_BWR_ENABLE_DISABLE);
	return 0;
}
Пример #3
0
int read_single_block(struct sd_card *card,
		uint32_t blknr,
		unsigned char * buf)
{
	uint32_t count;
	uint32_t value;

	count = 0;

	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
			MMCHS_SD_IE_BRR_ENABLE_ENABLE);

	set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);

	if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_READ_BLOCK_SINGLE) /* read single block */
	| MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
	| MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1) */
	| MMCHS_SD_CMD_MSBS_SINGLE /* single block */
	| MMCHS_SD_CMD_DDIR_READ /* read data from card */
	, blknr)) {
		return 1;
	}

	while ((read32(base_address + MMCHS_SD_STAT)
			& MMCHS_SD_IE_BRR_ENABLE_ENABLE) == 0) {
		count++;
	}

	if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN)) {
		return 1; /* We are not allowed to read data from the data buffer */
	}

	for (count = 0; count < 512; count += 4) {
		value = read32(base_address + MMCHS_SD_DATA);
		buf[count] = *((char*) &value);
		buf[count + 1] = *((char*) &value + 1);
		buf[count + 2] = *((char*) &value + 2);
		buf[count + 3] = *((char*) &value + 3);
	}

	/* Wait for TC */

	while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE)
			== 0) {
		count++;
	}
	write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);

	/* clear and disable the bbr interrupt */
	write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_BRR_ENABLE_CLEAR);
	set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
			MMCHS_SD_IE_BRR_ENABLE_DISABLE);
	return 0;
}
Пример #4
0
/*
 * \brief Initialize and identify
 *
 * This is according to SD card spec v3, chp 3.6
 */
int mmchs_init_and_ident_card(void)
{
    // Reset card
    // XXX Keep pin 1 high during execution??
    printf("identify: cmd0\n");
    mmchs_send_cmd(0, 0);

    mmchs_wait_msec(1000);

    // Free BSD: mmc_send_if_conf [mmc.c]
    // Sets vhs, and uses 0xAA as pattern
    uint32_t cmd8arg = 0;
    sdhc_cmd8_t cp= (sdhc_cmd8_t)&cmd8arg;
    // 2.7-3.6V (seems to  be the only value allowed .. )
    sdhc_cmd8_vhs_insert(cp, 0x1);
    // Recommended pattern is: 0x1010101010
    sdhc_cmd8_pattern_insert(cp, 0xaa);
    printf("identify: cmd8\n");
    mmchs_send_cmd(8, cmd8arg);

    // Wait for result
    return mmchs_finalize_cmd();
}
Пример #5
0
int mmc_send_cmd(struct mmc_command *c)
{

	/* convert the command to a hsmmc command */
	int ret;
	uint32_t cmd, arg;
	cmd = MMCHS_SD_CMD_INDX_CMD(c->cmd);
	arg = c->args;

	switch (c->resp_type) {
		case RESP_LEN_48_CHK_BUSY:
			cmd |= MMCHS_SD_CMD_RSP_TYPE_48B_BUSY;
			break;
		case RESP_LEN_48:
			cmd |= MMCHS_SD_CMD_RSP_TYPE_48B;
			break;
		case RESP_LEN_136:
			cmd |= MMCHS_SD_CMD_RSP_TYPE_136B;
			break;
		case NO_RESPONSE:
			cmd |= MMCHS_SD_CMD_RSP_TYPE_NO_RESP;
			break;
		default:
			return 1;
	}

	ret = mmchs_send_cmd(cmd, arg);

	/* copy response into cmd->resp	 */
	switch (c->resp_type) {
		case RESP_LEN_48_CHK_BUSY:
		case RESP_LEN_48:
			c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
			break;
		case RESP_LEN_136:
			c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
			c->resp[1] = read32(base_address + MMCHS_SD_RSP32);
			c->resp[2] = read32(base_address + MMCHS_SD_RSP54);
			c->resp[3] = read32(base_address + MMCHS_SD_RSP76);
			break;
		case NO_RESPONSE:
			break;
		default:
			return 1;
	}

	return ret;
}
Пример #6
0
int
mmc_send_cmd(struct mmc_command *c)
{

	/* convert the command to a hsmmc command */
	int ret;
	uint32_t cmd, arg;
	uint32_t count;
	uint32_t value;
	cmd = MMCHS_SD_CMD_INDX_CMD(c->cmd);
	arg = c->args;

	switch (c->resp_type) {
	case RESP_LEN_48_CHK_BUSY:
		cmd |= MMCHS_SD_CMD_RSP_TYPE_48B_BUSY;
		break;
	case RESP_LEN_48:
		cmd |= MMCHS_SD_CMD_RSP_TYPE_48B;
		break;
	case RESP_LEN_136:
		cmd |= MMCHS_SD_CMD_RSP_TYPE_136B;
		break;
	case NO_RESPONSE:
		cmd |= MMCHS_SD_CMD_RSP_TYPE_NO_RESP;
		break;
	default:
		return 1;
	}

	/* read single block */
	if (c->cmd == MMC_READ_BLOCK_SINGLE) {
		cmd |= MMCHS_SD_CMD_DP_DATA;	/* Command with data transfer */
		cmd |= MMCHS_SD_CMD_MSBS_SINGLE;	/* single block */
		cmd |= MMCHS_SD_CMD_DDIR_READ;	/* read data from card */

	}

	/* write single block */
	if (c->cmd == MMC_WRITE_BLOCK_SINGLE) {
		cmd |= MMCHS_SD_CMD_DP_DATA;	/* Command with data transfer */
		cmd |= MMCHS_SD_CMD_MSBS_SINGLE;	/* single block */
		cmd |= MMCHS_SD_CMD_DDIR_WRITE;	/* write to the card */
	}

	/* check we are in a sane state */
	if ((read32(base_address + MMCHS_SD_STAT) & 0xffffu)) {
		mmc_log_warn(&log, "%s, interrupt already raised stat  %08x\n",
		    __FUNCTION__, read32(base_address + MMCHS_SD_STAT));
		write32(base_address + MMCHS_SD_STAT,
		    MMCHS_SD_IE_CC_ENABLE_CLEAR);
	}

	if (cmd & MMCHS_SD_CMD_DP_DATA) {
		if (cmd & MMCHS_SD_CMD_DDIR_READ) {
			/* if we are going to read enable the buffer ready
			 * interrupt */
			set32(base_address + MMCHS_SD_IE,
			    MMCHS_SD_IE_BRR_ENABLE,
			    MMCHS_SD_IE_BRR_ENABLE_ENABLE);
		} else {
			set32(base_address + MMCHS_SD_IE,
			    MMCHS_SD_IE_BWR_ENABLE,
			    MMCHS_SD_IE_BWR_ENABLE_ENABLE);
		}
	}

	set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);

	ret = mmchs_send_cmd(cmd, arg);

	/* copy response into cmd->resp */
	switch (c->resp_type) {
	case RESP_LEN_48_CHK_BUSY:
	case RESP_LEN_48:
		c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
		break;
	case RESP_LEN_136:
		c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
		c->resp[1] = read32(base_address + MMCHS_SD_RSP32);
		c->resp[2] = read32(base_address + MMCHS_SD_RSP54);
		c->resp[3] = read32(base_address + MMCHS_SD_RSP76);
		break;
	case NO_RESPONSE:
		break;
	default:
		return 1;
	}

	if (cmd & MMCHS_SD_CMD_DP_DATA) {
		count = 0;
		assert(c->data_len);
		if (cmd & MMCHS_SD_CMD_DDIR_READ) {
			if (intr_wait(MMCHS_SD_IE_BRR_ENABLE_ENABLE)) {
				intr_assert(MMCHS_SD_IE_BRR_ENABLE_ENABLE);
				mmc_log_warn(&log,
				    "Timeout waiting for interrupt\n");
				return 1;
			}

			if (!(read32(base_address +
				    MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN))
			{
				mmc_log_warn(&log,
				    "Problem BRE should be true\n");
				return 1;	/* We are not allowed to read
						 * data from the data buffer */
			}

			for (count = 0; count < c->data_len; count += 4) {
				value = read32(base_address + MMCHS_SD_DATA);
				c->data[count] = *((char *) &value);
				c->data[count + 1] = *((char *) &value + 1);
				c->data[count + 2] = *((char *) &value + 2);
				c->data[count + 3] = *((char *) &value + 3);
			}

			/* Wait for TC */
			if (intr_wait(MMCHS_SD_IE_TC_ENABLE_ENABLE)) {
				intr_assert(MMCHS_SD_IE_TC_ENABLE_ENABLE);
				mmc_log_warn(&log,
				    "Timeout waiting for interrupt\n");
				return 1;
			}

			write32(base_address + MMCHS_SD_STAT,
			    MMCHS_SD_IE_TC_ENABLE_CLEAR);

			/* clear and disable the bbr interrupt */
			write32(base_address + MMCHS_SD_STAT,
			    MMCHS_SD_IE_BRR_ENABLE_CLEAR);
			set32(base_address + MMCHS_SD_IE,
			    MMCHS_SD_IE_BRR_ENABLE,
			    MMCHS_SD_IE_BRR_ENABLE_DISABLE);
		} else {
			/* Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt */
			if (intr_wait(MMCHS_SD_IE_BWR_ENABLE)) {
				intr_assert(MMCHS_SD_IE_BWR_ENABLE);
				mmc_log_warn(&log, "WFI failed\n");
				return 1;
			}
			/* clear the interrupt directly */
			intr_assert(MMCHS_SD_IE_BWR_ENABLE);

			if (!(read32(base_address +
				    MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN))
			{
				mmc_log_warn(&log,
				    "Error expected Buffer to be write enabled\n");
				return 1;	/* not ready to write data */
			}

			for (count = 0; count < 512; count += 4) {
				while (!(read32(base_address +
					    MMCHS_SD_PSTATE) &
					MMCHS_SD_PSTATE_BWE_EN)) {
					mmc_log_trace(&log,
					    "Error expected Buffer to be write enabled(%d)\n",
					    count);
				}
				*((char *) &value) = c->data[count];
				*((char *) &value + 1) = c->data[count + 1];
				*((char *) &value + 2) = c->data[count + 2];
				*((char *) &value + 3) = c->data[count + 3];
				write32(base_address + MMCHS_SD_DATA, value);
			}

			/* Wait for TC */
			if (intr_wait(MMCHS_SD_IE_TC_ENABLE_CLEAR)) {
				intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
				mmc_log_warn(&log,
				    "(Write) Timeout waiting for transfer complete\n");
				return 1;
			}
			intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
			set32(base_address + MMCHS_SD_IE,
			    MMCHS_SD_IE_BWR_ENABLE,
			    MMCHS_SD_IE_BWR_ENABLE_DISABLE);

		}
	}
	return ret;
}