All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200
@ 2017-01-30 10:38 ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 01/15] mmc: sdhci: Update host capabilities about host controller Siva Durga Prasad Paladugu
                     ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

This patch series adds support SD3.0 and eMMC HS200
modes for ZynqMP. This series also contains changes
in mmc and sdhci framework to support SD3.0 and HS200.

Siva Durga Prasad Paladugu (15):
  mmc: sdhci: Update host capabilities about host controller
  mmc: Add support for SD3.0
  mmc: sdhci: Add SD3.0 support
  mmc: sdhci: Add support for platform/board specific tuning
  mmc: sdhci: Add support for platform specific delay
  mmc: sdhci: Make sdhci_ops of host as modifiable
  zynqmp: Define routines for mmio write and read
  mmc: sdhci: zynq: Define private structure arasan_sdhci_priv
  mmc: sdhci: zynqmp: Add support of SD3.0
  mmc: sdhci: Add quirk for 1.8v switching not supported
  mmc: zynq_sdhci: Update quirk if 1.8v switching not supported
  mmc: sdhci: Add support for eMMC HS200 mode
  mmc: sdhci: Update execute tuning and set clock for HS200
  mmc: sdhci: zynqmp: Set tapdelays for eMMC HS200 mode
  mmc: Change frequency while accessing to boot partition

 arch/arm/cpu/armv8/zynqmp/cpu.c              |  51 ++++++
 arch/arm/include/asm/arch-zynqmp/sys_proto.h |   3 +
 board/xilinx/zynqmp/Makefile                 |   1 +
 board/xilinx/zynqmp/tap_delays.c             | 250 +++++++++++++++++++++++++++
 drivers/mmc/mmc-uclass.c                     |  52 ++++++
 drivers/mmc/mmc.c                            | 218 +++++++++++++++++++++--
 drivers/mmc/sdhci.c                          | 205 +++++++++++++++++++++-
 drivers/mmc/zynq_sdhci.c                     | 170 +++++++++++++++++-
 include/mmc.h                                |  74 +++++++-
 include/sdhci.h                              |  18 +-
 include/zynqmp_tap_delay.h                   |  20 +++
 11 files changed, 1040 insertions(+), 22 deletions(-)
 create mode 100644 board/xilinx/zynqmp/tap_delays.c
 create mode 100644 include/zynqmp_tap_delay.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 01/15] mmc: sdhci: Update host capabilities about host controller
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 02/15] mmc: Add support for SD3.0 Siva Durga Prasad Paladugu
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Update host capabilities for driver with host controller
information related to UHS modes incase of SD and HS200
mode incase of eMMC.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 drivers/mmc/sdhci.c | 28 +++++++++++++++++++++++++++-
 include/mmc.h       |  7 +++++++
 include/sdhci.h     |  5 +++++
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 93cefd8..884b6a6 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -517,7 +517,8 @@ static const struct mmc_ops sdhci_ops = {
 int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		u32 f_max, u32 f_min)
 {
-	u32 caps, caps_1;
+	u32 caps;
+	u32 caps_1 = 0;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 
@@ -588,6 +589,31 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 				SDHCI_CLOCK_MUL_SHIFT;
 	}
 
+	if (!(cfg->voltages & MMC_VDD_165_195))
+		caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+			    SDHCI_SUPPORT_DDR50);
+
+	if (caps_1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+		      SDHCI_SUPPORT_DDR50))
+		cfg->host_caps |= MMC_MODE_UHS_SDR12 | MMC_MODE_UHS_SDR25;
+
+	if (caps_1 & SDHCI_SUPPORT_SDR104) {
+		cfg->host_caps |= MMC_MODE_UHS_SDR104 | MMC_MODE_UHS_SDR50;
+		/*
+		 * SD3.0: SDR104 is supported so (for eMMC) the caps2
+		 * field can be promoted to support HS200.
+		 */
+		cfg->host_caps |= MMC_MODE_HS200;
+	} else if (caps_1 & SDHCI_SUPPORT_SDR50) {
+		cfg->host_caps |= MMC_MODE_UHS_SDR50;
+	}
+
+	if (caps_1 & SDHCI_SUPPORT_DDR50)
+		cfg->host_caps |= MMC_MODE_UHS_DDR50;
+
+	if (caps_1 & SDHCI_USE_SDR50_TUNING)
+		cfg->host_caps |= MMC_MODE_NEEDS_TUNING;
+
 	if (host->host_caps)
 		cfg->host_caps |= host->host_caps;
 
diff --git a/include/mmc.h b/include/mmc.h
index fad12d6..5c94eae 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -58,6 +58,13 @@
 #define MMC_MODE_8BIT		(1 << 3)
 #define MMC_MODE_SPI		(1 << 4)
 #define MMC_MODE_DDR_52MHz	(1 << 5)
+#define MMC_MODE_UHS_SDR12	(1 << 6)
+#define MMC_MODE_UHS_SDR25	(1 << 7)
+#define MMC_MODE_UHS_SDR50	(1 << 8)
+#define MMC_MODE_UHS_SDR104	(1 << 9)
+#define MMC_MODE_UHS_DDR50	(1 << 10)
+#define MMC_MODE_NEEDS_TUNING	(1 << 11)
+#define MMC_MODE_HS200		(1 << 12)
 
 #define SD_DATA_4BIT	0x00040000
 
diff --git a/include/sdhci.h b/include/sdhci.h
index 6a43271..685bcf2 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -167,6 +167,11 @@
 #define  SDHCI_CAN_64BIT	BIT(28)
 
 #define SDHCI_CAPABILITIES_1	0x44
+#define  SDHCI_SUPPORT_SDR50	0x00000001
+#define  SDHCI_SUPPORT_SDR104	0x00000002
+#define  SDHCI_SUPPORT_DDR50	0x00000004
+#define  SDHCI_USE_SDR50_TUNING		0x00002000
+#define  SDHCI_SUPPORT_HS400	0x80000000 /* Non-standard */
 #define  SDHCI_CLOCK_MUL_MASK	0x00FF0000
 #define  SDHCI_CLOCK_MUL_SHIFT	16
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 02/15] mmc: Add support for SD3.0
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 01/15] mmc: sdhci: Update host capabilities about host controller Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 03/15] mmc: sdhci: Add SD3.0 support Siva Durga Prasad Paladugu
                     ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

The SD3.0 needs voltage switching to 1.8V
based on host and cards capabilities and also
needs to switch to one of the uhs modes based
on cards capability. This supports frequencies
till 200MHz. This patch define hooks to perform
the same at sdhci driver level.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- Split the patch with only mmc changes
  as per comment
---
 drivers/mmc/mmc-uclass.c |  52 ++++++++++++++++++
 drivers/mmc/mmc.c        | 138 ++++++++++++++++++++++++++++++++++++++++++++---
 include/mmc.h            |  55 ++++++++++++++++++-
 3 files changed, 238 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 2fe5d61..3ca3e49 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -77,6 +77,58 @@ int mmc_getcd(struct mmc *mmc)
 {
 	return dm_mmc_get_cd(mmc->dev);
 }
+
+int dm_mmc_set_voltage(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->set_voltage)
+		return -ENOSYS;
+
+	return ops->set_voltage(dev);
+}
+
+int mmc_set_voltage(struct mmc *mmc)
+{
+	return dm_mmc_set_voltage(mmc->dev);
+}
+
+int dm_mmc_set_uhs(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->set_uhs)
+		return -ENOSYS;
+
+	return ops->set_uhs(dev);
+}
+
+int mmc_switch_uhs(struct mmc *mmc)
+{
+	return dm_mmc_set_uhs(mmc->dev);
+}
+
+int dm_mmc_execute_tuning(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+	u8 opcode;
+
+	if (!ops->execute_tuning)
+		return -ENOSYS;
+
+	if (IS_SD(mmc))
+		opcode = MMC_CMD_SEND_TUNING_BLOCK;
+	else
+		opcode = MMC_CMD_SEND_TUNING_BLOCK_HS200;
+
+	return ops->execute_tuning(dev, opcode);
+}
+
+int mmc_execute_tuning(struct mmc *mmc)
+{
+	return dm_mmc_execute_tuning(mmc->dev);
+}
 #endif
 
 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 3648950..0f0bfc8 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -339,6 +339,47 @@ static int mmc_go_idle(struct mmc *mmc)
 	return 0;
 }
 
