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; }
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; }