All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode
@ 2018-06-26 15:46 ernest.zhang
  2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: ernest.zhang @ 2018-06-26 15:46 UTC (permalink / raw)
  To: Adrian Hunter, Ulf Hansson, linux-mmc, linux-kernel
  Cc: ernest.zhang, chuanjin.pang, mike.li, chevron.li, shirley.her,
	xiaoguang.yu, bobby.wu

When use eMMC as boot device, the eMMC signaling voltage is tied to 1.8v
fixed output voltage, bios can set o2 sd host controller PCI configuration
register 0x308 bit4 to 1 to let driver skip 3.3v signaling voltage and
direct use 1.8v singling voltage in eMMC initialize process.

Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>
---
Changes in V6:
	1.Move change log to correct place.
	2.Change HS200 mode clock frequency from 208MHz to 200MHz to meet
	Specification.

Changes in V5:
	Modify code format to pass checkpatch.pl check and add a summary
	of what has changed in each version.

Changes in V4:
	Skip SDIO and SD initalization when register 0x308 bit 4 is set,
	and modify some typo.

Changes in V3:
	Rebase the patch on the mmc tree 'next' branch.

Changes in V2:
	Modify code format, and delete unused code path.

Changes in V1:
	Check PCIe register 0x308 bit 4 and skip eMMC 3.3v initialization
	process if it is set to 1.
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 555970a..94cf3cd 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -3,6 +3,7 @@
  *
  * Authors: Peter Guo <peter.guo@bayhubtech.com>
  *          Adam Lee <adam.lee@canonical.com>
+ *          Ernest Zhang <ernest.zhang@bayhubtech.com>
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -39,6 +40,7 @@
 #define O2_SD_MISC_CTRL4	0xFC
 #define O2_SD_TUNING_CTRL	0x300
 #define O2_SD_PLL_SETTING	0x304
+#define O2_SD_MISC_SETTING	0x308
 #define O2_SD_CLK_SETTING	0x328
 #define O2_SD_CAP_REG2		0x330
 #define O2_SD_CAP_REG0		0x334
@@ -184,6 +186,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 	struct sdhci_pci_chip *chip;
 	struct sdhci_host *host;
 	u32 reg;
+	int ret;
 
 	chip = slot->chip;
 	host = slot->host;
@@ -197,6 +200,21 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 		if (reg & 0x1)
 			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
 
+		if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
+			ret = pci_read_config_dword(chip->pdev,
+						    O2_SD_MISC_SETTING, &reg);
+			if (ret)
+				return -EIO;
+			if (reg & (1 << 4)) {
+				pr_info("%s: emmc 1.8v flag is set, force 1.8v signaling voltage\n",
+					mmc_hostname(host->mmc));
+				host->flags &= ~SDHCI_SIGNALING_330;
+				host->flags |= SDHCI_SIGNALING_180;
+				host->mmc->caps2 |= MMC_CAP2_NO_SD;
+				host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+			}
+		}
+
 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
 			break;
 		/* set dll watch dog timer */