+#ifndef CONFIG_DM_MMC_OPS
+static int mmc_set_voltage(struct mmc *mmc)
+{
+	int err = 0;
+
+	if (mmc->cfg->ops->set_voltage) {
+		err = mmc->cfg->ops->set_voltage(mmc);
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+#endif
+
+static int mmc_switch_voltage(struct mmc *mmc)
+{
+	struct mmc_cmd cmd;
+	int err = 0;
+
+	cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
+	cmd.cmdarg = 0;
+	cmd.resp_type = MMC_RSP_NONE;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err)
+		return err;
+
+	err = mmc_set_voltage(mmc);
+
+	return err;
+}
+
+static int mmc_host_uhs(struct mmc *mmc)
+{
+	return mmc->cfg->host_caps &
+		(MMC_MODE_UHS_SDR12 | MMC_MODE_UHS_SDR25 |
+		 MMC_MODE_UHS_SDR50 | MMC_MODE_UHS_SDR104 |
+		 MMC_MODE_UHS_DDR50);
+}
+
 static int sd_send_op_cond(struct mmc *mmc)
 {
 	int timeout = 1000;
@@ -371,6 +412,9 @@ static int sd_send_op_cond(struct mmc *mmc)
 		if (mmc->version == SD_VERSION_2)
 			cmd.cmdarg |= OCR_HCS;
 
+		if (mmc_host_uhs(mmc))
+			cmd.cmdarg |= SD_OCR_S18R;
+
 		err = mmc_send_cmd(mmc, &cmd, NULL);
 
 		if (err)
@@ -401,6 +445,13 @@ static int sd_send_op_cond(struct mmc *mmc)
 
 	mmc->ocr = cmd.response[0];
 
+	if (mmc->ocr & SD_OCR_S18R) {
+		err = mmc_switch_voltage(mmc);
+		if (err)
+			return err;
+		mmc->is_uhs = 1;
+	}
+
 	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
 	mmc->rca = 0;
 
@@ -886,6 +937,7 @@ static int sd_change_freq(struct mmc *mmc)
 	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
 	struct mmc_data data;
 	int timeout;
+	u8 mode;
 
 	mmc->card_caps = 0;
 
@@ -963,6 +1015,40 @@ retry_scr:
 			break;
 	}
 
+	mode = MMC_TIMING_HS;
+
+	if (mmc->is_uhs && mmc->version >= SD_VERSION_3) {
+		if (!(mmc_host_uhs(mmc)))
+			return 0;
+
+		if (__be32_to_cpu(switch_status[3]) &
+		    SD_UHS_SPEED_SDR104) {
+			mode = MMC_TIMING_UHS_SDR104;
+			mmc->card_caps |= MMC_MODE_UHS_SDR104;
+			mmc->tran_speed = 208000000;
+		} else if (__be32_to_cpu(switch_status[3]) &
+			   SD_UHS_SPEED_SDR50) {
+			mode = MMC_TIMING_UHS_SDR50;
+			mmc->card_caps |= MMC_MODE_UHS_SDR50;
+			mmc->tran_speed = 100000000;
+		} else if (__be32_to_cpu(switch_status[3]) &
+			   SD_UHS_SPEED_DDR50) {
+			mode = MMC_TIMING_UHS_DDR50;
+			mmc->card_caps |= MMC_MODE_UHS_DDR50;
+			mmc->tran_speed = 50000000;
+		} else if (__be32_to_cpu(switch_status[3]) &
+			   SD_UHS_SPEED_SDR25) {
+			mode = MMC_TIMING_UHS_SDR25;
+			mmc->card_caps |= MMC_MODE_UHS_SDR25;
+			mmc->tran_speed = 50000000;
+		} else {
+			mode = MMC_TIMING_UHS_SDR12;
+			mmc->card_caps |= MMC_MODE_UHS_SDR12;
+			mmc->tran_speed = 25000000;
+		}
+		mmc->uhsmode = mode;
+	}
+
 	/* If high-speed isn't supported, we return */
 	if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
 		return 0;
@@ -977,7 +1063,7 @@ retry_scr:
 		(mmc->cfg->host_caps & MMC_MODE_HS)))
 		return 0;
 
-	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
+	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, mode, (u8 *)switch_status);
 
 	if (err)
 		return err;
@@ -1102,6 +1188,33 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
 
 	mmc_set_ios(mmc);
 }
+#ifndef CONFIG_DM_MMC_OPS
+static int mmc_switch_uhs(struct mmc *mmc)
+{
+	int err = 0;
+
+	if (mmc->cfg->ops->set_uhs)
+		err = mmc->cfg->ops->set_uhs(mmc);
+
+	return err;
+}
+
+static int mmc_execute_tuning(struct mmc *mmc)
+{
+	int err = 0;
+	u8 cmd;
+
+	if (mmc->cfg->ops->execute_tuning) {
+		if (IS_SD(mmc))
+			cmd = MMC_CMD_SEND_TUNING_BLOCK;
+		else
+			cmd = MMC_CMD_SEND_TUNING_BLOCK_HS200;
+		err = mmc->cfg->ops->execute_tuning(mmc, cmd);
+	}
+
+	return err;
+}
+#endif
 
 static int mmc_startup(struct mmc *mmc)
 {
@@ -1452,11 +1565,16 @@ static int mmc_startup(struct mmc *mmc)
 		err = sd_read_ssr(mmc);
 		if (err)
 			return err;
-
-		if (mmc->card_caps & MMC_MODE_HS)
-			mmc->tran_speed = 50000000;
-		else
-			mmc->tran_speed = 25000000;
+		if (mmc->card_caps & MMC_MODE_UHS) {
+			err = mmc_switch_uhs(mmc);
+			if (err)
+				return err;
+		} else  {
+			if (mmc->card_caps & MMC_MODE_HS)
+				mmc->tran_speed = 50000000;
+			else
+				mmc->tran_speed = 25000000;
+		}
 	} else if (mmc->version >= MMC_VERSION_4) {
 		/* Only version 4 of MMC supports wider bus widths */
 		int idx;
@@ -1551,6 +1669,14 @@ static int mmc_startup(struct mmc *mmc)
 
 	mmc_set_clock(mmc, mmc->tran_speed);
 
+	if ((mmc->card_caps & (MMC_MODE_UHS_SDR50 |
+			       MMC_MODE_UHS_SDR104)) &&
+	    (mmc->cfg->host_caps & MMC_MODE_NEEDS_TUNING)) {
+		err = mmc_execute_tuning(mmc);
+		if (err)
+			return err;
+	}
+
 	/* Fix the block length for DDR mode */
 	if (mmc->ddr_mode) {
 		mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
diff --git a/include/mmc.h b/include/mmc.h
index 5c94eae..56395ee 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -66,6 +66,9 @@
 #define MMC_MODE_NEEDS_TUNING	(1 << 11)
 #define MMC_MODE_HS200		(1 << 12)
 
+#define MMC_MODE_UHS	(MMC_MODE_UHS_SDR12 | MMC_MODE_UHS_SDR25 |	\
+			 MMC_MODE_UHS_SDR50 | MMC_MODE_UHS_SDR104 |	\
+			 MMC_MODE_UHS_DDR50)
 #define SD_DATA_4BIT	0x00040000
 
 #define IS_SD(x)	((x)->version & SD_VERSION_SD)
@@ -89,6 +92,8 @@
 #define MMC_CMD_SET_BLOCKLEN		16
 #define MMC_CMD_READ_SINGLE_BLOCK	17
 #define MMC_CMD_READ_MULTIPLE_BLOCK	18
+#define MMC_CMD_SEND_TUNING_BLOCK	19
+#define MMC_CMD_SEND_TUNING_BLOCK_HS200	21
 #define MMC_CMD_SET_BLOCK_COUNT         23
 #define MMC_CMD_WRITE_SINGLE_BLOCK	24
 #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25
@@ -119,12 +124,18 @@
 /* SCR definitions in different words */
 #define SD_HIGHSPEED_BUSY	0x00020000
 #define SD_HIGHSPEED_SUPPORTED	0x00020000
+#define SD_UHS_SPEED_SDR104	0x00080000
+#define SD_UHS_SPEED_SDR50	0x00040000
+#define SD_UHS_SPEED_DDR50	0x00100000
+#define SD_UHS_SPEED_SDR25	0x00020000
 
 #define OCR_BUSY		0x80000000
 #define OCR_HCS			0x40000000
 #define OCR_VOLTAGE_MASK	0x007FFF80
 #define OCR_ACCESS_MODE		0x60000000
 
+#define SD_OCR_S18R		(1 << 24)
+
 #define MMC_ERASE_ARG		0x00000000
 #define MMC_SECURE_ERASE_ARG	0x80000000
 #define MMC_TRIM_ARG		0x00000001
@@ -277,6 +288,13 @@
 #define MMC_NUM_BOOT_PARTITION	2
 #define MMC_PART_RPMB           3       /* RPMB partition number */
 
+#define MMC_TIMING_UHS_SDR12	0
+#define MMC_TIMING_UHS_SDR25	1
+#define MMC_TIMING_UHS_SDR50	2
+#define MMC_TIMING_UHS_SDR104	3
+#define MMC_TIMING_UHS_DDR50	4
+#define MMC_TIMING_HS		1
+
 /* Driver model support */
 
 /**
@@ -364,6 +382,31 @@ struct dm_mmc_ops {
 	 * @return 0 if write-enabled, 1 if write-protected, -ve on error
 	 */
 	int (*get_wp)(struct udevice *dev);
+
+	/**
+	* set_volatge() - Switches host for new voltage
+	* @dev:>-------Device to check
+	*
+	* @return 0 on success otherwise error value
+	*/
+	int (*set_voltage)(struct udevice *dev);
+
+	/**
+	 * set_uhs() - Sets the controller for specific uhs mode
+	 * @dev:>-------Device to check
+	 *
+	 * @return 0 after setting uhs mode
+	 */
+	int (*set_uhs)(struct udevice *dev);
+
+	/**
+	* execute_tuning() - Executes the required tuning sequence
+	* @dev:>-------Device to check
+	* @opcode:>----Command to be sent for tuning
+	*
+	* @return 0 on success otherwise error value
+	*/
+	int (*execute_tuning)(struct udevice *dev, u8 opcode);
 };
 
 #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
