From 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 22 Oct 2024 10:36:11 +0000 Subject: [PATCH] 修改4g拨号为QMI,需要在系统里后台执行quectel-CM --- kernel/drivers/mmc/core/mmc.c | 139 ++++++++++++++++++++++++++++----------------- 1 files changed, 86 insertions(+), 53 deletions(-) diff --git a/kernel/drivers/mmc/core/mmc.c b/kernel/drivers/mmc/core/mmc.c index 0d96658..83b0876 100644 --- a/kernel/drivers/mmc/core/mmc.c +++ b/kernel/drivers/mmc/core/mmc.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/mmc/core/mmc.c * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/err.h> @@ -661,6 +658,9 @@ mmc_hostname(card->host), card->ext_csd.cmdq_depth); } + card->ext_csd.enhanced_rpmb_supported = + (card->ext_csd.rel_param & + EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR); } out: return err; @@ -697,7 +697,7 @@ u8 *ext_csd; int err; #ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC - void *ecsd = NULL; + void *ecsd; bool valid_ecsd = false; bool valid_reserved = false; struct device_node *mem; @@ -875,6 +875,8 @@ card->ext_csd.enhanced_area_offset); MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); +MMC_DEV_ATTR(enhanced_rpmb_supported, "%#x\n", + card->ext_csd.enhanced_rpmb_supported); MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); @@ -932,6 +934,7 @@ &dev_attr_enhanced_area_offset.attr, &dev_attr_enhanced_area_size.attr, &dev_attr_raw_rpmb_size_mult.attr, + &dev_attr_enhanced_rpmb_supported.attr, &dev_attr_rel_sectors.attr, &dev_attr_ocr.attr, &dev_attr_rca.attr, @@ -1048,7 +1051,7 @@ /* * Set the bus speed for the selected speed mode. */ -static void mmc_set_bus_speed(struct mmc_card *card) +void mmc_set_bus_speed(struct mmc_card *card) { unsigned int max_dtr = (unsigned int)-1; @@ -1068,7 +1071,7 @@ * If the bus width is changed successfully, return the selected width value. * Zero is returned instead of error value if the wide width is not supported. */ -static int mmc_select_bus_width(struct mmc_card *card) +int mmc_select_bus_width(struct mmc_card *card) { static unsigned ext_csd_bits[] = { EXT_CSD_BUS_WIDTH_8, @@ -1134,29 +1137,31 @@ return err; } +EXPORT_SYMBOL_GPL(mmc_select_bus_width); /* * Switch to the high-speed mode */ -static int mmc_select_hs(struct mmc_card *card) +int mmc_select_hs(struct mmc_card *card) { int err; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS, - true, true, true); + true, true); if (err) pr_warn("%s: switch to high-speed failed, err:%d\n", mmc_hostname(card->host), err); return err; } +EXPORT_SYMBOL_GPL(mmc_select_hs); /* * Activate wide bus and DDR if supported. */ -static int mmc_select_hs_ddr(struct mmc_card *card) +int mmc_select_hs_ddr(struct mmc_card *card) { struct mmc_host *host = card->host; u32 bus_width, ext_csd_bits; @@ -1177,7 +1182,7 @@ ext_csd_bits, card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_DDR52, - true, true, true); + true, true); if (err) { pr_err("%s: switch to bus width %d ddr failed\n", mmc_hostname(host), 1 << bus_width); @@ -1225,8 +1230,9 @@ return err; } +EXPORT_SYMBOL_GPL(mmc_select_hs_ddr); -static int mmc_select_hs400(struct mmc_card *card) +int mmc_select_hs400(struct mmc_card *card) { struct mmc_host *host = card->host; unsigned int max_dtr; @@ -1245,27 +1251,30 @@ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) { pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", mmc_hostname(host), err); return err; } - /* Set host controller to HS timing */ - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - /* Prepare host to downgrade to HS timing */ if (host->ops->hs400_downgrade) host->ops->hs400_downgrade(host); + + /* Set host controller to HS timing */ + mmc_set_timing(host, MMC_TIMING_MMC_HS); /* Reduce frequency to HS frequency */ max_dtr = card->ext_csd.hs_max_dtr; mmc_set_clock(host, max_dtr); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; + + if (host->ops->hs400_prepare_ddr) + host->ops->hs400_prepare_ddr(host); /* Switch card to DDR */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -1284,7 +1293,7 @@ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1298,7 +1307,7 @@ if (host->ops->hs400_complete) host->ops->hs400_complete(host); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1309,6 +1318,7 @@ __func__, err); return err; } +EXPORT_SYMBOL_GPL(mmc_select_hs400); int mmc_hs200_to_hs400(struct mmc_card *card) { @@ -1330,29 +1340,29 @@ val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) goto out_err; + if (host->ops->hs400_downgrade) + host->ops->hs400_downgrade(host); + mmc_set_timing(host, MMC_TIMING_MMC_DDR52); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; /* Switch HS DDR to HS */ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time, - 0, true, false, true); + 0, false, true); if (err) goto out_err; mmc_set_timing(host, MMC_TIMING_MMC_HS); - if (host->ops->hs400_downgrade) - host->ops->hs400_downgrade(host); - - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1361,7 +1371,7 @@ card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) goto out_err; @@ -1372,7 +1382,7 @@ * failed. If there really is a problem, we would expect tuning will * fail and the result ends up the same. */ - err = __mmc_switch_status(card, false); + err = mmc_switch_status(card, false); if (err) goto out_err; @@ -1445,18 +1455,22 @@ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) { pr_err("%s: switch to hs for hs400es failed, err:%d\n", mmc_hostname(host), err); goto out_err; } + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + */ mmc_set_timing(host, MMC_TIMING_MMC_HS); /* Set clock immediately after changing timing */ - mmc_set_clock(host, card->ext_csd.hs_max_dtr); + mmc_set_bus_speed(card); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1480,7 +1494,7 @@ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) { pr_err("%s: switch to hs400es failed, err:%d\n", mmc_hostname(host), err); @@ -1495,10 +1509,7 @@ if (host->ops->hs400_enhanced_strobe) host->ops->hs400_enhanced_strobe(host, &host->ios); - /* some emmc device need a delay before read status */ - usleep_range(100, 200); - - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1520,7 +1531,7 @@ static int mmc_select_hs200(struct mmc_card *card) { struct mmc_host *host = card->host; - unsigned int old_timing, old_signal_voltage; + unsigned int old_timing, old_signal_voltage, old_clock; int err = -EINVAL; u8 val; @@ -1548,25 +1559,36 @@ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true); if (err) goto err; + + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + * NB: We can't move to full (HS200) speeds until after we've + * successfully switched over. + */ old_timing = host->ios.timing; + old_clock = host->ios.clock; mmc_set_timing(host, MMC_TIMING_MMC_HS200); + mmc_set_clock(card->host, card->ext_csd.hs_max_dtr); /* * For HS200, CRC errors are not a reliable way to know the * switch failed. If there really is a problem, we would expect * tuning will fail and the result ends up the same. */ - err = __mmc_switch_status(card, false); + err = mmc_switch_status(card, false); /* * mmc_select_timing() assumes timing has not changed if * it is a switch error. */ - if (err == -EBADMSG) + if (err == -EBADMSG) { + mmc_set_clock(host, old_clock); mmc_set_timing(host, old_timing); + } } err: if (err) { @@ -1583,7 +1605,7 @@ /* * Activate High Speed, HS200 or HS400ES mode if supported. */ -static int mmc_select_timing(struct mmc_card *card) +int mmc_select_timing(struct mmc_card *card) { int err = 0; @@ -1608,12 +1630,13 @@ mmc_set_bus_speed(card); return 0; } +EXPORT_SYMBOL_GPL(mmc_select_timing); /* * Execute tuning sequence to seek the proper bus operating * conditions for HS200 and HS400, which sends CMD21 to the device. */ -static int mmc_hs200_tuning(struct mmc_card *card) +int mmc_hs200_tuning(struct mmc_card *card) { struct mmc_host *host = card->host; @@ -1628,6 +1651,7 @@ return mmc_execute_tuning(card); } +EXPORT_SYMBOL_GPL(mmc_hs200_tuning); /* * Handle the detection and initialisation of a card. @@ -1683,6 +1707,8 @@ if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); err = -ENOENT; goto err; } @@ -1836,6 +1862,14 @@ card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; } + /* set erase_arg */ + if (mmc_can_discard(card)) + card->erase_arg = MMC_DISCARD_ARG; + else if (mmc_can_trim(card)) + card->erase_arg = MMC_TRIM_ARG; + else + card->erase_arg = MMC_ERASE_ARG; + /* * Select timing interface */ @@ -1844,13 +1878,17 @@ goto free_card; if (mmc_card_hs200(card)) { + host->doing_init_tune = 1; + err = mmc_hs200_tuning(card); + if (!err) + err = mmc_select_hs400(card); + + host->doing_init_tune = 0; + if (err) goto free_card; - err = mmc_select_hs400(card); - if (err) - goto free_card; } else if (!mmc_card_hs400es(card)) { /* Select the desired bus width optionally */ err = mmc_select_bus_width(card); @@ -2050,7 +2088,7 @@ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, - notify_type, timeout, 0, true, false, false); + notify_type, timeout, 0, false, false); if (err) pr_err("%s: Power Off Notification timed out, %u\n", mmc_hostname(card->host), timeout); @@ -2121,18 +2159,13 @@ if (mmc_card_suspended(host->card)) goto out; - if (mmc_card_doing_bkops(host->card)) { - err = mmc_stop_bkops(host->card); - if (err) - goto out; - } - err = mmc_flush_cache(host->card); if (err) goto out; if (mmc_can_poweroff_notify(host->card) && - ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) + ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend || + (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND))) err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) err = mmc_sleep(host); -- Gitblit v1.6.2