From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 13 May 2024 10:30:14 +0000
Subject: [PATCH] modify sin led gpio

---
 kernel/drivers/mmc/host/sdhci-of-dwcmshc.c |  413 +++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 278 insertions(+), 135 deletions(-)

diff --git a/kernel/drivers/mmc/host/sdhci-of-dwcmshc.c b/kernel/drivers/mmc/host/sdhci-of-dwcmshc.c
index c1d95d7..ae9a2a9 100644
--- a/kernel/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ b/kernel/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -7,6 +7,7 @@
  * Author: Jisheng Zhang <jszhang@kernel.org>
  */
 
+#include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/iopoll.h>
@@ -26,11 +27,15 @@
 /* DWCMSHC specific Mode Select value */
 #define DWCMSHC_CTRL_HS400		0x7
 
-#define DWCMSHC_VER_ID			0x500
-#define DWCMSHC_VER_TYPE		0x504
-#define DWCMSHC_HOST_CTRL3		0x508
-#define DWCMSHC_EMMC_CONTROL		0x52c
-#define DWCMSHC_EMMC_ATCTRL		0x540
+/* DWC IP vendor area 1 pointer */
+#define DWCMSHC_P_VENDOR_AREA1		0xe8
+#define DWCMSHC_AREA1_MASK		GENMASK(11, 0)
+/* Offset inside the  vendor area 1 */
+#define DWCMSHC_HOST_CTRL3		0x8
+#define DWCMSHC_EMMC_CONTROL		0x2c
+#define DWCMSHC_CARD_IS_EMMC		BIT(0)
+#define DWCMSHC_ENHANCED_STROBE		BIT(8)
+#define DWCMSHC_EMMC_ATCTRL		0x40
 
 /* Rockchip specific Registers */
 #define DWCMSHC_EMMC_DLL_CTRL		0x800
@@ -40,31 +45,30 @@
 #define DECMSHC_EMMC_DLL_CMDOUT		0x810
 #define DWCMSHC_EMMC_DLL_STATUS0	0x840
 #define DWCMSHC_EMMC_DLL_STATUS1	0x844
-
 #define DWCMSHC_EMMC_DLL_START		BIT(0)
 #define DWCMSHC_EMMC_DLL_LOCKED		BIT(8)
 #define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9)
+#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL	29
 #define DWCMSHC_EMMC_DLL_START_POINT	16
 #define DWCMSHC_EMMC_DLL_INC		8
 #define DWCMSHC_EMMC_DLL_BYPASS		BIT(24)
 #define DWCMSHC_EMMC_DLL_DLYENA		BIT(27)
-
 #define DLL_TAP_VALUE_SEL		BIT(25)
 #define DLL_TAP_VALUE_OFFSET		8
-
+#define DLL_TXCLK_TAPNUM_DEFAULT	0x10
+#define DLL_TXCLK_TAPNUM_90_DEGREES	0xA
 #define DLL_TXCLK_TAPNUM_FROM_SW	BIT(24)
-#define DLL_TXCLK_NO_INVERTER		BIT(29)
-
+#define DLL_STRBIN_TAPNUM_DEFAULT	0x8
 #define DLL_STRBIN_TAPNUM_FROM_SW	BIT(24)
 #define DLL_STRBIN_DELAY_NUM_SEL	BIT(26)
 #define DLL_STRBIN_DELAY_NUM_OFFSET	16
-
-#define DLL_RXCLK_NO_INVERTER		BIT(29)
+#define DLL_STRBIN_DELAY_NUM_DEFAULT	0x16
+#define DLL_RXCLK_NO_INVERTER		1
+#define DLL_RXCLK_INVERTER		0
+#define DLL_CMDOUT_TAPNUM_90_DEGREES	0x8
+#define DLL_RXCLK_TAPNUM_FROM_SW	BIT(24)
 #define DLL_RXCLK_ORI_GATE		BIT(31)
-
-#define DWCMSHC_CARD_IS_EMMC		BIT(0)
-#define DWCMSHC_ENHANCED_STROBE		BIT(8)
-
+#define DLL_RXCLK_MAX_TAP		32
 #define DLL_CMDOUT_TAPNUM_FROM_SW	BIT(24)
 #define DLL_CMDOUT_SRC_CLK_NEG		BIT(28)
 #define DLL_CMDOUT_EN_SRC_CLK_NEG	BIT(29)