@@ -373,12 +416,17 @@ int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 int dm_mmc_set_ios(struct udevice *dev);
 int dm_mmc_get_cd(struct udevice *dev);
 int dm_mmc_get_wp(struct udevice *dev);
+int dm_mmc_set_voltage(struct udevice *dev);
+int dm_mmc_set_uhs(struct udevice *dev);
+int dm_mmc_execute_tuning(struct udevice *dev);
 
 /* Transition functions for compatibility */
 int mmc_set_ios(struct mmc *mmc);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
-
+int mmc_set_voltage(struct mmc *mmc);
+int mmc_switch_uhs(struct mmc *mmc);
+int mmc_execute_tuning(struct mmc *mmc);
 #else
 struct mmc_ops {
 	int (*send_cmd)(struct mmc *mmc,
@@ -387,6 +435,9 @@ struct mmc_ops {
 	int (*init)(struct mmc *mmc);
 	int (*getcd)(struct mmc *mmc);
 	int (*getwp)(struct mmc *mmc);
+	int (*set_voltage)(struct mmc *mmc);
+	int (*set_uhs)(struct mmc *mmc);
+	int (*execute_tuning)(struct mmc *mmc, u8 opcode);
 };
 #endif
 
@@ -461,6 +512,8 @@ struct mmc {
 #ifdef CONFIG_DM_MMC
 	struct udevice *dev;	/* Device for this MMC controller */
 #endif
+	u8 is_uhs;
+	u8 uhsmode;
 };
 
 struct mmc_hwpart_conf {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 03/15] mmc: sdhci: Add SD3.0 support
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 01/15] mmc: sdhci: Update host capabilities about host controller Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 02/15] mmc: Add support for SD3.0 Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 04/15] mmc: sdhci: Add support for platform/board specific tuning Siva Durga Prasad Paladugu
                     ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Add support for all UHS modes of SD3.0.
This patch defines the routines to switch
volatge, setting uhs modes and execute tuning
as these are needed for SD3.0 support

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- Split the patch with only sdhci changes
  as per comment
---
 drivers/mmc/sdhci.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/sdhci.h     |   8 +++
 2 files changed, 163 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 884b6a6..bba2c30 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -13,6 +13,7 @@
 #include <malloc.h>
 #include <mmc.h>
 #include <sdhci.h>
+#include <wait_bit.h>
 
 #if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER)
 void *aligned_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER;
@@ -155,7 +156,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 
 	/* We shouldn't wait for data inihibit for stop commands, even
 	   though they might use busy signaling */
-	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+	if ((cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) ||
+	    (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK))
 		mask &= ~SDHCI_DATA_INHIBIT;
 
 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
@@ -175,6 +177,11 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	}
 
 	mask = SDHCI_INT_RESPONSE;
+
+	/* only buffer read ready interrupt whil tuning */
+	if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+		mask = SDHCI_INT_DATA_AVAIL;
+
 	if (!(cmd->resp_type & MMC_RSP_PRESENT))
 		flags = SDHCI_CMD_RESP_NONE;
 	else if (cmd->resp_type & MMC_RSP_136)
@@ -190,7 +197,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 		flags |= SDHCI_CMD_CRC;
 	if (cmd->resp_type & MMC_RSP_OPCODE)
 		flags |= SDHCI_CMD_INDEX;
-	if (data)
+	if (data || (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK))
 		flags |= SDHCI_CMD_DATA;
 
 	/* Set Transfer mode regarding to data flag */
@@ -291,6 +298,80 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	else
 		return -ECOMM;
 }
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_execute_tuning(struct udevice *dev, u8 opcode)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
+{
+#endif
+	struct mmc_cmd cmd;
+	struct mmc_data data;
+	u32 ctrl;
+	u8 tuning_loop_counter = 40;
+	struct sdhci_host *host = mmc->priv;
+
+	debug("%s\n", __func__);
+
+	ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+
+	do {
+		cmd.cmdidx = opcode;
+		cmd.resp_type = MMC_RSP_R1;
+		cmd.cmdarg = 0;
+
+		data.blocksize = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+
+		if (tuning_loop_counter == 0)
+			break;
+
+		tuning_loop_counter--;
+
+		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
+		    mmc->bus_width == 8) {
+			data.blocksize = 128;
+		}
+
+		sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
+						    data.blocksize),
+			     SDHCI_BLOCK_SIZE);
+		sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
+		sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+		sdhci_send_command(dev, &cmd, &data);
+		ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+
+		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+			udelay(1);
+
+	} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
+
+	if (tuning_loop_counter < 0) {
+		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+		sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+	}
+
+	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+		debug("%s:Tuning failed\n", __func__);
+		return -1;
+	}
+
+	/* Enable only interrupts served by the SD controller */
+	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
+		     SDHCI_INT_ENABLE);
+	/* Mask all sdhci interrupt sources */
+	sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
+
+	return 0;
+}
 
 static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
