All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 1/3] mmc: sdhci-pci: Add AMD HS200 mode tuning function
  2015-12-22 16:40 ` Wan Zongshun
  (?)
@ 2015-12-22  9:52 ` Andy Shevchenko
  2015-12-23  0:40   ` Wan ZongShun
  -1 siblings, 1 reply; 13+ messages in thread
From: Andy Shevchenko @ 2015-12-22  9:52 UTC (permalink / raw)
  To: Wan Zongshun
  Cc: Ulf Hansson, linux-mmc, Wan Zongshun, Borislav Petkov,
	linux-kernel, Huang Rui

On Tue, Dec 22, 2015 at 6:40 PM, Wan Zongshun <vincent.wan@amd.com> wrote:
> From: Wan Zongshun <Vincent.Wan@amd.com>
>
> This patch is to add software tuning functions for AMD hs200
> mode.
>
> Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
> ---
>  drivers/mmc/host/sdhci-pci-core.c | 146 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 146 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
> index 08f4a9f..01c5723 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -729,6 +729,152 @@ enum amd_chipset_gen {
>         AMD_CHIPSET_UNKNOWN,
>  };
>
> +struct tuning_descriptor {
> +       unsigned char tune_around;
> +       bool this_tune_ok;
> +       bool last_tune_ok;
> +       bool valid_front_end;
> +       unsigned char valid_front;
> +       unsigned char valid_window_max;
> +       unsigned char tune_low_max;
> +       unsigned char tune_low;
> +       unsigned char valid_window;
> +       unsigned char tune_result;
> +};
> +
> +#define AMD_EMMC_TUNE_REG 0xb8
> +static struct tuning_descriptor tdescriptor;

Global variable?!

> +
> +static int tuning_reset(struct sdhci_host *host)

Better prefixes?

> +{
> +       unsigned int val;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&host->lock, flags);
> +
> +       val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +       val |= SDHCI_CTRL_PRESET_VAL_ENABLE | SDHCI_CTRL_EXEC_TUNING;
> +       sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
> +
> +       val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +       val &= ~SDHCI_CTRL_EXEC_TUNING;
> +       sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
> +
> +       spin_unlock_irqrestore(&host->lock, flags);
> +
> +       return 0;
> +}
> +
> +static int config_tuning_phase(struct sdhci_host *host, unsigned char phase)
> +{
> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
> +       struct pci_dev *pdev = slot->chip->pdev;
> +       unsigned int val;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&host->lock, flags);
> +
> +       pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
> +       val &= ~0xf;
> +       val |= (0x10800 | phase);

Magic.

> +       pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
> +
> +       spin_unlock_irqrestore(&host->lock, flags);
> +
> +       return 0;
> +}
> +
> +static int find_good_phase(struct sdhci_host *host)
> +{
> +       struct tuning_descriptor *td = &tdescriptor;
> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
> +       struct pci_dev *pdev = slot->chip->pdev;
> +       unsigned int val;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&host->lock, flags);
> +
> +       if (td->this_tune_ok == false)
> +               td->valid_front_end = 1;
> +
> +       if (td->valid_front_end)
> +               td->valid_front = td->valid_front;
> +       else if (td->this_tune_ok)
> +               td->valid_front = td->valid_front + 1;
> +
> +       if ((!td->this_tune_ok && td->last_tune_ok) ||
> +                                       (td->tune_around == 11)) {

Magic.

> +               if (td->valid_window > td->valid_window_max) {
> +                       td->valid_window_max = td->valid_window;
> +                       td->tune_low_max = td->tune_low;
> +               }
> +       }
> +
> +       if (td->this_tune_ok) {
> +               if (!td->last_tune_ok)
> +                       td->tune_low = td->tune_around;
> +               td->valid_window = td->valid_window + 1;
> +       } else {
> +               if (td->last_tune_ok)
> +                       td->valid_window = 0x0;
> +       }
> +
> +       td->last_tune_ok = td->this_tune_ok;
> +
> +       if (td->tune_around == 11) {
> +               if ((td->valid_front + td->valid_window) >
> +                                               td->valid_window_max) {
> +                       if (td->valid_front > td->valid_window)
> +                               td->tune_result =
> +                               ((td->valid_front - td->valid_window) >> 1);
> +                       else
> +                               td->tune_result = td->tune_low +
> +                               ((td->valid_window + td->valid_front) >> 1);
> +               } else {
> +                       td->tune_result =
> +                               td->tune_low_max + (td->valid_window_max >> 1);
> +               }
> +
> +               if (td->tune_result > 0x0b)
> +                       td->tune_result = 0x0b;
> +
> +               pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
> +               val &= ~0xf;
> +               val |= (0x10800 | td->tune_result);

Magic.

> +               pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
> +       }
> +
> +       spin_unlock_irqrestore(&host->lock, flags);
> +
> +       return 0;
> +}
> +
> +static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
> +{
> +       struct tuning_descriptor *td = &tdescriptor;
> +
> +       tuning_reset(host);
> +
> +       for (td->tune_around = 0; td->tune_around < 12; td->tune_around++) {

Magic.

Why loop is done with non-local variable?

> +
> +               config_tuning_phase(host, td->tune_around);
> +
> +               if (mmc_send_tuning(host->mmc, opcode, NULL)) {
> +                       td->this_tune_ok = false;
> +                       host->mmc->need_retune = 0;
> +                       mdelay(4);
> +               } else {
> +                       td->this_tune_ok = true;
> +               }
> +
> +               find_good_phase(host);
> +       }
> +
> +       host->mmc->retune_period = 0;
> +
> +       return 0;
> +}
> +
>  static int amd_probe(struct sdhci_pci_chip *chip)
>  {
>         struct pci_dev  *smbus_dev;

No users for such code. I don't think it makes sense to push it separately.


-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
  2015-12-22 16:40   ` Wan Zongshun
  (?)
@ 2015-12-22 12:30   ` Andy Shevchenko
  2015-12-23  0:18     ` Wan ZongShun
  -1 siblings, 1 reply; 13+ messages in thread