@@ -73,10 +77,15 @@
 #define DLL_LOCK_WO_TMOUT(x) \
 	((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
 	(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
-#define ROCKCHIP_MAX_CLKS		3
+#define RK35xx_MAX_CLKS 3
 
 #define BOUNDARY_OK(addr, len) \
 	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
+
+enum dwcmshc_rk_type {
+	DWCMSHC_RK3568,
+	DWCMSHC_RK3588,
+};
 
 struct dwcmshc_driver_data {
 	const struct sdhci_pltfm_data *pdata;
@@ -93,15 +102,22 @@
 	u8 hs400_strbin_tap;
 };
 
-struct dwcmshc_priv {
-	struct clk	*bus_clk;
-	u32 cclk_rate;
-
+struct rk35xx_priv {
 	/* Rockchip specified optional clocks */
-	struct clk_bulk_data rockchip_clks[ROCKCHIP_MAX_CLKS];
+	struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS];
 	struct reset_control *reset;
+	enum dwcmshc_rk_type devtype;
+	u8 txclk_tapnum;
+	u32 cclk_rate;
 	unsigned int actual_clk;
 	const struct dwcmshc_driver_data *drv_data;
+	u32 acpi_en;
+};
+
+struct dwcmshc_priv {
+	struct clk	*bus_clk;
+	int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
+	void *priv; /* pointer to SoC private stuff */
 };
 
 /*
@@ -125,6 +141,16 @@
 	addr += tmplen;
 	len -= tmplen;
 	sdhci_adma_write_desc(host, desc, addr, len, cmd);
+}
+
+static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	if (pltfm_host->clk)
+		return sdhci_pltfm_clk_get_max_clock(host);
+	else
+		return pltfm_host->clock;
 }
 
 static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,
@@ -153,7 +179,9 @@
 static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
 				      unsigned int timing)
 {
-	u16 ctrl_2, ctrl;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	u16 ctrl, ctrl_2;
 
 	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	/* Select Bus Speed Mode for host */
@@ -173,9 +201,9 @@
 		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
 	else if (timing == MMC_TIMING_MMC_HS400) {
 		/* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
-		ctrl = sdhci_readw(host, DWCMSHC_EMMC_CONTROL);
+		ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL);
 		ctrl |= DWCMSHC_CARD_IS_EMMC;
-		sdhci_writew(host, ctrl, DWCMSHC_EMMC_CONTROL);
+		sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL);
 
 		ctrl_2 |= DWCMSHC_CTRL_HS400;
 	}
@@ -188,22 +216,27 @@
 {
 	u32 vendor;
 	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL;
 
-	vendor = sdhci_readl(host, DWCMSHC_EMMC_CONTROL);
+	vendor = sdhci_readl(host, reg);
 	if (ios->enhanced_strobe)
 		vendor |= DWCMSHC_ENHANCED_STROBE;
 	else
 		vendor &= ~DWCMSHC_ENHANCED_STROBE;
 
-	sdhci_writel(host, vendor, DWCMSHC_EMMC_CONTROL);
+	sdhci_writel(host, vendor, reg);
 }
 
-static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
+static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
+	struct rk35xx_priv *priv = dwc_priv->priv;
 	const struct dwcmshc_driver_data *drv_data = priv->drv_data;
-	u32 txclk_tapnum, extra, dll_lock_value;
+	u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
+	u32 extra, reg, dll_lock_value;
 	int err;
 
 	host->mmc->actual_clock = 0;
@@ -218,16 +251,28 @@
 	if (clock <= 400000)
 		clock = 375000;
 
-	err = clk_set_rate(pltfm_host->clk, clock);
-	if (err)
-		dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock);
+	if (priv->acpi_en) {
+		union acpi_object params[1];
+		struct acpi_object_list param_objects;
+
+		params[0].type = ACPI_TYPE_INTEGER;
+		params[0].integer.value  = clock;
+		param_objects.count = 1;
+		param_objects.pointer = params;
+		acpi_evaluate_object(ACPI_HANDLE(mmc_dev(host->mmc)), "SCLK", &param_objects, NULL);
+	} else {
+		err = clk_set_rate(pltfm_host->clk, clock);
+		if (err)
+			dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock);
+	}
 
 	sdhci_set_clock(host, clock);
 
 	/* Disable cmd conflict check */
-	extra = sdhci_readl(host, DWCMSHC_HOST_CTRL3);
+	reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3;
+	extra = sdhci_readl(host, reg);
 	extra &= ~BIT(0);
-	sdhci_writel(host, extra, DWCMSHC_HOST_CTRL3);
+	sdhci_writel(host, extra, reg);
 
 	/* Disable output clock while config DLL */
 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
@@ -262,6 +307,7 @@
 
 	/* Init DLL settings, clean start bit before resetting */
 	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+	/* Init DLL settings */
 	extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT |
 		0x2 << DWCMSHC_EMMC_DLL_INC |
 		DWCMSHC_EMMC_DLL_START;
@@ -279,11 +325,11 @@
 	extra = 0x1 << 16 | /* tune clock stop en */
 		0x3 << 17 | /* pre-change delay */
 		0x3 << 19;  /* post-change delay */
-	sdhci_writel(host, extra, DWCMSHC_EMMC_ATCTRL);
+	sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
 
 	extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
 	if (drv_data->flags & RK_RXCLK_NO_INVERTER)
-		extra |= DLL_RXCLK_NO_INVERTER;
+		extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
 	if (drv_data->flags & RK_TAP_VALUE_SEL)
 		extra |= DLL_TAP_VALUE_SEL | dll_lock_value << DLL_TAP_VALUE_OFFSET;
 	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
@@ -305,7 +351,7 @@
 	}
 	extra = DWCMSHC_EMMC_DLL_DLYENA |
 		DLL_TXCLK_TAPNUM_FROM_SW |
-		DLL_RXCLK_NO_INVERTER |
+		DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL |
 		txclk_tapnum;
 	if (drv_data->flags & RK_TAP_VALUE_SEL)
 		extra |= DLL_TAP_VALUE_SEL | dll_lock_value << DLL_TAP_VALUE_OFFSET;
@@ -323,19 +369,16 @@
 	sdhci_enable_clk(host, 0);
 }
 
-static void rockchip_sdhci_reset(struct sdhci_host *host, u8 mask)
+static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
-	struct sdhci_pltfm_host *pltfm_host;
-	struct dwcmshc_priv *priv;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
+	struct rk35xx_priv *priv = dwc_priv->priv;
 
-	if (mask & SDHCI_RESET_ALL) {
-		pltfm_host = sdhci_priv(host);
-		priv = sdhci_pltfm_priv(pltfm_host);
-		if (!IS_ERR_OR_NULL(priv->reset)) {
-			reset_control_assert(priv->reset);
-			udelay(1);
-			reset_control_deassert(priv->reset);
-		}
+	if (mask & SDHCI_RESET_ALL && priv->reset) {
+		reset_control_assert(priv->reset);
+		udelay(1);
+		reset_control_deassert(priv->reset);
 	}
 
 	sdhci_reset(host, mask);
@@ -353,17 +396,17 @@
 	.set_clock		= sdhci_set_clock,
 	.set_bus_width		= sdhci_set_bus_width,
 	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,
-	.get_max_clock		= sdhci_pltfm_clk_get_max_clock,
+	.get_max_clock		= dwcmshc_get_max_clock,
 	.reset			= sdhci_reset,
 	.adma_write_desc	= dwcmshc_adma_write_desc,
 };
 
-static const struct sdhci_ops sdhci_dwcmshc_rk_ops = {
-	.set_clock		= dwcmshc_rk_set_clock,
+static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
+	.set_clock		= dwcmshc_rk3568_set_clock,
 	.set_bus_width		= sdhci_set_bus_width,
 	.set_uhs_signaling	= dwcmshc_set_uhs_signaling,
 	.get_max_clock		= sdhci_pltfm_clk_get_max_clock,
-	.reset			= rockchip_sdhci_reset,
+	.reset			= rk35xx_sdhci_reset,
 	.adma_write_desc	= dwcmshc_adma_write_desc,
 	.request_done		= sdhci_dwcmshc_request_done,
 };
@@ -374,12 +417,76 @@
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
-static const struct sdhci_pltfm_data sdhci_dwcmshc_rk_pdata = {
-	.ops = &sdhci_dwcmshc_rk_ops,
+#ifdef CONFIG_ACPI
+static const struct sdhci_pltfm_data sdhci_dwcmshc_bf3_pdata = {
+	.ops = &sdhci_dwcmshc_ops,
+	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+		   SDHCI_QUIRK2_ACMD23_BROKEN,
+};
+#endif
+
+static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
+	.ops = &sdhci_dwcmshc_rk35xx_ops,
 	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
 		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
 };
+
+static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
+{
+	int err;
+	struct rk35xx_priv *priv = dwc_priv->priv;
+
+	priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc));
+	if (IS_ERR(priv->reset)) {
+		err = PTR_ERR(priv->reset);
+		dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err);
+		return err;
+	}
+
+	priv->rockchip_clks[0].id = "axi";
+	priv->rockchip_clks[1].id = "block";
+	priv->rockchip_clks[2].id = "timer";
+	err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK35xx_MAX_CLKS,
+					 priv->rockchip_clks);
+	if (err) {
+		dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err);
+		return err;
+	}
+
+	err = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, priv->rockchip_clks);
+	if (err) {
+		dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err);
+		return err;
+	}
+
+	if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum",
+				&priv->txclk_tapnum))
+		priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
+
+	/* Disable cmd conflict check */
+	sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3);
+	/* Reset previous settings */
+	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
+
+	return 0;
+}
+
+static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
+{
+	/*
+	 * Don't support highspeed bus mode with low clk speed as we
+	 * cannot use DLL for this condition.
+	 */
+	if (host->mmc->f_max <= 52000000) {
+		dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n",
+			 host->mmc->f_max);
+		host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400);
+		host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR);
+	}
+}
 
 static const struct dwcmshc_driver_data dwcmshc_drvdata = {
 	.pdata = &sdhci_dwcmshc_pdata,
@@ -387,7 +494,7 @@
 };
 
 static const struct dwcmshc_driver_data rk3568_drvdata = {
-	.pdata = &sdhci_dwcmshc_rk_pdata,
+	.pdata = &sdhci_dwcmshc_rk35xx_pdata,
 	.flags = RK_PLATFROM | RK_RXCLK_NO_INVERTER,
 	.hs200_tx_tap = 16,
 	.hs400_tx_tap = 8,
@@ -397,7 +504,7 @@
 };
 
 static const struct dwcmshc_driver_data rk3588_drvdata = {
-	.pdata = &sdhci_dwcmshc_rk_pdata,
+	.pdata = &sdhci_dwcmshc_rk35xx_pdata,
 	.flags = RK_PLATFROM | RK_DLL_CMD_OUT,
 	.hs200_tx_tap = 16,
 	.hs400_tx_tap = 9,
@@ -407,7 +514,7 @@
 };
 
 static const struct dwcmshc_driver_data rk3528_drvdata = {
-	.pdata = &sdhci_dwcmshc_rk_pdata,
+	.pdata = &sdhci_dwcmshc_rk35xx_pdata,
 	.flags = RK_PLATFROM | RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
 	.hs200_tx_tap = 12,
 	.hs400_tx_tap = 6,
@@ -416,51 +523,23 @@
 	.ddr50_strbin_delay_num = 10,
 };
 