@@ -384,6 +465,72 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 	return 0;
 }
 
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_set_voltage(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int sdhci_set_voltage(struct mmc *mmc)
+{
+#endif
+	struct sdhci_host *host = mmc->priv;
+	u32 reg;
+	int err;
+
+	debug("%s\n", __func__);
+
+	reg = (unsigned long)host->ioaddr + SDHCI_PRESENT_STATE;
+	/* Wait max 20ms for the bits to clear*/
+	err = wait_for_bit(__func__, (const u32 *)(uintptr_t)reg,
+			   (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT),
+			   false, 20, false);
+	if (err < 0)
+		return err;
+
+	reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	reg &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
+	sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
+
+	/* keep clock gated for 5 msec as per spec */
+	udelay(5000);
+
+	reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	reg |= SDHCI_18V_SIGNAL;
+	sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+
+	sdhci_set_clock(mmc, mmc->cfg->f_min);
+
+	reg = (unsigned long)host->ioaddr + SDHCI_PRESENT_STATE;
+	/* Wait max 20ms for bits to be clear */
+	err = wait_for_bit(__func__, (const u32 *)(uintptr_t)reg,
+			   (SDHCI_CMD_BUSY | SDHCI_DATA_BUSY),
+			   true, 20, false);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_set_uhs(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int sdhci_set_uhs(struct mmc *mmc)
+{
+#endif
+	struct sdhci_host *host = mmc->priv;
+	u32 reg;
+
+	debug("%s\n", __func__);
+	reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	reg &= ~SDHCI_CTRL2_MODE_MASK;
+	reg |= mmc->uhsmode;
+	sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+
+	return 0;
+}
+
 static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
 	u8 pwr = 0;
@@ -505,12 +652,18 @@ int sdhci_probe(struct udevice *dev)
 const struct dm_mmc_ops sdhci_ops = {
 	.send_cmd	= sdhci_send_command,
 	.set_ios	= sdhci_set_ios,
+	.set_voltage	= sdhci_set_voltage,
+	.set_uhs	= sdhci_set_uhs,
+	.execute_tuning	= sdhci_execute_tuning,
 };
 #else
 static const struct mmc_ops sdhci_ops = {
 	.send_cmd	= sdhci_send_command,
 	.set_ios	= sdhci_set_ios,
 	.init		= sdhci_init,
+	.set_voltage	= sdhci_set_voltage,
+	.set_uhs	= sdhci_set_uhs,
+	.execute_tuning	= sdhci_execute_tuning,
 };
 #endif
 
diff --git a/include/sdhci.h b/include/sdhci.h
index 685bcf2..fc0708c 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -64,6 +64,8 @@
 #define  SDHCI_CARD_STATE_STABLE	BIT(17)
 #define  SDHCI_CARD_DETECT_PIN_LEVEL	BIT(18)
 #define  SDHCI_WRITE_PROTECT	BIT(19)
+#define  SDHCI_DATA_BUSY	0xF00000
+#define  SDHCI_CMD_BUSY		0x1000000
 
 #define SDHCI_HOST_CONTROL	0x28
 #define  SDHCI_CTRL_LED		BIT(0)
@@ -146,6 +148,12 @@
 #define SDHCI_ACMD12_ERR	0x3C
 
 /* 3E-3F reserved */
+#define SDHCI_HOST_CTRL2	0x3E
+#define SDHCI_CTRL2_MODE_MASK	0x7
+
+#define SDHCI_18V_SIGNAL	0x8
+#define SDHCI_CTRL_EXEC_TUNING	0x0040
+#define SDHCI_CTRL_TUNED_CLK	0x80
 
 #define SDHCI_CAPABILITIES	0x40
 #define  SDHCI_TIMEOUT_CLK_MASK	0x0000003F
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 04/15] mmc: sdhci: Add support for platform/board specific tuning
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (2 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 03/15] mmc: sdhci: Add SD3.0 support Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 05/15] mmc: sdhci: Add support for platform specific delay Siva Durga Prasad Paladugu
                     ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Add support to execute platform/board specific tuning needed
for SDR104 and SDR50 UHS modes.This patch adds hook routine
to support specific tuning requirements.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 drivers/mmc/sdhci.c | 8 ++++++++
 include/sdhci.h     | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index bba2c30..a24cc15 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -309,11 +309,19 @@ static int sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 	struct mmc_cmd cmd;
 	struct mmc_data data;
 	u32 ctrl;
+	int err;
 	u8 tuning_loop_counter = 40;
 	struct sdhci_host *host = mmc->priv;
 
 	debug("%s\n", __func__);
 
+	if (host->ops->platform_execute_tuning) {
+		err = host->ops->platform_execute_tuning(mmc, opcode);
+		if (err)
+			return err;
+		return 0;
+	}
+
 	ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
 	sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
diff --git a/include/sdhci.h b/include/sdhci.h
index fc0708c..dbe3836 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -250,6 +250,7 @@ struct sdhci_ops {
 	void	(*set_control_reg)(struct sdhci_host *host);
 	void	(*set_ios_post)(struct sdhci_host *host);
 	void	(*set_clock)(struct sdhci_host *host, u32 div);
+	int	(*platform_execute_tuning)(struct mmc *host, u8 opcode);
 };
 
 struct sdhci_host {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 05/15] mmc: sdhci: Add support for platform specific delay
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (3 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 04/15] mmc: sdhci: Add support for platform/board specific tuning Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 06/15] mmc: sdhci: Make sdhci_ops of host as modifiable Siva Durga Prasad Paladugu
                     ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Add support for any platform/board specific delays
requirement while setting clocks. Some boards needs
to program tapdelay for setting certain high frequencies
and this patch adds hook for supporting the same.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 drivers/mmc/sdhci.c | 3 +++
 include/sdhci.h     | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index a24cc15..bbb6302 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -405,6 +405,9 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 	if (clock == 0)
 		return 0;
 
+	if (mmc->is_uhs && host->ops->set_delay)
+		host->ops->set_delay(host, mmc->uhsmode);
+
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		/*
 		 * Check if the Host Controller supports Programmable Clock
diff --git a/include/sdhci.h b/include/sdhci.h
index dbe3836..a0449d9 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -251,6 +251,7 @@ struct sdhci_ops {
 	void	(*set_ios_post)(struct sdhci_host *host);
 	void	(*set_clock)(struct sdhci_host *host, u32 div);
 	int	(*platform_execute_tuning)(struct mmc *host, u8 opcode);
+	void	(*set_delay)(struct sdhci_host *host, u8 uhsmode);
 };
 
 struct sdhci_host {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 06/15] mmc: sdhci: Make sdhci_ops of host as modifiable
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (4 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 05/15] mmc: sdhci: Add support for platform specific delay Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 07/15] zynqmp: Define routines for mmio write and read Siva Durga Prasad Paladugu
                     ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Make sdhci_ops of host modifiable as ops may contain
platform specific funtion pointers which may need
to be defined for some platforms(example: platform specific
tuning and delays)

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 include/sdhci.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/sdhci.h b/include/sdhci.h
index a0449d9..2317eac 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -264,7 +264,7 @@ struct sdhci_host {
 	unsigned int clk_mul;   /* Clock Multiplier value */
 	unsigned int clock;
 	struct mmc *mmc;
-	const struct sdhci_ops *ops;
+	struct sdhci_ops *ops;
 	int index;
 
 	int bus_width;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 07/15] zynqmp: Define routines for mmio write and read
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (5 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 06/15] mmc: sdhci: Make sdhci_ops of host as modifiable Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 08/15] mmc: sdhci: zynq: Define private structure arasan_sdhci_priv Siva Durga Prasad Paladugu
                     ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Define routines of mmio write and read functionalities
for zynqmp platform.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 arch/arm/cpu/armv8/zynqmp/cpu.c              | 51 ++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-zynqmp/sys_proto.h |  3 ++
 2 files changed, 54 insertions(+)

diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
index b0f1295..54afa9e 100644
--- a/arch/arm/cpu/armv8/zynqmp/cpu.c
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -104,3 +104,54 @@ unsigned int zynqmp_get_silicon_version(void)
 
 	return ZYNQMP_CSU_VERSION_SILICON;
 }
+
+#define PAYLOAD_ARG_CNT		5
+#define ZYNQMP_MMIO_READ	0xC2000014
+#define ZYNQMP_MMIO_WRITE	0xC2000013
+
+static int invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, u32 arg3,
+			u32 *ret_payload)
+{
+	/*
+	 * Added SIP service call Function Identifier
+	 * Make sure to stay in x0 register
+	 */
+	struct pt_regs regs;
+
+	regs.regs[0] = pm_api_id;
+	regs.regs[1] = ((u64)arg1 << 32) | arg0;
+	regs.regs[2] = ((u64)arg3 << 32) | arg2;
+
+	smc_call(&regs);
+
+	if (ret_payload != NULL) {
+		ret_payload[0] = (u32)regs.regs[0];
+		ret_payload[1] = upper_32_bits(regs.regs[0]);
+		ret_payload[2] = (u32)regs.regs[1];
+		ret_payload[3] = upper_32_bits(regs.regs[1]);
+		ret_payload[4] = (u32)regs.regs[2];
+	}
+
+	return regs.regs[0];
+}
+
+int zynqmp_mmio_write(const u32 address,
+		      const u32 mask,
+		      const u32 value)
+{
+	return invoke_smc(ZYNQMP_MMIO_WRITE, address, mask, value, 0, NULL);
+}
+
+int zynqmp_mmio_read(const u32 address, u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u32 ret;
+
+	if (!value)
+		return -EINVAL;
+
+	ret = invoke_smc(ZYNQMP_MMIO_READ, address, 0, 0, 0, ret_payload);
+	*value = ret_payload[1];
+
+	return ret;
+}
diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
index 8c54fce..446e89c 100644
--- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
+++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
@@ -23,4 +23,7 @@ void psu_init(void);
 
 void handoff_setup(void);
 
+int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value);
+int zynqmp_mmio_read(const u32 address, u32 *value);
+
 #endif /* _ASM_ARCH_SYS_PROTO_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 08/15] mmc: sdhci: zynq: Define private structure arasan_sdhci_priv
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (6 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 07/15] zynqmp: Define routines for mmio write and read Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 09/15] mmc: sdhci: zynqmp: Add support of SD3.0 Siva Durga Prasad Paladugu
                     ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Deine private structure arasan_sdhci_priv instead of sdhci_host
as private. This allows us in adding more private data  as required
for usage in driver.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 drivers/mmc/zynq_sdhci.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 69efa38..f98089e 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -22,13 +22,20 @@ struct arasan_sdhci_plat {
 	struct mmc mmc;
 };
 
