Loading drivers/mmc/core/block.c +2 −1 Original line number Diff line number Diff line Loading @@ -871,7 +871,8 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, int ret = 0; struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev); if (main_md->part_curr == part_type) if ((main_md->part_curr == part_type) && (card->part_curr == part_type)) return 0; if (mmc_card_mmc(card)) { Loading drivers/mmc/core/mmc.c +216 −66 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/mmc/mmc.h> #include <linux/reboot.h> #include <trace/events/mmc.h> #include "core.h" #include "card.h" Loading Loading @@ -356,6 +358,53 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd) } } /* check whether the eMMC card supports HPI */ void mmc_check_hpi_support(struct mmc_card *card, u8 *ext_csd) { if ((ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) && !(card->quirks & MMC_QUIRK_BROKEN_HPI)) { card->ext_csd.hpi = 1; if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; else card->ext_csd.hpi_cmd = MMC_SEND_STATUS; /* * Indicate the maximum timeout to close * a command interrupted by HPI */ card->ext_csd.out_of_int_time = ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10; pr_info("%s: Out-of-interrupt timeout is %d[ms]\n", mmc_hostname(card->host), card->ext_csd.out_of_int_time); } } /* Check bkops support of card */ void mmc_check_bkops_support(struct mmc_card *card, u8 *ext_csd) { if (!mmc_card_broken_hpi(card) && (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) && card->ext_csd.hpi) { card->ext_csd.bkops = 1; card->ext_csd.man_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_MANUAL_BKOPS_MASK); card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; if (card->ext_csd.man_bkops_en) pr_debug("%s: MAN_BKOPS_EN bit is set\n", mmc_hostname(card->host)); card->ext_csd.auto_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_AUTO_BKOPS_MASK); if (card->ext_csd.auto_bkops_en) pr_debug("%s: AUTO_BKOPS_EN bit is set\n", mmc_hostname(card->host)); } } /* Minimum partition switch timeout in milliseconds */ #define MMC_MIN_PART_SWITCH_TIME 300 Loading Loading @@ -521,30 +570,15 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_PWR_CL_DDR_200_360]; } mmc_check_hpi_support(card, ext_csd); if (card->ext_csd.rev >= 5) { /* Adjust production date as per JEDEC JESD84-B451 */ if (card->cid.year < 2010) card->cid.year += 16; /* check whether the eMMC card supports BKOPS */ if (!mmc_card_broken_hpi(card) && ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { card->ext_csd.bkops = 1; card->ext_csd.man_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_MANUAL_BKOPS_MASK); card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; if (card->ext_csd.man_bkops_en) pr_debug("%s: MAN_BKOPS_EN bit is set\n", mmc_hostname(card->host)); card->ext_csd.auto_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_AUTO_BKOPS_MASK); if (card->ext_csd.auto_bkops_en) pr_debug("%s: AUTO_BKOPS_EN bit is set\n", mmc_hostname(card->host)); } mmc_check_bkops_support(card, ext_csd); /* check whether the eMMC card supports HPI */ if (!mmc_card_broken_hpi(card) && Loading Loading @@ -659,6 +693,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) static int mmc_read_ext_csd(struct mmc_card *card) { struct mmc_host *host = card->host; u8 *ext_csd; int err; Loading @@ -667,6 +702,8 @@ static int mmc_read_ext_csd(struct mmc_card *card) err = mmc_get_ext_csd(card, &ext_csd); if (err) { pr_err("%s: %s: mmc_get_ext_csd() fails %d\n", mmc_hostname(host), __func__, err); /* If the host or the card can't do the switch, * fail more gracefully. */ if ((err != -EINVAL) Loading Loading @@ -1529,6 +1566,17 @@ static int mmc_select_hs200(struct mmc_card *card) return err; } static int mmc_reboot_notify(struct notifier_block *notify_block, unsigned long event, void *unused) { struct mmc_card *card = container_of( notify_block, struct mmc_card, reboot_notify); card->pon_type = (event != SYS_RESTART) ? MMC_LONG_PON : MMC_SHRT_PON; return NOTIFY_OK; } /* * Activate High Speed, HS200 or HS400ES mode if supported. */ Loading Loading @@ -1582,8 +1630,7 @@ static int mmc_hs200_tuning(struct mmc_card *card) */ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && host->ios.bus_width == MMC_BUS_WIDTH_8) if (host->ops->prepare_hs400_tuning) host->ops->prepare_hs400_tuning(host, &host->ios); mmc_set_timing(host, MMC_TIMING_MMC_HS400); return mmc_execute_tuning(card); } Loading Loading @@ -1827,6 +1874,21 @@ static int mmc_change_bus_speed_deferred(struct mmc_host *host, out: return err; } void mmc_init_setup_scaling(struct mmc_card *card, struct mmc_host *host) { card->clk_scaling_lowest = host->f_min; if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)) card->clk_scaling_highest = card->ext_csd.hs200_max_dtr; else if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52)) card->clk_scaling_highest = card->ext_csd.hs_max_dtr; else card->clk_scaling_highest = card->csd.max_dtr; } /* * Handle the detection and initialisation of a card. * Loading Loading @@ -1858,8 +1920,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, /* The extra bit indicates that we support high capacity */ err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr); if (err) if (err) { pr_err("%s: %s: mmc_send_op_cond() fails %d\n", mmc_hostname(host), __func__, err); goto err; } /* * For SPI, enable CRC as appropriate. Loading @@ -1874,12 +1939,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Fetch CID from card. */ err = mmc_send_cid(host, cid); if (err) if (err) { pr_err("%s: %s: mmc_send_cid() fails %d\n", mmc_hostname(host), __func__, err); goto err; } if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { err = -ENOENT; pr_err("%s: %s: CID memcmp failed %d\n", mmc_hostname(host), __func__, err); goto err; } Loading @@ -1891,6 +1961,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card = mmc_alloc_card(host, &mmc_type); if (IS_ERR(card)) { err = PTR_ERR(card); pr_err("%s: %s: no memory to allocate for card %d\n", mmc_hostname(host), __func__, err); goto err; } Loading @@ -1899,6 +1971,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->rca = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); host->card = card; card->reboot_notify.notifier_call = mmc_reboot_notify; } /* Loading @@ -1912,8 +1985,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, */ if (!mmc_host_is_spi(host)) { err = mmc_set_relative_addr(card); if (err) if (err) { pr_err("%s: %s: mmc_set_relative_addr() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } Loading @@ -1923,16 +1999,25 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Fetch CSD from card. */ err = mmc_send_csd(card, card->raw_csd); if (err) if (err) { pr_err("%s: %s: mmc_send_csd() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } err = mmc_decode_csd(card); if (err) if (err) { pr_err("%s: %s: mmc_decode_csd() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } err = mmc_decode_cid(card); if (err) if (err) { pr_err("%s: %s: mmc_decode_cid() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } } /* * handling only for cards supporting DSR and hosts requesting Loading @@ -1946,15 +2031,21 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, */ if (!mmc_host_is_spi(host)) { err = mmc_select_card(card); if (err) if (err) { pr_err("%s: %s: mmc_select_card() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } } if (!oldcard) { /* Read extended CSD. */ err = mmc_read_ext_csd(card); if (err) if (err) { pr_err("%s: %s: mmc_read_ext_csd() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } /* * If doing byte addressing, check if required to do sector Loading @@ -1975,8 +2066,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, EXT_CSD_ERASE_GROUP_DEF, 1, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for ERASE_GRP_DEF fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } if (err) { err = 0; Loading Loading @@ -2006,9 +2100,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG, card->ext_csd.part_config, card->ext_csd.part_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for PART_CONFIG fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } card->part_curr = card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK; } /* * Enable power_off_notification byte in the ext_csd register Loading @@ -2018,8 +2117,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, EXT_CSD_POWER_OFF_NOTIFICATION, EXT_CSD_POWER_ON, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for POWER_ON PON fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } /* * The err can be -EBADMSG or 0, Loading @@ -2033,8 +2135,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Select timing interface */ err = mmc_select_timing(card); if (err) if (err) { pr_err("%s: %s: mmc_select_timing() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } if (mmc_card_hs200(card)) { err = mmc_hs200_tuning(card); Loading @@ -2054,15 +2159,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } } card->clk_scaling_lowest = host->f_min; if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)) card->clk_scaling_highest = card->ext_csd.hs200_max_dtr; else if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52)) card->clk_scaling_highest = card->ext_csd.hs_max_dtr; else card->clk_scaling_highest = card->csd.max_dtr; mmc_init_setup_scaling(card, host); /* * Choose the power class with selected bus interface Loading @@ -2076,8 +2173,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HPI_MGMT, 1, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for HPI_MGMT fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } if (err) { pr_warn("%s: Enabling HPI failed\n", mmc_hostname(card->host)); Loading @@ -2092,13 +2192,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * If cache size is higher than 0, this indicates * the existence of cache and it can be turned on. */ if (!mmc_card_broken_hpi(card) && card->ext_csd.cache_size > 0) { if (!mmc_card_broken_hpi(card) && card->ext_csd.cache_size > 0) { if (card->ext_csd.hpi_en && (!(card->quirks & MMC_QUIRK_CACHE_DISABLE))) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CACHE_CTRL, 1, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: fail on CACHE_CTRL ON %d\n", mmc_hostname(host), __func__, err); goto free_card; } /* * Only if no error, cache is turned on successfully. Loading @@ -2111,6 +2215,24 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } else { card->ext_csd.cache_ctrl = 1; } } else { /* * mmc standard doesn't say what is the card default * value for EXT_CSD_CACHE_CTRL. * Hence, cache may be enabled by default by * card vendors. * Thus, it is best to explicitly disable cache in case * we want to avoid cache. */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CACHE_CTRL, 0, card->ext_csd.generic_cmd6_time); if (err) { pr_err("%s: %s: fail on CACHE_CTRL OFF %d\n", mmc_hostname(host), __func__, err); goto free_card; } } } /* Loading Loading @@ -2163,8 +2285,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, return 0; free_card: if (!oldcard) if (!oldcard) { host->card = NULL; mmc_remove_card(card); } err: return err; } Loading Loading @@ -2279,6 +2403,7 @@ int mmc_send_pon(struct mmc_card *card) static void mmc_remove(struct mmc_host *host) { mmc_exit_clk_scaling(host); unregister_reboot_notifier(&host->card->reboot_notify); mmc_remove_card(host->card); mmc_claim_host(host); host->card = NULL; Loading Loading @@ -2322,8 +2447,6 @@ static void mmc_detect(struct mmc_host *host) static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : EXT_CSD_POWER_OFF_LONG; err = mmc_suspend_clk_scaling(host); if (err) { Loading Loading @@ -2354,10 +2477,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (err) goto out; if (mmc_can_poweroff_notify(host->card) && ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) if (mmc_can_sleep(host->card)) err = mmc_sleep(host); else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); Loading @@ -2380,6 +2500,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) static int mmc_suspend(struct mmc_host *host) { int err; ktime_t start = ktime_get(); err = _mmc_suspend(host, true); if (!err) { Loading @@ -2387,6 +2508,8 @@ static int mmc_suspend(struct mmc_host *host) pm_runtime_set_suspended(&host->card->dev); } trace_mmc_suspend(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); return err; } Loading @@ -2397,6 +2520,7 @@ static int mmc_suspend(struct mmc_host *host) static int _mmc_resume(struct mmc_host *host) { int err = 0; int retries = 3; mmc_claim_host(host); Loading @@ -2407,7 +2531,20 @@ static int _mmc_resume(struct mmc_host *host) mmc_log_string(host, "Enter\n"); mmc_power_up(host, host->card->ocr); while (retries) { err = mmc_init_card(host, host->card->ocr, host->card); if (err) { pr_err("%s: MMC card re-init failed rc = %d (retries = %d)\n", mmc_hostname(host), err, retries); retries--; mmc_power_off(host); usleep_range(5000, 5500); mmc_power_up(host, host->card->ocr); mmc_select_voltage(host, host->card->ocr); continue; } break; } mmc_card_clr_suspended(host->card); mmc_log_string(host, "Exit err %d\n", err); Loading Loading @@ -2482,11 +2619,14 @@ static int mmc_shutdown(struct mmc_host *host) static int mmc_resume(struct mmc_host *host) { int err = 0; ktime_t start = ktime_get(); err = _mmc_resume(host); pm_runtime_set_active(&host->card->dev); pm_runtime_mark_last_busy(&host->card->dev); pm_runtime_enable(&host->card->dev); trace_mmc_resume(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); mmc_log_string(host, "Done\n"); Loading Loading @@ -2516,6 +2656,7 @@ static int mmc_deferred_resume(struct mmc_host *host) static int mmc_runtime_suspend(struct mmc_host *host) { int err; ktime_t start = ktime_get(); if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; Loading @@ -2524,6 +2665,9 @@ static int mmc_runtime_suspend(struct mmc_host *host) if (err) pr_err("%s: error %d doing aggressive suspend\n", mmc_hostname(host), err); trace_mmc_runtime_suspend(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); mmc_log_string(host, "done err %d\n", err); return err; } Loading @@ -2534,11 +2678,15 @@ static int mmc_runtime_suspend(struct mmc_host *host) static int mmc_runtime_resume(struct mmc_host *host) { int err; ktime_t start = ktime_get(); err = _mmc_resume(host); if (err && err != -ENOMEDIUM) pr_err("%s: error %d doing runtime resume\n", mmc_hostname(host), err); trace_mmc_runtime_resume(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); mmc_log_string(host, "done err %d\n", err); return 0; } Loading Loading @@ -2662,6 +2810,8 @@ int mmc_attach_mmc(struct mmc_host *host) goto remove_card; } register_reboot_notifier(&host->card->reboot_notify); return 0; remove_card: Loading drivers/mmc/core/mmc_ops.c +3 −2 Original line number Diff line number Diff line Loading @@ -802,7 +802,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) unsigned int opcode; int err; if (!card->ext_csd.hpi) { if (!card->ext_csd.hpi_en) { pr_warn("%s: Card didn't support HPI command\n", mmc_hostname(card->host)); return -EINVAL; Loading Loading @@ -1017,7 +1017,8 @@ int mmc_flush_cache(struct mmc_card *card) if (mmc_card_mmc(card) && (card->ext_csd.cache_size > 0) && (card->ext_csd.cache_ctrl & 1)) { (card->ext_csd.cache_ctrl & 1) && (!(card->quirks & MMC_QUIRK_CACHE_DISABLE))) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_FLUSH_CACHE, 1, 0); if (err) Loading drivers/mmc/core/quirks.h +8 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,10 @@ static const struct mmc_fixup mmc_blk_fixups[] = { MMC_FIXUP("SEM04G", 0x45, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_INAND_DATA_TIMEOUT), /* Disable cache for specific cards */ MMC_FIXUP("MMC16G", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_CACHE_DISABLE), END_FIXUP }; Loading @@ -134,6 +138,10 @@ static const struct mmc_fixup mmc_ext_csd_fixups[] = { MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_NUMONYX, 0x014e, add_quirk, MMC_QUIRK_BROKEN_HPI, 6), /* avoid HPI for specific cards */ MMC_FIXUP_EXT_CSD_REV("MMC16G", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk, MMC_QUIRK_BROKEN_HPI, MMC_V4_41), END_FIXUP }; Loading Loading
drivers/mmc/core/block.c +2 −1 Original line number Diff line number Diff line Loading @@ -871,7 +871,8 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, int ret = 0; struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev); if (main_md->part_curr == part_type) if ((main_md->part_curr == part_type) && (card->part_curr == part_type)) return 0; if (mmc_card_mmc(card)) { Loading
drivers/mmc/core/mmc.c +216 −66 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/mmc/mmc.h> #include <linux/reboot.h> #include <trace/events/mmc.h> #include "core.h" #include "card.h" Loading Loading @@ -356,6 +358,53 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd) } } /* check whether the eMMC card supports HPI */ void mmc_check_hpi_support(struct mmc_card *card, u8 *ext_csd) { if ((ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) && !(card->quirks & MMC_QUIRK_BROKEN_HPI)) { card->ext_csd.hpi = 1; if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; else card->ext_csd.hpi_cmd = MMC_SEND_STATUS; /* * Indicate the maximum timeout to close * a command interrupted by HPI */ card->ext_csd.out_of_int_time = ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10; pr_info("%s: Out-of-interrupt timeout is %d[ms]\n", mmc_hostname(card->host), card->ext_csd.out_of_int_time); } } /* Check bkops support of card */ void mmc_check_bkops_support(struct mmc_card *card, u8 *ext_csd) { if (!mmc_card_broken_hpi(card) && (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) && card->ext_csd.hpi) { card->ext_csd.bkops = 1; card->ext_csd.man_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_MANUAL_BKOPS_MASK); card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; if (card->ext_csd.man_bkops_en) pr_debug("%s: MAN_BKOPS_EN bit is set\n", mmc_hostname(card->host)); card->ext_csd.auto_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_AUTO_BKOPS_MASK); if (card->ext_csd.auto_bkops_en) pr_debug("%s: AUTO_BKOPS_EN bit is set\n", mmc_hostname(card->host)); } } /* Minimum partition switch timeout in milliseconds */ #define MMC_MIN_PART_SWITCH_TIME 300 Loading Loading @@ -521,30 +570,15 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_PWR_CL_DDR_200_360]; } mmc_check_hpi_support(card, ext_csd); if (card->ext_csd.rev >= 5) { /* Adjust production date as per JEDEC JESD84-B451 */ if (card->cid.year < 2010) card->cid.year += 16; /* check whether the eMMC card supports BKOPS */ if (!mmc_card_broken_hpi(card) && ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { card->ext_csd.bkops = 1; card->ext_csd.man_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_MANUAL_BKOPS_MASK); card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; if (card->ext_csd.man_bkops_en) pr_debug("%s: MAN_BKOPS_EN bit is set\n", mmc_hostname(card->host)); card->ext_csd.auto_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_AUTO_BKOPS_MASK); if (card->ext_csd.auto_bkops_en) pr_debug("%s: AUTO_BKOPS_EN bit is set\n", mmc_hostname(card->host)); } mmc_check_bkops_support(card, ext_csd); /* check whether the eMMC card supports HPI */ if (!mmc_card_broken_hpi(card) && Loading Loading @@ -659,6 +693,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) static int mmc_read_ext_csd(struct mmc_card *card) { struct mmc_host *host = card->host; u8 *ext_csd; int err; Loading @@ -667,6 +702,8 @@ static int mmc_read_ext_csd(struct mmc_card *card) err = mmc_get_ext_csd(card, &ext_csd); if (err) { pr_err("%s: %s: mmc_get_ext_csd() fails %d\n", mmc_hostname(host), __func__, err); /* If the host or the card can't do the switch, * fail more gracefully. */ if ((err != -EINVAL) Loading Loading @@ -1529,6 +1566,17 @@ static int mmc_select_hs200(struct mmc_card *card) return err; } static int mmc_reboot_notify(struct notifier_block *notify_block, unsigned long event, void *unused) { struct mmc_card *card = container_of( notify_block, struct mmc_card, reboot_notify); card->pon_type = (event != SYS_RESTART) ? MMC_LONG_PON : MMC_SHRT_PON; return NOTIFY_OK; } /* * Activate High Speed, HS200 or HS400ES mode if supported. */ Loading Loading @@ -1582,8 +1630,7 @@ static int mmc_hs200_tuning(struct mmc_card *card) */ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && host->ios.bus_width == MMC_BUS_WIDTH_8) if (host->ops->prepare_hs400_tuning) host->ops->prepare_hs400_tuning(host, &host->ios); mmc_set_timing(host, MMC_TIMING_MMC_HS400); return mmc_execute_tuning(card); } Loading Loading @@ -1827,6 +1874,21 @@ static int mmc_change_bus_speed_deferred(struct mmc_host *host, out: return err; } void mmc_init_setup_scaling(struct mmc_card *card, struct mmc_host *host) { card->clk_scaling_lowest = host->f_min; if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)) card->clk_scaling_highest = card->ext_csd.hs200_max_dtr; else if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52)) card->clk_scaling_highest = card->ext_csd.hs_max_dtr; else card->clk_scaling_highest = card->csd.max_dtr; } /* * Handle the detection and initialisation of a card. * Loading Loading @@ -1858,8 +1920,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, /* The extra bit indicates that we support high capacity */ err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr); if (err) if (err) { pr_err("%s: %s: mmc_send_op_cond() fails %d\n", mmc_hostname(host), __func__, err); goto err; } /* * For SPI, enable CRC as appropriate. Loading @@ -1874,12 +1939,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Fetch CID from card. */ err = mmc_send_cid(host, cid); if (err) if (err) { pr_err("%s: %s: mmc_send_cid() fails %d\n", mmc_hostname(host), __func__, err); goto err; } if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { err = -ENOENT; pr_err("%s: %s: CID memcmp failed %d\n", mmc_hostname(host), __func__, err); goto err; } Loading @@ -1891,6 +1961,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card = mmc_alloc_card(host, &mmc_type); if (IS_ERR(card)) { err = PTR_ERR(card); pr_err("%s: %s: no memory to allocate for card %d\n", mmc_hostname(host), __func__, err); goto err; } Loading @@ -1899,6 +1971,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->rca = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); host->card = card; card->reboot_notify.notifier_call = mmc_reboot_notify; } /* Loading @@ -1912,8 +1985,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, */ if (!mmc_host_is_spi(host)) { err = mmc_set_relative_addr(card); if (err) if (err) { pr_err("%s: %s: mmc_set_relative_addr() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } Loading @@ -1923,16 +1999,25 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Fetch CSD from card. */ err = mmc_send_csd(card, card->raw_csd); if (err) if (err) { pr_err("%s: %s: mmc_send_csd() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } err = mmc_decode_csd(card); if (err) if (err) { pr_err("%s: %s: mmc_decode_csd() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } err = mmc_decode_cid(card); if (err) if (err) { pr_err("%s: %s: mmc_decode_cid() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } } /* * handling only for cards supporting DSR and hosts requesting Loading @@ -1946,15 +2031,21 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, */ if (!mmc_host_is_spi(host)) { err = mmc_select_card(card); if (err) if (err) { pr_err("%s: %s: mmc_select_card() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } } if (!oldcard) { /* Read extended CSD. */ err = mmc_read_ext_csd(card); if (err) if (err) { pr_err("%s: %s: mmc_read_ext_csd() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } /* * If doing byte addressing, check if required to do sector Loading @@ -1975,8 +2066,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, EXT_CSD_ERASE_GROUP_DEF, 1, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for ERASE_GRP_DEF fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } if (err) { err = 0; Loading Loading @@ -2006,9 +2100,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG, card->ext_csd.part_config, card->ext_csd.part_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for PART_CONFIG fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } card->part_curr = card->ext_csd.part_config & EXT_CSD_PART_CONFIG_ACC_MASK; } /* * Enable power_off_notification byte in the ext_csd register Loading @@ -2018,8 +2117,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, EXT_CSD_POWER_OFF_NOTIFICATION, EXT_CSD_POWER_ON, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for POWER_ON PON fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } /* * The err can be -EBADMSG or 0, Loading @@ -2033,8 +2135,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Select timing interface */ err = mmc_select_timing(card); if (err) if (err) { pr_err("%s: %s: mmc_select_timing() fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } if (mmc_card_hs200(card)) { err = mmc_hs200_tuning(card); Loading @@ -2054,15 +2159,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } } card->clk_scaling_lowest = host->f_min; if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)) card->clk_scaling_highest = card->ext_csd.hs200_max_dtr; else if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) || (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52)) card->clk_scaling_highest = card->ext_csd.hs_max_dtr; else card->clk_scaling_highest = card->csd.max_dtr; mmc_init_setup_scaling(card, host); /* * Choose the power class with selected bus interface Loading @@ -2076,8 +2173,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HPI_MGMT, 1, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: mmc_switch() for HPI_MGMT fails %d\n", mmc_hostname(host), __func__, err); goto free_card; } if (err) { pr_warn("%s: Enabling HPI failed\n", mmc_hostname(card->host)); Loading @@ -2092,13 +2192,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * If cache size is higher than 0, this indicates * the existence of cache and it can be turned on. */ if (!mmc_card_broken_hpi(card) && card->ext_csd.cache_size > 0) { if (!mmc_card_broken_hpi(card) && card->ext_csd.cache_size > 0) { if (card->ext_csd.hpi_en && (!(card->quirks & MMC_QUIRK_CACHE_DISABLE))) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CACHE_CTRL, 1, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) if (err && err != -EBADMSG) { pr_err("%s: %s: fail on CACHE_CTRL ON %d\n", mmc_hostname(host), __func__, err); goto free_card; } /* * Only if no error, cache is turned on successfully. Loading @@ -2111,6 +2215,24 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } else { card->ext_csd.cache_ctrl = 1; } } else { /* * mmc standard doesn't say what is the card default * value for EXT_CSD_CACHE_CTRL. * Hence, cache may be enabled by default by * card vendors. * Thus, it is best to explicitly disable cache in case * we want to avoid cache. */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CACHE_CTRL, 0, card->ext_csd.generic_cmd6_time); if (err) { pr_err("%s: %s: fail on CACHE_CTRL OFF %d\n", mmc_hostname(host), __func__, err); goto free_card; } } } /* Loading Loading @@ -2163,8 +2285,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, return 0; free_card: if (!oldcard) if (!oldcard) { host->card = NULL; mmc_remove_card(card); } err: return err; } Loading Loading @@ -2279,6 +2403,7 @@ int mmc_send_pon(struct mmc_card *card) static void mmc_remove(struct mmc_host *host) { mmc_exit_clk_scaling(host); unregister_reboot_notifier(&host->card->reboot_notify); mmc_remove_card(host->card); mmc_claim_host(host); host->card = NULL; Loading Loading @@ -2322,8 +2447,6 @@ static void mmc_detect(struct mmc_host *host) static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : EXT_CSD_POWER_OFF_LONG; err = mmc_suspend_clk_scaling(host); if (err) { Loading Loading @@ -2354,10 +2477,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (err) goto out; if (mmc_can_poweroff_notify(host->card) && ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) if (mmc_can_sleep(host->card)) err = mmc_sleep(host); else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); Loading @@ -2380,6 +2500,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) static int mmc_suspend(struct mmc_host *host) { int err; ktime_t start = ktime_get(); err = _mmc_suspend(host, true); if (!err) { Loading @@ -2387,6 +2508,8 @@ static int mmc_suspend(struct mmc_host *host) pm_runtime_set_suspended(&host->card->dev); } trace_mmc_suspend(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); return err; } Loading @@ -2397,6 +2520,7 @@ static int mmc_suspend(struct mmc_host *host) static int _mmc_resume(struct mmc_host *host) { int err = 0; int retries = 3; mmc_claim_host(host); Loading @@ -2407,7 +2531,20 @@ static int _mmc_resume(struct mmc_host *host) mmc_log_string(host, "Enter\n"); mmc_power_up(host, host->card->ocr); while (retries) { err = mmc_init_card(host, host->card->ocr, host->card); if (err) { pr_err("%s: MMC card re-init failed rc = %d (retries = %d)\n", mmc_hostname(host), err, retries); retries--; mmc_power_off(host); usleep_range(5000, 5500); mmc_power_up(host, host->card->ocr); mmc_select_voltage(host, host->card->ocr); continue; } break; } mmc_card_clr_suspended(host->card); mmc_log_string(host, "Exit err %d\n", err); Loading Loading @@ -2482,11 +2619,14 @@ static int mmc_shutdown(struct mmc_host *host) static int mmc_resume(struct mmc_host *host) { int err = 0; ktime_t start = ktime_get(); err = _mmc_resume(host); pm_runtime_set_active(&host->card->dev); pm_runtime_mark_last_busy(&host->card->dev); pm_runtime_enable(&host->card->dev); trace_mmc_resume(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); mmc_log_string(host, "Done\n"); Loading Loading @@ -2516,6 +2656,7 @@ static int mmc_deferred_resume(struct mmc_host *host) static int mmc_runtime_suspend(struct mmc_host *host) { int err; ktime_t start = ktime_get(); if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; Loading @@ -2524,6 +2665,9 @@ static int mmc_runtime_suspend(struct mmc_host *host) if (err) pr_err("%s: error %d doing aggressive suspend\n", mmc_hostname(host), err); trace_mmc_runtime_suspend(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); mmc_log_string(host, "done err %d\n", err); return err; } Loading @@ -2534,11 +2678,15 @@ static int mmc_runtime_suspend(struct mmc_host *host) static int mmc_runtime_resume(struct mmc_host *host) { int err; ktime_t start = ktime_get(); err = _mmc_resume(host); if (err && err != -ENOMEDIUM) pr_err("%s: error %d doing runtime resume\n", mmc_hostname(host), err); trace_mmc_runtime_resume(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); mmc_log_string(host, "done err %d\n", err); return 0; } Loading Loading @@ -2662,6 +2810,8 @@ int mmc_attach_mmc(struct mmc_host *host) goto remove_card; } register_reboot_notifier(&host->card->reboot_notify); return 0; remove_card: Loading
drivers/mmc/core/mmc_ops.c +3 −2 Original line number Diff line number Diff line Loading @@ -802,7 +802,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) unsigned int opcode; int err; if (!card->ext_csd.hpi) { if (!card->ext_csd.hpi_en) { pr_warn("%s: Card didn't support HPI command\n", mmc_hostname(card->host)); return -EINVAL; Loading Loading @@ -1017,7 +1017,8 @@ int mmc_flush_cache(struct mmc_card *card) if (mmc_card_mmc(card) && (card->ext_csd.cache_size > 0) && (card->ext_csd.cache_ctrl & 1)) { (card->ext_csd.cache_ctrl & 1) && (!(card->quirks & MMC_QUIRK_CACHE_DISABLE))) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_FLUSH_CACHE, 1, 0); if (err) Loading
drivers/mmc/core/quirks.h +8 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,10 @@ static const struct mmc_fixup mmc_blk_fixups[] = { MMC_FIXUP("SEM04G", 0x45, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_INAND_DATA_TIMEOUT), /* Disable cache for specific cards */ MMC_FIXUP("MMC16G", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_CACHE_DISABLE), END_FIXUP }; Loading @@ -134,6 +138,10 @@ static const struct mmc_fixup mmc_ext_csd_fixups[] = { MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_NUMONYX, 0x014e, add_quirk, MMC_QUIRK_BROKEN_HPI, 6), /* avoid HPI for specific cards */ MMC_FIXUP_EXT_CSD_REV("MMC16G", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk, MMC_QUIRK_BROKEN_HPI, MMC_V4_41), END_FIXUP }; Loading