-static int rockchip_pltf_init(struct sdhci_host *host, struct dwcmshc_priv *priv)
-{
-	int err;
-
-	priv->rockchip_clks[0].id = "axi";
-	priv->rockchip_clks[1].id = "block";
-	priv->rockchip_clks[2].id = "timer";
-	err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), ROCKCHIP_MAX_CLKS,
-					 priv->rockchip_clks);
-	if (err) {
-		dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err);
-		return err;
-	}
-
-	err = clk_bulk_prepare_enable(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
-	if (err) {
-		dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err);
-		return err;
-	}
-
-	/* Disable cmd conflict check */
-	sdhci_writel(host, 0x0, DWCMSHC_HOST_CTRL3);
-	/* Reset previous settings */
-	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
-	sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
-
-	/*
-	 * Don't support highspeed bus mode with low clk speed as we
-	 * cannot use DLL for this condition.
-	 */
-	if (host->mmc->f_max <= 52000000) {
-		host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400);
-		host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR);
-	}
-
-	return 0;
-}
+static const struct dwcmshc_driver_data rk3562_drvdata = {
+	.pdata = &sdhci_dwcmshc_rk35xx_pdata,
+	.flags = RK_PLATFROM | RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
+	.hs200_tx_tap = 12,
+	.hs400_tx_tap = 6,
+	.hs400_cmd_tap = 6,
+	.hs400_strbin_tap = 3,
+	.ddr50_strbin_delay_num = 10,
+};
 
 static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
 	{
-		.compatible = "snps,dwcmshc-sdhci",
-		.data = &dwcmshc_drvdata,
+		.compatible = "rockchip,rk3588-dwcmshc",
+		.data = &rk3588_drvdata,
 	},
 	{
-		.compatible = "rockchip,dwcmshc-sdhci",
+		.compatible = "rockchip,rk3568-dwcmshc",
 		.data = &rk3568_drvdata,
 	},
 	{
@@ -468,17 +547,35 @@
 		.data = &rk3528_drvdata,
 	},
 	{
-		.compatible = "rockchip,rk3588-dwcmshc",
-		.data = &rk3588_drvdata,
+		.compatible = "rockchip,rk3562-dwcmshc",
+		.data = &rk3562_drvdata,
+	},
+	{
+		.compatible = "snps,dwcmshc-sdhci",
+		.data = &dwcmshc_drvdata,
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = {
+	{
+		.id = "MLNXBF30",
+		.driver_data = (kernel_ulong_t)&sdhci_dwcmshc_bf3_pdata,
+	},
+	{}
+};
+#endif
 
 static int dwcmshc_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_host *host;
 	struct dwcmshc_priv *priv;
+	struct rk35xx_priv *rk_priv = NULL;
+	const struct sdhci_pltfm_data *pltfm_data;
 	const struct dwcmshc_driver_data *drv_data;
 	struct mmc_hsq *hsq;
 	int err;
@@ -489,8 +586,9 @@
 		dev_err(&pdev->dev, "Error: No device match data found\n");
 		return -ENODEV;
 	}