+struct arasan_sdhci_priv {
+	struct sdhci_host *host;
+};
+
 static int arasan_sdhci_probe(struct udevice *dev)
 {
 	struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
-	struct sdhci_host *host = dev_get_priv(dev);
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	struct sdhci_host *host;
 	int ret;
 
+	host = priv->host;
+
 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
 		       SDHCI_QUIRK_BROKEN_R1B;
 
@@ -52,10 +59,14 @@ static int arasan_sdhci_probe(struct udevice *dev)
 
 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 {
-	struct sdhci_host *host = dev_get_priv(dev);
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+
+	priv->host = calloc(1, sizeof(struct sdhci_host));
+	if (priv->host == NULL)
+		return -1;
 
-	host->name = dev->name;
-	host->ioaddr = (void *)dev_get_addr(dev);
+	priv->host->name = dev->name;
+	priv->host->ioaddr = (void *)dev_get_addr(dev);
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 09/15] mmc: sdhci: zynqmp: Add support of SD3.0
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (7 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 08/15] mmc: sdhci: zynq: Define private structure arasan_sdhci_priv Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 10/15] mmc: sdhci: Add quirk for 1.8v switching not supported Siva Durga Prasad Paladugu
                     ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Add SD3.0 support for ZynqMP, this support needs a
platform specific tuning and tap delays for UHS
modes of SD3.0 and this patch takes care of it.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 board/xilinx/zynqmp/Makefile     |   1 +
 board/xilinx/zynqmp/tap_delays.c | 249 +++++++++++++++++++++++++++++++++++++++
 drivers/mmc/zynq_sdhci.c         | 142 +++++++++++++++++++++-
 include/zynqmp_tap_delay.h       |  20 ++++
 4 files changed, 411 insertions(+), 1 deletion(-)
 create mode 100644 board/xilinx/zynqmp/tap_delays.c
 create mode 100644 include/zynqmp_tap_delay.h

diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 9d69d65..2bf0375 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -20,6 +20,7 @@ $(warning Put custom psu_init_gpl.c/h to board/xilinx/zynqmp/custom_hw_platform/
 endif
 endif
 
+obj-$(CONFIG_ZYNQ_SDHCI) += tap_delays.o
 obj-$(CONFIG_SPL_BUILD) += $(init-objs)
 
 # Suppress "warning: function declaration isn't a prototype"
diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
new file mode 100644
index 0000000..d57587e
--- /dev/null
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -0,0 +1,249 @@
+/*
+ * Xilinx ZynqMP SoC Tap Delay Programming
+ *
+ * Copyright (C) 2016 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/sys_proto.h>
+
+#define SD_DLL_CTRL			0xFF180358
+#define SD_ITAP_DLY			0xFF180314
+#define SD_OTAP_DLY			0xFF180318
+#define SD0_DLL_RST_MASK		0x00000004
+#define SD0_DLL_RST			0x00000004
+#define SD1_DLL_RST_MASK		0x00040000
+#define SD1_DLL_RST			0x00040000
+#define SD0_ITAPCHGWIN_MASK		0x00000200
+#define SD0_ITAPCHGWIN			0x00000200
+#define SD1_ITAPCHGWIN_MASK		0x02000000
+#define SD1_ITAPCHGWIN			0x02000000
+#define SD0_ITAPDLYENA_MASK		0x00000100
+#define SD0_ITAPDLYENA			0x00000100
+#define SD1_ITAPDLYENA_MASK		0x01000000
+#define SD1_ITAPDLYENA			0x01000000
+#define SD0_ITAPDLYSEL_MASK		0x000000FF
+#define SD0_ITAPDLYSEL_HSD		0x00000015
+#define SD0_ITAPDLYSEL_SD_DDR50		0x0000003D
+#define SD0_ITAPDLYSEL_MMC_DDR50	0x00000012
+
+#define SD1_ITAPDLYSEL_MASK		0x00FF0000
+#define SD1_ITAPDLYSEL_HSD		0x00150000
+#define SD1_ITAPDLYSEL_SD_DDR50		0x003D0000
+#define SD1_ITAPDLYSEL_MMC_DDR50	0x00120000
+
+#define SD0_OTAPDLYENA_MASK		0x00000040
+#define SD0_OTAPDLYENA			0x00000040
+#define SD1_OTAPDLYENA_MASK		0x00400000
+#define SD1_OTAPDLYENA			0x00400000
+#define SD0_OTAPDLYSEL_MASK		0x0000003F
+#define SD0_OTAPDLYSEL_MMC_HSD		0x00000006
+#define SD0_OTAPDLYSEL_SD_HSD		0x00000005
+#define SD0_OTAPDLYSEL_SDR50		0x00000003
+#define SD0_OTAPDLYSEL_SDR104_B0	0x00000003
+#define SD0_OTAPDLYSEL_SDR104_B2	0x00000002
+#define SD0_OTAPDLYSEL_SD_DDR50		0x00000004
+#define SD0_OTAPDLYSEL_MMC_DDR50	0x00000006
+
+#define SD1_OTAPDLYSEL_MASK		0x003F0000
+#define SD1_OTAPDLYSEL_MMC_HSD		0x00060000
+#define SD1_OTAPDLYSEL_SD_HSD		0x00050000
+#define SD1_OTAPDLYSEL_SDR50		0x00030000
+#define SD1_OTAPDLYSEL_SDR104_B0	0x00030000
+#define SD1_OTAPDLYSEL_SDR104_B2	0x00020000
+#define SD1_OTAPDLYSEL_SD_DDR50		0x00040000
+#define SD1_OTAPDLYSEL_MMC_DDR50	0x00060000
+
+#define MMC_BANK2		0x2
+
+#define MMC_TIMING_UHS_SDR25		1
+#define MMC_TIMING_UHS_SDR50		2
+#define MMC_TIMING_UHS_SDR104		3
+#define MMC_TIMING_UHS_DDR50		4
+#define MMC_TIMING_MMC_HS200		5
+#define MMC_TIMING_SD_HS		6
+#define MMC_TIMING_MMC_DDR52		7
+#define MMC_TIMING_MMC_HS		8
+
+void zynqmp_dll_reset(u8 deviceid)
+{
+	/* Issue DLL Reset */
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+				  SD0_DLL_RST);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
+				  SD1_DLL_RST);
+
+	mdelay(1);
+
+	/* Release DLL Reset */
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+}
+
+static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYENA_MASK,
+				  SD0_OTAPDLYENA);
+		if (bank == MMC_BANK2)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SDR104_B2);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SDR104_B0);
+	} else {
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYENA_MASK,
+				  SD1_OTAPDLYENA);
+		if (bank == MMC_BANK2)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SDR104_B2);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SDR104_B0);
+	}
+}
+
+static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+				  SD0_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+				  SD0_ITAPDLYENA);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+				  SD0_ITAPDLYSEL_HSD);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYENA_MASK,
+				  SD0_OTAPDLYENA);
+		if (timing == MMC_TIMING_MMC_HS)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_MMC_HSD);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SD_HSD);
+	} else {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+				  SD1_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+				  SD1_ITAPDLYENA);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+				  SD1_ITAPDLYSEL_HSD);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYENA_MASK,
+				  SD1_OTAPDLYENA);
+		if (timing == MMC_TIMING_MMC_HS)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_MMC_HSD);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SD_HSD);
+	}
+}
+
+static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+				  SD0_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+				  SD0_ITAPDLYENA);
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+					  SD0_ITAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+					  SD0_ITAPDLYSEL_MMC_DDR50);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYENA_MASK,
+				  SD0_OTAPDLYENA);
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+					  SD0_OTAPDLYSEL_MMC_DDR50);
+	} else {
+		/* Program ITAP */
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+				  SD1_ITAPCHGWIN);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+				  SD1_ITAPDLYENA);
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					  SD1_ITAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					  SD1_ITAPDLYSEL_MMC_DDR50);
+		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYENA_MASK,
+				  SD1_OTAPDLYENA);
+		if (timing == MMC_TIMING_UHS_DDR50)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_SD_DDR50);
+		else
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  SD1_OTAPDLYSEL_MMC_DDR50);
+	}
+}
+
+static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0) {
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYENA_MASK,
+				  SD0_OTAPDLYENA);
+		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
+				  SD0_OTAPDLYSEL_SDR50);
+	} else {
+		/* Program OTAP */
+		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYENA_MASK,
+				  SD1_OTAPDLYENA);
+		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+				  SD1_OTAPDLYSEL_SDR50);
+	}
+}
+
+void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
+{
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+				  SD0_DLL_RST);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
+				  SD1_DLL_RST);
+
+	switch (timing) {
+	case MMC_TIMING_UHS_SDR25:
+		arasan_zynqmp_tap_hs(deviceid, timing, bank);
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
+		break;
+	case MMC_TIMING_UHS_SDR104:
+		arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
+		break;
+	case MMC_TIMING_UHS_DDR50:
+		arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
+		break;
+	}
+
+	if (deviceid == 0)
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+	else
+		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+}
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index f98089e..7c42a78 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -12,11 +12,18 @@
 #include <libfdt.h>
 #include <malloc.h>
 #include <sdhci.h>
