From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:45:28 +0000
Subject: [PATCH] add boot partition  size

---
 kernel/drivers/mmc/host/dw_mmc.c |  239 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 127 insertions(+), 112 deletions(-)

diff --git a/kernel/drivers/mmc/host/dw_mmc.c b/kernel/drivers/mmc/host/dw_mmc.c
index 954e932..fde4946 100644
--- a/kernel/drivers/mmc/host/dw_mmc.c
+++ b/kernel/drivers/mmc/host/dw_mmc.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Synopsys DesignWare Multimedia Card Interface driver
  *  (Based on NXP driver for lpc 31xx)
  *
  * Copyright (C) 2009 NXP Semiconductors
  * Copyright (C) 2009, 2010 Imagination Technologies Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #include <linux/blkdev.h>
@@ -40,6 +36,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/mmc/slot-gpio.h>
+#include <linux/soc/rockchip/rk_sdmmc.h>
 #include <linux/soc/rockchip/rockchip_decompress.h>
 
 #include "dw_mmc.h"
@@ -109,6 +106,24 @@
 /* Each descriptor can transfer up to 4KB of data in chained mode */
 #define DW_MCI_DESC_DATA_LENGTH	0x1000
 
+#if IS_ENABLED(CONFIG_CPU_RV1106)
+static spinlock_t *g_sdmmc_ispvicap_lock;
+
+void rv1106_sdmmc_get_lock(void)
+{
+	if (g_sdmmc_ispvicap_lock)
+		spin_lock(g_sdmmc_ispvicap_lock);
+}
+EXPORT_SYMBOL(rv1106_sdmmc_get_lock);
+
+void rv1106_sdmmc_put_lock(void)
+{
+	if (g_sdmmc_ispvicap_lock)
+		spin_unlock(g_sdmmc_ispvicap_lock);
+}
+EXPORT_SYMBOL(rv1106_sdmmc_put_lock);
+#endif
+
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
 {
@@ -175,40 +190,18 @@
 	struct mmc_host	*mmc = slot->mmc;
 	struct dw_mci *host = slot->host;
 	struct dentry *root;
-	struct dentry *node;
 
 	root = mmc->debugfs_root;
 	if (!root)
 		return;
 
-	node = debugfs_create_file("regs", S_IRUSR, root, host,
-				   &dw_mci_regs_fops);
-	if (!node)
-		goto err;
-
-	node = debugfs_create_file("req", S_IRUSR, root, slot,
-				   &dw_mci_req_fops);
-	if (!node)
-		goto err;
-
-	node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state);
-	if (!node)
-		goto err;
-
-	node = debugfs_create_x32("pending_events", S_IRUSR, root,
-				  (u32 *)&host->pending_events);
-	if (!node)
-		goto err;
-
-	node = debugfs_create_x32("completed_events", S_IRUSR, root,
-				  (u32 *)&host->completed_events);
-	if (!node)
-		goto err;
-
-	return;
-
-err:
-	dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
+	debugfs_create_file("regs", S_IRUSR, root, host, &dw_mci_regs_fops);
+	debugfs_create_file("req", S_IRUSR, root, slot, &dw_mci_req_fops);
+	debugfs_create_u32("state", S_IRUSR, root, &host->state);
+	debugfs_create_xul("pending_events", S_IRUSR, root,
+			   &host->pending_events);
+	debugfs_create_xul("completed_events", S_IRUSR, root,
+			   &host->completed_events);
 }
 #endif /* defined(CONFIG_DEBUG_FS) */
 
@@ -247,7 +240,8 @@
 	 * expected.
 	 */
 #ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
-	if (host->slot->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
+	if (host->slot->mmc->caps2 & MMC_CAP2_NO_SD &&
+	    host->slot->mmc->caps2 & MMC_CAP2_NO_SDIO)
 		delay = 0;
 #endif
 	if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) &&
@@ -488,14 +482,20 @@
 
 	/* Disable and reset the IDMAC interface */
 	temp = mci_readl(host, CTRL);
-	temp &= ~SDMMC_CTRL_USE_IDMAC;
+	if (!host->is_rv1106_sd)
+		temp &= ~SDMMC_CTRL_USE_IDMAC;
+
 	temp |= SDMMC_CTRL_DMA_RESET;
 	mci_writel(host, CTRL, temp);
 
 	/* Stop the IDMAC running */
 	temp = mci_readl(host, BMOD);