+	pltfm_data = drv_data->pdata;
 
-	host = sdhci_pltfm_init(pdev, drv_data->pdata,
+	host = sdhci_pltfm_init(pdev, pltfm_data,
 				sizeof(struct dwcmshc_priv));
 	if (IS_ERR(host))
 		return PTR_ERR(host);
@@ -498,34 +596,38 @@
 	/*
 	 * extra adma table cnt for cross 128M boundary handling.
 	 */
-	extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M);
+	extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M);
 	if (extra > SDHCI_MAX_SEGS)
 		extra = SDHCI_MAX_SEGS;
 	host->adma_table_cnt += extra;
 
 	pltfm_host = sdhci_priv(host);
 	priv = sdhci_pltfm_priv(pltfm_host);
-	priv->drv_data = drv_data;
-	priv->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
-	pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
-	if (IS_ERR(pltfm_host->clk)) {
-		err = PTR_ERR(pltfm_host->clk);
-		dev_err(&pdev->dev, "failed to get core clk: %d\n", err);
-		goto free_pltfm;
-	}
-	err = clk_prepare_enable(pltfm_host->clk);
-	if (err)
-		goto free_pltfm;
 
-	priv->bus_clk = devm_clk_get(&pdev->dev, "bus");
-	if (!IS_ERR(priv->bus_clk))
-		clk_prepare_enable(priv->bus_clk);
+	if (dev->of_node) {
+		pltfm_host->clk = devm_clk_get(dev, "core");
+		if (IS_ERR(pltfm_host->clk)) {
+			err = PTR_ERR(pltfm_host->clk);
+			dev_err(dev, "failed to get core clk: %d\n", err);
+			goto free_pltfm;
+		}
+		err = clk_prepare_enable(pltfm_host->clk);
+		if (err)
+			goto free_pltfm;
+
+		priv->bus_clk = devm_clk_get(dev, "bus");
+		if (!IS_ERR(priv->bus_clk))
+			clk_prepare_enable(priv->bus_clk);
+	}
 
 	err = mmc_of_parse(host->mmc);
 	if (err)
 		goto err_clk;
 
 	sdhci_get_of_property(pdev);