From: Andy Shevchenko @ 2015-12-22 12:30 UTC (permalink / raw)
  To: Wan Zongshun
  Cc: Ulf Hansson, linux-mmc, Wan Zongshun, Borislav Petkov,
	linux-kernel, Huang Rui

On Tue, Dec 22, 2015 at 6:40 PM, Wan Zongshun <vincent.wan@amd.com> wrote:
> From: Wan Zongshun <Vincent.Wan@amd.com>
>
> AMD hs200 mode tuning mode is not compatible with standard tuning process,
> so we need .platform_execute_tuning callback support in sdhci-pci-core.c,
> this patch is to do:
>
> 1. Add platform_execute_tuning callback in sdhci_pci_slot.
> 2. Implement sdhci_pci_ops.platform_execute_tuning function.
>
> Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
> ---
> Hi Ulf,
>
> Though modifying sdhci_pci_ops to be not const that is easy to implement
> my requirement, I am not sure it is right to do this.
>
> So I just follow sdhci_pci_select_drive_strength style to add new callback:
> sdhci_pci_platform_execute_tuning.
>
> But I also met trouble in sdhci_execute_tuning of sdhci.c, I have to suppose
> only sdhci_pci_platform_execute_tuning is returning -EPERM(current code,
> my assumption is right), so that those vendor that has no
> slot->platform_execute_tuning could be skipped and go next standard
> tuning process.
>
> If you have better idea for my requirement, please correct me.
>
> Thanks!
> Wan Zongshun.
>
> ---
>  drivers/mmc/host/sdhci-pci-core.c | 23 +++++++++++++++++++++++
>  drivers/mmc/host/sdhci-pci.h      |  1 +
>  drivers/mmc/host/sdhci.c          |  3 ++-
>  3 files changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
> index 01c5723..e7b2bbe 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -905,8 +905,19 @@ static int amd_probe(struct sdhci_pci_chip *chip)
>         return 0;
>  }
>
> +static int amd_probe_slot(struct sdhci_pci_slot *slot)
> +{
> +       struct sdhci_host *host = slot->host;
> +
> +       if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD)
> +               slot->platform_execute_tuning = amd_execute_tuning;
> +
> +       return 0;
> +}
> +
>  static const struct sdhci_pci_fixes sdhci_amd = {
>         .probe          = amd_probe,
> +       .probe_slot     = amd_probe_slot,
>  };
>
>  static const struct pci_device_id pci_ids[] = {
> @@ -1508,6 +1519,17 @@ static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
>                                            card_drv, drv_type);
>  }
>
> +static int sdhci_pci_platform_execute_tuning(struct sdhci_host *host,
> +                                            u32 opcode)
> +{
> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
> +
> +       if (!slot->platform_execute_tuning)
> +               return -EPERM;

Here you return an error code.

> +
> +       return slot->platform_execute_tuning(host, opcode);
> +}
> +
>  static const struct sdhci_ops sdhci_pci_ops = {
>         .set_clock      = sdhci_set_clock,
>         .enable_dma     = sdhci_pci_enable_dma,
> @@ -1516,6 +1538,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
>         .set_uhs_signaling = sdhci_set_uhs_signaling,
>         .hw_reset               = sdhci_pci_hw_reset,
>         .select_drive_strength  = sdhci_pci_select_drive_strength,
> +       .platform_execute_tuning = sdhci_pci_platform_execute_tuning,
>  };
>
>  /*****************************************************************************\
> diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
> index d1a0b4d..48d98f1 100644
> --- a/drivers/mmc/host/sdhci-pci.h
> +++ b/drivers/mmc/host/sdhci-pci.h
> @@ -83,6 +83,7 @@ struct sdhci_pci_slot {
>                                      struct mmc_card *card,
>                                      unsigned int max_dtr, int host_drv,
>                                      int card_drv, int *drv_type);
> +       int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
>  };
>
>  struct sdhci_pci_chip {
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2753b722d..2a5a6ce 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1937,7 +1937,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>                 spin_unlock_irqrestore(&host->lock, flags);
>                 err = host->ops->platform_execute_tuning(host, opcode);
>                 sdhci_runtime_pm_put(host);
> -               return err;
> +               if (err != EPERM)

…and here you ignore it. Perhaps better to introduce various positive codes

#define AMD_TUNNING_DONE 0
#define AMD_TUNNING_NA 1


> +                       return err;
>         }
>
>         ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
With Best Regards,
Andy Shevchenko

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

* [PATCH 1/3] mmc: sdhci-pci: Add AMD HS200 mode tuning function
@ 2015-12-22 16:40 ` Wan Zongshun
  0 siblings, 0 replies; 13+ messages in thread
From: Wan Zongshun @ 2015-12-22 16:40 UTC (permalink / raw)
  To: Ulf Hansson, linux-mmc
  Cc: Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui, Wan Zongshun

From: Wan Zongshun <Vincent.Wan@amd.com>

This patch is to add software tuning functions for AMD hs200
mode.

Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
---
 drivers/mmc/host/sdhci-pci-core.c | 146 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 146 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 08f4a9f..01c5723 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -729,6 +729,152 @@ enum amd_chipset_gen {
 	AMD_CHIPSET_UNKNOWN,
 };
 
+struct tuning_descriptor {
+	unsigned char tune_around;
+	bool this_tune_ok;
+	bool last_tune_ok;
+	bool valid_front_end;
+	unsigned char valid_front;
+	unsigned char valid_window_max;
+	unsigned char tune_low_max;
+	unsigned char tune_low;
+	unsigned char valid_window;
+	unsigned char tune_result;
+};
+
+#define AMD_EMMC_TUNE_REG 0xb8
+static struct tuning_descriptor tdescriptor;
+
+static int tuning_reset(struct sdhci_host *host)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	val |= SDHCI_CTRL_PRESET_VAL_ENABLE | SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+
+	val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	val &= ~SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int config_tuning_phase(struct sdhci_host *host, unsigned char phase)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct pci_dev *pdev = slot->chip->pdev;
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
+	val &= ~0xf;
+	val |= (0x10800 | phase);
+	pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int find_good_phase(struct sdhci_host *host)
+{
+	struct tuning_descriptor *td = &tdescriptor;
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct pci_dev *pdev = slot->chip->pdev;
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (td->this_tune_ok == false)
+		td->valid_front_end = 1;
+
+	if (td->valid_front_end)
+		td->valid_front = td->valid_front;
+	else if (td->this_tune_ok)
+		td->valid_front = td->valid_front + 1;
+
+	if ((!td->this_tune_ok && td->last_tune_ok) ||
+					(td->tune_around == 11)) {
+		if (td->valid_window > td->valid_window_max) {
+			td->valid_window_max = td->valid_window;
+			td->tune_low_max = td->tune_low;
+		}
+	}
+
+	if (td->this_tune_ok) {
+		if (!td->last_tune_ok)
+			td->tune_low = td->tune_around;
+		td->valid_window = td->valid_window + 1;
+	} else {
+		if (td->last_tune_ok)
+			td->valid_window = 0x0;
+	}
+
+	td->last_tune_ok = td->this_tune_ok;
+
+	if (td->tune_around == 11) {
+		if ((td->valid_front + td->valid_window) >
+						td->valid_window_max) {
+			if (td->valid_front > td->valid_window)
+				td->tune_result =
+				((td->valid_front - td->valid_window) >> 1);
+			else
+				td->tune_result = td->tune_low +
+				((td->valid_window + td->valid_front) >> 1);
+		} else {
+			td->tune_result =
+				td->tune_low_max + (td->valid_window_max >> 1);
+		}
+
+		if (td->tune_result > 0x0b)
+			td->tune_result = 0x0b;
+
+		pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
+		val &= ~0xf;
+		val |= (0x10800 | td->tune_result);
+		pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	struct tuning_descriptor *td = &tdescriptor;
+
+	tuning_reset(host);
+
+	for (td->tune_around = 0; td->tune_around < 12; td->tune_around++) {
+
+		config_tuning_phase(host, td->tune_around);
+
+		if (mmc_send_tuning(host->mmc, opcode, NULL)) {
+			td->this_tune_ok = false;
+			host->mmc->need_retune = 0;
+			mdelay(4);
+		} else {
+			td->this_tune_ok = true;
+		}
+
+		find_good_phase(host);
+	}
+
+	host->mmc->retune_period = 0;
+
+	return 0;
+}
+
 static int amd_probe(struct sdhci_pci_chip *chip)
 {
 	struct pci_dev	*smbus_dev;
-- 
1.9.1


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

* [PATCH 1/3] mmc: sdhci-pci: Add AMD HS200 mode tuning function
@ 2015-12-22 16:40 ` Wan Zongshun
  0 siblings, 0 replies; 13+ messages in thread
From: Wan Zongshun @ 2015-12-22 16:40 UTC (permalink / raw)
  To: Ulf Hansson, linux-mmc
  Cc: Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui, Wan Zongshun

From: Wan Zongshun <Vincent.Wan@amd.com>

This patch is to add software tuning functions for AMD hs200
mode.

Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
---
 drivers/mmc/host/sdhci-pci-core.c | 146 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 146 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 08f4a9f..01c5723 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -729,6 +729,152 @@ enum amd_chipset_gen {
 	AMD_CHIPSET_UNKNOWN,
 };
 
+struct tuning_descriptor {
+	unsigned char tune_around;
+	bool this_tune_ok;
+	bool last_tune_ok;
+	bool valid_front_end;
+	unsigned char valid_front;
+	unsigned char valid_window_max;
+	unsigned char tune_low_max;
+	unsigned char tune_low;
+	unsigned char valid_window;
+	unsigned char tune_result;
+};
+
+#define AMD_EMMC_TUNE_REG 0xb8
+static struct tuning_descriptor tdescriptor;
+
+static int tuning_reset(struct sdhci_host *host)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	val |= SDHCI_CTRL_PRESET_VAL_ENABLE | SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+
+	val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	val &= ~SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int config_tuning_phase(struct sdhci_host *host, unsigned char phase)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct pci_dev *pdev = slot->chip->pdev;
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
+	val &= ~0xf;
+	val |= (0x10800 | phase);
+	pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int find_good_phase(struct sdhci_host *host)
+{
+	struct tuning_descriptor *td = &tdescriptor;
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct pci_dev *pdev = slot->chip->pdev;
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (td->this_tune_ok == false)
+		td->valid_front_end = 1;
+
+	if (td->valid_front_end)
+		td->valid_front = td->valid_front;
+	else if (td->this_tune_ok)
+		td->valid_front = td->valid_front + 1;
+
+	if ((!td->this_tune_ok && td->last_tune_ok) ||
+					(td->tune_around == 11)) {
+		if (td->valid_window > td->valid_window_max) {
+			td->valid_window_max = td->valid_window;
+			td->tune_low_max = td->tune_low;
+		}
+	}
+
+	if (td->this_tune_ok) {
+		if (!td->last_tune_ok)
+			td->tune_low = td->tune_around;
+		td->valid_window = td->valid_window + 1;
+	} else {
+		if (td->last_tune_ok)
+			td->valid_window = 0x0;
+	}
+
+	td->last_tune_ok = td->this_tune_ok;
+
+	if (td->tune_around == 11) {
+		if ((td->valid_front + td->valid_window) >
+						td->valid_window_max) {
+			if (td->valid_front > td->valid_window)
+				td->tune_result =
+				((td->valid_front - td->valid_window) >> 1);
+			else
+				td->tune_result = td->tune_low +
+				((td->valid_window + td->valid_front) >> 1);
+		} else {
+			td->tune_result =
+				td->tune_low_max + (td->valid_window_max >> 1);
+		}
+
+		if (td->tune_result > 0x0b)
+			td->tune_result = 0x0b;
+
+		pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
+		val &= ~0xf;
+		val |= (0x10800 | td->tune_result);
+		pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+	struct tuning_descriptor *td = &tdescriptor;
+
+	tuning_reset(host);
+
+	for (td->tune_around = 0; td->tune_around < 12; td->tune_around++) {
+
+		config_tuning_phase(host, td->tune_around);
+
+		if (mmc_send_tuning(host->mmc, opcode, NULL)) {
+			td->this_tune_ok = false;
+			host->mmc->need_retune = 0;
+			mdelay(4);
+		} else {
+			td->this_tune_ok = true;
+		}
+
+		find_good_phase(host);
+	}
+
+	host->mmc->retune_period = 0;
+
+	return 0;
+}
+
 static int amd_probe(struct sdhci_pci_chip *chip)
 {
 	struct pci_dev	*smbus_dev;
-- 
1.9.1

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

* [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
  2015-12-22 16:40 ` Wan Zongshun
@ 2015-12-22 16:40   ` Wan Zongshun
  -1 siblings, 0 replies; 13+ messages in thread
From: Wan Zongshun @ 2015-12-22 16:40 UTC (permalink / raw)
  To: Ulf Hansson, linux-mmc
  Cc: Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui, Wan Zongshun

From: Wan Zongshun <Vincent.Wan@amd.com>

AMD hs200 mode tuning mode is not compatible with standard tuning process,
so we need .platform_execute_tuning callback support in sdhci-pci-core.c,
this patch is to do:

1. Add platform_execute_tuning callback in sdhci_pci_slot.
2. Implement sdhci_pci_ops.platform_execute_tuning function.

Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
---
Hi Ulf,

Though modifying sdhci_pci_ops to be not const that is easy to implement
my requirement, I am not sure it is right to do this.

So I just follow sdhci_pci_select_drive_strength style to add new callback:
sdhci_pci_platform_execute_tuning.

But I also met trouble in sdhci_execute_tuning of sdhci.c, I have to suppose
only sdhci_pci_platform_execute_tuning is returning -EPERM(current code,
my assumption is right), so that those vendor that has no
slot->platform_execute_tuning could be skipped and go next standard
tuning process.

If you have better idea for my requirement, please correct me.

Thanks!
Wan Zongshun.

---
 drivers/mmc/host/sdhci-pci-core.c | 23 +++++++++++++++++++++++
 drivers/mmc/host/sdhci-pci.h      |  1 +
 drivers/mmc/host/sdhci.c          |  3 ++-
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 01c5723..e7b2bbe 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -905,8 +905,19 @@ static int amd_probe(struct sdhci_pci_chip *chip)
 	return 0;
 }
 
+static int amd_probe_slot(struct sdhci_pci_slot *slot)
+{
+	struct sdhci_host *host = slot->host;
+
+	if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD)
+		slot->platform_execute_tuning = amd_execute_tuning;
+
+	return 0;
+}
+
 static const struct sdhci_pci_fixes sdhci_amd = {
 	.probe		= amd_probe,
+	.probe_slot	= amd_probe_slot,
 };
 
 static const struct pci_device_id pci_ids[] = {
@@ -1508,6 +1519,17 @@ static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
 					   card_drv, drv_type);
 }
 
+static int sdhci_pci_platform_execute_tuning(struct sdhci_host *host,
+					     u32 opcode)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+
+	if (!slot->platform_execute_tuning)
+		return -EPERM;
+
+	return slot->platform_execute_tuning(host, opcode);
+}
+
 static const struct sdhci_ops sdhci_pci_ops = {
 	.set_clock	= sdhci_set_clock,
 	.enable_dma	= sdhci_pci_enable_dma,
@@ -1516,6 +1538,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.hw_reset		= sdhci_pci_hw_reset,
 	.select_drive_strength	= sdhci_pci_select_drive_strength,
+	.platform_execute_tuning = sdhci_pci_platform_execute_tuning,
 };
 
 /*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index d1a0b4d..48d98f1 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -83,6 +83,7 @@ struct sdhci_pci_slot {
 				     struct mmc_card *card,
 				     unsigned int max_dtr, int host_drv,
 				     int card_drv, int *drv_type);
+	int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
 };
 
 struct sdhci_pci_chip {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2753b722d..2a5a6ce 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1937,7 +1937,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		spin_unlock_irqrestore(&host->lock, flags);
 		err = host->ops->platform_execute_tuning(host, opcode);
 		sdhci_runtime_pm_put(host);
-		return err;
+		if (err != EPERM)
+			return err;
 	}
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-- 
1.9.1


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

* [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
@ 2015-12-22 16:40   ` Wan Zongshun
  0 siblings, 0 replies; 13+ messages in thread
From: Wan Zongshun @ 2015-12-22 16:40 UTC (permalink / raw)
  To: Ulf Hansson, linux-mmc
  Cc: Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui, Wan Zongshun

From: Wan Zongshun <Vincent.Wan@amd.com>

AMD hs200 mode tuning mode is not compatible with standard tuning process,
so we need .platform_execute_tuning callback support in sdhci-pci-core.c,
this patch is to do:

1. Add platform_execute_tuning callback in sdhci_pci_slot.
2. Implement sdhci_pci_ops.platform_execute_tuning function.

Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
---
Hi Ulf,

Though modifying sdhci_pci_ops to be not const that is easy to implement
my requirement, I am not sure it is right to do this.

So I just follow sdhci_pci_select_drive_strength style to add new callback:
sdhci_pci_platform_execute_tuning.

But I also met trouble in sdhci_execute_tuning of sdhci.c, I have to suppose
only sdhci_pci_platform_execute_tuning is returning -EPERM(current code,
my assumption is right), so that those vendor that has no
slot->platform_execute_tuning could be skipped and go next standard
tuning process.

If you have better idea for my requirement, please correct me.

Thanks!
Wan Zongshun.

---
 drivers/mmc/host/sdhci-pci-core.c | 23 +++++++++++++++++++++++
 drivers/mmc/host/sdhci-pci.h      |  1 +
 drivers/mmc/host/sdhci.c          |  3 ++-
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 01c5723..e7b2bbe 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -905,8 +905,19 @@ static int amd_probe(struct sdhci_pci_chip *chip)
 	return 0;
 }
 
+static int amd_probe_slot(struct sdhci_pci_slot *slot)
+{
+	struct sdhci_host *host = slot->host;
+
+	if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD)
+		slot->platform_execute_tuning = amd_execute_tuning;
+
+	return 0;
+}
+
 static const struct sdhci_pci_fixes sdhci_amd = {
 	.probe		= amd_probe,
+	.probe_slot	= amd_probe_slot,
 };
 
 static const struct pci_device_id pci_ids[] = {
@@ -1508,6 +1519,17 @@ static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
 					   card_drv, drv_type);
 }
 
+static int sdhci_pci_platform_execute_tuning(struct sdhci_host *host,
+					     u32 opcode)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+
+	if (!slot->platform_execute_tuning)
+		return -EPERM;
+
+	return slot->platform_execute_tuning(host, opcode);
+}
+
 static const struct sdhci_ops sdhci_pci_ops = {
 	.set_clock	= sdhci_set_clock,
 	.enable_dma	= sdhci_pci_enable_dma,
@@ -1516,6 +1538,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 	.hw_reset		= sdhci_pci_hw_reset,
 	.select_drive_strength	= sdhci_pci_select_drive_strength,
+	.platform_execute_tuning = sdhci_pci_platform_execute_tuning,
 };
 
 /*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index d1a0b4d..48d98f1 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -83,6 +83,7 @@ struct sdhci_pci_slot {
 				     struct mmc_card *card,
 				     unsigned int max_dtr, int host_drv,
 				     int card_drv, int *drv_type);
+	int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
 };
 
 struct sdhci_pci_chip {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2753b722d..2a5a6ce 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1937,7 +1937,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		spin_unlock_irqrestore(&host->lock, flags);
 		err = host->ops->platform_execute_tuning(host, opcode);
 		sdhci_runtime_pm_put(host);
-		return err;
+		if (err != EPERM)
+			return err;
 	}
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-- 
1.9.1

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

* [PATCH 3/3] mmc: sdhci-pci: enable AMD emmc hs200 mode
  2015-12-22 16:40 ` Wan Zongshun
@ 2015-12-22 16:40   ` Wan Zongshun
  -1 siblings, 0 replies; 13+ messages in thread
From: Wan Zongshun @ 2015-12-22 16:40 UTC (permalink / raw)
  To: Ulf Hansson, linux-mmc
  Cc: Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui, Wan Zongshun

From: Wan Zongshun <Vincent.Wan@amd.com>

This patch is to remove the SDHCI_QUIRK2_BROKEN_HS200 quirk and
enable the emmc hs200 mode for AMD current platforms.

Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
---
 drivers/mmc/host/sdhci-pci-core.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index e7b2bbe..17697fd 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -897,10 +897,8 @@ static int amd_probe(struct sdhci_pci_chip *chip)
 		}
 	}
 
-	if ((gen == AMD_CHIPSET_BEFORE_ML) || (gen == AMD_CHIPSET_CZ)) {
+	if ((gen == AMD_CHIPSET_BEFORE_ML) || (gen == AMD_CHIPSET_CZ))
 		chip->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
-		chip->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
-	}
 
 	return 0;
 }
-- 
1.9.1


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

* [PATCH 3/3] mmc: sdhci-pci: enable AMD emmc hs200 mode
@ 2015-12-22 16:40   ` Wan Zongshun
  0 siblings, 0 replies; 13+ messages in thread
From: Wan Zongshun @ 2015-12-22 16:40 UTC (permalink / raw)
  To: Ulf Hansson, linux-mmc
  Cc: Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui, Wan Zongshun

From: Wan Zongshun <Vincent.Wan@amd.com>

This patch is to remove the SDHCI_QUIRK2_BROKEN_HS200 quirk and
enable the emmc hs200 mode for AMD current platforms.

Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
---
 drivers/mmc/host/sdhci-pci-core.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index e7b2bbe..17697fd 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -897,10 +897,8 @@ static int amd_probe(struct sdhci_pci_chip *chip)
 		}
 	}
 
-	if ((gen == AMD_CHIPSET_BEFORE_ML) || (gen == AMD_CHIPSET_CZ)) {
+	if ((gen == AMD_CHIPSET_BEFORE_ML) || (gen == AMD_CHIPSET_CZ))
 		chip->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
-		chip->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
-	}
 
 	return 0;
 }
-- 
1.9.1

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

* Re: [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
  2015-12-22 12:30   ` Andy Shevchenko
@ 2015-12-23  0:18     ` Wan ZongShun
  0 siblings, 0 replies; 13+ messages in thread
From: Wan ZongShun @ 2015-12-23  0:18 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Wan Zongshun, Ulf Hansson, linux-mmc, Borislav Petkov,
	linux-kernel, Huang Rui

>> +
>>  static const struct sdhci_pci_fixes sdhci_amd = {
>>         .probe          = amd_probe,
>> +       .probe_slot     = amd_probe_slot,
>>  };
>>
>>  static const struct pci_device_id pci_ids[] = {
>> @@ -1508,6 +1519,17 @@ static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
>>                                            card_drv, drv_type);
>>  }
>>
>> +static int sdhci_pci_platform_execute_tuning(struct sdhci_host *host,
>> +                                            u32 opcode)
>> +{
>> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
>> +
>> +       if (!slot->platform_execute_tuning)
>> +               return -EPERM;
>
> Here you return an error code.
>
>> +
>> +       return slot->platform_execute_tuning(host, opcode);
>> +}
>> +
>>  static const struct sdhci_ops sdhci_pci_ops = {
>>         .set_clock      = sdhci_set_clock,
>>         .enable_dma     = sdhci_pci_enable_dma,
>> @@ -1516,6 +1538,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
>>         .set_uhs_signaling = sdhci_set_uhs_signaling,
>>         .hw_reset               = sdhci_pci_hw_reset,
>>         .select_drive_strength  = sdhci_pci_select_drive_strength,
>> +       .platform_execute_tuning = sdhci_pci_platform_execute_tuning,
>>  };
>>
>>  /*****************************************************************************\
>> diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
>> index d1a0b4d..48d98f1 100644
>> --- a/drivers/mmc/host/sdhci-pci.h
>> +++ b/drivers/mmc/host/sdhci-pci.h
>> @@ -83,6 +83,7 @@ struct sdhci_pci_slot {
>>                                      struct mmc_card *card,
>>                                      unsigned int max_dtr, int host_drv,
>>                                      int card_drv, int *drv_type);
>> +       int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
>>  };
>>
>>  struct sdhci_pci_chip {
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 2753b722d..2a5a6ce 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1937,7 +1937,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>>                 spin_unlock_irqrestore(&host->lock, flags);
>>                 err = host->ops->platform_execute_tuning(host, opcode);
>>                 sdhci_runtime_pm_put(host);
>> -               return err;
>> +               if (err != EPERM)
>
> …and here you ignore it. Perhaps better to introduce various positive codes
>
> #define AMD_TUNNING_DONE 0
> #define AMD_TUNNING_NA 1

Andy, It looks a good idea, thanks.


>
>
>> +                       return err;
>>         }
>>
>>         ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>> --
>> 1.9.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
>
>
> --
> With Best Regards,
> Andy Shevchenko



-- 
---
Vincent Wan(Zongshun)
www.mcuos.com

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

* Re: [PATCH 1/3] mmc: sdhci-pci: Add AMD HS200 mode tuning function
  2015-12-22  9:52 ` Andy Shevchenko
@ 2015-12-23  0:40   ` Wan ZongShun
  0 siblings, 0 replies; 13+ messages in thread
From: Wan ZongShun @ 2015-12-23  0:40 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Wan Zongshun, Ulf Hansson, linux-mmc, Borislav Petkov,
	linux-kernel, Huang Rui

2015-12-22 17:52 GMT+08:00 Andy Shevchenko <andy.shevchenko@gmail.com>:
> On Tue, Dec 22, 2015 at 6:40 PM, Wan Zongshun <vincent.wan@amd.com> wrote:
>> From: Wan Zongshun <Vincent.Wan@amd.com>
>>
>> This patch is to add software tuning functions for AMD hs200
>> mode.
>>
>> Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
>> ---
>>  drivers/mmc/host/sdhci-pci-core.c | 146 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 146 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
>> index 08f4a9f..01c5723 100644
>> --- a/drivers/mmc/host/sdhci-pci-core.c
>> +++ b/drivers/mmc/host/sdhci-pci-core.c
>> @@ -729,6 +729,152 @@ enum amd_chipset_gen {
>>         AMD_CHIPSET_UNKNOWN,
>>  };
>>
>> +struct tuning_descriptor {
>> +       unsigned char tune_around;
>> +       bool this_tune_ok;
>> +       bool last_tune_ok;
>> +       bool valid_front_end;
>> +       unsigned char valid_front;
>> +       unsigned char valid_window_max;
>> +       unsigned char tune_low_max;
>> +       unsigned char tune_low;
>> +       unsigned char valid_window;
>> +       unsigned char tune_result;
>> +};
>> +
>> +#define AMD_EMMC_TUNE_REG 0xb8
>> +static struct tuning_descriptor tdescriptor;
>
> Global variable?!

Okay, will change it to local.

>
>> +
>> +static int tuning_reset(struct sdhci_host *host)
>
> Better prefixes?

Do you mean I should not name this function to tuning reset?

>
>> +{
>> +       unsigned int val;
>> +       unsigned long flags;
>> +
>> +       spin_lock_irqsave(&host->lock, flags);
>> +
>> +       val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>> +       val |= SDHCI_CTRL_PRESET_VAL_ENABLE | SDHCI_CTRL_EXEC_TUNING;
>> +       sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
>> +
>> +       val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>> +       val &= ~SDHCI_CTRL_EXEC_TUNING;
>> +       sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
>> +
>> +       spin_unlock_irqrestore(&host->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static int config_tuning_phase(struct sdhci_host *host, unsigned char phase)
>> +{
>> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
>> +       struct pci_dev *pdev = slot->chip->pdev;
>> +       unsigned int val;
>> +       unsigned long flags;
>> +
>> +       spin_lock_irqsave(&host->lock, flags);
>> +
>> +       pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
>> +       val &= ~0xf;
>> +       val |= (0x10800 | phase);
>
> Magic.

Okay, I will make 0x10800 to be see more clearly, will define each bit
Macro for it.

>
>> +       pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
>> +
>> +       spin_unlock_irqrestore(&host->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static int find_good_phase(struct sdhci_host *host)
>> +{
>> +       struct tuning_descriptor *td = &tdescriptor;
>> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
>> +       struct pci_dev *pdev = slot->chip->pdev;
>> +       unsigned int val;
>> +       unsigned long flags;
>> +
>> +       spin_lock_irqsave(&host->lock, flags);
>> +
>> +       if (td->this_tune_ok == false)
>> +               td->valid_front_end = 1;
>> +
>> +       if (td->valid_front_end)
>> +               td->valid_front = td->valid_front;
>> +       else if (td->this_tune_ok)
>> +               td->valid_front = td->valid_front + 1;
>> +
>> +       if ((!td->this_tune_ok && td->last_tune_ok) ||
>> +                                       (td->tune_around == 11)) {
>
> Magic.
>
>> +               if (td->valid_window > td->valid_window_max) {
>> +                       td->valid_window_max = td->valid_window;
>> +                       td->tune_low_max = td->tune_low;
>> +               }
>> +       }
>> +
>> +       if (td->this_tune_ok) {
>> +               if (!td->last_tune_ok)
>> +                       td->tune_low = td->tune_around;
>> +               td->valid_window = td->valid_window + 1;
>> +       } else {
>> +               if (td->last_tune_ok)
>> +                       td->valid_window = 0x0;
>> +       }
>> +
>> +       td->last_tune_ok = td->this_tune_ok;
>> +
>> +       if (td->tune_around == 11) {
>> +               if ((td->valid_front + td->valid_window) >
>> +                                               td->valid_window_max) {
>> +                       if (td->valid_front > td->valid_window)
>> +                               td->tune_result =
>> +                               ((td->valid_front - td->valid_window) >> 1);
>> +                       else
>> +                               td->tune_result = td->tune_low +
>> +                               ((td->valid_window + td->valid_front) >> 1);
>> +               } else {
>> +                       td->tune_result =
>> +                               td->tune_low_max + (td->valid_window_max >> 1);
>> +               }
>> +
>> +               if (td->tune_result > 0x0b)
>> +                       td->tune_result = 0x0b;
>> +
>> +               pci_read_config_dword(pdev, AMD_EMMC_TUNE_REG, &val);
>> +               val &= ~0xf;
>> +               val |= (0x10800 | td->tune_result);
>
> Magic.
>
>> +               pci_write_config_dword(pdev, AMD_EMMC_TUNE_REG, val);
>> +       }
>> +
>> +       spin_unlock_irqrestore(&host->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static int amd_execute_tuning(struct sdhci_host *host, u32 opcode)
>> +{
>> +       struct tuning_descriptor *td = &tdescriptor;
>> +
>> +       tuning_reset(host);
>> +
>> +       for (td->tune_around = 0; td->tune_around < 12; td->tune_around++) {
>
> Magic.
>
> Why loop is done with non-local variable?

It will be changed at next version.
thanks!

>
>> +
>> +               config_tuning_phase(host, td->tune_around);
>> +
>> +               if (mmc_send_tuning(host->mmc, opcode, NULL)) {
>> +                       td->this_tune_ok = false;
>> +                       host->mmc->need_retune = 0;
>> +                       mdelay(4);
>> +               } else {
>> +                       td->this_tune_ok = true;
>> +               }
>> +
>> +               find_good_phase(host);
>> +       }
>> +
>> +       host->mmc->retune_period = 0;
>> +
>> +       return 0;
>> +}
>> +
>>  static int amd_probe(struct sdhci_pci_chip *chip)
>>  {
>>         struct pci_dev  *smbus_dev;
>
> No users for such code. I don't think it makes sense to push it separately.

Since I am not sure the patch 2/3 is ok to every body, so it just is my try.
If we can make decision for patch2/3, I can integrate them into one
patch per your suggestion.

Thanks Andy.

>
> --
> With Best Regards,
> Andy Shevchenko



-- 
---
Vincent Wan(Zongshun)
www.mcuos.com

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

* Re: [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
  2015-12-22 16:40   ` Wan Zongshun
  (?)
  (?)
@ 2016-01-12 14:34   ` Ulf Hansson
  2016-01-15  1:38     ` Wan Zongshun
  -1 siblings, 1 reply; 13+ messages in thread
From: Ulf Hansson @ 2016-01-12 14:34 UTC (permalink / raw)
  To: Wan Zongshun
  Cc: linux-mmc, Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui

On 22 December 2015 at 17:40, Wan Zongshun <vincent.wan@amd.com> wrote:
> From: Wan Zongshun <Vincent.Wan@amd.com>
>
> AMD hs200 mode tuning mode is not compatible with standard tuning process,
> so we need .platform_execute_tuning callback support in sdhci-pci-core.c,
> this patch is to do:
>
> 1. Add platform_execute_tuning callback in sdhci_pci_slot.
> 2. Implement sdhci_pci_ops.platform_execute_tuning function.
>
> Signed-off-by: Wan Zongshun <Vincent.Wan@amd.com>
> ---
> Hi Ulf,
>
> Though modifying sdhci_pci_ops to be not const that is easy to implement
> my requirement, I am not sure it is right to do this.
>
> So I just follow sdhci_pci_select_drive_strength style to add new callback:
> sdhci_pci_platform_execute_tuning.

No thanks, please don't add new sdhci callbacks (or quirks).

>
> But I also met trouble in sdhci_execute_tuning of sdhci.c, I have to suppose
> only sdhci_pci_platform_execute_tuning is returning -EPERM(current code,
> my assumption is right), so that those vendor that has no
> slot->platform_execute_tuning could be skipped and go next standard
> tuning process.
>
> If you have better idea for my requirement, please correct me.

sdhci needs to become a set of library functions.

Typically the mmc_host_ops ->execute_tuning() callback for sdhci,
should be assigned to a default function, unless the sdhci variant has
assigned it to something else.

Yes, I realize that it requires core changes to sdhci to allow this.
Although it's necessary do this conversion as I won't accept any more
changes for sdhci that doesn't move the code into this direction.

Kind regards
Uffe

>
> Thanks!
> Wan Zongshun.
>
> ---
>  drivers/mmc/host/sdhci-pci-core.c | 23 +++++++++++++++++++++++
>  drivers/mmc/host/sdhci-pci.h      |  1 +
>  drivers/mmc/host/sdhci.c          |  3 ++-
>  3 files changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
> index 01c5723..e7b2bbe 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -905,8 +905,19 @@ static int amd_probe(struct sdhci_pci_chip *chip)
>         return 0;
>  }
>
> +static int amd_probe_slot(struct sdhci_pci_slot *slot)
> +{
> +       struct sdhci_host *host = slot->host;
> +
> +       if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD)
> +               slot->platform_execute_tuning = amd_execute_tuning;
> +
> +       return 0;
> +}
> +
>  static const struct sdhci_pci_fixes sdhci_amd = {
>         .probe          = amd_probe,
> +       .probe_slot     = amd_probe_slot,
>  };
>
>  static const struct pci_device_id pci_ids[] = {
> @@ -1508,6 +1519,17 @@ static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
>                                            card_drv, drv_type);
>  }
>
> +static int sdhci_pci_platform_execute_tuning(struct sdhci_host *host,
> +                                            u32 opcode)
> +{
> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
> +
> +       if (!slot->platform_execute_tuning)
> +               return -EPERM;
> +
> +       return slot->platform_execute_tuning(host, opcode);
> +}
> +
>  static const struct sdhci_ops sdhci_pci_ops = {
>         .set_clock      = sdhci_set_clock,
>         .enable_dma     = sdhci_pci_enable_dma,
> @@ -1516,6 +1538,7 @@ static const struct sdhci_ops sdhci_pci_ops = {
>         .set_uhs_signaling = sdhci_set_uhs_signaling,
>         .hw_reset               = sdhci_pci_hw_reset,
>         .select_drive_strength  = sdhci_pci_select_drive_strength,
> +       .platform_execute_tuning = sdhci_pci_platform_execute_tuning,
>  };
>
>  /*****************************************************************************\
> diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
> index d1a0b4d..48d98f1 100644
> --- a/drivers/mmc/host/sdhci-pci.h
> +++ b/drivers/mmc/host/sdhci-pci.h
> @@ -83,6 +83,7 @@ struct sdhci_pci_slot {
>                                      struct mmc_card *card,
>                                      unsigned int max_dtr, int host_drv,
>                                      int card_drv, int *drv_type);
> +       int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
>  };
>
>  struct sdhci_pci_chip {
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2753b722d..2a5a6ce 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1937,7 +1937,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>                 spin_unlock_irqrestore(&host->lock, flags);
>                 err = host->ops->platform_execute_tuning(host, opcode);
>                 sdhci_runtime_pm_put(host);
> -               return err;
> +               if (err != EPERM)
> +                       return err;
>         }
>
>         ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> --
> 1.9.1
>

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

* Re: [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
  2016-01-12 14:34   ` Ulf Hansson
@ 2016-01-15  1:38     ` Wan Zongshun
  2016-01-15  7:26       ` Ulf Hansson
  0 siblings, 1 reply; 13+ messages in thread
From: Wan Zongshun @ 2016-01-15  1:38 UTC (permalink / raw)
  To: Ulf Hansson, Wan Zongshun
  Cc: linux-mmc, Wan Zongshun, Borislav Petkov, linux-kernel, Huang Rui

>>
>> But I also met trouble in sdhci_execute_tuning of sdhci.c, I have to suppose
>> only sdhci_pci_platform_execute_tuning is returning -EPERM(current code,
>> my assumption is right), so that those vendor that has no
>> slot->platform_execute_tuning could be skipped and go next standard
>> tuning process.
>>
>> If you have better idea for my requirement, please correct me.
>
> sdhci needs to become a set of library functions.
>
> Typically the mmc_host_ops ->execute_tuning() callback for sdhci,
> should be assigned to a default function, unless the sdhci variant has
> assigned it to something else.
>
> Yes, I realize that it requires core changes to sdhci to allow this.
> Although it's necessary do this conversion as I won't accept any more
> changes for sdhci that doesn't move the code into this direction.
>

Ulf,

Then Can you point me what's my next step for submitting tuning 
workaround for AMD emmc4.5 driver?

What your mean is you will change sdhci-pci-core.c to a core and library 
function?
And then I can implement a AMD specific emmc-pci driver call to those libs?


> Kind regards
> Uffe
>
>>
>> Thanks!
>> Wan Zongshun.
>>
>> ---
>>   drivers/mmc/host/sdhci-pci-core.c | 23 +++++++++++++++++++++++
>>   drivers/mmc/host/sdhci-pci.h      |  1 +
>>   drivers/mmc/host/sdhci.c          |  3 ++-
>>   3 files changed, 26 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
>> index 01c5723..e7b2bbe 100644
>> --- a/drivers/mmc/host/sdhci-pci-core.c
>> +++ b/drivers/mmc/host/sdhci-pci-core.c
>> @@ -905,8 +905,19 @@ static int amd_probe(struct sdhci_pci_chip *chip)
>>          return 0;
>>   }
>>

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

* Re: [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode
  2016-01-15  1:38     ` Wan Zongshun
@ 2016-01-15  7:26       ` Ulf Hansson
  0 siblings, 0 replies; 13+ messages in thread
From: Ulf Hansson @ 2016-01-15  7:26 UTC (permalink / raw)
  To: Wan Zongshun
  Cc: Wan Zongshun, linux-mmc, Wan Zongshun, Borislav Petkov,
	linux-kernel, Huang Rui

On 15 January 2016 at 02:38, Wan Zongshun <vw@iommu.org> wrote:
>>>
>>> But I also met trouble in sdhci_execute_tuning of sdhci.c, I have to
>>> suppose
>>> only sdhci_pci_platform_execute_tuning is returning -EPERM(current code,
>>> my assumption is right), so that those vendor that has no
>>> slot->platform_execute_tuning could be skipped and go next standard
>>> tuning process.
>>>
>>> If you have better idea for my requirement, please correct me.
>>
>>
>> sdhci needs to become a set of library functions.
>>
>> Typically the mmc_host_ops ->execute_tuning() callback for sdhci,
>> should be assigned to a default function, unless the sdhci variant has
>> assigned it to something else.
>>
>> Yes, I realize that it requires core changes to sdhci to allow this.
>> Although it's necessary do this conversion as I won't accept any more
>> changes for sdhci that doesn't move the code into this direction.
>>
>
> Ulf,
>
> Then Can you point me what's my next step for submitting tuning workaround
> for AMD emmc4.5 driver?
>
> What your mean is you will change sdhci-pci-core.c to a core and library
> function?

Not me personally as I don't have the bandwidth to do it. Anybody that
cares about sdhci are encouraged to give it a try!

> And then I can implement a AMD specific emmc-pci driver call to those libs?

The lib should provide common functionality needed among sdhci variants.

If there specific needs for any sdhci variant, that variant should
implement that part separately without affecting other variants. This
isn't the case when adding an sdhci callback/quirk to the sdhci core,
as that would affect more or less *all* sdhci variants.

[...]

Kind regards
Uffe

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

end of thread, other threads:[~2016-01-15  7:26 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-22 16:40 [PATCH 1/3] mmc: sdhci-pci: Add AMD HS200 mode tuning function Wan Zongshun
2015-12-22 16:40 ` Wan Zongshun
2015-12-22  9:52 ` Andy Shevchenko
2015-12-23  0:40   ` Wan ZongShun
2015-12-22 16:40 ` [PATCH 2/3] mmc: sdhci-pci: Add platform tuning callback for amd hs200 mode Wan Zongshun
2015-12-22 16:40   ` Wan Zongshun
2015-12-22 12:30   ` Andy Shevchenko
2015-12-23  0:18     ` Wan ZongShun
2016-01-12 14:34   ` Ulf Hansson
2016-01-15  1:38     ` Wan Zongshun
2016-01-15  7:26       ` Ulf Hansson
2015-12-22 16:40 ` [PATCH 3/3] mmc: sdhci-pci: enable AMD emmc " Wan Zongshun
2015-12-22 16:40   ` Wan Zongshun

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.