-	temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB);
-	temp |= SDMMC_IDMAC_SWRESET;
+	if (host->is_rv1106_sd) {
+		temp |= SDMMC_IDMAC_SWRESET;
+	} else {
+		temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB);
+		temp |= SDMMC_IDMAC_SWRESET;
+	}
 	mci_writel(host, BMOD, temp);
 }
 
@@ -736,6 +736,13 @@
 		}
 	}
 
+	if (host->is_rv1106_sd && (data->flags & MMC_DATA_WRITE)) {
+		desc->des0 = desc_last->des0;
+		desc->des2 = desc_last->des2;
+		desc->des1 = 0x8; /* Random dirty data for last one desc */
+		desc_last = desc;
+	}
+
 	/* Set first descriptor */
 	desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD);
 
@@ -871,12 +878,14 @@
 	if (!host->dms)
 		return -ENOMEM;
 
-	host->dms->ch = dma_request_slave_channel(host->dev, "rx-tx");
-	if (!host->dms->ch) {
+	host->dms->ch = dma_request_chan(host->dev, "rx-tx");
+	if (IS_ERR(host->dms->ch)) {
+		int ret = PTR_ERR(host->dms->ch);
+
 		dev_err(host->dev, "Failed to get external DMA channel.\n");
 		kfree(host->dms);
 		host->dms = NULL;
-		return -ENXIO;
+		return ret;
 	}
 
 	return 0;
@@ -918,7 +927,7 @@
 	 * non-word-aligned buffers or lengths. Also, we don't bother
 	 * with all the DMA setup overhead for short transfers.
 	 */
-	if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
+	if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD && !host->is_rv1106_sd)
 		return -EINVAL;
 
 	if (data->blksz & 3)
@@ -976,39 +985,12 @@
 	data->host_cookie = COOKIE_UNMAPPED;
 }
 
-static int dw_mci_set_sdio_status(struct mmc_host *mmc, int val)
-{
-	struct dw_mci_slot *slot = mmc_priv(mmc);
-	struct dw_mci *host = slot->host;
-
-	if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO))
-		return 0;
-
-	spin_lock_bh(&host->lock);
-
-	if (val)
-		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-	else
-		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
-	spin_unlock_bh(&host->lock);
-
-	mmc_detect_change(slot->mmc, 20);
-
-	return 0;
-}
-
 static int dw_mci_get_cd(struct mmc_host *mmc)
 {
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci *host = slot->host;
 	int gpio_cd = mmc_gpio_get_cd(mmc);
-
-#ifdef CONFIG_SDIO_KEEPALIVE
-	if (mmc->logic_remove_card)
-		return test_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-#endif
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (((mmc->caps & MMC_CAP_NEEDS_POLL)
@@ -1358,10 +1340,16 @@
 	host->data_status = 0;
 	host->dir_status = 0;
 
+	if (host->is_rv1106_sd)
+		mci_writel(host, CTYPE, (slot->ctype << slot->id));
+
 	data = cmd->data;
 	if (data) {
 		mci_writel(host, TMOUT, 0xFFFFFFFF);
-		mci_writel(host, BYTCNT, data->blksz*data->blocks);
+		if (host->is_rv1106_sd && (data->flags & MMC_DATA_WRITE))
+			mci_writel(host, BYTCNT, 0);
+		else
+			mci_writel(host, BYTCNT, data->blksz*data->blocks);
 		mci_writel(host, BLKSIZ, data->blksz);
 	}
 
@@ -1439,6 +1427,7 @@
 	}
 }
 
+static bool dw_mci_reset(struct dw_mci *host);
 static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -1458,7 +1447,17 @@
 		return;
 	}
 
+	if (host->is_rv1106_sd) {
+		u32 reg;
+
+		readl_poll_timeout(host->regs + SDMMC_STATUS, reg,
+				   reg & BIT(2), USEC_PER_MSEC, 500 * USEC_PER_MSEC);
+	}
+
 	spin_lock_bh(&host->lock);
+
+	if (host->is_rv1106_sd)
+		dw_mci_reset(host);
 
 	dw_mci_queue_request(host, slot, mrq);
 
@@ -1563,11 +1562,8 @@
 		if (!IS_ERR(mmc->supply.vmmc))
 			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
 
-		if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) {
-			ios->signal_voltage = MMC_SIGNAL_VOLTAGE_330;
-			mmc_regulator_set_vqmmc(mmc, ios);
+		if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled)
 			regulator_disable(mmc->supply.vqmmc);