+#include <mmc.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <zynqmp_tap_delay.h>
+#include "mmc_private.h"
 
 #ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ
 # define CONFIG_ZYNQ_SDHCI_MIN_FREQ	0
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 struct arasan_sdhci_plat {
 	struct mmc_config cfg;
 	struct mmc mmc;
@@ -24,8 +31,131 @@ struct arasan_sdhci_plat {
 
 struct arasan_sdhci_priv {
 	struct sdhci_host *host;
+	u8 deviceid;
+	u8 bank;
 };
 
+#if defined(CONFIG_ARCH_ZYNQMP)
+static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+{
+	u16 clk;
+	unsigned long timeout;
+
+	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	clk &= ~(SDHCI_CLOCK_CARD_EN);
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	/* Issue DLL Reset */
+	zynqmp_dll_reset(deviceid);
+
+	/* Wait max 20 ms */
+	timeout = 100;
+	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+				& SDHCI_CLOCK_INT_STABLE)) {
+		if (timeout == 0) {
+			dev_err(mmc_dev(host->mmc),
+				": Internal clock never stabilised.\n");
+			return;
+		}
+		timeout--;
+		udelay(1000);
+	}
+
+	clk |= SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
+{
+	struct mmc_cmd cmd;
+	struct mmc_data data;
+	u32 ctrl;
+	struct sdhci_host *host;
+	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+	u8 tuning_loop_counter = 40;
+	u8 deviceid;
+
+	debug("%s\n", __func__);
+
+	host = priv->host;
+	deviceid = priv->deviceid;
+
+	ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+
+	mdelay(1);
+
+	arasan_zynqmp_dll_reset(host, deviceid);
+
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+
+	do {
+		cmd.cmdidx = opcode;
+		cmd.resp_type = MMC_RSP_R1;
+		cmd.cmdarg = 0;
+
+		data.blocksize = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+
+		if (tuning_loop_counter-- == 0)
+			break;
+
+		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
+		    mmc->bus_width == 8)
+			data.blocksize = 128;
+
+		sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
+						    data.blocksize),
+			     SDHCI_BLOCK_SIZE);
+		sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
+		sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+		mmc_send_cmd(mmc, &cmd, NULL);
+		ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+
+		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+			udelay(1);
+
+	} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
+
+	if (tuning_loop_counter < 0) {
+		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+		sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+	}
+
+	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+		debug("%s:Tuning failed\n", __func__);
+		return -1;
+	} else {
+		udelay(1);
+		arasan_zynqmp_dll_reset(host, deviceid);
+	}
+
+	/* Enable only interrupts served by the SD controller */
+	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
+		     SDHCI_INT_ENABLE);
+	/* Mask all sdhci interrupt sources */
+	sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
+
+	return 0;
+}
+
+static void arasan_sdhci_set_tapdelay(struct sdhci_host *host, u8 uhsmode)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+
+	debug("%s, %d:%d, mode:%d\n", __func__, priv->deviceid, priv->bank,
+	      uhsmode);
+	if ((uhsmode >= MMC_TIMING_UHS_SDR25) &&
+	    (uhsmode <= MMC_TIMING_UHS_DDR50))
+		arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
+					   priv->bank);
+}
+#endif
+
 static int arasan_sdhci_probe(struct udevice *dev)
 {
 	struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
@@ -54,6 +184,11 @@ static int arasan_sdhci_probe(struct udevice *dev)
 	host->mmc->dev = dev;
 	upriv->mmc = host->mmc;
 
+#if defined(CONFIG_ARCH_ZYNQMP)
+	host->ops->set_delay = arasan_sdhci_set_tapdelay;
+	host->ops->platform_execute_tuning = arasan_sdhci_execute_tuning;
+#endif
+
 	return sdhci_probe(dev);
 }
 
@@ -68,6 +203,11 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 	priv->host->name = dev->name;
 	priv->host->ioaddr = (void *)dev_get_addr(dev);
 
+	priv->deviceid = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					"xlnx,device_id", -1);
+	priv->bank = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+				    "xlnx,mio_bank", -1);
+
 	return 0;
 }
 
@@ -91,6 +231,6 @@ U_BOOT_DRIVER(arasan_sdhci_drv) = {
 	.ops		= &sdhci_ops,
 	.bind		= arasan_sdhci_bind,
 	.probe		= arasan_sdhci_probe,
-	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.priv_auto_alloc_size = sizeof(struct arasan_sdhci_priv),
 	.platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat),
 };
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
new file mode 100644
index 0000000..14cff9d
--- /dev/null
+++ b/include/zynqmp_tap_delay.h
@@ -0,0 +1,20 @@
+/*
+ * Xilinx ZynqMP SoC Tap Delay Programming
+ *
+ * Copyright (C) 2016 Xilinx, Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __ZYNQMP_TAP_DELAY_H__
+#define __ZYNQMP_TAP_DELAY_H__
+
+#ifdef CONFIG_ARCH_ZYNQMP
+void zynqmp_dll_reset(u8 deviceid);
+void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank);
+#else
+inline void zynqmp_dll_reset(u8 deviceid) {}
+inline void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank) {}
+#endif
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 10/15] mmc: sdhci: Add quirk for 1.8v switching not supported
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (8 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 09/15] mmc: sdhci: zynqmp: Add support of SD3.0 Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 11/15] mmc: zynq_sdhci: Update quirk if " Siva Durga Prasad Paladugu
                     ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Add quirk if voltage switching to 1.8v is broken, in this
case no UHS modes were supported

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 drivers/mmc/sdhci.c | 3 ++-
 include/sdhci.h     | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index bbb6302..c5538ab 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -753,7 +753,8 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 				SDHCI_CLOCK_MUL_SHIFT;
 	}
 
-	if (!(cfg->voltages & MMC_VDD_165_195))
+	if (!(cfg->voltages & MMC_VDD_165_195) ||
+	    (host->quirks & SDHCI_QUIRK_NO_1_8_V))
 		caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
 			    SDHCI_SUPPORT_DDR50);
 
diff --git a/include/sdhci.h b/include/sdhci.h
index 2317eac..37b23ad 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -228,6 +228,7 @@
 #define SDHCI_QUIRK_BROKEN_VOLTAGE	(1 << 4)
 #define SDHCI_QUIRK_WAIT_SEND_CMD	(1 << 6)
 #define SDHCI_QUIRK_USE_WIDE8		(1 << 8)
+#define SDHCI_QUIRK_NO_1_8_V		(1 << 9)
 
 /* to make gcc happy */
 struct sdhci_host;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 11/15] mmc: zynq_sdhci: Update quirk if 1.8v switching not supported
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (9 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 10/15] mmc: sdhci: Add quirk for 1.8v switching not supported Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 12/15] mmc: sdhci: Add support for eMMC HS200 mode Siva Durga Prasad Paladugu
                     ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Update quirk if 1.8 voltage switching is not supported
on boards by reading the property "no-1-8-v" from device
tree.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 drivers/mmc/zynq_sdhci.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 7c42a78..4875a4e 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -33,6 +33,7 @@ struct arasan_sdhci_priv {
 	struct sdhci_host *host;
 	u8 deviceid;
 	u8 bank;
+	u8 no_1p8;
 };
 
 #if defined(CONFIG_ARCH_ZYNQMP)
@@ -175,8 +176,12 @@ static int arasan_sdhci_probe(struct udevice *dev)
 
 	host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
 
+	if (priv->no_1p8)
+		host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+
 	ret = sdhci_setup_cfg(&plat->cfg, host, 0,
 			      CONFIG_ZYNQ_SDHCI_MIN_FREQ);
+
 	host->mmc = &plat->mmc;
 	if (ret)
 		return ret;
@@ -207,6 +212,10 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 					"xlnx,device_id", -1);
 	priv->bank = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
 				    "xlnx,mio_bank", -1);
+	if (fdt_get_property(gd->fdt_blob, dev->of_offset, "no-1-8-v", NULL))
+		priv->no_1p8 = 1;
+	else
+		priv->no_1p8 = 0;
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 12/15] mmc: sdhci: Add support for eMMC HS200 mode
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (10 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 11/15] mmc: zynq_sdhci: Update quirk if " Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 13/15] mmc: sdhci: Update execute tuning and set clock for HS200 Siva Durga Prasad Paladugu
                     ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Add support for eMMC HS200 mode by reading
