Esempio n. 1
0
static sdmmc_rt sdmmc_acmd(int nr, uint32_t arg) {
	sdmmc_rt r;

	r = sdmmc_cmd(CMD55R1_APP_CMD, sd_sm->rca << 16);
	if (r != SDMMC_OK) {
		printk("SDMMC status = 0x%.8X\n", sdmmc_resp());
		return r;
	}

	//sdmmc_print_r1();

	return sdmmc_cmd(nr, arg);
}
Esempio n. 2
0
static sdmmc_rt CMD1(void) {
	sdmmc_rt r;
	uint32_t ocr, msk;

	ocr = OCR_VOLTAGE_WINDOW(BUS_POWER_VOLTAGE);
	msk = OCR_PowerUpEnd;
	do {
		r = sdmmc_cmd(CMD1R3_SEND_OP_COND, ocr & ~OCR_PowerUpEnd);
		if (r != SDMMC_OK) {
			printk("MMCPROT\tcards with non compatible voltage range\n");
			return r;
		}
		ocr = sdmmc_resp();
		if ((ocr & msk) == msk) break;

		printk("MMCPROT\tcard is busy or\n");
		printk("\thost omitted voltage range\n");
		sd_sm->ci_stat = SDP_IDLE;
	} while (AM18X_TRUE);

	if (ocr & MOCR_VOLTAGE_165to195) {
		printk("MMCPROT\tLow Voltage MultiMediaCard\n");
	} else {
		printk("MMCPROT\tHigh Voltage MultiMediaCard\n");
	}

	printk("%s() ocr = 0x%.8X\n", __func__, ocr);

	if (0 == (ocr & OCR_VOLTAGE_WINDOW(BUS_POWER_VOLTAGE))) {
		return SDMMC_UNSUP;
	}
	return SDMMC_OK;
}
int sdmmc_write_multiple_blocks(uint32_t address, uint32_t n_blocks, uint8_t (*next_byte)())
{
	int result;
	int i;

	if ((result = sdmmc_cmd(25, block_addressing ? address : address << 9)) < 0) {
		cs_high();
		return result;
	}

	spi(0xff);							// initiate write

	while (n_blocks--) {
		spi(0xfc);						// data token
		for (i = 0; i < 512; i++) {		// sector data
			spi(next_byte());
		}
		spi(0xff);						// CRC
		spi(0xff);
		result = spi(0xff);				// data response
		if ((result & 0x1f) != 0x05) {
			cs_high();
			return result;
		}
		i = 0;
		do {							// wait while card is busy
			if (++i == 131072) {
				cs_high();
				return -10;
			}
		} while (spi(0xff) != 0xff);
	}

	return sdmmc_stop_transmission();
}
int sdmmc_read_block(uint32_t address, uint8_t *buffer)
{
	int i;
	int result;

	// CMD17 - READ_SINGLE_BLOCK
	result = sdmmc_cmd(17, block_addressing ? address : address << 9);
	if (result < 0) {
		cs_high();
		return -1;
	}

	// wait for data token
	for (i = 0; i < TOKEN_COUNT; i++) {
		if (spi(0xff) == 0xfe) {
			break;
		}
	}
	if (i == TOKEN_COUNT) {
		return -2;
	}

	// read data
	for (i = 0; i < 512; i++) {
		*buffer++ = spi(0xff);
	}
	
	// skip CRC
	spi(0xff);
	spi(0xff);

	sdmmc_cmd_term();

	return 0;
}
int sdmmc_stop_transmission()
{
	int result;

	if ((result = sdmmc_cmd(12, 0)) < 0) {
		while (spi(0xff) != 0xff);
		cs_high();
		return result;
	}
	return 0;
}
int sdmmc_read_multiple_blocks_start(uint32_t address)
{
	int result;

	if ((result = sdmmc_cmd(18, block_addressing ? address : address << 9)) < 0) {
		cs_high();
		return result;
	}

	return 0;
}
Esempio n. 7
0
// Protocol
// 4.2.3 Card Initialization and Identification Process
static sdmmc_rt sdmmc_card_init(void) {
	sdmmc_rt r;
	int i;

	sd_sm->rca = 0;
	sd_sm->is_mmc = 0;
	sd_sm->is_bus4bit = 0;
	sd_sm->ci_stat = SDP_IDLE;

	for (i = 0; i < 1000; i++);

	sdmmc_cmd_noarg(CMD0_GO_IDLE_STATE);
	printk("SDPROT\tIdle State(idle)\n");

	r = sdmmc_cmd(CMD8R7_SEND_IF_COND, CMD8_VHS_27to36 | CMD8_CHECK_PATTERN);
	printk("SDMMC cmd8() %s\n", sdmmc_err_string(r));

	if (r == SDMMC_NO_RSP) {
		printk("SDPROT\tVer2.00 or later SD Memory Card(voltage mismatch)\n");
		printk("\tor Ver1.X SD Memory Card\n");
		printk("\tor not SD Memory Card\n");
	} else if ((sdmmc_resp() & CMD8_CHECK_PATTERN_MASK) == CMD8_CHECK_PATTERN) {
		printk("SDPROT\tVer2.00 or later SD Memory Card\n");
	} else {
		// unsupported
		return SDMMC_UNSUP;
	}

	if ((r = ACMD41()) == SDMMC_OK) {
		printk("SDPROT\tCard returns ready\n");
		printk("\tVer1.X Standard Capacity SD Memory Card\n");
	} else {
		printk("SDPROT\tNo Response(Non valid command)\n");
		printk("\tMust be a MultiMediaCard\n");
		printk("SDPORT\tStart MultiMediaCard initialization process\n");
		printk("\tstarting at CMD1\n");

		if ((r = CMD1()) != SDMMC_OK) {
			return r;
		}
		sd_sm->is_mmc = 1;
		sd_sm->rca = MMC_RCA;
	}

	printk("SDPROT\tReady State(ready)\n");

	for (i = 0; i < SDMMC_CMD_RETRY; i++) {
		r = sdmmc_cmd_noarg(CMD2R2_ALL_SEND_CID);
		if (r == SDMMC_OK) break;
	}
	if (r != SDMMC_OK) {
		return r;
	}
	printk("SDPROT\tIdentification State(ident)\n");

	sdmmc_get_cid();
	// sdprot_print_cid(&sd_sm->cid);

	for (i = 0; i < SDMMC_CMD_RETRY; i++) {
		uint32_t arg = 0;

		if (sd_sm->is_mmc) {
			arg = sd_sm->rca << 16;
		}
		r = sdmmc_cmd(CMD3R6_SEND_RELATIVE, arg);
		if (r == SDMMC_OK) break;
	}
	if (r != SDMMC_OK) {
		return r;
	}

	printk("SDPROT\tCard responds with new RCA\n");

	if (!sd_sm->is_mmc) {
		sd_sm->rca = (sdmmc_resp() >> 16);
	}
Esempio n. 8
0
static inline sdmmc_rt sdmmc_cmd_noarg(int nr) {
	return sdmmc_cmd(nr, SDMMC_ARG_NULL);
}
int sdmmc_init()
{
	int i;
	int result;

	// send > 74 clock pulses with CS = DI = 1
	cs_high();
	for (i = 0; i < 10; i++) {
		spi(0xff);
	}

	// CMD0 - GO_IDLE_STATE
	result = sdmmc_cmd(0, 0);
	sdmmc_cmd_term();
	if (result != 0x01) {
		return -1;
	}

	// CMD8 - SEND_IF_COND
	result = sdmmc_cmd(8, 0x1aa);
	if (result != 0x01) {
		// TODO: initialize SD v1 or MMC v3
		sdmmc_cmd_term();
		return -2;
	}
	if ((result = sdmmc_read_word()) != 0x1aa) {
		sdmmc_cmd_term();
		return -3;
	}
	sdmmc_cmd_term();

	for (i = 0; i < CMD41_COUNT; i++) {
		// CMD55 - APP_CMD
		result = sdmmc_cmd(55, 0);
		sdmmc_cmd_term();
		if (result < 0) {
			return -5;
		}

		// CMD41 - APP_SEND_OP_COND
		result = sdmmc_cmd(41, 0x40000000);
		sdmmc_cmd_term();
		if (result == 0x00) {
			break;
		} else if (result != 0x01) {
			return -6;
		}
	}
	if (i == CMD41_COUNT) {
		return -7;
	}

	// CMD58 - READ_OCR
	result = sdmmc_cmd(58, 0);
	if (result < 0) {
		sdmmc_cmd_term();
		return -8;
	}
	if ((result = sdmmc_read_word()) & 0x40000000) {
		block_addressing = 1;
	} else {
		block_addressing = 0;
		sdmmc_cmd_term();
		// CMD16 - SET_BLOCK_LEN (512 bytes)
		result = sdmmc_cmd(16, 512);
		if (result < 0) {
			sdmmc_cmd_term();
			return -9;
		}
	}
	sdmmc_cmd_term();

	return 0;
}