Ejemplo n.º 1
0
bool sdmmcShowDeviceInfo(SdmmcDriver *sdmmcp)
{
	sSdCard *pSd =&sdmmcp->card;
		TRACE_INFO("Show Device Info:\n\r");

	#ifndef SDMMC_TRIM_INFO
		const uint8_t card_type = sdmmcp->card.bCardType;
		TRACE_INFO_1("Card Type: %d\n\r", card_type);
	#endif
		TRACE_INFO("Dumping Status ... \n\r");
		SD_DumpStatus(pSd);
	#ifndef SDMMC_TRIM_INFO
		if (card_type & CARD_TYPE_bmSDMMC)
			SD_DumpCID(pSd);
		if (card_type & CARD_TYPE_bmSD) {
			SD_DumpSCR(pSd->SCR);
			SD_DumpSSR(pSd->SSR);
		}
		if (card_type & CARD_TYPE_bmSDMMC)
			SD_DumpCSD(pSd);
	#ifndef SDMMC_TRIM_MMC
		if (card_type & CARD_TYPE_bmMMC)
			SD_DumpExtCSD(pSd->EXT);
	#endif
	#ifndef SDMMC_TRIM_SDIO
		if (card_type & CARD_TYPE_bmSDIO)
			SDIO_DumpCardInformation(sdmmcp);
	#endif

	#endif
		return true;
}
Ejemplo n.º 2
0
static uint32_t handle_cmd_initialize(uint32_t cmd, uint32_t *mailbox)
{
	union initialize_mailbox *mbx = (union initialize_mailbox*)mailbox;
	uint32_t instance = mbx->in.parameters[0];
	uint32_t boot_partition = mbx->in.parameters[1];
	uint32_t bus_width = mbx->in.parameters[2];
	uint32_t supported_voltages = mbx->in.parameters[3];
	const struct sdmmc_pin_definition* instance_def;
	uint32_t max_bus_width, sdmmc_id, caps0;
	uint8_t rc, card_type;

	assert(cmd == APPLET_CMD_INITIALIZE);

	applet_set_init_params(mbx->in.comm_type, mbx->in.trace_level);
	initialized = false;

	trace_info_wp("\r\nApplet 'SD/MMC' from "
			"softpack " SOFTPACK_VERSION ".\r\n");

	if (bus_width != 0 && bus_width != 1 &&
			bus_width != 4 && bus_width != 8) {
		trace_error_wp("Invalid configuration: Unsupported bus width %u\r\n",
			(unsigned)bus_width);
		return APPLET_FAIL;
	}

	if (!supported_voltages || (supported_voltages & ~SUPPORTED_VOLTAGE_MASK)) {
		trace_error_wp("Invalid supported voltages value: 0x%x\r\n",
			(unsigned)supported_voltages);
		return APPLET_FAIL;
	}

	instance_def = find_instance(instance);
	if (!instance_def) {
		trace_error_wp("Invalid configuration: SDMMC%u\r\n",
			(unsigned)instance);
		return APPLET_FAIL;
	}

	max_bus_width = get_max_bus_width(instance_def);
	if (!bus_width) {
		bus_width = max_bus_width;
	} else if (bus_width > max_bus_width) {
		trace_error_wp("Invalid configuration: SDMMC%u Bus Width %u\r\n",
			(unsigned)instance, (unsigned)bus_width);
		return APPLET_FAIL;
	}

	if (boot_partition > 2) {
		trace_error_wp("Invalid configuration: Unknown partition %u\r\n",
			(unsigned)boot_partition);
		return APPLET_FAIL;
	}

	trace_info_wp("Initializing SDMMC%u", (unsigned)instance);
	if (boot_partition)
		trace_info_wp(", boot partition %u",
				(unsigned)boot_partition);
	else
		trace_info_wp(", user partition");
	if (bus_width == 1)
		trace_info_wp(", 1-bit");
	else if (bus_width == 4)
		trace_info_wp(", 4-bit");
	else if (bus_width == 8)
		trace_info_wp(", 8-bit");
	trace_info_wp(", %s",
			get_supported_voltage_string(supported_voltages));
	trace_info_wp("\r\n");

	/* Configure PIO */
	configure_instance_pio(instance_def, bus_width, supported_voltages);

	/* The SDMMC peripherals are clocked by their Peripheral Clock, the
	 * Master Clock, and a Generated Clock (at least on SAMA5D2x).
	 * Configure GCLKx = <PLLA clock> divided by 1
	 * As of writing, the PLLA clock runs at 498 MHz */
	sdmmc_id = get_sdmmc_id_from_addr(instance_def->addr);
	pmc_configure_gck(sdmmc_id, PMC_PCR_GCKCSS_PLLA_CLK, 1 - 1);
	pmc_enable_gck(sdmmc_id);
	pmc_enable_peripheral(sdmmc_id);

	// set SDMMC controller capabilities
	caps0 = SDMMC_CA0R_SLTYPE_EMBEDDED;
	if (bus_width == 8)
		caps0 |= SDMMC_CA0R_ED8SUP;
	if (supported_voltages & SUPPORTED_VOLTAGE_18V)
		caps0 |= SDMMC_CA0R_V18VSUP;
	if (supported_voltages & SUPPORTED_VOLTAGE_30V)
		caps0 |= SDMMC_CA0R_V30VSUP;
	if (supported_voltages & SUPPORTED_VOLTAGE_33V)
		caps0 |= SDMMC_CA0R_V33VSUP;
	sdmmc_set_capabilities(instance_def->addr,
			caps0, CAPS0_MASK, 0, 0);

	sdmmc_initialize(&drv, instance_def->addr, sdmmc_id,
			TIMER0_MODULE, TIMER0_CHANNEL, NULL, 0);

	SDD_InitializeSdmmcMode(&lib, &drv, 0);
	if (SD_GetStatus(&lib) == SDMMC_NOT_SUPPORTED) {
		trace_error_wp("Device not detected.\n\r");
		return APPLET_FAIL;
	}

	rc = SD_Init(&lib);
	if (rc != SDMMC_OK) {
		trace_error_wp("SD/MMC device initialization failed: %d\n\r", rc);
		return APPLET_FAIL;
	}

	card_type = SD_GetCardType(&lib);
	if (!(card_type & CARD_TYPE_bmSDMMC)) {
		trace_error_wp("Invalid card type: only SD/MMC is supported\n\r");
		return APPLET_FAIL;
	}

	SD_DumpStatus(&lib);

	if (boot_partition) {
		/* check that card is MMC */
		if (!(card_type & CARD_TYPE_bmMMC)) {
			trace_error_wp("Invalid card type: boot partition in only supported on MMC\n\r");
			return APPLET_FAIL;
		}

		/* get and check boot partition size */
		mem_size = MMC_EXT_BOOT_SIZE_MULTI(lib.EXT) * (128 * 1024 / BLOCK_SIZE);
		if (mem_size == 0) {
			trace_error_wp("No boot partition available\n\r");
			return APPLET_FAIL;
		}

		/* configure boot partition */
		mmc_configure_partition(&lib, EMMC_BOOT_PARTITION_ACCESS(boot_partition) |
		                              EMMC_BOOT_PARTITION_ENABLE(boot_partition) |
		                              EMMC_BOOT_ACK);
		mmc_configure_boot_bus(&lib, 0);
	} else {
		mem_size = SD_GetTotalSizeKB(&lib) * 1024 / BLOCK_SIZE;
	}

	buffer = applet_buffer;
	buffer_size = applet_buffer_size & ~(BLOCK_SIZE - 1);
	if (buffer_size == 0) {
		trace_info_wp("Not enough memory for buffer\r\n");
		return APPLET_FAIL;
	}

	mbx->out.buf_addr = (uint32_t)buffer;
	mbx->out.buf_size = buffer_size;
	mbx->out.page_size = BLOCK_SIZE;
	mbx->out.erase_support = 0;
	mbx->out.mem_size = mem_size;

	trace_info_wp("SD/MMC device initialization successful\n\r");
	trace_info_wp("Buffer Address: 0x%lx\r\n", mbx->out.buf_addr);
	trace_info_wp("Buffer Size: %ld bytes\r\n", mbx->out.buf_size);
	trace_info_wp("Page Size: %ld bytes\r\n", mbx->out.page_size);
	trace_info_wp("Memory Size: %ld pages\r\n", mbx->out.mem_size);

	initialized = true;
	return APPLET_SUCCESS;
}