+
+	priv->vendor_specific_area1 =
+		sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK;
 
 	host->mmc_host_ops.request = dwcmshc_request;
 	host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe;
@@ -540,29 +642,60 @@
 	if (err)
 		goto err_clk;
 
-	err = sdhci_add_host(host);
-	if (err)
-		goto err_clk;
-
 	if (drv_data->flags & RK_PLATFROM) {
-		err = rockchip_pltf_init(host, priv);
+		rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL);
+		if (!rk_priv) {
+			err = -ENOMEM;
+			goto err_clk;
+		}
+
+		rk_priv->drv_data = drv_data;
+		rk_priv->acpi_en = has_acpi_companion(&pdev->dev);
+
+		if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc"))
+			rk_priv->devtype = DWCMSHC_RK3588;
+		else
+			rk_priv->devtype = DWCMSHC_RK3568;
+
+		priv->priv = rk_priv;
+
+		err = dwcmshc_rk35xx_init(host, priv);
 		if (err)
 			goto err_clk;
 	}
 
-	pm_runtime_get_noresume(&pdev->dev);
-	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
-	pm_runtime_use_autosuspend(&pdev->dev);
-	pm_runtime_put_autosuspend(&pdev->dev);
+	host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
+
+	err = sdhci_setup_host(host);
+	if (err)
+		goto err_clk;
+
+	if (rk_priv)
+		dwcmshc_rk35xx_postinit(host, priv);
+
+	err = __sdhci_add_host(host);
+	if (err)
+		goto err_setup_host;
+
+	if (rk_priv && !rk_priv->acpi_en) {
+		pm_runtime_get_noresume(&pdev->dev);
+		pm_runtime_set_active(&pdev->dev);
+		pm_runtime_enable(&pdev->dev);
+		pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+		pm_runtime_use_autosuspend(&pdev->dev);
+		pm_runtime_put_autosuspend(&pdev->dev);
+	}
 
 	return 0;
 