card type from ext_csd and then by switching to
HS200 timing mode.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- Split the patch with only mmc changes
---
 drivers/mmc/mmc.c | 24 ++++++++++++++++++------
 include/mmc.h     |  7 +++++++
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 0f0bfc8..02c0408 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -619,9 +619,16 @@ static int mmc_change_freq(struct mmc *mmc)
 	if (err)
 		return err;
 
-	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
+	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
 
-	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
+	if (cardtype & EXT_CSD_CARD_TYPE_HS200)
+		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_HS_TIMING,
+				 EXT_CSD_HS_TIMING_HS200);
+	else
+		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+				 EXT_CSD_HS_TIMING,
+				 EXT_CSD_HS_TIMING_HIGH_SPEED);
 
 	if (err)
 		return err;
@@ -636,8 +643,10 @@ static int mmc_change_freq(struct mmc *mmc)
 	if (!ext_csd[EXT_CSD_HS_TIMING])
 		return 0;
 
-	/* High Speed is set, there are two types: 52MHz and 26MHz */
-	if (cardtype & EXT_CSD_CARD_TYPE_52) {
+	/* High Speed is set, there are three types: 200MHZ, 52MHz and 26MHz */
+	if (cardtype & EXT_CSD_CARD_TYPE_HS200) {
+		mmc->card_caps |= MMC_MODE_HS200;
+	} else if (cardtype & EXT_CSD_CARD_TYPE_52) {
 		if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
 			mmc->card_caps |= MMC_MODE_DDR_52MHz;
 		mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
@@ -1659,7 +1668,9 @@ static int mmc_startup(struct mmc *mmc)
 		if (err)
 			return err;
 
-		if (mmc->card_caps & MMC_MODE_HS) {
+		if (mmc->card_caps & MMC_MODE_HS200) {
+			mmc->tran_speed = 200000000;
+		} else if (mmc->card_caps & MMC_MODE_HS) {
 			if (mmc->card_caps & MMC_MODE_HS_52MHz)
 				mmc->tran_speed = 52000000;
 			else
@@ -1670,7 +1681,8 @@ static int mmc_startup(struct mmc *mmc)
 	mmc_set_clock(mmc, mmc->tran_speed);
 
 	if ((mmc->card_caps & (MMC_MODE_UHS_SDR50 |
-			       MMC_MODE_UHS_SDR104)) &&
+			       MMC_MODE_UHS_SDR104 |
+			       MMC_MODE_HS200)) &&
 	    (mmc->cfg->host_caps & MMC_MODE_NEEDS_TUNING)) {
 		err = mmc_execute_tuning(mmc);
 		if (err)
diff --git a/include/mmc.h b/include/mmc.h
index 56395ee..90e1dcc 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -223,6 +223,13 @@
 #define EXT_CSD_CARD_TYPE_DDR_1_2V	(1 << 3)
 #define EXT_CSD_CARD_TYPE_DDR_52	(EXT_CSD_CARD_TYPE_DDR_1_8V \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1 << 4)
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1 << 5)
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V \
+					| EXT_CSD_CARD_TYPE_HS200_1_2V)
+
+#define EXT_CSD_HS_TIMING_HIGH_SPEED	1
+#define EXT_CSD_HS_TIMING_HS200		2
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 13/15] mmc: sdhci: Update execute tuning and set clock for HS200
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (11 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 12/15] mmc: sdhci: Add support for eMMC HS200 mode Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 14/15] mmc: sdhci: zynqmp: Set tapdelays for eMMC HS200 mode Siva Durga Prasad Paladugu
                     ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Update execute tuning and set clock to support for
HS200 mode.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- Split the patch with only sdhci related changes
---
 drivers/mmc/sdhci.c | 18 +++++++++++++-----
 include/mmc.h       |  1 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c5538ab..e8d76ba 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -157,7 +157,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	/* We shouldn't wait for data inihibit for stop commands, even
 	   though they might use busy signaling */
 	if ((cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) ||
-	    (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK))
+	    (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK) ||
+	    (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK_HS200))
 		mask &= ~SDHCI_DATA_INHIBIT;
 
 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
@@ -179,7 +180,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	mask = SDHCI_INT_RESPONSE;
 
 	/* only buffer read ready interrupt whil tuning */
-	if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
+	if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) ||
+	    (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK_HS200))
 		mask = SDHCI_INT_DATA_AVAIL;
 
 	if (!(cmd->resp_type & MMC_RSP_PRESENT))
@@ -197,7 +199,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 		flags |= SDHCI_CMD_CRC;
 	if (cmd->resp_type & MMC_RSP_OPCODE)
 		flags |= SDHCI_CMD_INDEX;
-	if (data || (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK))
+	if (data || (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK) ||
+	    (cmd->cmdidx ==  MMC_CMD_SEND_TUNING_BLOCK_HS200))
 		flags |= SDHCI_CMD_DATA;
 
 	/* Set Transfer mode regarding to data flag */
@@ -405,8 +408,13 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 	if (clock == 0)
 		return 0;
 
-	if (mmc->is_uhs && host->ops->set_delay)
-		host->ops->set_delay(host, mmc->uhsmode);
+	if (((mmc->card_caps & MMC_MODE_HS200) || mmc->is_uhs) &&
+	    host->ops->set_delay) {
+		if (mmc->is_uhs)
+			host->ops->set_delay(host, mmc->uhsmode);
+		else
+			host->ops->set_delay(host, MMC_TIMING_HS200);
+	}
 
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		/*
diff --git a/include/mmc.h b/include/mmc.h
index 90e1dcc..e0b5510 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -300,6 +300,7 @@
 #define MMC_TIMING_UHS_SDR50	2
 #define MMC_TIMING_UHS_SDR104	3
 #define MMC_TIMING_UHS_DDR50	4
+#define MMC_TIMING_HS200	5
 #define MMC_TIMING_HS		1
 
 /* Driver model support */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 14/15] mmc: sdhci: zynqmp: Set tapdelays for eMMC HS200 mode
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (12 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 13/15] mmc: sdhci: Update execute tuning and set clock for HS200 Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 15/15] mmc: Change frequency while accessing to boot partition Siva Durga Prasad Paladugu
  2017-02-02 10:52   ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Jaehoon Chung
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Sets the tapdelays for eMMC HS200 mode support for
ZynqMP as tapdelays needs to be programmed for it to
work

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- None
---
 board/xilinx/zynqmp/tap_delays.c | 1 +
 drivers/mmc/zynq_sdhci.c         | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
