static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) { unsigned int bus_speed = 0, timing = 0; int err; /* * If the host doesn't support any of the UHS-I modes, fallback on * default speed. */ if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) return 0; if ((card->host->caps & MMC_CAP_UHS_SDR104) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) { bus_speed = UHS_SDR104_BUS_SPEED; timing = MMC_TIMING_UHS_SDR104; card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { bus_speed = UHS_DDR50_BUS_SPEED; timing = MMC_TIMING_UHS_DDR50; card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50)) { bus_speed = UHS_SDR50_BUS_SPEED; timing = MMC_TIMING_UHS_SDR50; card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { bus_speed = UHS_SDR25_BUS_SPEED; timing = MMC_TIMING_UHS_SDR25; card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR12)) { bus_speed = UHS_SDR12_BUS_SPEED; timing = MMC_TIMING_UHS_SDR12; card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; } card->sd_bus_speed = bus_speed; err = mmc_sd_switch(card, 1, 0, bus_speed, status); if (err) return err; if ((status[16] & 0xF) != bus_speed) { printk(KERN_WARNING "%s: Problem setting bus speed mode!\n", mmc_hostname(card->host)); } else { mmc_set_timing(card->host, timing); mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr); } return 0; }
/* * Test if the card supports high-speed mode and, if so, switch to it. */ static int mmc_switch_hs(struct mmc_request *request) { unsigned int status[64 / 4]; mmc_sd_switch(request, 1, 0, 1, (unsigned char *) status); return 0; }
static int mmc_set_timing(struct mmc_softc *sc, int timing) { int err; uint8_t value; u_char switch_res[64]; switch (timing) { case bus_timing_normal: value = 0; break; case bus_timing_hs: value = 1; break; default: return (MMC_ERR_INVALID); } if (mmcbr_get_mode(sc->dev) == mode_sd) err = mmc_sd_switch(sc, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1, value, switch_res); else err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, value); return (err); }
/* * Fetches and decodes switch information */ static int mmc_read_switch(struct mmc_card *card) { int err; u8 *status; #if defined(CONFIG_AMBARELLA_IPC) && defined(CONFIG_MMC_AMBARELLA) && !defined(CONFIG_NOT_SHARE_SD_CONTROLLER_WITH_UITRON) struct ipc_sdinfo *sdinfo = ambarella_sd_get_sdinfo(card->host); if (sdinfo->from_ipc && sdinfo->is_init) { card->sw_caps.hs_max_dtr = 50000000; return 0; } #endif if (card->scr.sda_vsn < SCR_SPEC_VER_1) return 0; if (!(card->csd.cmdclass & CCC_SWITCH)) { printk(KERN_WARNING "%s: card lacks mandatory switch " "function, performance might suffer.\n", mmc_hostname(card->host)); return 0; } err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); return -ENOMEM; } err = mmc_sd_switch(card, 0, 0, 1, status); if (err) { /* If the host or the card can't do the switch, * fail more gracefully. */ if ((err != -EINVAL) && (err != -ENOSYS) && (err != -EFAULT)) goto out; printk(KERN_WARNING "%s: problem reading switch " "capabilities, performance might suffer.\n", mmc_hostname(card->host)); err = 0; goto out; } if (status[13] & 0x02) card->sw_caps.hs_max_dtr = 50000000; out: kfree(status); return err; }
/* * Test if the card supports high-speed mode and, if so, switch to it. */ static int mmc_switch_hs(struct mmc_card *card) { int err; u8 *status; DBG("[%s] s\n",__func__); if (card->scr.sda_vsn < SCR_SPEC_VER_1) { DBG("[%s] e1\n",__func__); return 0; } if (!(card->csd.cmdclass & CCC_SWITCH)) { DBG("[%s] e2\n",__func__); return 0; } if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) { DBG("[%s] e3\n",__func__); return 0; } if (card->sw_caps.hs_max_dtr == 0) { DBG("[%s] e4\n",__func__); return 0; } err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); DBG("[%s] e5\n",__func__); return -ENOMEM; } err = mmc_sd_switch(card, 1, 0, 1, status); if (err) goto out; if ((status[16] & 0xF) != 1) { printk(KERN_WARNING "%s: Problem switching card " "into high-speed mode!\n", mmc_hostname(card->host)); } else { mmc_card_set_highspeed(card); mmc_set_timing(card->host, MMC_TIMING_SD_HS); } out: kfree(status); DBG("[%s] e6\n",__func__); return err; }
/* * Fetches and decodes switch information */ static int mmc_read_switch(struct mmc_card *card) { int err; u8 *status; DBG("[%s] s\n",__func__); if (card->scr.sda_vsn < SCR_SPEC_VER_1) { DBG("[%s] e\n",__func__); return 0; } if (!(card->csd.cmdclass & CCC_SWITCH)) { printk(KERN_WARNING "%s: card lacks mandatory switch " "function, performance might suffer.\n", mmc_hostname(card->host)); DBG("[%s] e1\n",__func__); return 0; } err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); DBG("[%s] e2\n",__func__); return -ENOMEM; } err = mmc_sd_switch(card, 0, 0, 1, status); if (err) { /* If the host or the card can't do the switch, * fail more gracefully. */ if ((err != -EINVAL) && (err != -ENOSYS) && (err != -EFAULT)) goto out; printk(KERN_WARNING "%s: problem reading switch " "capabilities, performance might suffer.\n", mmc_hostname(card->host)); err = 0; goto out; } if (status[13] & 0x02) card->sw_caps.hs_max_dtr = 50000000; out: kfree(status); DBG("[%s] e3\n",__func__); return err; }
/* * Fetches and decodes switch information */ static int mmc_read_switch(struct mmc_request *request) { unsigned int status[64 / 4]; memset ((unsigned char *)status,0,64); mmc_sd_switch(request, 0, 0, 1, (unsigned char *) status); if (((unsigned char *)status)[13] & 0x02) return 0; else return 1; }
static int sd_select_driver_type(struct mmc_card *card, u8 *status) { int host_drv_type = 0, card_drv_type = 0; int err; /* * If the host doesn't support any of the Driver Types A,C or D, * default Driver Type B is used. */ if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C | MMC_CAP_DRIVER_TYPE_D))) return 0; if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) { host_drv_type = MMC_SET_DRIVER_TYPE_A; if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) card_drv_type = MMC_SET_DRIVER_TYPE_A; else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B) card_drv_type = MMC_SET_DRIVER_TYPE_B; else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) card_drv_type = MMC_SET_DRIVER_TYPE_C; } else if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) { host_drv_type = MMC_SET_DRIVER_TYPE_C; if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) card_drv_type = MMC_SET_DRIVER_TYPE_C; } else if (!(card->host->caps & MMC_CAP_DRIVER_TYPE_D)) { /* * If we are here, that means only the default driver type * B is supported by the host. */ host_drv_type = MMC_SET_DRIVER_TYPE_B; if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B) card_drv_type = MMC_SET_DRIVER_TYPE_B; else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) card_drv_type = MMC_SET_DRIVER_TYPE_C; } err = mmc_sd_switch(card, 1, 2, card_drv_type, status); if (err) return err; if ((status[15] & 0xF) != card_drv_type) { printk(KERN_WARNING "%s: Problem setting driver strength!\n", mmc_hostname(card->host)); return 0; } mmc_set_driver_type(card->host, host_drv_type); return 0; }
/* * Test if the card supports high-speed mode and, if so, switch to it. */ int mmc_sd_switch_hs(struct mmc_card *card) { int err; u8 *status; #if defined(CONFIG_AMBARELLA_IPC) && defined(CONFIG_MMC_AMBARELLA) && !defined(CONFIG_NOT_SHARE_SD_CONTROLLER_WITH_UITRON) struct ipc_sdinfo *sdinfo = ambarella_sd_get_sdinfo(card->host); if (sdinfo->from_ipc) return 0; #endif if (card->scr.sda_vsn < SCR_SPEC_VER_1) return 0; if (!(card->csd.cmdclass & CCC_SWITCH)) return 0; if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) return 0; if (card->sw_caps.hs_max_dtr == 0) return 0; err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); return -ENOMEM; } err = mmc_sd_switch(card, 1, 0, 1, status); if (err) goto out; if ((status[16] & 0xF) != 1) { printk(KERN_WARNING "%s: Problem switching card " "into high-speed mode!\n", mmc_hostname(card->host)); err = 0; } else { err = 1; } out: kfree(status); return err; }
/* * Fetches and decodes switch information */ static int mmc_read_switch(struct mmc_card *card) { int err; u8 *status; if (card->scr.sda_vsn < SCR_SPEC_VER_1) return 0; if (!(card->csd.cmdclass & CCC_SWITCH)) { printk(KERN_WARNING "%s: card lacks mandatory switch " "function, performance might suffer.\n", mmc_hostname(card->host)); return 0; } err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); return -ENOMEM; } err = mmc_sd_switch(card, 0, 0, 1, status); if (err) { /* * We all hosts that cannot perform the command * to fail more gracefully */ if (err != -EINVAL) goto out; printk(KERN_WARNING "%s: problem reading switch " "capabilities, performance might suffer.\n", mmc_hostname(card->host)); err = 0; goto out; } if (status[13] & 0x02) card->sw_caps.hs_max_dtr = 50000000; out: kfree(status); return err; }
/* * Test if the card supports high-speed mode and, if so, switch to it. */ static int mmc_switch_hs(struct mmc_card *card) { int err; u8 *status; if (card->scr.sda_vsn < SCR_SPEC_VER_1) return 0; if (!(card->csd.cmdclass & CCC_SWITCH)) return 0; if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) return 0; if (card->sw_caps.hs_max_dtr == 0) return 0; /* LIBtt04854 : All of 2GB sd card set to 24Mhz */ if (card->csd.read_blkbits == 10) return 0; err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); return -ENOMEM; } err = mmc_sd_switch(card, 1, 0, 1, status); if (err) goto out; if ((status[16] & 0xF) != 1) { printk(KERN_WARNING "%s: Problem switching card " "into high-speed mode!\n", mmc_hostname(card->host)); } else { mmc_card_set_highspeed(card); mmc_set_timing(card->host, MMC_TIMING_SD_HS); } out: kfree(status); return err; }
/* * Test if the card supports high-speed mode and, if so, switch to it. */ int mmc_sd_switch_hs(struct mmc_card *card) { int err; u8 *status; if (card->scr.sda_vsn < SCR_SPEC_VER_1) return 0; if (!(card->csd.cmdclass & CCC_SWITCH)) return 0; if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) return 0; if (card->sw_caps.hs_max_dtr == 0) return 0; err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); return -ENOMEM; } err = mmc_sd_switch(card, 1, 0, 1, status); if (err) goto out; if ((status[16] & 0xF) != 1) { printk(KERN_WARNING "%s: Problem switching card " "into high-speed mode!\n", mmc_hostname(card->host)); err = 0; } else { err = 1; } out: kfree(status); return err; }
static int check_assd(struct mmc_host *host, int mode, int func) { int ret = 0; struct mmc_card *card; BUG_ON(!host); pr_debug("assd: check_assd()\n"); mmc_claim_host(host); card = host->card; if (card == NULL) { ret = -ENODEV; goto out; } /* * SD memory cards compatible with versions earlier than 1.10 do not * support the Switch function command. */ if (!card->scr.sda_vsn) { ret = -ENODEV; goto out; } /* * See [1] chapter "Switch Function Command" for information * about modes, groups, and functions. */ mmc_sd_switch(card, mode, GROUP_2, func, assd_block); /* * We verify the response only if we switched to a non-default * function. */ if (func) { /* * See [1] chapter "Switch Function Status" for information * about the status bits. The function was successfully * switched if bits 383:380 hold the function number, * and in bits 431:416 the function group information show * that our function is supported. */ if (!(assd_block[11] & (1 << func))) { ret = -ENODEV; goto out; } if ((assd_block[16] & 0xf0) != (func << 4)) { ret = -ENODEV; if (assd_block[27] & (1 << func)) ret = -EBUSY; } } out: mmc_release_host(host); return ret; }
/* * Fetches and decodes switch information */ static int mmc_read_switch(struct mmc_card *card) { int err; u8 *status; if (card->scr.sda_vsn < SCR_SPEC_VER_1) return 0; if (!(card->csd.cmdclass & CCC_SWITCH)) { printk(KERN_WARNING "%s: card lacks mandatory switch " "function, performance might suffer.\n", mmc_hostname(card->host)); return 0; } err = -EIO; status = kmalloc(64, GFP_KERNEL); if (!status) { printk(KERN_ERR "%s: could not allocate a buffer for " "switch capabilities.\n", mmc_hostname(card->host)); return -ENOMEM; } /* Find out the supported Bus Speed Modes. */ err = mmc_sd_switch(card, 0, 0, 1, status); if (err) { /* * If the host or the card can't do the switch, * fail more gracefully. */ if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) goto out; printk(KERN_WARNING "%s: problem reading Bus Speed modes.\n", mmc_hostname(card->host)); err = 0; goto out; } if (card->scr.sda_spec3) { card->sw_caps.sd3_bus_mode = status[13]; /* Find out Driver Strengths supported by the card */ err = mmc_sd_switch(card, 0, 2, 1, status); if (err) { /* * If the host or the card can't do the switch, * fail more gracefully. */ if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) goto out; printk(KERN_WARNING "%s: problem reading " "Driver Strength.\n", mmc_hostname(card->host)); err = 0; goto out; } card->sw_caps.sd3_drv_type = status[9]; /* Find out Current Limits supported by the card */ err = mmc_sd_switch(card, 0, 3, 1, status); if (err) { /* * If the host or the card can't do the switch, * fail more gracefully. */ if (err != -EINVAL && err != -ENOSYS && err != -EFAULT) goto out; printk(KERN_WARNING "%s: problem reading " "Current Limit.\n", mmc_hostname(card->host)); err = 0; goto out; } card->sw_caps.sd3_curr_limit = status[7]; } if (status[13] & 0x02) card->sw_caps.hs_max_dtr = 50000000; out: kfree(status); return err; }
static int sd_select_driver_type(struct mmc_card *card, u8 *status) { int host_drv_type = SD_DRIVER_TYPE_B; int card_drv_type = SD_DRIVER_TYPE_B; int drive_strength; int err; /* * If the host doesn't support any of the Driver Types A,C or D, * or there is no board specific handler then default Driver * Type B is used. */ if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C | MMC_CAP_DRIVER_TYPE_D))) return 0; if (!card->host->ops->select_drive_strength) return 0; if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) host_drv_type |= SD_DRIVER_TYPE_A; if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) host_drv_type |= SD_DRIVER_TYPE_C; if (card->host->caps & MMC_CAP_DRIVER_TYPE_D) host_drv_type |= SD_DRIVER_TYPE_D; if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) card_drv_type |= SD_DRIVER_TYPE_A; if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) card_drv_type |= SD_DRIVER_TYPE_C; if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D) card_drv_type |= SD_DRIVER_TYPE_D; /* * The drive strength that the hardware can support * depends on the board design. Pass the appropriate * information and let the hardware specific code * return what is possible given the options */ drive_strength = card->host->ops->select_drive_strength( card->sw_caps.uhs_max_dtr, host_drv_type, card_drv_type); err = mmc_sd_switch(card, 1, 2, drive_strength, status); if (err) return err; if ((status[15] & 0xF) != drive_strength) { printk(KERN_WARNING "%s: Problem setting drive strength!\n", mmc_hostname(card->host)); return 0; } mmc_set_driver_type(card->host, drive_strength); return 0; }
static void mmc_discover_cards(struct mmc_softc *sc) { struct mmc_ivars *ivar = NULL; device_t *devlist; int err, i, devcount, newcard; uint32_t raw_cid[4]; uint32_t resp, sec_count; device_t child; uint16_t rca = 2; u_char switch_res[64]; if (bootverbose || mmc_debug) device_printf(sc->dev, "Probing cards\n"); while (1) { err = mmc_all_send_cid(sc, raw_cid); if (err == MMC_ERR_TIMEOUT) break; if (err != MMC_ERR_NONE) { device_printf(sc->dev, "Error reading CID %d\n", err); break; } newcard = 1; if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) return; for (i = 0; i < devcount; i++) { ivar = device_get_ivars(devlist[i]); if (memcmp(ivar->raw_cid, raw_cid, sizeof(raw_cid)) == 0) { newcard = 0; break; } } free(devlist, M_TEMP); if (bootverbose || mmc_debug) { device_printf(sc->dev, "%sard detected (CID %08x%08x%08x%08x)\n", newcard ? "New c" : "C", raw_cid[0], raw_cid[1], raw_cid[2], raw_cid[3]); } if (newcard) { ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF, M_WAITOK | M_ZERO); if (!ivar) return; memcpy(ivar->raw_cid, raw_cid, sizeof(raw_cid)); } if (mmcbr_get_ro(sc->dev)) ivar->read_only = 1; ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; ivar->mode = mmcbr_get_mode(sc->dev); if (ivar->mode == mode_sd) { mmc_decode_cid_sd(ivar->raw_cid, &ivar->cid); mmc_send_relative_addr(sc, &resp); ivar->rca = resp >> 16; /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); mmc_decode_csd_sd(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; if (ivar->csd.csd_structure > 0) ivar->high_cap = 1; ivar->tran_speed = ivar->csd.tran_speed; ivar->erase_sector = ivar->csd.erase_sector * ivar->csd.write_bl_len / MMC_SECTOR_SIZE; /* Get card SCR. Card must be selected to fetch it. */ mmc_select_card(sc, ivar->rca); mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); mmc_app_decode_scr(ivar->raw_scr, &ivar->scr); /* Get card switch capabilities (command class 10). */ if ((ivar->scr.sda_vsn >= 1) && (ivar->csd.ccc & (1<<10))) { mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK, SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE, switch_res); if (switch_res[13] & 2) { ivar->timing = bus_timing_hs; ivar->hs_tran_speed = SD_MAX_HS; } } mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status); mmc_app_decode_sd_status(ivar->raw_sd_status, &ivar->sd_status); if (ivar->sd_status.au_size != 0) { ivar->erase_sector = 16 << ivar->sd_status.au_size; } mmc_select_card(sc, 0); /* Find max supported bus width. */ if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) ivar->bus_width = bus_width_4; if (bootverbose || mmc_debug) mmc_log_card(sc->dev, ivar, newcard); if (newcard) { /* Add device. */ child = device_add_child(sc->dev, NULL, -1); device_set_ivars(child, ivar); } return; } mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid); ivar->rca = rca++; mmc_set_relative_addr(sc, ivar->rca); /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); mmc_decode_csd_mmc(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; ivar->tran_speed = ivar->csd.tran_speed; ivar->erase_sector = ivar->csd.erase_sector * ivar->csd.write_bl_len / MMC_SECTOR_SIZE; /* Only MMC >= 4.x cards support EXT_CSD. */ if (ivar->csd.spec_vers >= 4) { /* Card must be selected to fetch EXT_CSD. */ mmc_select_card(sc, ivar->rca); mmc_send_ext_csd(sc, ivar->raw_ext_csd); /* Handle extended capacity from EXT_CSD */ sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] + (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 1] << 8) + (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 2] << 16) + (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 3] << 24); if (sec_count != 0) { ivar->sec_count = sec_count; ivar->high_cap = 1; } /* Get card speed in high speed mode. */ ivar->timing = bus_timing_hs; if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_52) ivar->hs_tran_speed = MMC_TYPE_52_MAX_HS; else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_26) ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS; else ivar->hs_tran_speed = ivar->tran_speed; /* Find max supported bus width. */ ivar->bus_width = mmc_test_bus_width(sc); mmc_select_card(sc, 0); /* Handle HC erase sector size. */ if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) { ivar->erase_sector = 1024 * ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE]; mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_ERASE_GRP_DEF, 1); } } else { ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; } if (bootverbose || mmc_debug) mmc_log_card(sc->dev, ivar, newcard); if (newcard) { /* Add device. */ child = device_add_child(sc->dev, NULL, -1); device_set_ivars(child, ivar); } }