+err_setup_host:
+	sdhci_cleanup_host(host);
 err_clk:
 	clk_disable_unprepare(pltfm_host->clk);
 	clk_disable_unprepare(priv->bus_clk);
-	clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
+	if (rk_priv)
+		clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
+					   rk_priv->rockchip_clks);
 free_pltfm:
 	sdhci_pltfm_free(pdev);
 	return err;
@@ -573,13 +706,15 @@
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	struct rk35xx_priv *rk_priv = priv->priv;
 
 	sdhci_remove_host(host, 0);
 
 	clk_disable_unprepare(pltfm_host->clk);
 	clk_disable_unprepare(priv->bus_clk);
-	clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
-
+	if (rk_priv)
+		clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
+					   rk_priv->rockchip_clks);
 	sdhci_pltfm_free(pdev);
 
 	return 0;
@@ -591,6 +726,7 @@
 	struct sdhci_host *host = dev_get_drvdata(dev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	struct rk35xx_priv *rk_priv = priv->priv;
 	int ret;
 
 	mmc_hsq_suspend(host->mmc);
@@ -603,7 +739,10 @@
 	if (!IS_ERR(priv->bus_clk))
 		clk_disable_unprepare(priv->bus_clk);
 
-	clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
+	if (rk_priv)
+		clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
+					   rk_priv->rockchip_clks);
+
 	return ret;
 }
 
@@ -612,6 +751,7 @@
 	struct sdhci_host *host = dev_get_drvdata(dev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	struct rk35xx_priv *rk_priv = priv->priv;
 	int ret;
 
 	ret = clk_prepare_enable(pltfm_host->clk);
@@ -624,9 +764,12 @@
 			return ret;
 	}
 
-	ret = clk_bulk_prepare_enable(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
-	if (ret)
-		return ret;
+	if (rk_priv) {
+		ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS,
+					      rk_priv->rockchip_clks);
+		if (ret)
+			return ret;
+	}
 
 	ret = sdhci_resume_host(host);
 	if (ret)
@@ -664,13 +807,13 @@
 	SET_SYSTEM_SLEEP_PM_OPS(dwcmshc_suspend, dwcmshc_resume)
 	SET_RUNTIME_PM_OPS(dwcmshc_runtime_suspend, dwcmshc_runtime_resume, NULL)
 };
-MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
 
 static struct platform_driver sdhci_dwcmshc_driver = {
 	.driver	= {
 		.name	= "sdhci-dwcmshc",
 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
 		.of_match_table = sdhci_dwcmshc_dt_ids,
+		.acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids),
 		.pm = &dwcmshc_pmops,
 	},
 	.probe	= dwcmshc_probe,

--
Gitblit v1.6.2