@@ -293,7 +311,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
 
 			/* Check Whether subId is 0x11 or 0x12 */
 			if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) {
-				scratch_32 = 0x2c280000;
+				scratch_32 = 0x25100000;
 
 				/* Set Base Clock to 208MZ */
 				o2_pci_set_baseclk(chip, scratch_32);
@@ -388,7 +406,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
 					       O2_SD_PLL_SETTING, scratch_32);
 		} else {
 			scratch_32 &= 0x0000FFFF;
-			scratch_32 |= 0x2c280000;
+			scratch_32 |= 0x25100000;
 
 			pci_write_config_dword(chip->pdev,
 					       O2_SD_PLL_SETTING, scratch_32);
-- 
2.7.4


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

* [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning
  2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang
@ 2018-06-26 15:46 ` ernest.zhang
  2018-07-10 12:43   ` Adrian Hunter
  2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang
  2018-07-10 12:23 ` [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode Adrian Hunter
  2 siblings, 1 reply; 6+ messages in thread
From: ernest.zhang @ 2018-06-26 15:46 UTC (permalink / raw)
  To: Adrian Hunter, Ulf Hansson, linux-mmc, linux-kernel
  Cc: ernest.zhang, chuanjin.pang, mike.li, chevron.li, shirley.her,
	xiaoguang.yu, bobby.wu

Add hardware tuning function instead of software tuning because O2/Bayhub
SD host controller support hardware tuning.

Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>
---
Changes in V6:
	1. From module 'sdhci' export the symbols 'sdhci_start_tuning',
	'sdhci_end_tuning','sdhci_send_tuning' and 'sdhci_reset_tuning'.
	2. Remove local tuning related functions in sdhci-pci-o2-micro.c
	instead of above function exported in sdhci module.
	3. Remove unneeded braces in function sdhci_set_transfer_mode.
	4. Move change log to correct place.

Changes in V5:
	In function sdhci_o2_send_tuning, mrq.data should set to NULL for
	cmd.data has been set to NULL.

Changes in V4:
	Patch V3 delete register SDHCI_TRANSFER_MODE write operation before
	send hardware tuning command in function sdhci_o2_send_tuning. This
	is a mistake. The write operation is essential for tuning command.
	Add it back.

Changes in V3:
	Rebase the patch on the mmc tree 'next' branch.

Changes in V2:
	Modify code format, and delete unused code path.

Changes in V1:
	Add many functions to execute hardware tuning for eMMC 1.8V HS200
	mode, the hardware tuning procedure is based on O2/Bayhub hardware
	tuning spec.
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 81 ++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci.c             | 16 ++++---
 drivers/mmc/host/sdhci.h             |  5 +++
 3 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 94cf3cd..7747e8b 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -17,6 +17,9 @@
  */
 
 #include <linux/pci.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/delay.h>
 
 #include "sdhci.h"
 #include "sdhci-pci.h"
@@ -55,6 +58,82 @@
 
 #define O2_SD_VENDOR_SETTING	0x110
 #define O2_SD_VENDOR_SETTING2	0x1C8
+#define O2_SD_HW_TUNING_DISABLE	BIT(4)
+
+static void sdhci_o2_set_tuning_mode(struct sdhci_host *host)
+{
+	u16 reg;
+
+	/* enable hardware tuning */
+	reg = sdhci_readw(host, O2_SD_VENDOR_SETTING);
+	reg &= ~O2_SD_HW_TUNING_DISABLE;
+	sdhci_writew(host, reg, O2_SD_VENDOR_SETTING);
+}
+
+static void __sdhci_o2_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	int i;
+
+	sdhci_send_tuning(host, MMC_SEND_TUNING_BLOCK_HS200);
+
+	for (i = 0; i < 150; i++) {
+		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+		if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
+			if (ctrl & SDHCI_CTRL_TUNED_CLK) {
+				host->tuning_done = true;
+				return;
+			}
+			pr_warn("%s: HW tuning failed !\n",
+				mmc_hostname(host->mmc));
+			break;
+		}
+
+		mdelay(1);
+	}
+
+	pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
+		mmc_hostname(host->mmc));
+	sdhci_reset_tuning(host);
+}
+
+static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int current_bus_width = 0;
+
+	/*
+	 * This handler only implements the eMMC tuning that is specific to
+	 * this controller.  Fall back to the standard method for other TIMING.
+	 */
+	if (host->timing != MMC_TIMING_MMC_HS200)
+		return sdhci_execute_tuning(mmc, opcode);
+
+	if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200))
+		return -EINVAL;
+
+	/*
+	 * o2 sdhci host didn't support 8bit emmc tuning
+	 */
+	if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
+		current_bus_width = mmc->ios.bus_width;
+		sdhci_set_bus_width(host, MMC_BUS_WIDTH_4);
+	}
+
+	sdhci_o2_set_tuning_mode(host);
+
+	sdhci_start_tuning(host);
+
+	__sdhci_o2_execute_tuning(host, opcode);
+
+	sdhci_end_tuning(host);
+
+	if (current_bus_width == MMC_BUS_WIDTH_8)
+		sdhci_set_bus_width(host, current_bus_width);
+
+	host->flags &= ~SDHCI_HS400_TUNING;
+	return 0;
+}
 
 static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value)
 {
@@ -215,6 +294,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 			}
 		}
 
+		host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
+
 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
 			break;
 		/* set dll watch dog timer */
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1c828e0..4f3e3c2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1029,7 +1029,9 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
 	if (data == NULL) {
 		if (host->quirks2 &
 			SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
-			sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
+			/* must not clear SDHCI_TRANSFER_MODE when tuning */
+			if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
+				sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
 		} else {
 		/* clear Auto CMD settings for no data CMDs */
 			mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
@@ -2103,7 +2105,7 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
 	return 0;
 }
 
-static void sdhci_start_tuning(struct sdhci_host *host)
+void sdhci_start_tuning(struct sdhci_host *host)
 {
 	u16 ctrl;
 
@@ -2126,14 +2128,16 @@ static void sdhci_start_tuning(struct sdhci_host *host)
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
 }
+EXPORT_SYMBOL_GPL(sdhci_start_tuning);
 
-static void sdhci_end_tuning(struct sdhci_host *host)
+void sdhci_end_tuning(struct sdhci_host *host)
 {
 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 }
+EXPORT_SYMBOL_GPL(sdhci_end_tuning);
 
-static void sdhci_reset_tuning(struct sdhci_host *host)
+void sdhci_reset_tuning(struct sdhci_host *host)
 {
 	u16 ctrl;
 
@@ -2142,6 +2146,7 @@ static void sdhci_reset_tuning(struct sdhci_host *host)
 	ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 }
+EXPORT_SYMBOL_GPL(sdhci_reset_tuning);
 
 static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
 {
@@ -2162,7 +2167,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
  * interrupt setup is different to other commands and there is no timeout
  * interrupt so special handling is needed.
  */
-static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
+void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
 {
 	struct mmc_host *mmc = host->mmc;
 	struct mmc_command cmd = {};
@@ -2212,6 +2217,7 @@ static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
 			   msecs_to_jiffies(50));
 
 }
+EXPORT_SYMBOL_GPL(sdhci_send_tuning);
 
 static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
 {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 23966f8..2a09c0a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -748,4 +748,9 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
 
 void sdhci_dumpregs(struct sdhci_host *host);
 
+void sdhci_start_tuning(struct sdhci_host *host);
+void sdhci_end_tuning(struct sdhci_host *host);
+void sdhci_send_tuning(struct sdhci_host *host, u32 opcode);
+void sdhci_reset_tuning(struct sdhci_host *host);
+
 #endif /* __SDHCI_HW_H */
-- 
2.7.4


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

* [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host
  2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang
  2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang
@ 2018-06-26 15:46 ` ernest.zhang
  2018-07-10 12:44   ` Adrian Hunter
  2018-07-10 12:23 ` [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode Adrian Hunter
  2 siblings, 1 reply; 6+ messages in thread
From: ernest.zhang @ 2018-06-26 15:46 UTC (permalink / raw)
  To: Adrian Hunter, Ulf Hansson, linux-mmc, linux-kernel
  Cc: ernest.zhang, chuanjin.pang, mike.li, chevron.li, shirley.her,
	xiaoguang.yu, bobby.wu

Add MSI interrupt support if the SD host device can support MSI interrupt.

Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>
---
Changes in V6:
	1. Move change log to correct place.
	2. Reduce unneeded pr_info prints.
	3. In function sdhci_pci_o2_probe_slot, remove using local
	variable 'mmc' instead of using 'host->mmc'.
	3. Make the msi enable code a sperate function.

Changes in V5:
	1. Because pci_enable_msi is marked as deprecated and should not be
	used in new code, use pci_alloc_irq_vectors instead.
	2. Remove unneeded CONFIG_PCI_MSI macro check.

Changes in V4:
	Enable MSI interrupt if the MSI capability bit is set in
	capability register.
---
 drivers/mmc/host/sdhci-pci-o2micro.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 7747e8b..56bc717 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -260,6 +260,29 @@ static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
 	pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32);
 }
 
+static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip,
+				    struct sdhci_host *host)
+{
+	int ret;
+
+	ret = pci_find_capability(chip->pdev, PCI_CAP_ID_MSI);
+	if (!ret) {
+		pr_info("%s: unsupport msi, use INTx irq\n",
+			mmc_hostname(host->mmc));
+		return;
+	}
+
+	ret = pci_alloc_irq_vectors(chip->pdev, 1, 1,
+				    PCI_IRQ_MSI | PCI_IRQ_MSIX);
+	if (ret < 0) {
+		pr_err("%s: enable PCI MSI failed, err=%d\n",
+		       mmc_hostname(host->mmc), ret);
+		return;
+	}
+
+	host->irq = pci_irq_vector(chip->pdev, 0);
+}
+
 int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 {
 	struct sdhci_pci_chip *chip;
@@ -279,6 +302,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
 		if (reg & 0x1)
 			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
 
+		sdhci_pci_o2_enable_msi(chip, host);
+
 		if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
 			ret = pci_read_config_dword(chip->pdev,
 						    O2_SD_MISC_SETTING, &reg);
-- 
2.7.4


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

* Re: [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode
  2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang
  2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang
  2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang
@ 2018-07-10 12:23 ` Adrian Hunter
  2 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2018-07-10 12:23 UTC (permalink / raw)
  To: ernest.zhang, Ulf Hansson, linux-mmc, linux-kernel
  Cc: chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu

On 26/06/18 18:46, ernest.zhang wrote:
> When use eMMC as boot device, the eMMC signaling voltage is tied to 1.8v
> fixed output voltage, bios can set o2 sd host controller PCI configuration
> register 0x308 bit4 to 1 to let driver skip 3.3v signaling voltage and
> direct use 1.8v singling voltage in eMMC initialize process.
> 
> Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>
> ---
> Changes in V6:
> 	1.Move change log to correct place.
> 	2.Change HS200 mode clock frequency from 208MHz to 200MHz to meet
> 	Specification.

That 2nd change should be a separate patch.

> 
> Changes in V5:
> 	Modify code format to pass checkpatch.pl check and add a summary
> 	of what has changed in each version.
> 
> Changes in V4:
> 	Skip SDIO and SD initalization when register 0x308 bit 4 is set,
> 	and modify some typo.
> 
> Changes in V3:
> 	Rebase the patch on the mmc tree 'next' branch.
> 
> Changes in V2:
> 	Modify code format, and delete unused code path.
> 
> Changes in V1:
> 	Check PCIe register 0x308 bit 4 and skip eMMC 3.3v initialization
> 	process if it is set to 1.
> ---
>  drivers/mmc/host/sdhci-pci-o2micro.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
> index 555970a..94cf3cd 100644
> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
> @@ -3,6 +3,7 @@
>   *
>   * Authors: Peter Guo <peter.guo@bayhubtech.com>
>   *          Adam Lee <adam.lee@canonical.com>
> + *          Ernest Zhang <ernest.zhang@bayhubtech.com>
>   *
>   * This software is licensed under the terms of the GNU General Public
>   * License version 2, as published by the Free Software Foundation, and
> @@ -39,6 +40,7 @@
>  #define O2_SD_MISC_CTRL4	0xFC
>  #define O2_SD_TUNING_CTRL	0x300
>  #define O2_SD_PLL_SETTING	0x304
> +#define O2_SD_MISC_SETTING	0x308
>  #define O2_SD_CLK_SETTING	0x328
>  #define O2_SD_CAP_REG2		0x330
>  #define O2_SD_CAP_REG0		0x334
> @@ -184,6 +186,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  	struct sdhci_pci_chip *chip;
>  	struct sdhci_host *host;
>  	u32 reg;
> +	int ret;
>  
>  	chip = slot->chip;
>  	host = slot->host;
> @@ -197,6 +200,21 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  		if (reg & 0x1)
>  			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>  
> +		if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
> +			ret = pci_read_config_dword(chip->pdev,
> +						    O2_SD_MISC_SETTING, &reg);
> +			if (ret)
> +				return -EIO;
> +			if (reg & (1 << 4)) {
> +				pr_info("%s: emmc 1.8v flag is set, force 1.8v signaling voltage\n",
> +					mmc_hostname(host->mmc));
> +				host->flags &= ~SDHCI_SIGNALING_330;
> +				host->flags |= SDHCI_SIGNALING_180;
> +				host->mmc->caps2 |= MMC_CAP2_NO_SD;
> +				host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> +			}
> +		}
> +
>  		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
>  			break;
>  		/* set dll watch dog timer */
> @@ -293,7 +311,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
>  
>  			/* Check Whether subId is 0x11 or 0x12 */
>  			if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) {
> -				scratch_32 = 0x2c280000;
> +				scratch_32 = 0x25100000;
>  
>  				/* Set Base Clock to 208MZ */

Need to change the comment too i.e. 208MZ -> 200 MHz

>  				o2_pci_set_baseclk(chip, scratch_32);
> @@ -388,7 +406,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
>  					       O2_SD_PLL_SETTING, scratch_32);
>  		} else {
>  			scratch_32 &= 0x0000FFFF;
> -			scratch_32 |= 0x2c280000;
> +			scratch_32 |= 0x25100000;
>  
>  			pci_write_config_dword(chip->pdev,
>  					       O2_SD_PLL_SETTING, scratch_32);
> 


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

* Re: [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning
  2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang
@ 2018-07-10 12:43   ` Adrian Hunter
  0 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2018-07-10 12:43 UTC (permalink / raw)
  To: ernest.zhang, Ulf Hansson, linux-mmc, linux-kernel
  Cc: chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu

On 26/06/18 18:46, ernest.zhang wrote:
> Add hardware tuning function instead of software tuning because O2/Bayhub
> SD host controller support hardware tuning.
> 
> Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>
> ---
> Changes in V6:
> 	1. From module 'sdhci' export the symbols 'sdhci_start_tuning',
> 	'sdhci_end_tuning','sdhci_send_tuning' and 'sdhci_reset_tuning'.
> 	2. Remove local tuning related functions in sdhci-pci-o2-micro.c
> 	instead of above function exported in sdhci module.
> 	3. Remove unneeded braces in function sdhci_set_transfer_mode.
> 	4. Move change log to correct place.
> 
> Changes in V5:
> 	In function sdhci_o2_send_tuning, mrq.data should set to NULL for
> 	cmd.data has been set to NULL.
> 
> Changes in V4:
> 	Patch V3 delete register SDHCI_TRANSFER_MODE write operation before
> 	send hardware tuning command in function sdhci_o2_send_tuning. This
> 	is a mistake. The write operation is essential for tuning command.
> 	Add it back.
> 
> Changes in V3:
> 	Rebase the patch on the mmc tree 'next' branch.
> 
> Changes in V2:
> 	Modify code format, and delete unused code path.
> 
> Changes in V1:
> 	Add many functions to execute hardware tuning for eMMC 1.8V HS200
> 	mode, the hardware tuning procedure is based on O2/Bayhub hardware
> 	tuning spec.
> ---
>  drivers/mmc/host/sdhci-pci-o2micro.c | 81 ++++++++++++++++++++++++++++++++++++
>  drivers/mmc/host/sdhci.c             | 16 ++++---
>  drivers/mmc/host/sdhci.h             |  5 +++
>  3 files changed, 97 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
> index 94cf3cd..7747e8b 100644
> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
> @@ -17,6 +17,9 @@
>   */
>  
>  #include <linux/pci.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/delay.h>
>  
>  #include "sdhci.h"
>  #include "sdhci-pci.h"
> @@ -55,6 +58,82 @@
>  
>  #define O2_SD_VENDOR_SETTING	0x110
>  #define O2_SD_VENDOR_SETTING2	0x1C8
> +#define O2_SD_HW_TUNING_DISABLE	BIT(4)
> +
> +static void sdhci_o2_set_tuning_mode(struct sdhci_host *host)
> +{
> +	u16 reg;
> +
> +	/* enable hardware tuning */
> +	reg = sdhci_readw(host, O2_SD_VENDOR_SETTING);
> +	reg &= ~O2_SD_HW_TUNING_DISABLE;
> +	sdhci_writew(host, reg, O2_SD_VENDOR_SETTING);
> +}
> +
> +static void __sdhci_o2_execute_tuning(struct sdhci_host *host, u32 opcode)
> +{
> +	int i;
> +
> +	sdhci_send_tuning(host, MMC_SEND_TUNING_BLOCK_HS200);
> +
> +	for (i = 0; i < 150; i++) {
> +		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +
> +		if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
> +			if (ctrl & SDHCI_CTRL_TUNED_CLK) {
> +				host->tuning_done = true;
> +				return;
> +			}
> +			pr_warn("%s: HW tuning failed !\n",
> +				mmc_hostname(host->mmc));
> +			break;
> +		}
> +
> +		mdelay(1);
> +	}
> +
> +	pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
> +		mmc_hostname(host->mmc));
> +	sdhci_reset_tuning(host);
> +}
> +
> +static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	int current_bus_width = 0;
> +
> +	/*
> +	 * This handler only implements the eMMC tuning that is specific to
> +	 * this controller.  Fall back to the standard method for other TIMING.
> +	 */
> +	if (host->timing != MMC_TIMING_MMC_HS200)
> +		return sdhci_execute_tuning(mmc, opcode);
> +
> +	if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200))
> +		return -EINVAL;
> +
> +	/*
> +	 * o2 sdhci host didn't support 8bit emmc tuning
> +	 */
> +	if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
> +		current_bus_width = mmc->ios.bus_width;
> +		sdhci_set_bus_width(host, MMC_BUS_WIDTH_4);
> +	}
> +
> +	sdhci_o2_set_tuning_mode(host);
> +
> +	sdhci_start_tuning(host);
> +
> +	__sdhci_o2_execute_tuning(host, opcode);
> +
> +	sdhci_end_tuning(host);
> +
> +	if (current_bus_width == MMC_BUS_WIDTH_8)
> +		sdhci_set_bus_width(host, current_bus_width);
> +
> +	host->flags &= ~SDHCI_HS400_TUNING;
> +	return 0;
> +}
>  
>  static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value)
>  {
> @@ -215,6 +294,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  			}
>  		}
>  
> +		host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
> +
>  		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
>  			break;
>  		/* set dll watch dog timer */
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1c828e0..4f3e3c2 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1029,7 +1029,9 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
>  	if (data == NULL) {
>  		if (host->quirks2 &
>  			SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
> -			sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
> +			/* must not clear SDHCI_TRANSFER_MODE when tuning */
> +			if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
> +				sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
>  		} else {
>  		/* clear Auto CMD settings for no data CMDs */
>  			mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
> @@ -2103,7 +2105,7 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
>  	return 0;
>  }
>  


Please put the export changes below into a separate patch.


> -static void sdhci_start_tuning(struct sdhci_host *host)
> +void sdhci_start_tuning(struct sdhci_host *host)
>  {
>  	u16 ctrl;
>  
> @@ -2126,14 +2128,16 @@ static void sdhci_start_tuning(struct sdhci_host *host)
>  	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
>  	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
>  }
> +EXPORT_SYMBOL_GPL(sdhci_start_tuning);
>  
> -static void sdhci_end_tuning(struct sdhci_host *host)
> +void sdhci_end_tuning(struct sdhci_host *host)
>  {
>  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
>  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
>  }
> +EXPORT_SYMBOL_GPL(sdhci_end_tuning);
>  
> -static void sdhci_reset_tuning(struct sdhci_host *host)
> +void sdhci_reset_tuning(struct sdhci_host *host)
>  {
>  	u16 ctrl;
>  
> @@ -2142,6 +2146,7 @@ static void sdhci_reset_tuning(struct sdhci_host *host)
>  	ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
>  	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  }
> +EXPORT_SYMBOL_GPL(sdhci_reset_tuning);
>  
>  static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
>  {
> @@ -2162,7 +2167,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
>   * interrupt setup is different to other commands and there is no timeout
>   * interrupt so special handling is needed.
>   */
> -static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
> +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
>  {
>  	struct mmc_host *mmc = host->mmc;
>  	struct mmc_command cmd = {};
> @@ -2212,6 +2217,7 @@ static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
>  			   msecs_to_jiffies(50));
>  
>  }
> +EXPORT_SYMBOL_GPL(sdhci_send_tuning);
>  
>  static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
>  {
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 23966f8..2a09c0a 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -748,4 +748,9 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
>  
>  void sdhci_dumpregs(struct sdhci_host *host);
>  
> +void sdhci_start_tuning(struct sdhci_host *host);
> +void sdhci_end_tuning(struct sdhci_host *host);
> +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode);
> +void sdhci_reset_tuning(struct sdhci_host *host);
> +
>  #endif /* __SDHCI_HW_H */
> 


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

* Re: [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host
  2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang
@ 2018-07-10 12:44   ` Adrian Hunter
  0 siblings, 0 replies; 6+ messages in thread
From: Adrian Hunter @ 2018-07-10 12:44 UTC (permalink / raw)
  To: ernest.zhang, Ulf Hansson, linux-mmc, linux-kernel
  Cc: chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu

On 26/06/18 18:46, ernest.zhang wrote:
> Add MSI interrupt support if the SD host device can support MSI interrupt.
> 
> Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
> Changes in V6:
> 	1. Move change log to correct place.
> 	2. Reduce unneeded pr_info prints.
> 	3. In function sdhci_pci_o2_probe_slot, remove using local
> 	variable 'mmc' instead of using 'host->mmc'.
> 	3. Make the msi enable code a sperate function.
> 
> Changes in V5:
> 	1. Because pci_enable_msi is marked as deprecated and should not be
> 	used in new code, use pci_alloc_irq_vectors instead.
> 	2. Remove unneeded CONFIG_PCI_MSI macro check.
> 
> Changes in V4:
> 	Enable MSI interrupt if the MSI capability bit is set in
> 	capability register.
> ---
>  drivers/mmc/host/sdhci-pci-o2micro.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
> index 7747e8b..56bc717 100644
> --- a/drivers/mmc/host/sdhci-pci-o2micro.c
> +++ b/drivers/mmc/host/sdhci-pci-o2micro.c
> @@ -260,6 +260,29 @@ static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
>  	pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32);
>  }
>  
> +static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip,
> +				    struct sdhci_host *host)
> +{
> +	int ret;
> +
> +	ret = pci_find_capability(chip->pdev, PCI_CAP_ID_MSI);
> +	if (!ret) {
> +		pr_info("%s: unsupport msi, use INTx irq\n",
> +			mmc_hostname(host->mmc));
> +		return;
> +	}
> +
> +	ret = pci_alloc_irq_vectors(chip->pdev, 1, 1,
> +				    PCI_IRQ_MSI | PCI_IRQ_MSIX);
> +	if (ret < 0) {
> +		pr_err("%s: enable PCI MSI failed, err=%d\n",
> +		       mmc_hostname(host->mmc), ret);
> +		return;
> +	}
> +
> +	host->irq = pci_irq_vector(chip->pdev, 0);
> +}
> +
>  int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  {
>  	struct sdhci_pci_chip *chip;
> @@ -279,6 +302,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
>  		if (reg & 0x1)
>  			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
>  
> +		sdhci_pci_o2_enable_msi(chip, host);
> +
>  		if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
>  			ret = pci_read_config_dword(chip->pdev,
>  						    O2_SD_MISC_SETTING, &reg);
> 


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

end of thread, other threads:[~2018-07-10 12:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang
2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang
2018-07-10 12:43   ` Adrian Hunter
2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang
2018-07-10 12:44   ` Adrian Hunter
2018-07-10 12:23 ` [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode Adrian Hunter

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.