-		}
 		slot->host->vqmmc_enabled = false;
 
 		regs = mci_readl(slot->host, PWREN);
@@ -1621,8 +1617,7 @@
 
 	if (!IS_ERR(mmc->supply.vqmmc)) {
 		ret = mmc_regulator_set_vqmmc(mmc, ios);
-
-		if (ret) {
+		if (ret < 0) {
 			dev_dbg(&mmc->class_dev,
 					 "Regulator set error %d - %s V\n",
 					 ret, uhs & v18 ? "1.8" : "3.3");
@@ -1852,7 +1847,6 @@
 	.pre_req		= dw_mci_pre_req,
 	.post_req		= dw_mci_post_req,
 	.set_ios		= dw_mci_set_ios,
-	.set_sdio_status	= dw_mci_set_sdio_status,
 	.get_ro			= dw_mci_get_ro,
 	.get_cd			= dw_mci_get_cd,
 	.hw_reset               = dw_mci_hw_reset,
@@ -1894,6 +1888,7 @@
 	}
 
 	spin_unlock(&host->lock);
+
 	mmc_request_done(prev_mmc, mrq);
 	spin_lock(&host->lock);
 }
@@ -1935,6 +1930,9 @@
 {
 	u32 status = host->data_status;
 
+	if (host->is_rv1106_sd && (data->flags & MMC_DATA_WRITE) && (status & SDMMC_INT_DATA_OVER))
+		goto finish;
+
 	if (status & DW_MCI_DATA_ERROR_FLAGS) {
 		if (status & SDMMC_INT_DRTO) {
 			data->error = -ETIMEDOUT;
@@ -1967,6 +1965,7 @@
 		 */
 		dw_mci_reset(host);
 	} else {
+finish:
 		data->bytes_xfered = data->blocks * data->blksz;
 		data->error = 0;
 	}
@@ -2132,7 +2131,7 @@
 			}
 
 			prev_state = state = STATE_SENDING_DATA;
-			/* fall through */
+			fallthrough;
 
 		case STATE_SENDING_DATA:
 			/*
@@ -2193,7 +2192,7 @@
 			}
 			prev_state = state = STATE_DATA_BUSY;
 
-			/* fall through */
+			fallthrough;
 
 		case STATE_DATA_BUSY:
 			if (!dw_mci_clear_pending_data_complete(host)) {
@@ -2246,7 +2245,7 @@
 			 */
 			prev_state = state = STATE_SENDING_STOP;
 
-			/* fall through */
+			fallthrough;
 
 		case STATE_SENDING_STOP:
 			if (!dw_mci_clear_pending_cmd_complete(host))
@@ -2771,11 +2770,14 @@
 		}
 
 		if (pending & SDMMC_INT_DATA_OVER) {
+rv1106_sd:
 			spin_lock_irqsave(&host->irq_lock, irqflags);
 
 			del_timer(&host->dto_timer);
 
 			mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
+			if (host->is_rv1106_sd)
+				pending |= SDMMC_INT_DATA_OVER;
 			if (!host->data_status)
 				host->data_status = pending;
 			smp_wmb(); /* drain writebuffer */
@@ -2845,6 +2847,9 @@
 			mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
 			if (!test_bit(EVENT_DATA_ERROR, &host->pending_events))
 				host->dma_ops->complete((void *)host);
+
+			if (host->is_rv1106_sd && (pending & SDMMC_IDMAC_INT_TI))
+				goto rv1106_sd;
 		}
 	}
 
@@ -2860,12 +2865,6 @@
 
 	if (host->pdata->caps)
 		mmc->caps = host->pdata->caps;
-
-	/*
-	 * Support MMC_CAP_ERASE by default.
-	 * It needs to use trim/discard/erase commands.
-	 */
-	mmc->caps |= MMC_CAP_ERASE;
 
 	if (host->pdata->pm_caps)
 		mmc->pm_caps = host->pdata->pm_caps;
@@ -2884,15 +2883,7 @@
 				ctrl_id);
 			return -EINVAL;
 		}
-		/*
-		 * Some sd cards violate the spec. They claim to support
-		 * CMD23 but actually not. We don't have a good method to
-		 * work around them except for adding MMC_QUIRK_BLK_NO_CMD23
-		 * one by one. But it's not a acceptable way for our custmors.
-		 * So removing CMD23 support for all sd cards to solve it.
-		 */
-		if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD))
-			mmc->caps |= drv_data->caps[ctrl_id];
+		mmc->caps |= drv_data->caps[ctrl_id];
 	}
 
 	if (host->pdata->caps2)
