From ea08eeccae9297f7aabd2ef7f0c2517ac4549acc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:18:26 +0000
Subject: [PATCH] write in 30M
---
kernel/drivers/mmc/core/mmc.c | 160 ++++++++++++++++++++++++++++++++--------------------
1 files changed, 98 insertions(+), 62 deletions(-)
diff --git a/kernel/drivers/mmc/core/mmc.c b/kernel/drivers/mmc/core/mmc.c
index 1315805..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>
@@ -70,7 +67,7 @@
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static int mmc_decode_cid(struct mmc_card *card)
{
u32 *resp = card->raw_cid;
@@ -661,12 +658,15 @@
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;
}
-#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static void *mmc_tb_map_ecsd(phys_addr_t start, size_t len)
{
int i;
@@ -696,8 +696,8 @@
{
u8 *ext_csd;
int err;
-#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
- void *ecsd = NULL;
+#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
+ void *ecsd;
bool valid_ecsd = false;
bool valid_reserved = false;
struct device_node *mem;
@@ -707,7 +707,7 @@
if (!mmc_can_ext_csd(card))
return 0;
-#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mem = of_parse_phandle(dev->of_node, "memory-region-ecsd", 0);
if (mem) {
err = of_address_to_resource(mem, 0, ®);
@@ -758,11 +758,11 @@
return err;
}
-#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
decode:
#endif
err = mmc_decode_ext_csd(card, ext_csd);
-#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (!valid_ecsd)
kfree(ext_csd);
else
@@ -777,7 +777,7 @@
return err;
}
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
{
u8 *bw_ext_csd;
@@ -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,
@@ -1117,7 +1120,7 @@
* compare ext_csd previously read in 1 bit mode
* against ext_csd at new bus width
*/
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
err = mmc_compare_ext_csds(card, bus_width);
else
@@ -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,7 +1509,7 @@
if (host->ops->hs400_enhanced_strobe)
host->ops->hs400_enhanced_strobe(host, &host->ios);
- err = mmc_switch_status(card);
+ err = mmc_switch_status(card, true);
if (err)
goto out_err;
@@ -1517,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;
@@ -1545,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) {
@@ -1580,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;
@@ -1605,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;
@@ -1625,6 +1651,7 @@
return mmc_execute_tuning(card);
}
+EXPORT_SYMBOL_GPL(mmc_hs200_tuning);
/*
* Handle the detection and initialisation of a card.
@@ -1653,7 +1680,7 @@
* respond.
* mmc_go_idle is needed for eMMC that are asleep
*/
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mmc_go_idle(host);
#endif
@@ -1680,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;
}
@@ -1698,7 +1727,7 @@
card->ocr = ocr;
card->type = MMC_TYPE_MMC;
card->rca = 1;
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
#endif
}
@@ -1731,7 +1760,7 @@
err = mmc_decode_csd(card);
if (err)
goto free_card;
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
err = mmc_decode_cid(card);
if (err)
goto free_card;
@@ -1833,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
*/
@@ -1841,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);
@@ -1866,7 +1907,7 @@
/*
* Enable HPI feature (if supported)
*/
-#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
+#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (card->ext_csd.hpi) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HPI_MGMT, 1,
@@ -2047,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);
@@ -2118,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