index d57587e..aa0825a 100644
--- a/board/xilinx/zynqmp/tap_delays.c
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -235,6 +235,7 @@ void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
 		arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
 		break;
 	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
 		arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
 		break;
 	case MMC_TIMING_UHS_DDR50:
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 4875a4e..8fa5df8 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -151,7 +151,7 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host, u8 uhsmode)
 	debug("%s, %d:%d, mode:%d\n", __func__, priv->deviceid, priv->bank,
 	      uhsmode);
 	if ((uhsmode >= MMC_TIMING_UHS_SDR25) &&
-	    (uhsmode <= MMC_TIMING_UHS_DDR50))
+	    (uhsmode <= MMC_TIMING_HS200))
 		arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
 					   priv->bank);
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 15/15] mmc: Change frequency while accessing to boot partition
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (13 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 14/15] mmc: sdhci: zynqmp: Set tapdelays for eMMC HS200 mode Siva Durga Prasad Paladugu
@ 2017-01-30 10:38   ` Siva Durga Prasad Paladugu
  2017-02-02 10:52   ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Jaehoon Chung
  15 siblings, 0 replies; 17+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-01-30 10:38 UTC (permalink / raw)
  To: u-boot

Boot partition is not supported in HS200 mode, hence change
clock to high speed while accessing boot partition and
revert back when partition is switching to other than boot
partition

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
Changes from v1:
- Added this in series as per review comment
---
 drivers/mmc/mmc.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/mmc.h     |  2 ++
 2 files changed, 60 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 02c0408..be6003f 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -621,6 +621,9 @@ static int mmc_change_freq(struct mmc *mmc)
 
 	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
 
+	if (mmc->forcehs)
+		cardtype &= ~EXT_CSD_CARD_TYPE_HS200;
+
 	if (cardtype & EXT_CSD_CARD_TYPE_HS200)
 		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
 				 EXT_CSD_HS_TIMING,
@@ -685,10 +688,65 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
 	return 0;
 }
 
+static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num)
+{
+	int ret;
+
+	if (((part_num & PART_ACCESS_MASK) == PART_ACCESS_BOOT0) &&
+	    (mmc->card_caps == MMC_MODE_HS200)) {
+		mmc->forcehs = 1;
+		ret = mmc_change_freq(mmc);
+		if (ret)
+			return ret;
+
+		mmc->card_caps &= mmc->cfg->host_caps;
+		if (mmc->card_caps & MMC_MODE_HS) {
+			if (mmc->card_caps & MMC_MODE_HS_52MHz)
+				mmc->tran_speed = 52000000;
+			else
+				mmc->tran_speed = 26000000;
+		}
+		mmc_set_clock(mmc, mmc->tran_speed);
+	}
+
+	if (((part_num & PART_ACCESS_MASK) != PART_ACCESS_BOOT0) &&
+	    mmc->forcehs) {
+		mmc->forcehs = 0;
+		ret = mmc_change_freq(mmc);
+		if (ret)
+			return ret;
+
+		mmc->card_caps &= mmc->cfg->host_caps;
+		if (mmc->card_caps & MMC_MODE_HS200) {
+			mmc->tran_speed = 200000000;
+		} else if (mmc->card_caps & MMC_MODE_HS) {
+			if (mmc->card_caps & MMC_MODE_HS_52MHz)
+				mmc->tran_speed = 52000000;
+			else
+				mmc->tran_speed = 26000000;
+		}
+
+		mmc_set_clock(mmc, mmc->tran_speed);
+
+		if ((mmc->card_caps &  MMC_MODE_HS200) &&
+		    (mmc->cfg->host_caps & MMC_MODE_NEEDS_TUNING)) {
+			ret = mmc_execute_tuning(mmc);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
 {
 	int ret;
 
+	ret = mmc_boot_part_access_chk(mmc, part_num);
+	if (ret)
+		return ret;
+
 	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
 			 (mmc->part_config & ~PART_ACCESS_MASK)
 			 | (part_num & PART_ACCESS_MASK));
diff --git a/include/mmc.h b/include/mmc.h
index e0b5510..6f9a41c 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -282,6 +282,7 @@
 
 #define MMCPART_NOAVAILABLE	(0xff)
 #define PART_ACCESS_MASK	(0x7)
+#define PART_ACCESS_BOOT0	(0x2)
 #define PART_SUPPORT		(0x1)
 #define ENHNCD_SUPPORT		(0x2)
 #define PART_ENH_ATTRIB		(0x1f)
@@ -522,6 +523,7 @@ struct mmc {
 #endif
 	u8 is_uhs;
 	u8 uhsmode;
+	u8 forcehs;
 };
 
 struct mmc_hwpart_conf {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200
  2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
                     ` (14 preceding siblings ...)
  2017-01-30 10:38   ` [U-Boot] [UBOOT v2 15/15] mmc: Change frequency while accessing to boot partition Siva Durga Prasad Paladugu
@ 2017-02-02 10:52   ` Jaehoon Chung
  15 siblings, 0 replies; 17+ messages in thread
From: Jaehoon Chung @ 2017-02-02 10:52 UTC (permalink / raw)
  To: u-boot

Hi Siva,

On 01/30/2017 07:38 PM, Siva Durga Prasad Paladugu wrote:
> This patch series adds support SD3.0 and eMMC HS200
> modes for ZynqMP. This series also contains changes
> in mmc and sdhci framework to support SD3.0 and HS200.

Your patches can't be applied yet. Just for testing..i had built your patches for Samsung SoC boards.

drivers/mmc/mmc.c: In function 'mmc_boot_part_access_chk':
drivers/mmc/mmc.c:733:10: warning: implicit declaration of function 'mmc_execute_tuning' [-Wimplicit-function-declaration]
    ret = mmc_execute_tuning(mmc);
          ^~~~~~~~~~~~~~~~~~
drivers/mmc/mmc.c: At top level:
drivers/mmc/mmc.c:1269:12: error: static declaration of 'mmc_execute_tuning' follows non-static declaration
 static int mmc_execute_tuning(struct mmc *mmc)
            ^~~~~~~~~~~~~~~~~~
drivers/mmc/mmc.c:733:10: note: previous implicit declaration of 'mmc_execute_tuning' was here
    ret = mmc_execute_tuning(mmc);
          ^~~~~~~~~~~~~~~~~~
make[1]: *** [drivers/mmc/mmc.o] Error 1
make[1]: *** Waiting for unfinished jobs....

       arm:  +   trats
+drivers/mmc/sdhci.c: In function 'sdhci_execute_tuning':
+drivers/mmc/sdhci.c:357:22: error: 'dev' undeclared (first use in this function)
+   sdhci_send_command(dev, &cmd, &data);
+                      ^~~
+drivers/mmc/sdhci.c:357:22: note: each undeclared identifier is reported only once for each function it appears in
+make[2]: *** [drivers/mmc/sdhci.o] Error 1
+make[1]: *** [drivers/mmc] Error 2
+make[1]: *** wait: No child processes.  Stop.
+make: *** [sub-make] Error 2

Plz, fix these issue..Then i can test your patches.

Best Regards,
Jaehoon Chung

> 
> Siva Durga Prasad Paladugu (15):
>   mmc: sdhci: Update host capabilities about host controller
>   mmc: Add support for SD3.0
>   mmc: sdhci: Add SD3.0 support
>   mmc: sdhci: Add support for platform/board specific tuning
>   mmc: sdhci: Add support for platform specific delay
>   mmc: sdhci: Make sdhci_ops of host as modifiable
>   zynqmp: Define routines for mmio write and read
>   mmc: sdhci: zynq: Define private structure arasan_sdhci_priv
>   mmc: sdhci: zynqmp: Add support of SD3.0
>   mmc: sdhci: Add quirk for 1.8v switching not supported
>   mmc: zynq_sdhci: Update quirk if 1.8v switching not supported
>   mmc: sdhci: Add support for eMMC HS200 mode
>   mmc: sdhci: Update execute tuning and set clock for HS200
>   mmc: sdhci: zynqmp: Set tapdelays for eMMC HS200 mode
>   mmc: Change frequency while accessing to boot partition
> 
>  arch/arm/cpu/armv8/zynqmp/cpu.c              |  51 ++++++
>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |   3 +
>  board/xilinx/zynqmp/Makefile                 |   1 +
>  board/xilinx/zynqmp/tap_delays.c             | 250 +++++++++++++++++++++++++++
>  drivers/mmc/mmc-uclass.c                     |  52 ++++++
>  drivers/mmc/mmc.c                            | 218 +++++++++++++++++++++--
>  drivers/mmc/sdhci.c                          | 205 +++++++++++++++++++++-
>  drivers/mmc/zynq_sdhci.c                     | 170 +++++++++++++++++-
>  include/mmc.h                                |  74 +++++++-
>  include/sdhci.h                              |  18 +-
>  include/zynqmp_tap_delay.h                   |  20 +++
>  11 files changed, 1040 insertions(+), 22 deletions(-)
>  create mode 100644 board/xilinx/zynqmp/tap_delays.c
>  create mode 100644 include/zynqmp_tap_delay.h
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2017-02-02 10:52 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20170130103830epcas1p195ed3f0d004b3724edeebd6f000212ce@epcas1p1.samsung.com>
2017-01-30 10:38 ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 01/15] mmc: sdhci: Update host capabilities about host controller Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 02/15] mmc: Add support for SD3.0 Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 03/15] mmc: sdhci: Add SD3.0 support Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 04/15] mmc: sdhci: Add support for platform/board specific tuning Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 05/15] mmc: sdhci: Add support for platform specific delay Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 06/15] mmc: sdhci: Make sdhci_ops of host as modifiable Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 07/15] zynqmp: Define routines for mmio write and read Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 08/15] mmc: sdhci: zynq: Define private structure arasan_sdhci_priv Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 09/15] mmc: sdhci: zynqmp: Add support of SD3.0 Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 10/15] mmc: sdhci: Add quirk for 1.8v switching not supported Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 11/15] mmc: zynq_sdhci: Update quirk if " Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 12/15] mmc: sdhci: Add support for eMMC HS200 mode Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 13/15] mmc: sdhci: Update execute tuning and set clock for HS200 Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 14/15] mmc: sdhci: zynqmp: Set tapdelays for eMMC HS200 mode Siva Durga Prasad Paladugu
2017-01-30 10:38   ` [U-Boot] [UBOOT v2 15/15] mmc: Change frequency while accessing to boot partition Siva Durga Prasad Paladugu
2017-02-02 10:52   ` [U-Boot] [UBOOT v2 00/15] Add support for SD3.0 and eMMC HS200 Jaehoon Chung

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.