@@ -2946,6 +2937,10 @@
 
 	/* Useful defaults if platform data is unset. */
 	if (host->use_dma == TRANS_MODE_IDMAC) {
+		/* Reserve last desc for dirty data */
+		if (host->is_rv1106_sd)
+			host->ring_size--;
+
 		mmc->max_segs = host->ring_size;
 		mmc->max_blk_size = 65535;
 		mmc->max_seg_size = 0x1000;
@@ -2969,11 +2964,6 @@
 	}
 
 	dw_mci_get_cd(mmc);
-
-#ifdef CONFIG_SDIO_KEEPALIVE
-	if (mmc->logic_remove_card)
-		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-#endif
 
 	ret = mmc_add_host(mmc);
 	if (ret)
@@ -3336,12 +3326,9 @@
 
 	if (!host->pdata) {
 		host->pdata = dw_mci_parse_dt(host);
-		if (PTR_ERR(host->pdata) == -EPROBE_DEFER) {
-			return -EPROBE_DEFER;
-		} else if (IS_ERR(host->pdata)) {
-			dev_err(host->dev, "platform data not available\n");
-			return -EINVAL;
-		}
+		if (IS_ERR(host->pdata))
+			return dev_err_probe(host->dev, PTR_ERR(host->pdata),
+					     "platform data not available\n");
 	}
 
 	host->biu_clk = devm_clk_get(host->dev, "biu");
@@ -3354,8 +3341,10 @@
 			return ret;
 		}
 	}
+
 #ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
-	if (device_property_read_bool(host->dev, "supports-emmc")) {
+	if (device_property_read_bool(host->dev, "no-sd") &&
+	    device_property_read_bool(host->dev, "no-sdio")) {
 		if (readl_poll_timeout(host->regs + SDMMC_STATUS,
 				fifo_size,
 				!(fifo_size & (BIT(10) | GENMASK(7, 4))),
@@ -3532,6 +3521,24 @@
 		goto err_dmaunmap;
 	}
 
+	if (host->is_rv1106_sd) {
+#if IS_ENABLED(CONFIG_CPU_RV1106)
+		g_sdmmc_ispvicap_lock = &host->lock;
+#endif
+		/* Select IDMAC interface */
+		fifo_size = mci_readl(host, CTRL);
+		fifo_size |= SDMMC_CTRL_USE_IDMAC;
+		mci_writel(host, CTRL, fifo_size);
+
+		fifo_size = mci_readl(host, INTMASK);
+		fifo_size &= ~SDMMC_INT_HTO;
+		mci_writel(host, INTMASK, fifo_size);
+
+		host->slot->mmc->caps &= ~(MMC_CAP_UHS_DDR50 | MMC_CAP_UHS_SDR104 |
+					   MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
+					   MMC_CAP_UHS_SDR12);
+	}
+
 	/* Now that slots are all setup, we can enable card detect */
 	dw_mci_enable_cd(host);
 
@@ -3629,18 +3636,26 @@
 	 * Restore the initial value at FIFOTH register
 	 * And Invalidate the prev_blksz with zero
 	 */
-	 mci_writel(host, FIFOTH, host->fifoth_val);
-	 host->prev_blksz = 0;
+	mci_writel(host, FIFOTH, host->fifoth_val);
+	host->prev_blksz = 0;
 
 	/* Put in max timeout */
 	mci_writel(host, TMOUT, 0xFFFFFFFF);
 
 	mci_writel(host, RINTSTS, 0xFFFFFFFF);
-	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
-		   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
-		   DW_MCI_ERROR_FLAGS);
+	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | DW_MCI_ERROR_FLAGS);
 	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
 
+	if (host->is_rv1106_sd) {
+		/* Select IDMAC interface */
+		ret = mci_readl(host, CTRL);
+		ret |= SDMMC_CTRL_USE_IDMAC;
+		mci_writel(host, CTRL, ret);
+
+		ret = mci_readl(host, INTMASK);
+		ret &= ~SDMMC_INT_HTO;
+		mci_writel(host, INTMASK, ret);
+	}
 
 	if (host->slot->mmc->pm_flags & MMC_PM_KEEP_POWER)
 		dw_mci_set_ios(host->slot->mmc, &host->slot->mmc->ios);

--
Gitblit v1.6.2