Linux MultiMedia Card development
 help / color / mirror / Atom feed
* Re: [PATCH v2 0/7] mmc: core: Re-work CMD13 polling method for CMD6 for mmc
From: Linus Walleij @ 2016-11-23  8:55 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: linux-mmc@vger.kernel.org, Jaehoon Chung, Adrian Hunter,
	Chaotian Jing, Stephen Boyd, Michael Walle, Yong Mao, Shawn Lin
In-Reply-To: <1479848173-20881-1-git-send-email-ulf.hansson@linaro.org>

On Tue, Nov 22, 2016 at 9:56 PM, Ulf Hansson <ulf.hansson@linaro.org> wrote:

> Changes in v2:
>
>         - From discussions around the difficulties for how to support CMD13
>         polling for HS200, HS400 HS400ES, I decided to drop those patches for
>         now. It's is particularly due to the need for tuning, after a speed mode
>         switch, that makes it hard to rely on CMD13 polling for these cases.
>         Perhaps we can allow CMD13 polling when switching to the intermediate
>         speed modes, but let's deal with that outside of this series.

ALso v2 works like a charm on APQ8060 Dragonboard:
Tested-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH v9 00/16] mmc: sdhci-msm: Add clk-rates, DDR, HS400 support
From: Ulf Hansson @ 2016-11-23  8:32 UTC (permalink / raw)
  To: Andy Gross
  Cc: Ritesh Harjani, linux-mmc, Adrian Hunter, Stephen Boyd, Shawn Lin,
	devicetree@vger.kernel.org, linux-clk, David Brown,
	linux-arm-msm@vger.kernel.org, Georgi Djakov, Alex Lemberg,
	Mateusz Nowak, Yuliy Izrailov, Asutosh Das, David Griego,
	Sahitya Tummala, Venkat Gopalakrishnan, Rajendra Nayak
In-Reply-To: <20161123050038.GD16531@hector.attlocal.net>

On 23 November 2016 at 06:00, Andy Gross <andy.gross@linaro.org> wrote:
> On Mon, Nov 21, 2016 at 11:06:13AM +0100, Ulf Hansson wrote:
>> On 21 November 2016 at 07:37, Ritesh Harjani <riteshh@codeaurora.org> wrote:
>> > Hi,
>> >
>> > This is v9 version of the patch series which adds support for MSM8996.
>> > Adds HS400 driver support as well.
>> > These are tested on internal msm8996 & db410c HW.
>> >
>> > The patch series is ready. Do we think we can apply these
>> > patches for next now?
>>
>> I guess the DTS changes can be picked up by Andy, so they can go via arm-soc?
>
> Yeah I'll pick up the DTS change and the Documentation change.

Andy, I would rather like to pick the DT Documentation change via my
mmc tree. Just because I normally do that.

This one:
[PATCH v9 05/16] dt-bindings: sdhci-msm: Add xo value

Kind regards
Uffe

^ permalink raw reply

* Re: [PATCH 0/10] mmc: Add support to Marvell Xenon SD Host Controller
From: Gregory CLEMENT @ 2016-11-23  8:30 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Hilbert Zhang, Andrew Lunn, Romain Perier, Liuliu Zhao, Peng Zhu,
	linux-kernel, Nadav Haklai, Ziji Hu, Victor Gu, Doug Jones,
	Jisheng Zhang, Yehu da Yitschak, Marcin Wojtas, Xueping Liu,
	Shiwu Zhang, Yu Cao, Sebastian Hesselbarth, devicetree,
	Jason Cooper, Hanna Hawa, Kostya Porotchkin, Rob Herring,
	Ryan Gao, Wei(SOCP) Liu, linux-arm-kernel
In-Reply-To: <cover.86006f271b60cf7c0b4c5a51762a9dacca4c4718.1477911954.git-series.gregory.clement@free-electrons.com>

Hi Ulf,
 
 On lun., oct. 31 2016, Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:

> Hello,
>
> This the second version of the series adding support for the SDHCI
> Xenon controller. It can be currently found on the Armada 37xx and the
> Armada 7K/8K but will be also used in more Marvell SoC (and not only
> the mvebu ones actually).
>
> Some of the remarks had been taking into account since the first
> version, according to Ziji Hu, here are the following chcanges:
> "Changes in V2:
>   rebase on v4.9-rc2.
>   Re-write Xenon bindings. Ajust Xenon DT property naming.
>   Add a new DT property to indicate eMMC card type, instead of using
>   variable card_candidate.
>   Clear quirks SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 in Xenon platform data
>   Add support to HS400 retuning."
>
> I think the main open point which remains is about issuing commands
> from the ->set_ios() callback (in patch 7).
> Ulf, could you comment about it?

This part is the last thing missing, we are about to solve the last
issues about the binding, but we still didn't have your opinion about
issuing commands from the ->set_ios() callback and Adrian required it to
take this series.

To have more context you can have a look on:
http://marc.info/?l=linux-mmc&m=147618996414673&w=2

it is the original email where Adrian wanted your agreement.

Thanks,

Gregory

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH v2 2/2] mmc: sdhci-pci: Use ACPI to get max frequency for Intel byt sdio controller sub-vended by NI
From: Adrian Hunter @ 2016-11-23  7:35 UTC (permalink / raw)
  To: Zach Brown, ulf.hansson; +Cc: linux-mmc, linux-kernel
In-Reply-To: <1479851602-19788-3-git-send-email-zach.brown@ni.com>

On 22/11/16 23:53, Zach Brown wrote:
> On NI 9037 boards the max SDIO frequency is limited by trace lengths
> and other layout choices. The max SDIO frequency is stored in an ACPI
> table.
> 
> The driver reads the ACPI entry MXFQ during sdio_probe_slot and sets the
> f_max field of the host.
> 
> Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
> Reviewed-by: Jaeden Amero <jaeden.amero@ni.com>
> Reviewed-by: Josh Cartwright <joshc@ni.com>
> Signed-off-by: Zach Brown <zach.brown@ni.com>
> ---
>  drivers/mmc/host/sdhci-pci-core.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
> index 9741505..34284b8 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -27,6 +27,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/mmc/slot-gpio.h>
>  #include <linux/mmc/sdhci-pci-data.h>
> +#include <linux/acpi.h>
>  
>  #include "sdhci.h"
>  #include "sdhci-pci.h"
> @@ -375,6 +376,30 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_ACPI
> +
> +static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
> +{
> +	acpi_status status;
> +	unsigned long long max_freq;
> +
> +	status = acpi_evaluate_integer(ACPI_HANDLE(&slot->chip->pdev->dev),
> +				       "MXFQ", NULL, &max_freq);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(&slot->chip->pdev->dev,
> +			"MXFQ not found in acpi table\n");
> +		return -EINVAL;
> +	}
> +
> +	slot->host->mmc->f_max = max_freq * 1000000;
> +
> +	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
> +				 MMC_CAP_WAIT_WHILE_BUSY;
> +	return 0;
> +}
> +
> +#else

No, it is the ACPI access that needs to be a separate function.  We don't
want 2 ni_byt_sdio_probe_slot(). Perhaps, something like:

#ifdef CONFIG_ACPI
static int ni_set_max_freq(struct sdhci_pci_slot *slot)
{
	acpi_status status;
	unsigned long long max_freq;

	status = acpi_evaluate_integer(ACPI_HANDLE(&slot->chip->pdev->dev),
				       "MXFQ", NULL, &max_freq);
	if (ACPI_FAILURE(status))
		dev_err(&slot->chip->pdev->dev,
			"MXFQ not found in acpi table\n");
		return -EINVAL;
	}

	slot->host->mmc->f_max = max_freq * 1000000;

	return 0;
}
#else
static inline int ni_set_max_freq(struct sdhci_pci_slot *slot)
{
	return 0;
}
#endif

^ permalink raw reply

* Re: [PATCH 5/5] sdhci: Add quirk for delayed IRQ ACK
From: Jeremy McNicoll @ 2016-11-23  5:23 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: Jeremy McNicoll, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	andy.gross-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	robh-DgEjT+Ai2ygdnm+yROfE0A, arnd-r2nGTMty4D4,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	riteshh-sgV2jX0FEOL9JmXXK+q4OQ
In-Reply-To: <20161123121209.3623e14b@xhacker>

On 2016-11-22 8:12 PM, Jisheng Zhang wrote:
> On Tue, 22 Nov 2016 19:48:56 -0800 Jeremy McNicoll wrote:
>
>> On 2016-11-22 7:36 PM, Jisheng Zhang wrote:
>>> On Tue, 22 Nov 2016 17:09:48 -0800
>>> Jeremy McNicoll <jeremymc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>>
>>>> On msm8992 it has been observed that IRQs were not getting
>>>> ACK'd correctly when clocked at speeds greater than 400KHz.
>>>>
>>>> Signed-off-by: Jeremy McNicoll <jeremymc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>>> ---
>>>>  drivers/mmc/host/sdhci-msm.c |  7 +++++++
>>>>  drivers/mmc/host/sdhci.c     | 12 ++++++++++--
>>>>  drivers/mmc/host/sdhci.h     |  2 ++
>>>>  3 files changed, 19 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
>>>> index 1fcda96..459003c 100644
>>>> --- a/drivers/mmc/host/sdhci-msm.c
>>>> +++ b/drivers/mmc/host/sdhci-msm.c
>>>> @@ -1303,6 +1303,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>>>>  			       CORE_VENDOR_SPEC_CAPABILITIES0);
>>>>  	}
>>>>
>>>> +	/* Enable delayed IRQ handling workaround on 8992 */
>>>> +	if (core_major == 1 && core_minor == 0x3e) {
>>>> +		/* Add 40us delay in interrupt handler when operating
>>>> +		 * at initialization frequency of 400KHz. */
>>>> +		host->quirks2 |= SDHCI_QUIRK2_SLOW_INT_CLR;
>>>> +	}
>>>> +
>>>>  	/* Setup IRQ for handling power/voltage tasks with PMIC */
>>>>  	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
>>>>  	if (msm_host->pwr_irq < 0) {
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 5911f98..c1aae22 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -2703,11 +2703,19 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
>>>>  			result = IRQ_WAKE_THREAD;
>>>>  		}
>>>>
>>>> -		if (intmask & SDHCI_INT_CMD_MASK)
>>>> +		if (intmask & SDHCI_INT_CMD_MASK) {
>>>> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
>>>> +				udelay(40);
>>>> +			}
>>>>  			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
>>>> +		}
>>>>
>>>> -		if (intmask & SDHCI_INT_DATA_MASK)
>>>> +		if (intmask & SDHCI_INT_DATA_MASK) {
>>>> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
>>>> +				udelay(40);
>>>> +			}
>>>>  			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
>>>> +		}
>>>>
>>>>  		if (intmask & SDHCI_INT_BUS_POWER)
>>>>  			pr_err("%s: Card is consuming too much power!\n",
>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>>> index c055e24..5f8301e 100644
>>>> --- a/drivers/mmc/host/sdhci.h
>>>> +++ b/drivers/mmc/host/sdhci.h
>>>> @@ -24,6 +24,8 @@
>>>>   * Controller registers
>>>>   */
>>>>
>>>> +#define SDHCI_QUIRK2_SLOW_INT_CLR	(1<<5)
>>>
>>> IIRC, new quirk isn't allowed now.
>>>
>>
>> Why not?
>
> IIRC, mmc subsystem will behave as a lib in the long run, so the community
> and developers call for no new quirk. For your case, we may need to handle
> the udelay in sdhci-msm.c, export sdhci_irq as a helper function?
>
Thanks for the details and suggestions.  I am going to wait until the US
Thanksgiving (and cyber Monday) is over before I do any more.

-jeremy

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v9 00/16] mmc: sdhci-msm: Add clk-rates, DDR, HS400 support
From: Andy Gross @ 2016-11-23  5:00 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Ritesh Harjani, linux-mmc, Adrian Hunter, Stephen Boyd, Shawn Lin,
	devicetree@vger.kernel.org, linux-clk, David Brown,
	linux-arm-msm@vger.kernel.org, Georgi Djakov, Alex Lemberg,
	Mateusz Nowak, Yuliy Izrailov, Asutosh Das, David Griego,
	Sahitya Tummala, Venkat Gopalakrishnan, Rajendra Nayak
In-Reply-To: <CAPDyKFrRbf0+G5K=-jsaevAGbTqhTAss2zJv3QdiyCrv0BG-zA@mail.gmail.com>

On Mon, Nov 21, 2016 at 11:06:13AM +0100, Ulf Hansson wrote:
> On 21 November 2016 at 07:37, Ritesh Harjani <riteshh@codeaurora.org> wrote:
> > Hi,
> >
> > This is v9 version of the patch series which adds support for MSM8996.
> > Adds HS400 driver support as well.
> > These are tested on internal msm8996 & db410c HW.
> >
> > The patch series is ready. Do we think we can apply these
> > patches for next now?
> 
> I guess the DTS changes can be picked up by Andy, so they can go via arm-soc?

Yeah I'll pick up the DTS change and the Documentation change.

> 
> Then, does the mmc changes depend on the clock changes? If so, I can
> pick them as well, but then I need an ack from Stephen....
> 
> Kind regards
> Uffe

Andy

^ permalink raw reply

* Re: [PATCH 5/5] sdhci: Add quirk for delayed IRQ ACK
From: Jisheng Zhang @ 2016-11-23  4:12 UTC (permalink / raw)
  To: Jeremy McNicoll
  Cc: Jeremy McNicoll, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	andy.gross-QSEj5FYQhm4dnm+yROfE0A, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	robh-DgEjT+Ai2ygdnm+yROfE0A, arnd-r2nGTMty4D4,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A,
	riteshh-sgV2jX0FEOL9JmXXK+q4OQ
In-Reply-To: <ecacec51-4b06-49cd-c756-489128729499-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On Tue, 22 Nov 2016 19:48:56 -0800 Jeremy McNicoll wrote:

> On 2016-11-22 7:36 PM, Jisheng Zhang wrote:
> > On Tue, 22 Nov 2016 17:09:48 -0800
> > Jeremy McNicoll <jeremymc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> >  
> >> On msm8992 it has been observed that IRQs were not getting
> >> ACK'd correctly when clocked at speeds greater than 400KHz.
> >>
> >> Signed-off-by: Jeremy McNicoll <jeremymc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> >> ---
> >>  drivers/mmc/host/sdhci-msm.c |  7 +++++++
> >>  drivers/mmc/host/sdhci.c     | 12 ++++++++++--
> >>  drivers/mmc/host/sdhci.h     |  2 ++
> >>  3 files changed, 19 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> >> index 1fcda96..459003c 100644
> >> --- a/drivers/mmc/host/sdhci-msm.c
> >> +++ b/drivers/mmc/host/sdhci-msm.c
> >> @@ -1303,6 +1303,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
> >>  			       CORE_VENDOR_SPEC_CAPABILITIES0);
> >>  	}
> >>
> >> +	/* Enable delayed IRQ handling workaround on 8992 */
> >> +	if (core_major == 1 && core_minor == 0x3e) {
> >> +		/* Add 40us delay in interrupt handler when operating
> >> +		 * at initialization frequency of 400KHz. */
> >> +		host->quirks2 |= SDHCI_QUIRK2_SLOW_INT_CLR;
> >> +	}
> >> +
> >>  	/* Setup IRQ for handling power/voltage tasks with PMIC */
> >>  	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
> >>  	if (msm_host->pwr_irq < 0) {
> >> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >> index 5911f98..c1aae22 100644
> >> --- a/drivers/mmc/host/sdhci.c
> >> +++ b/drivers/mmc/host/sdhci.c
> >> @@ -2703,11 +2703,19 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
> >>  			result = IRQ_WAKE_THREAD;
> >>  		}
> >>
> >> -		if (intmask & SDHCI_INT_CMD_MASK)
> >> +		if (intmask & SDHCI_INT_CMD_MASK) {
> >> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
> >> +				udelay(40);
> >> +			}
> >>  			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
> >> +		}
> >>
> >> -		if (intmask & SDHCI_INT_DATA_MASK)
> >> +		if (intmask & SDHCI_INT_DATA_MASK) {
> >> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
> >> +				udelay(40);
> >> +			}
> >>  			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
> >> +		}
> >>
> >>  		if (intmask & SDHCI_INT_BUS_POWER)
> >>  			pr_err("%s: Card is consuming too much power!\n",
> >> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> >> index c055e24..5f8301e 100644
> >> --- a/drivers/mmc/host/sdhci.h
> >> +++ b/drivers/mmc/host/sdhci.h
> >> @@ -24,6 +24,8 @@
> >>   * Controller registers
> >>   */
> >>
> >> +#define SDHCI_QUIRK2_SLOW_INT_CLR	(1<<5)  
> >
> > IIRC, new quirk isn't allowed now.
> >  
> 
> Why not?

IIRC, mmc subsystem will behave as a lib in the long run, so the community
and developers call for no new quirk. For your case, we may need to handle
the udelay in sdhci-msm.c, export sdhci_irq as a helper function?

Thanks
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 5/5] sdhci: Add quirk for delayed IRQ ACK
From: Jeremy McNicoll @ 2016-11-23  3:48 UTC (permalink / raw)
  To: Jisheng Zhang, Jeremy McNicoll
  Cc: linux-arm-msm, linux-soc, devicetree, linux-mmc, andy.gross,
	sboyd, robh, arnd, bjorn.andersson, riteshh
In-Reply-To: <20161123113647.0b3deac0@xhacker>

On 2016-11-22 7:36 PM, Jisheng Zhang wrote:
> On Tue, 22 Nov 2016 17:09:48 -0800
> Jeremy McNicoll <jeremymc@redhat.com> wrote:
>
>> On msm8992 it has been observed that IRQs were not getting
>> ACK'd correctly when clocked at speeds greater than 400KHz.
>>
>> Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
>> ---
>>  drivers/mmc/host/sdhci-msm.c |  7 +++++++
>>  drivers/mmc/host/sdhci.c     | 12 ++++++++++--
>>  drivers/mmc/host/sdhci.h     |  2 ++
>>  3 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
>> index 1fcda96..459003c 100644
>> --- a/drivers/mmc/host/sdhci-msm.c
>> +++ b/drivers/mmc/host/sdhci-msm.c
>> @@ -1303,6 +1303,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>>  			       CORE_VENDOR_SPEC_CAPABILITIES0);
>>  	}
>>
>> +	/* Enable delayed IRQ handling workaround on 8992 */
>> +	if (core_major == 1 && core_minor == 0x3e) {
>> +		/* Add 40us delay in interrupt handler when operating
>> +		 * at initialization frequency of 400KHz. */
>> +		host->quirks2 |= SDHCI_QUIRK2_SLOW_INT_CLR;
>> +	}
>> +
>>  	/* Setup IRQ for handling power/voltage tasks with PMIC */
>>  	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
>>  	if (msm_host->pwr_irq < 0) {
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 5911f98..c1aae22 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2703,11 +2703,19 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
>>  			result = IRQ_WAKE_THREAD;
>>  		}
>>
>> -		if (intmask & SDHCI_INT_CMD_MASK)
>> +		if (intmask & SDHCI_INT_CMD_MASK) {
>> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
>> +				udelay(40);
>> +			}
>>  			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
>> +		}
>>
>> -		if (intmask & SDHCI_INT_DATA_MASK)
>> +		if (intmask & SDHCI_INT_DATA_MASK) {
>> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
>> +				udelay(40);
>> +			}
>>  			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
>> +		}
>>
>>  		if (intmask & SDHCI_INT_BUS_POWER)
>>  			pr_err("%s: Card is consuming too much power!\n",
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index c055e24..5f8301e 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -24,6 +24,8 @@
>>   * Controller registers
>>   */
>>
>> +#define SDHCI_QUIRK2_SLOW_INT_CLR	(1<<5)
>
> IIRC, new quirk isn't allowed now.
>

Why not?

-jeremy

> Thanks,
> Jisheng
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


^ permalink raw reply

* Re: [PATCH 5/5] sdhci: Add quirk for delayed IRQ ACK
From: Jisheng Zhang @ 2016-11-23  3:36 UTC (permalink / raw)
  To: Jeremy McNicoll
  Cc: linux-arm-msm, linux-soc, devicetree, linux-mmc, andy.gross,
	sboyd, robh, arnd, bjorn.andersson, riteshh
In-Reply-To: <1479863388-23678-6-git-send-email-jeremymc@redhat.com>

On Tue, 22 Nov 2016 17:09:48 -0800
Jeremy McNicoll <jeremymc@redhat.com> wrote:

> On msm8992 it has been observed that IRQs were not getting
> ACK'd correctly when clocked at speeds greater than 400KHz.
> 
> Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
> ---
>  drivers/mmc/host/sdhci-msm.c |  7 +++++++
>  drivers/mmc/host/sdhci.c     | 12 ++++++++++--
>  drivers/mmc/host/sdhci.h     |  2 ++
>  3 files changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index 1fcda96..459003c 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -1303,6 +1303,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>  			       CORE_VENDOR_SPEC_CAPABILITIES0);
>  	}
>  
> +	/* Enable delayed IRQ handling workaround on 8992 */
> +	if (core_major == 1 && core_minor == 0x3e) {
> +		/* Add 40us delay in interrupt handler when operating
> +		 * at initialization frequency of 400KHz. */
> +		host->quirks2 |= SDHCI_QUIRK2_SLOW_INT_CLR;
> +	}
> +
>  	/* Setup IRQ for handling power/voltage tasks with PMIC */
>  	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
>  	if (msm_host->pwr_irq < 0) {
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 5911f98..c1aae22 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2703,11 +2703,19 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
>  			result = IRQ_WAKE_THREAD;
>  		}
>  
> -		if (intmask & SDHCI_INT_CMD_MASK)
> +		if (intmask & SDHCI_INT_CMD_MASK) {
> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
> +				udelay(40);
> +			}
>  			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
> +		}
>  
> -		if (intmask & SDHCI_INT_DATA_MASK)
> +		if (intmask & SDHCI_INT_DATA_MASK) {
> +			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
> +				udelay(40);
> +			}
>  			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
> +		}
>  
>  		if (intmask & SDHCI_INT_BUS_POWER)
>  			pr_err("%s: Card is consuming too much power!\n",
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index c055e24..5f8301e 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -24,6 +24,8 @@
>   * Controller registers
>   */
>  
> +#define SDHCI_QUIRK2_SLOW_INT_CLR	(1<<5)

IIRC, new quirk isn't allowed now.

Thanks,
Jisheng


^ permalink raw reply

* Re: [PATCH 7/9] mmc: core: Allow CMD13 polling when switch to HS200 mode
From: Shawn Lin @ 2016-11-23  1:24 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: shawn.lin, linux-mmc, Jaehoon Chung, Adrian Hunter, Linus Walleij,
	Chaotian Jing, Stephen Boyd, Michael Walle, Yong Mao
In-Reply-To: <CAPDyKFqeyxN54ntW=sQ7WHic9caPzy8dduXDeUD_JtmHKi7QbA@mail.gmail.com>

在 2016/11/18 19:45, Ulf Hansson 写道:
> Hi Shawn,
>
> On 18 November 2016 at 09:05, Shawn Lin <shawn.lin@rock-chips.com> wrote:
>> Hi Ulf,
>>
>>
>> 在 2016/11/16 18:51, Ulf Hansson 写道:
>>>
>>> In cases when the mmc host doesn't support HW busy detection, polling for
>>> busy by using CMD13 is beneficial. The reasons have already been explained
>>> in earlier change logs.
>>>
>>> To allow polling with CMD13, let's provide MMC_TIMING_MMC_HS200 as the
>>> timing parameter to __mmc_switch(), which makes sure the mmc host and the
>>> mmc card operates at the same bus timing during the polling.
>>>
>>> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
>>> ---
>>>  drivers/mmc/core/mmc.c | 21 +++++----------------
>>>  1 file changed, 5 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>>> index 3268fcd..0b26383 100644
>>> --- a/drivers/mmc/core/mmc.c
>>> +++ b/drivers/mmc/core/mmc.c
>>> @@ -1351,7 +1351,7 @@ static void mmc_select_driver_type(struct mmc_card
>>> *card)
>>>  static int mmc_select_hs200(struct mmc_card *card)
>>>  {
>>>         struct mmc_host *host = card->host;
>>> -       unsigned int old_timing, old_signal_voltage;
>>> +       unsigned int old_signal_voltage;
>>>         int err = -EINVAL;
>>>         u8 val;
>>>
>>> @@ -1378,22 +1378,11 @@ static int mmc_select_hs200(struct mmc_card *card)
>>>                       card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>>>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>>                                    EXT_CSD_HS_TIMING, val,
>>> -                                  card->ext_csd.generic_cmd6_time, 0,
>>> -                                  true, false, true);
>>> -               if (err)
>>> -                       goto err;
>>> -               old_timing = host->ios.timing;
>>> -               mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>>> -
>>> -               err = mmc_switch_status(card);
>>> -               /*
>>> -                * mmc_select_timing() assumes timing has not changed if
>>> -                * it is a switch error.
>>> -                */
>>> -               if (err == -EBADMSG)
>>> -                       mmc_set_timing(host, old_timing);
>>> +                                  card->ext_csd.generic_cmd6_time,
>>> +                                  MMC_TIMING_MMC_HS200,
>>> +                                  true, true, true);
>>
>>
>> I was finding a failure from the test last night after applying these
>> patches and using HS200 only.
>>
>> It seems like the controller(sdhci-of-arasan,5.1) continuously generate
>> response timeout for checking CMD13.. Per TRM, response timeout could
>> means the device didn't ack the CMD13 or the controller was failing to
>> latch the response..
>
> Did you make any changes to the sdchi driver while testing this?

Nope, I didn't.

>
> What I am wondering is whether you tested this with an implemented
> ->card_busy() host ops or not, as sdhci has a default implementation
> of it.

yes, I was using sdhci's default card_busy callback.

I haven't reproduced that failure until now. :(

>
> BTW, some sdhci hosts have lately shown problem [1] with sdhci's
> default ->card_busy() host ops.
>
>>
>> The eMMC part number is KLMBG2JENB-B041. I will use two boards to check
>> if it was indeed related to these patches.
>>
>>>         }
>>> -err:
>>> +
>>>         if (err) {
>>>                 /* fall back to the old signal voltage, if fails report
>>> error */
>>>                 if (__mmc_set_signal_voltage(host, old_signal_voltage))
>>>
>>
>>
>> --
>> Best Regards
>> Shawn Lin
>>
>
> Thanks for helping out with testing etc, I really appreciate it!
>
> Kind regards
> Uffe
>
> [1]
> https://patchwork.kernel.org/patch/9429299/
>
>
>


-- 
Best Regards
Shawn Lin


^ permalink raw reply

* [PATCH 1/5] clk: gcc: Updates for SDHCI enablement
From: Jeremy McNicoll @ 2016-11-23  1:09 UTC (permalink / raw)
  To: linux-arm-msm, linux-soc, devicetree, linux-mmc
  Cc: andy.gross, sboyd, robh, arnd, bjorn.andersson, riteshh, jeremymc
In-Reply-To: <1479863388-23678-1-git-send-email-jeremymc@redhat.com>

Global clock updates to enable onboard SDHCI / MMC.
Re-tabify dt-bindings to align correctly in vim.

Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
---
 drivers/clk/qcom/gcc-msm8994.c               | 108 +++++++++++++++++++++------
 include/dt-bindings/clock/qcom,gcc-msm8994.h |  32 ++++----
 2 files changed, 106 insertions(+), 34 deletions(-)

diff --git a/drivers/clk/qcom/gcc-msm8994.c b/drivers/clk/qcom/gcc-msm8994.c
index e3d15e4..5a8ff2a 100644
--- a/drivers/clk/qcom/gcc-msm8994.c
+++ b/drivers/clk/qcom/gcc-msm8994.c
@@ -24,6 +24,7 @@
 
 #include "common.h"
 #include "clk-regmap.h"
+#include "clk-pll.h"
 #include "clk-alpha-pll.h"
 #include "clk-rcg.h"
 #include "clk-branch.h"
@@ -54,7 +55,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
 static const char * const gcc_xo_gpll0_gpll4[] = {
 	"xo",
 	"gpll0",
-	"gpll4",
+	"gpll4_vote",
 };
 
 #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
@@ -97,29 +98,65 @@ static struct clk_alpha_pll_postdiv gpll0 = {
 	},
 };
 
-static struct clk_alpha_pll gpll4_early = {
-	.offset = 0x1dc0,
-	.clkr = {
-		.enable_reg = 0x1480,
-		.enable_mask = BIT(4),
-		.hw.init = &(struct clk_init_data)
-		{
-			.name = "gpll4_early",
-			.parent_names = (const char *[]) { "xo" },
-			.num_parents = 1,
-			.ops = &clk_alpha_pll_ops,
-		},
+
+static struct clk_rcg2 config_noc_clk_src = {
+	.cmd_rcgr = 0x0150,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "config_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 periph_noc_clk_src = {
+	.cmd_rcgr = 0x0190,
+	.hid_width = 5,
+	.mnd_width = 8,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "periph_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 system_noc_clk_src = {
+	.cmd_rcgr = 0x0120, //TODO
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.clkr.hw.init = &(struct clk_init_data) {
+		.name = "system_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
 	},
 };
 
-static struct clk_alpha_pll_postdiv gpll4 = {
-	.offset = 0x1dc0,
+static struct clk_pll gpll4 = {
+	.status_reg = 0x1dc0,
+	.status_bit = 30,
 	.clkr.hw.init = &(struct clk_init_data)
 	{
 		.name = "gpll4",
-		.parent_names = (const char *[]) { "gpll4_early" },
+		.parent_names = (const char *[]) { "xo" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_regmap gpll4_vote = {
+	.enable_reg = 0x1480,
+	.enable_mask = BIT(4),
+	.hw.init = &(struct clk_init_data)
+	{
+		.name = "gpll4_vote",
+		.parent_names = (const char *[]) { "gpll4" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
 	},
 };
 
@@ -896,8 +933,8 @@ static struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
 	F(25000000, P_GPLL0, 12, 1, 2),
 	F(50000000, P_GPLL0, 12, 0, 0),
 	F(100000000, P_GPLL0, 6, 0, 0),
-	F(192000000, P_GPLL4, 2, 0, 0),
-	F(384000000, P_GPLL4, 1, 0, 0),
+	F(172000000, P_GPLL4, 2, 0, 0),
+	F(344000000, P_GPLL4, 1, 0, 0),
 	{ }
 };
 
@@ -1057,6 +1094,10 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
 		.hw.init = &(struct clk_init_data)
 		{
 			.name = "gcc_blsp1_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -1872,6 +1913,7 @@ static struct clk_branch gcc_pdm2_clk = {
 
 static struct clk_branch gcc_sdcc1_apps_clk = {
 	.halt_reg = 0x04c4,
+	.halt_check = BRANCH_HALT_VOTED,
 	.clkr = {
 		.enable_reg = 0x04c4,
 		.enable_mask = BIT(0),
@@ -1888,6 +1930,26 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
 	},
 };
 
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+	.halt_reg = 0x04c8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x04c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sdcc1_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+
 static struct clk_branch gcc_sdcc2_apps_clk = {
 	.halt_reg = 0x0504,
 	.clkr = {
@@ -2123,10 +2185,13 @@ static struct clk_branch gcc_usb_hs_system_clk = {
 };
 
 static struct clk_regmap *gcc_msm8994_clocks[] = {
-	[GPLL0_EARLY] = &gpll0_early.clkr,
+	[GPLL0_VOTE] = &gpll0_early.clkr,
 	[GPLL0] = &gpll0.clkr,
-	[GPLL4_EARLY] = &gpll4_early.clkr,
+	[CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr,
+	[PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr,
+	[SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr,
 	[GPLL4] = &gpll4.clkr,
+	[GPLL4_VOTE] = &gpll4_vote,
 	[UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
 	[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
 	[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
@@ -2231,6 +2296,7 @@ static struct clk_regmap *gcc_msm8994_clocks[] = {
 	[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
 	[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
 	[GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+	[GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
 	[GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
 	[GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
 	[GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8994.h b/include/dt-bindings/clock/qcom,gcc-msm8994.h
index 0ae494b..76ef541 100644
--- a/include/dt-bindings/clock/qcom,gcc-msm8994.h
+++ b/include/dt-bindings/clock/qcom,gcc-msm8994.h
@@ -15,10 +15,10 @@
 #ifndef _DT_BINDINGS_CLK_MSM_GCC_8994_H
 #define _DT_BINDINGS_CLK_MSM_GCC_8994_H
 
-#define GPLL0_EARLY				0
 #define GPLL0					1
-#define GPLL4_EARLY				2
-#define GPLL4					3
+#define GPLL0_VOTE				0
+#define GPLL4					2
+#define GPLL4_VOTE				3
 #define UFS_AXI_CLK_SRC				4
 #define USB30_MASTER_CLK_SRC			5
 #define BLSP1_QUP1_I2C_APPS_CLK_SRC		6
@@ -123,16 +123,22 @@
 #define GCC_SDCC2_APPS_CLK			105
 #define GCC_SDCC3_APPS_CLK			106
 #define GCC_SDCC4_APPS_CLK			107
-#define GCC_SYS_NOC_UFS_AXI_CLK			108
-#define GCC_SYS_NOC_USB3_AXI_CLK		109
-#define GCC_TSIF_REF_CLK			110
-#define GCC_UFS_AXI_CLK				111
-#define GCC_UFS_RX_CFG_CLK			112
-#define GCC_UFS_TX_CFG_CLK			113
-#define GCC_USB30_MASTER_CLK			114
-#define GCC_USB30_MOCK_UTMI_CLK			115
-#define GCC_USB3_PHY_AUX_CLK			116
-#define GCC_USB_HS_SYSTEM_CLK			117
+#define GCC_SDCC1_AHB_CLK			108
+#define GCC_SDCC2_AHB_CLK			109
+
+#define GCC_SYS_NOC_UFS_AXI_CLK			110
+#define GCC_SYS_NOC_USB3_AXI_CLK		111
+#define GCC_TSIF_REF_CLK			112
+#define GCC_UFS_AXI_CLK				113
+#define GCC_UFS_RX_CFG_CLK			114
+#define GCC_UFS_TX_CFG_CLK			115
+#define GCC_USB30_MASTER_CLK			116
+#define GCC_USB30_MOCK_UTMI_CLK			117
+#define GCC_USB3_PHY_AUX_CLK			118
+#define GCC_USB_HS_SYSTEM_CLK			119
+#define SYSTEM_NOC_CLK_SRC			120
+#define PERIPH_NOC_CLK_SRC			121
+#define CONFIG_NOC_CLK_SRC			122
 
 /* Indexes for GDSCs */
 #define BIMC_GDSC				0
-- 
2.6.1


^ permalink raw reply related

* [PATCH 4/5] sdhci: dump vendor state and regs
From: Jeremy McNicoll @ 2016-11-23  1:09 UTC (permalink / raw)
  To: linux-arm-msm, linux-soc, devicetree, linux-mmc
  Cc: andy.gross, sboyd, robh, arnd, bjorn.andersson, riteshh, jeremymc
In-Reply-To: <1479863388-23678-1-git-send-email-jeremymc@redhat.com>

This has proven very useful in debugging SDHCI RPM interaction
issues.

Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
---
 drivers/mmc/host/sdhci-msm.c | 79 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci.c     | 25 ++++++++++++++
 drivers/mmc/host/sdhci.h     |  1 +
 3 files changed, 105 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index ee01d95..1fcda96 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -678,6 +678,84 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
 	return ret;
 }
 
+
+
+#define MAX_TEST_BUS				20
+#define CORE_MCI_DATA_CNT			0x30
+#define CORE_MCI_FIFO_CNT			0x44
+#define CORE_MCI_STATUS				0x34
+#define CORE_VENDOR_SPEC_ADMA_ERR_ADDR0		0x114
+#define CORE_VENDOR_SPEC_ADMA_ERR_ADDR1		0x118
+#define CORE_TESTBUS_SEL2_BIT			4
+#define CORE_TESTBUS_SEL2			(1 << CORE_TESTBUS_SEL2_BIT)
+
+#define CORE_TESTBUS_ENA			(1 << 3)
+
+#define CORE_TESTBUS_CONFIG			0x0CC
+
+#define CORE_SDCC_DEBUG_REG			0x124
+
+void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
+{
+
+	int tbsel, tbsel2;
+	int i, index = 0;
+	u32 test_bus_val = 0;
+	u32 debug_reg[MAX_TEST_BUS] = {0};
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_msm_host *msm_host;
+
+	pltfm_host = sdhci_priv(host);
+	msm_host = sdhci_pltfm_priv(pltfm_host);
+
+	pr_info("----------- VENDOR REGISTER DUMP -----------\n");
+	pr_info("Data cnt: 0x%08x | Fifo cnt: 0x%08x | Int sts: 0x%08x\n",
+		readl_relaxed(msm_host->core_mem + CORE_MCI_DATA_CNT),
+		readl_relaxed(msm_host->core_mem + CORE_MCI_FIFO_CNT),
+		readl_relaxed(msm_host->core_mem + CORE_MCI_STATUS));
+	pr_info("DLL cfg:  0x%08x | DLL sts:  0x%08x | SDCC ver: 0x%08x\n",
+		readl_relaxed(host->ioaddr + CORE_DLL_CONFIG),
+		readl_relaxed(host->ioaddr + CORE_DLL_STATUS),
+		readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION));
+	pr_info("Vndr func: 0x%08x | Vndr adma err : addr0: 0x%08x addr1: 0x%08x\n",
+		readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC),
+		readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_ADMA_ERR_ADDR0),
+		readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_ADMA_ERR_ADDR1));
+
+	/*
+	 * tbsel indicates [2:0] bits and tbsel2 indicates [7:4] bits
+	 * of CORE_TESTBUS_CONFIG register.
+	 *
+	 * To select test bus 0 to 7 use tbsel and to select any test bus
+	 * above 7 use (tbsel2 | tbsel) to get the test bus number. For eg,
+	 * to select test bus 14, write 0x1E to CORE_TESTBUS_CONFIG register
+	 * i.e., tbsel2[7:4] = 0001, tbsel[2:0] = 110.
+	 */
+	for (tbsel2 = 0; tbsel2 < 3; tbsel2++) {
+		for (tbsel = 0; tbsel < 8; tbsel++) {
+			if (index >= MAX_TEST_BUS)
+				break;
+			test_bus_val = (tbsel2 << CORE_TESTBUS_SEL2_BIT) |
+				tbsel | CORE_TESTBUS_ENA;
+			writel_relaxed(test_bus_val,
+				msm_host->core_mem + CORE_TESTBUS_CONFIG);
+			debug_reg[index++] = readl_relaxed(msm_host->core_mem +
+				CORE_SDCC_DEBUG_REG);
+		}
+	}
+
+	for (i = 0; i < MAX_TEST_BUS; i = i + 4)
+		pr_info(" Test bus[%d to %d]: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			i, i + 3, debug_reg[i], debug_reg[i+1],
+			debug_reg[i+2], debug_reg[i+3]);
+			/* Disable test bus */
+		writel_relaxed(~CORE_TESTBUS_ENA, msm_host->core_mem +
+			CORE_TESTBUS_CONFIG);
+}
+
+
+
+
 static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 {
 	int tuning_seq_cnt = 3;
@@ -1081,6 +1159,7 @@ static const struct sdhci_ops sdhci_msm_ops = {
 	.set_bus_width = sdhci_set_bus_width,
 	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
 	.voltage_switch = sdhci_msm_voltage_switch,
+	.dump_vendor_regs = sdhci_msm_dump_vendor_regs,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 71654b9..5911f98 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -47,6 +47,27 @@ static void sdhci_finish_data(struct sdhci_host *);
 
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
 
+static void sdhci_dump_rpm_info(struct sdhci_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	pr_info("%s: rpmstatus[pltfm](runtime-suspend:usage_count:disable_depth)(%d:%d:%d)\n",
+		mmc_hostname(mmc), mmc->parent->power.runtime_status,
+		atomic_read(&mmc->parent->power.usage_count),
+		mmc->parent->power.disable_depth);
+}
+
+
+static void sdhci_dump_state(struct sdhci_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	pr_info("%s: clk: %d claimer: %s pwr: %d\n",
+		mmc_hostname(mmc), host->clock,
+		mmc->claimer->comm, host->pwr);
+		sdhci_dump_rpm_info(host);
+}
+
 static void sdhci_dumpregs(struct sdhci_host *host)
 {
 	pr_err(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
@@ -100,6 +121,10 @@ static void sdhci_dumpregs(struct sdhci_host *host)
 			       readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
 	}
 
+	if (host->ops->dump_vendor_regs)
+		host->ops->dump_vendor_regs(host);
+
+	sdhci_dump_state(host);
 	pr_err(DRIVER_NAME ": ===========================================\n");
 }
 
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 766df17..c055e24 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -563,6 +563,7 @@ struct sdhci_ops {
 					 struct mmc_card *card,
 					 unsigned int max_dtr, int host_drv,
 					 int card_drv, int *drv_type);
+	void    (*dump_vendor_regs)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-- 
2.6.1


^ permalink raw reply related

* [PATCH 5/5] sdhci: Add quirk for delayed IRQ ACK
From: Jeremy McNicoll @ 2016-11-23  1:09 UTC (permalink / raw)
  To: linux-arm-msm, linux-soc, devicetree, linux-mmc
  Cc: andy.gross, sboyd, robh, arnd, bjorn.andersson, riteshh, jeremymc
In-Reply-To: <1479863388-23678-1-git-send-email-jeremymc@redhat.com>

On msm8992 it has been observed that IRQs were not getting
ACK'd correctly when clocked at speeds greater than 400KHz.

Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
---
 drivers/mmc/host/sdhci-msm.c |  7 +++++++
 drivers/mmc/host/sdhci.c     | 12 ++++++++++--
 drivers/mmc/host/sdhci.h     |  2 ++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 1fcda96..459003c 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1303,6 +1303,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 			       CORE_VENDOR_SPEC_CAPABILITIES0);
 	}
 
+	/* Enable delayed IRQ handling workaround on 8992 */
+	if (core_major == 1 && core_minor == 0x3e) {
+		/* Add 40us delay in interrupt handler when operating
+		 * at initialization frequency of 400KHz. */
+		host->quirks2 |= SDHCI_QUIRK2_SLOW_INT_CLR;
+	}
+
 	/* Setup IRQ for handling power/voltage tasks with PMIC */
 	msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
 	if (msm_host->pwr_irq < 0) {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5911f98..c1aae22 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2703,11 +2703,19 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 			result = IRQ_WAKE_THREAD;
 		}
 
-		if (intmask & SDHCI_INT_CMD_MASK)
+		if (intmask & SDHCI_INT_CMD_MASK) {
+			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
+				udelay(40);
+			}
 			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
+		}
 
-		if (intmask & SDHCI_INT_DATA_MASK)
+		if (intmask & SDHCI_INT_DATA_MASK) {
+			if ((host->quirks2 & SDHCI_QUIRK2_SLOW_INT_CLR) && (host->clock <= 400000)) {
+				udelay(40);
+			}
 			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
+		}
 
 		if (intmask & SDHCI_INT_BUS_POWER)
 			pr_err("%s: Card is consuming too much power!\n",
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c055e24..5f8301e 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -24,6 +24,8 @@
  * Controller registers
  */
 
+#define SDHCI_QUIRK2_SLOW_INT_CLR	(1<<5)
+
 #define SDHCI_DMA_ADDRESS	0x00
 #define SDHCI_ARGUMENT2		SDHCI_DMA_ADDRESS
 
-- 
2.6.1

^ permalink raw reply related

* [PATCH 3/5] arm64: dts: Enable SDHCI for Nexus 5X (msm8992)
From: Jeremy McNicoll @ 2016-11-23  1:09 UTC (permalink / raw)
  To: linux-arm-msm, linux-soc, devicetree, linux-mmc
  Cc: andy.gross, sboyd, robh, arnd, bjorn.andersson, riteshh, jeremymc
In-Reply-To: <1479863388-23678-1-git-send-email-jeremymc@redhat.com>

Add Nexus 5X (msm8992) SDHCI support, including initial regulator
entries to support enabling the main SDHCI/MMC.

The msm8994 RPM regulator talks over SMD to the APPS processor.

Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
---
 .../bindings/regulator/qcom,smd-rpm-regulator.txt  |  40 ++++
 .../boot/dts/qcom/msm8992-bullhead-rev-101.dts     | 262 +++++++++++++++++++++
 arch/arm64/boot/dts/qcom/msm8992-pins.dtsi         |  82 +++++++
 arch/arm64/boot/dts/qcom/msm8992.dtsi              | 153 ++++++++++++
 drivers/regulator/qcom_smd-regulator.c             |  49 ++++
 5 files changed, 586 insertions(+)

diff --git a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt
index 1f8d6f8..126989b 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt
@@ -23,6 +23,7 @@ Regulator nodes are identified by their compatible:
 		    "qcom,rpm-pm8916-regulators"
 		    "qcom,rpm-pm8941-regulators"
 		    "qcom,rpm-pma8084-regulators"
+		    "qcom,rpm-pm8994-regulators"
 
 - vdd_s1-supply:
 - vdd_s2-supply:
@@ -97,6 +98,40 @@ Regulator nodes are identified by their compatible:
 	Definition: reference to regulator supplying the input pin, as
 		    described in the data sheet
 
+- vdd_s1-supply:
+- vdd_s2-supply:
+- vdd_s3-supply:
+- vdd_s4-supply:
+- vdd_s5-supply:
+- vdd_s6-supply:
+- vdd_s7-supply:
+- vdd_l1_l11-supply:
+- vdd_l2_l3_l4_l27-supply:
+- vdd_l5_l7-supply:
+- vdd_l6_l12_l14_l15_l26-supply:
+- vdd_l8-supply:
+- vdd_l9_l10_l13_l20_l23_l24-supply:
+- vdd_l1_l11-supply:
+- vdd_l6_l12_l14_l15_l26-supply:
+- vdd_l16_l25-supply:
+- vdd_l17-supply:
+- vdd_l18-supply:
+- vdd_l19-supply:
+- vdd_l21-supply:
+- vdd_l22-supply:
+- vdd_l16_l25-supply:
+- vdd_l27-supply:
+- vdd_l28-supply:
+- vdd_l29-supply:
+- vdd_l30-supply:
+- vdd_l31-supply:
+- vdd_l32-supply:
+	Usage: optional (pm8994 only)
+	Value type: <phandle>
+	Definition: reference to regulator supplying the input pin, as
+		    described in the data sheet.
+
+
 The regulator node houses sub-nodes for each regulator within the device. Each
 sub-node is identified using the node's name, with valid values listed for each
 of the pmics below.
@@ -118,6 +153,11 @@ pma8084:
 	l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20,
 	l21, l22, l23, l24, l25, l26, l27, lvs1, lvs2, lvs3, lvs4, 5vs1
 
+pm8994:
+	s1, s2, s3, s4, s5, s6, s7, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11,
+	l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26,
+	l27, l28, l29, l30, l31, l32, lvs1, lvs2
+
 The content of each sub-node is defined by the standard binding for regulators -
 see regulator.txt.
 
diff --git a/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts b/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
index 4542133..2ce8798 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
@@ -39,3 +39,265 @@
 		};
 	};
 };
+
+&smd_rpm {
+	rpm {
+		rpm_requests {
+			pm8994-regulators {
+
+				vdd_l1-supply = <&pm8994_s1>;
+				vdd_l2_26_28-supply = <&pm8994_s3>;
+				vdd_l3_11-supply = <&pm8994_s3>;
+				vdd_l4_27_31-supply = <&pm8994_s3>;
+				vdd_l5_7-supply = <&pm8994_s3>;
+				vdd_l6_12_32-supply = <&pm8994_s5>;
+				vdd_l8_16_30-supply = <&vreg_vph_pwr>;
+				vdd_l9_10_18_22-supply = <&vreg_vph_pwr>;
+				vdd_l13_19_23_24-supply = <&vreg_vph_pwr>;
+				vdd_l14_15-supply = <&pm8994_s5>;
+				vdd_l17_29-supply = <&vreg_vph_pwr>;
+				vdd_l20_21-supply = <&vreg_vph_pwr>;
+				vdd_l25-supply = <&pm8994_s5>;
+				/*vin_lvs1_2 = <&pm8994_s4>; */
+
+				s1 {
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <800000>;
+				};
+
+				s2 {
+				};
+
+				s3 {
+					regulator-min-microvolt = <1300000>;
+					regulator-max-microvolt = <1300000>;
+				};
+
+				s4 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-allow-set-load;
+					regulator-system-load = <325000>;
+				};
+
+				s5 {
+					regulator-min-microvolt = <2150000>;
+					regulator-max-microvolt = <2150000>;
+				};
+
+				s7 {
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+				};
+
+				l1 {
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+				};
+
+				l2 {
+					regulator-min-microvolt = <1250000>;
+					regulator-max-microvolt = <1250000>;
+				};
+
+				l3 {
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				l4 {
+					regulator-min-microvolt = <1225000>;
+					regulator-max-microvolt = <1225000>;
+				};
+
+				l5 {
+				};
+
+				l6 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				l7 {
+				};
+
+				l8 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				l9 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				l10 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+				};
+
+				l11 {
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					qcom,init-voltage = <1200000>;
+				};
+
+				l12 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+					proxy-supply = <&pm8994_l12>;
+					qcom,proxy-consumer-enable;
+					qcom,proxy-consumer-current = <10000>;
+					status = "okay";
+				};
+
+				l13 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <2950000>;
+					qcom,init-voltage = <2950000>;
+					status = "okay";
+				};
+
+				l14 {
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					qcom,init-voltage = <1200000>;
+					proxy-supply = <&pm8994_l14>;
+					qcom,proxy-consumer-enable;
+					qcom,proxy-consumer-current = <10000>;
+					status = "okay";
+				};
+
+				l15 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+					status = "okay";
+				};
+
+				l16 {
+					regulator-min-microvolt = <2700000>;
+					regulator-max-microvolt = <2700000>;
+					qcom,init-voltage = <2700000>;
+					status = "okay";
+				};
+
+				l17 {
+					regulator-min-microvolt = <2700000>;
+					regulator-max-microvolt = <2700000>;
+					qcom,init-voltage = <2700000>;
+					status = "okay";
+				};
+
+				l18 {
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
+					qcom,init-voltage = <3000000>;
+					qcom,init-ldo-mode = <1>;
+				};
+
+				l19 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+					status = "okay";
+				};
+
+				l20 {
+					regulator-min-microvolt = <2950000>;
+					regulator-max-microvolt = <2950000>;
+					regulator-always-on;
+					regulator-boot-on;
+					regulator-allow-set-load;
+					regulator-system-load = <570000>;
+				};
+
+				l21 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					qcom,init-voltage = <1800000>;
+				};
+
+				l22 {
+					regulator-min-microvolt = <3100000>;
+					regulator-max-microvolt = <3100000>;
+					qcom,init-voltage = <3100000>;
+				};
+
+				l23 {
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					qcom,init-voltage = <2800000>;
+				};
+
+				l24 {
+					regulator-min-microvolt = <3075000>;
+					regulator-max-microvolt = <3150000>;
+					qcom,init-voltage = <3075000>;
+				};
+
+				l25 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+				};
+
+				l26 {
+					/* TODO: value from downstream
+					regulator-min-microvolt = <987500>;
+					fails to apply */
+				};
+
+				l27 {
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					qcom,init-voltage = <1050000>;
+				};
+
+				l28 {
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					qcom,init-voltage = <1000000>;
+					proxy-supply = <&pm8994_l28>;
+					qcom,proxy-consumer-enable;
+					qcom,proxy-consumer-current = <10000>;
+				};
+
+				l29 {
+					/* TODO: Unsupported voltage range.. 
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					qcom,init-voltage = <2800000>;
+					*/
+				};
+
+				l30 {
+					/* TODO: get this verified
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+					*/
+				};
+
+				l31 {
+					regulator-min-microvolt = <1262500>;
+					regulator-max-microvolt = <1262500>;
+					qcom,init-voltage = <1262500>;
+				};
+
+				l32 {
+					/* TODO: get this verified
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,init-voltage = <1800000>;
+					*/
+				};
+
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
index d2a26f0..15202c8 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
@@ -35,4 +35,86 @@
 			bias-pull-down;
 		};
 	};
+
+	/* 0-3 for sdc1 4-6 for sdc2 */
+	/* Order of pins */
+	/* SDC1: CLK -> 0, CMD -> 1, DATA -> 2, RCLK -> 3 */
+	/* SDC2: CLK -> 4, CMD -> 5, DATA -> 6 */
+	pmx_sdc1_clk {
+		sdc1_clk_on: clk_on {
+			pinmux {
+				pins = "sdc1_clk";
+			};
+			pinconf {
+				pins = "sdc1_clk";
+				bias-disable = <0>; /* No pull */
+				drive-strength = <16>; /* 16mA */
+			};
+		};
+		sdc1_clk_off: clk_off {
+			pinmux {
+				pins = "sdc1_clk";
+			};
+			pinconf {
+				pins = "sdc1_clk";
+				bias-disable = <0>; /* No pull */
+				drive-strength = <2>; /* 2mA */
+			};
+		};
+	};
+
+	pmx_sdc1_cmd {
+		sdc1_cmd_on: cmd_on {
+			pinmux {
+				pins = "sdc1_cmd";
+			};
+			pinconf {
+				pins = "sdc1_cmd";
+				bias-pull-up;
+				drive-strength = <8>;
+			};
+		};
+		sdc1_cmd_off: cmd_off {
+			pinmux {
+				pins = "sdc1_cmd";
+			};
+			pinconf {
+				pins = "sdc1_cmd";
+				bias-pull-up = <0x3>; /* same as 3.10 ?? */
+				drive-strength = <2>; /* 2mA */
+			};
+		};
+	};
+
+	pmx_sdc1_data {
+		sdc1_data_on: data_on {
+			pinmux {
+				pins = "sdc1_data";
+			};
+			pinconf {
+				pins = "sdc1_data";
+				bias-pull-up;
+				drive-strength = <8>; /* 8mA */
+			};
+		};
+		sdc1_data_off: data_off {
+			pinmux {
+				pins = "sdc1_data";
+			};
+			pinconf {
+				pins = "sdc1_data";
+				bias-pull-up;
+				drive-strength = <2>;
+			};
+		};
+	};
+
+	pmx_sdc1_rclk {
+		sdc1_rclk_on: rclk_on {
+			bias-pull-down; /* pull down */
+		};
+		sdc1_rclk_off: rclk_off {
+			bias-pull-down; /* pull down */
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8992.dtsi b/arch/arm64/boot/dts/qcom/msm8992.dtsi
index 44b2d37..d104770 100644
--- a/arch/arm64/boot/dts/qcom/msm8992.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992.dtsi
@@ -82,6 +82,12 @@
 				<0xf9002000 0x1000>;
 		};
 
+		apcs: syscon@0xf900d000 {
+			compatible = "syscon";
+			reg = <0xf900d000 0x2000>;
+		};
+
+
 		timer@f9020000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -172,12 +178,159 @@
 			#power-domain-cells = <1>;
 			reg = <0xfc400000 0x2000>;
 		};
+
+		sdhci1: qcom,sdhci@f9824900 {
+			compatible = "qcom,sdhci-msm-v4";
+			reg = <0xf9824900 0x1a0>, <0xf9824000 0x800>;
+			reg-names = "hc_mem", "core_mem";
+
+			interrupts = <GIC_SPI 123 IRQ_TYPE_NONE>,
+					<GIC_SPI 138 IRQ_TYPE_NONE>;
+			interrupt-names = "hc_irq", "pwr_irq";
+
+			clocks = <&clock_gcc GCC_SDCC1_APPS_CLK>,
+				<&clock_gcc GCC_SDCC1_AHB_CLK>;
+			clock-names = "core", "iface";
+
+			pinctrl-names = "default", "sleep";
+			pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on
+					&sdc1_rclk_on>;
+			pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off
+					&sdc1_rclk_off>;
+
+			vdd-supply = <&pm8994_l20>;
+			qcom,vdd-voltage-level = <2950000 2950000>;
+			qcom,vdd-current-level = <200 570000>;
+
+			vdd-io-supply = <&pm8994_s4>;
+			qcom,vdd-io-voltage-level = <1800000 1800000>;
+			qcom,vdd-io-current-level = <200 325000>;
+
+			regulator-always-on;
+			bus-width = <8>;
+			mmc-hs400-1_8v;
+			status = "okay";
+		};
+
+		vreg_vph_pwr: vreg-vph-pwr {
+			compatible = "regulator-fixed";
+			status = "okay";
+			regulator-name = "vph-pwr";
+
+			regulator-min-microvolt = <3600000>;
+			regulator-max-microvolt = <3600000>;
+
+			regulator-always-on;
+		};
+
+		rpm_msg_ram: memory@fc428000 {
+			compatible = "qcom,rpm-msg-ram";
+			reg = <0xfc428000 0x4000>;
+		};
+
+		sfpb_mutex_regs: syscon@fd484000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "syscon";
+			reg = <0xfd484000 0x400>;
+		};
+
+		sfpb_mutex: hwmutex {
+			compatible = "qcom,sfpb-mutex";
+			syscon = <&sfpb_mutex_regs 0x0 0x100>;
+			#hwlock-cells = <1>;
+		};
+
+		smem {
+			compatible = "qcom,smem";
+			memory-region = <&smem_region>;
+			qcom,rpm-msg-ram = <&rpm_msg_ram>;
+			hwlocks = <&sfpb_mutex 3>;
+		};
 	};
 
 	memory {
 		device_type = "memory";
 		reg = <0 0 0 0>; // bootloader will update
 	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		smem_region: smem@6a00000 {
+			reg = <0x0 0x6a00000 0x0 0x200000>;
+			no-map;
+		};
+	};
+
+	smd_rpm: smd {
+		compatible = "qcom,smd";
+
+		rpm {
+			interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
+			qcom,ipc = <&apcs 8 0>;
+			qcom,smd-edge = <15>;
+			qcom,local-pid = <0>;
+			qcom,remote-pid = <6>;
+
+			rpm_requests {
+				compatible = "qcom,rpm-msm8994";
+				qcom,smd-channels = "rpm_requests";
+
+				rpmcc: qcom,rpmcc {
+					/* TODO: update when rpmcc-msm8994 support added */
+					compatible = "qcom,rpmcc-msm8916",
+							"qcom,rpmcc";
+					#clock-cells = <1>;
+				};
+
+				smd_rpm_regulators: pm8994-regulators {
+					compatible = "qcom,rpm-pm8994-regulators";
+
+					pm8994_s1: s1 {};
+					pm8994_s2: s2 {};
+					pm8994_s3: s3 {};
+					pm8994_s4: s4 {};
+					pm8994_s5: s5 {};
+					pm8994_s6: s6 {};
+					pm8994_s7: s7 {};
+
+					pm8994_l1: l1 {};
+					pm8994_l2: l2 {};
+					pm8994_l3: l3 {};
+					pm8994_l4: l4 {};
+					pm8994_l6: l6 {};
+					pm8994_l8: l8 {};
+					pm8994_l9: l9 {};
+					pm8994_l10: l10 {};
+					pm8994_l11: l11 {};
+					pm8994_l12: l12 {};
+					pm8994_l13: l13 {};
+					pm8994_l14: l14 {};
+					pm8994_l15: l15 {};
+					pm8994_l16: l16 {};
+					pm8994_l17: l17 {};
+					pm8994_l18: l18 {};
+					pm8994_l19: l19 {};
+					pm8994_l20: l20 {};
+					pm8994_l21: l21 {};
+					pm8994_l22: l22 {};
+					pm8994_l23: l23 {};
+					pm8994_l24: l24 {};
+					pm8994_l25: l25 {};
+					pm8994_l26: l26 {};
+					pm8994_l27: l27 {};
+					pm8994_l28: l28 {};
+					pm8994_l29: l29 {};
+					pm8994_l30: l30 {};
+					pm8994_l31: l31 {};
+					pm8994_l32: l32 {};
+				};
+			};
+		};
+	};
 };
 
 
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index 8ed46a9..a7e8ce7 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -443,11 +443,60 @@ static const struct rpm_regulator_data rpm_pma8084_regulators[] = {
 	{}
 };
 
+static const struct rpm_regulator_data rpm_pm8994_regulators[] = {
+	{ "s1", QCOM_SMD_RPM_SMPA, 1, &pma8084_ftsmps, "vdd_s1" },
+	{ "s2", QCOM_SMD_RPM_SMPA, 2, &pma8084_ftsmps, "vdd_s2" },
+	{ "s3", QCOM_SMD_RPM_SMPA, 3, &pma8084_hfsmps, "vdd_s3" },
+	{ "s4", QCOM_SMD_RPM_SMPA, 4, &pma8084_hfsmps, "vdd_s4" },
+	{ "s5", QCOM_SMD_RPM_SMPA, 5, &pma8084_hfsmps, "vdd_s5" },
+	{ "s6", QCOM_SMD_RPM_SMPA, 6, &pma8084_ftsmps, "vdd_s6" },
+	{ "s7", QCOM_SMD_RPM_SMPA, 7, &pma8084_ftsmps, "vdd_s7" },
+
+	{ "l1", QCOM_SMD_RPM_LDOA, 1, &pma8084_nldo, "vdd_l1_l11" },
+	{ "l2", QCOM_SMD_RPM_LDOA, 2, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
+	{ "l3", QCOM_SMD_RPM_LDOA, 3, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
+	{ "l4", QCOM_SMD_RPM_LDOA, 4, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
+	{ "l5", QCOM_SMD_RPM_LDOA, 5, &pma8084_pldo, "vdd_l5_l7" },
+	{ "l6", QCOM_SMD_RPM_LDOA, 6, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
+	{ "l7", QCOM_SMD_RPM_LDOA, 7, &pma8084_pldo, "vdd_l5_l7" },
+	{ "l8", QCOM_SMD_RPM_LDOA, 8, &pma8084_pldo, "vdd_l8" },
+	{ "l9", QCOM_SMD_RPM_LDOA, 9, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
+	{ "l10", QCOM_SMD_RPM_LDOA, 10, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
+	{ "l11", QCOM_SMD_RPM_LDOA, 11, &pma8084_nldo, "vdd_l1_l11" },
+	{ "l12", QCOM_SMD_RPM_LDOA, 12, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
+	{ "l13", QCOM_SMD_RPM_LDOA, 13, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
+	{ "l14", QCOM_SMD_RPM_LDOA, 14, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
+	{ "l15", QCOM_SMD_RPM_LDOA, 15, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
+	{ "l16", QCOM_SMD_RPM_LDOA, 16, &pma8084_pldo, "vdd_l16_l25" },
+	{ "l17", QCOM_SMD_RPM_LDOA, 17, &pma8084_pldo, "vdd_l17" },
+	{ "l18", QCOM_SMD_RPM_LDOA, 18, &pma8084_pldo, "vdd_l18" },
+	{ "l19", QCOM_SMD_RPM_LDOA, 19, &pma8084_pldo, "vdd_l19" },
+	{ "l20", QCOM_SMD_RPM_LDOA, 20, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
+	{ "l21", QCOM_SMD_RPM_LDOA, 21, &pma8084_pldo, "vdd_l21" },
+	{ "l22", QCOM_SMD_RPM_LDOA, 22, &pma8084_pldo, "vdd_l22" },
+	{ "l23", QCOM_SMD_RPM_LDOA, 23, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
+	{ "l24", QCOM_SMD_RPM_LDOA, 24, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
+	{ "l25", QCOM_SMD_RPM_LDOA, 25, &pma8084_pldo, "vdd_l16_l25" },
+	{ "l26", QCOM_SMD_RPM_LDOA, 26, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
+	{ "l27", QCOM_SMD_RPM_LDOA, 27, &pma8084_nldo, "vdd_l27" },
+	{ "l28", QCOM_SMD_RPM_LDOA, 28, &pma8084_nldo, "vdd_l28" },
+	{ "l29", QCOM_SMD_RPM_LDOA, 29, &pma8084_nldo, "vdd_l29" },
+	{ "l30", QCOM_SMD_RPM_LDOA, 30, &pma8084_nldo, "vdd_l30" },
+	{ "l31", QCOM_SMD_RPM_LDOA, 31, &pma8084_nldo, "vdd_l31" },
+	{ "l32", QCOM_SMD_RPM_LDOA, 32, &pma8084_nldo, "vdd_l32" },
+
+	{ "lvs1", QCOM_SMD_RPM_VSA, 1, &pma8084_switch },
+	{ "lvs2", QCOM_SMD_RPM_VSA, 2, &pma8084_switch },
+
+	{}
+};
+
 static const struct of_device_id rpm_of_match[] = {
 	{ .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
 	{ .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators },
 	{ .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
 	{ .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
+	{ .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators },
 	{}
 };
 MODULE_DEVICE_TABLE(of, rpm_of_match);
-- 
2.6.1

^ permalink raw reply related

* [PATCH 2/5] smd: Make packet size a constant
From: Jeremy McNicoll @ 2016-11-23  1:09 UTC (permalink / raw)
  To: linux-arm-msm, linux-soc, devicetree, linux-mmc
  Cc: andy.gross, sboyd, robh, arnd, bjorn.andersson, riteshh, jeremymc
In-Reply-To: <1479863388-23678-1-git-send-email-jeremymc@redhat.com>

Use a macro to define the maximum size of a RPM message.

Signed-off-by: Jeremy McNicoll <jeremymc@redhat.com>
---
 drivers/soc/qcom/smd-rpm.c   | 2 +-
 include/linux/soc/qcom/smd.h | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 6609d7e..b5a2836 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -114,7 +114,7 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
 	size_t size = sizeof(*pkt) + count;
 
 	/* SMD packets to the RPM may not exceed 256 bytes */
-	if (WARN_ON(size >= 256))
+	if (WARN_ON(size >= SMD_RPM_MAX_SIZE))
 		return -EINVAL;
 
 	pkt = kmalloc(size, GFP_KERNEL);
diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h
index f148e0f..8039015 100644
--- a/include/linux/soc/qcom/smd.h
+++ b/include/linux/soc/qcom/smd.h
@@ -4,6 +4,13 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
+
+/*
+ * SMD packets to the RPM may not exceed 256 bytes
+ */
+#define SMD_RPM_MAX_SIZE 256
+
+
 struct qcom_smd;
 struct qcom_smd_channel;
 struct qcom_smd_lookup;
-- 
2.6.1

^ permalink raw reply related

* [PATCH 0/5] Enable onboard SDHCI for Nexus 5X (msm8992)
From: Jeremy McNicoll @ 2016-11-23  1:09 UTC (permalink / raw)
  To: linux-arm-msm, linux-soc, devicetree, linux-mmc
  Cc: andy.gross, sboyd, robh, arnd, bjorn.andersson, riteshh, jeremymc



Now that the basic board support is available:
     http://www.spinics.net/lists/linux-arm-msm/msg24533.html

and the associated clock changes have been picked up for next,
      http://www.spinics.net/lists/linux-arm-msm/msg24499.html


Using V8 from Ritesh Harjani, with the additional changes provided to him for gcc-msm8994.c 
 [ http://www.spinics.net/lists/linux-arm-msm/msg24652.html ]


Additionally V9 of the RPM clock support [http://www.spinics.net/lists/linux-arm-msm/msg24211.html]
 is needed.  

At this point, "qcom,rpmcc-msm8916" was used successfully for testing of
the rpm clock controller.  It has been marked as a TODO item in the DTS
and once the rpmcc clocks are added for 8992/8994 the needed change will
be made.  i.e.) expect a follow up patch for rpmcc 

Currently, the minimal regulators to verify / enable SDHCI functionality
have been added.   While looking at the downstream code, I saw a few more
obvious entries so they have been included (completely untested).   Hopefully
someone with the hardware docs can provide feedback  and/or an individual
with better eye site than I who can ferret out more of the entries from
downstream.

The nonremovable "keyword/flag" was used to assess the reliability of the
initial mmc detection.  When the flag is present in the DTS only 1 check
for SDHCI was made, without non removable it checks over and over again.
Without the workaround (patch 5/5) mmc/sdhci didn't get detected 8/20
times.  When including the afore mentioned workaround MMC detection is
100% (35 boots) .  

While at it, I took the liberty of re-tabifying include/dt-bindings/
clock/qcom,gcc-msm8994.h to make it look nice according to VIM using (:set list ).  
Sorry emacs users, you are on your own.


Question:
   In what DT-bindings txt file should the following, compatible = "qcom,rpm-msm8994"; 
  be placed?  (arch/arm64/boot/dts/qcom/msm8992.dtsi, rpm_requests node)


Obviously, this is a work in progress,  and its progressing :-)



Jeremy McNicoll (5):
  clk: gcc: Updates for SDHCI enablement
  smd: Make packet size a constant
  arm64: dts: Enable SDHCI for Nexus 5X (msm8992)
  sdhci: dump vendor state and regs
  sdhci: Add quirk for delayed IRQ ACK

 .../bindings/regulator/qcom,smd-rpm-regulator.txt  |  40 ++++
 .../boot/dts/qcom/msm8992-bullhead-rev-101.dts     | 262 +++++++++++++++++++++
 arch/arm64/boot/dts/qcom/msm8992-pins.dtsi         |  82 +++++++
 arch/arm64/boot/dts/qcom/msm8992.dtsi              | 153 ++++++++++++
 drivers/clk/qcom/gcc-msm8994.c                     | 108 +++++++--
 drivers/mmc/host/sdhci-msm.c                       |  86 +++++++
 drivers/mmc/host/sdhci.c                           |  37 ++-
 drivers/mmc/host/sdhci.h                           |   3 +
 drivers/regulator/qcom_smd-regulator.c             |  49 ++++
 drivers/soc/qcom/smd-rpm.c                         |   2 +-
 include/dt-bindings/clock/qcom,gcc-msm8994.h       |  32 ++-
 include/linux/soc/qcom/smd.h                       |   7 +
 12 files changed, 824 insertions(+), 37 deletions(-)

-- 
2.6.1

^ permalink raw reply

* Re: [PATCH v9 00/16] mmc: sdhci-msm: Add clk-rates, DDR, HS400 support
From: Ritesh Harjani @ 2016-11-23  0:05 UTC (permalink / raw)
  To: Stephen Boyd, Ulf Hansson, Andy Gross
  Cc: linux-mmc, Adrian Hunter, Shawn Lin, devicetree@vger.kernel.org,
	linux-clk, David Brown, linux-arm-msm@vger.kernel.org,
	Georgi Djakov, Alex Lemberg, Mateusz Nowak, Yuliy Izrailov,
	Asutosh Das, David Griego, Sahitya Tummala, Venkat Gopalakrishnan,
	Rajendra Nayak, Pramod Gurav, jeremymc
In-Reply-To: <20161121231138.GY25626@codeaurora.org>



On 11/22/2016 4:41 AM, Stephen Boyd wrote:
> On 11/21, Ritesh Harjani wrote:
>>
>>
>> On 11/21/2016 3:36 PM, Ulf Hansson wrote:
>>> On 21 November 2016 at 07:37, Ritesh Harjani <riteshh@codeaurora.org> wrote:
>>>> Hi,
>>>>
>>>> This is v9 version of the patch series which adds support for MSM8996.
>>>> Adds HS400 driver support as well.
>>>> These are tested on internal msm8996 & db410c HW.
>>>>
>>>> The patch series is ready. Do we think we can apply these
>>>> patches for next now?
>>>
>>> I guess the DTS changes can be picked up by Andy, so they can go via arm-soc?
>> Yes.
>>
>>>
>>> Then, does the mmc changes depend on the clock changes? If so, I can
>>> pick them as well, but then I need an ack from Stephen....
>> Ideal and preferable, would be that clk & mmc changes go in
>> together. But either ways should be fine.
>>
>
> There's only a runtime dependency where the clk rates will be
> wrong if clk tree isn't merged. I'd rather just apply the clk
> ones directly to clk tree and let all three trees come together
> in linux-next and work.

Ok great! So can we queue this patch series to next?
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v2 1/2] mmc: sdhci-pci: Add PCI ID for Intel byt sdio host controller sub-vended by NI
From: Zach Brown @ 2016-11-22 21:53 UTC (permalink / raw)
  To: ulf.hansson; +Cc: adrian.hunter, linux-mmc, linux-kernel, zach.brown
In-Reply-To: <1479851602-19788-1-git-send-email-zach.brown@ni.com>

Add PCI ID for Intel byt sdio host controller sub-vended by NI.

The controller has different behavior because of the board layout NI
puts it on.

Signed-off-by: Zach Brown <zach.brown@ni.com>
---
 drivers/mmc/host/sdhci-pci-core.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 1d9e00a..9741505 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -375,6 +375,13 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 	return 0;
 }
 
+static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
+{
+	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
+				 MMC_CAP_WAIT_WHILE_BUSY;
+	return 0;
+}
+
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
@@ -447,6 +454,15 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
 	.ops		= &sdhci_intel_byt_ops,
 };
 
+static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
+	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+	.quirks2	= SDHCI_QUIRK2_HOST_OFF_CARD_ON |
+			  SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+	.allow_runtime_pm = true,
+	.probe_slot	= ni_byt_sdio_probe_slot,
+	.ops		= &sdhci_intel_byt_ops,
+};
+
 static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 	.quirks2	= SDHCI_QUIRK2_HOST_OFF_CARD_ON |
@@ -1079,6 +1095,14 @@ static const struct pci_device_id pci_ids[] = {
 	{
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_BYT_SDIO,
+		.subvendor	= PCI_VENDOR_ID_NI,
+		.subdevice	= 0x7884,
+		.driver_data	= (kernel_ulong_t)&sdhci_ni_byt_sdio,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BYT_SDIO,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.driver_data	= (kernel_ulong_t)&sdhci_intel_byt_sdio,
-- 
2.7.4


^ permalink raw reply related

* [PATCH v2 2/2] mmc: sdhci-pci: Use ACPI to get max frequency for Intel byt sdio controller sub-vended by NI
From: Zach Brown @ 2016-11-22 21:53 UTC (permalink / raw)
  To: ulf.hansson; +Cc: adrian.hunter, linux-mmc, linux-kernel, zach.brown
In-Reply-To: <1479851602-19788-1-git-send-email-zach.brown@ni.com>

On NI 9037 boards the max SDIO frequency is limited by trace lengths
and other layout choices. The max SDIO frequency is stored in an ACPI
table.

The driver reads the ACPI entry MXFQ during sdio_probe_slot and sets the
f_max field of the host.

Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
Reviewed-by: Jaeden Amero <jaeden.amero@ni.com>
Reviewed-by: Josh Cartwright <joshc@ni.com>
Signed-off-by: Zach Brown <zach.brown@ni.com>
---
 drivers/mmc/host/sdhci-pci-core.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 9741505..34284b8 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -27,6 +27,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/sdhci-pci-data.h>
+#include <linux/acpi.h>
 
 #include "sdhci.h"
 #include "sdhci-pci.h"
@@ -375,6 +376,30 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
+{
+	acpi_status status;
+	unsigned long long max_freq;
+
+	status = acpi_evaluate_integer(ACPI_HANDLE(&slot->chip->pdev->dev),
+				       "MXFQ", NULL, &max_freq);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&slot->chip->pdev->dev,
+			"MXFQ not found in acpi table\n");
+		return -EINVAL;
+	}
+
+	slot->host->mmc->f_max = max_freq * 1000000;
+
+	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
+				 MMC_CAP_WAIT_WHILE_BUSY;
+	return 0;
+}
+
+#else
+
 static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
@@ -382,6 +407,9 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 	return 0;
 }
 
+#endif
+
+
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 0/2] mmc: sdhci-pci: Use ACPI to set max frequency of sdio host controller
From: Zach Brown @ 2016-11-22 21:53 UTC (permalink / raw)
  To: ulf.hansson; +Cc: adrian.hunter, linux-mmc, linux-kernel, zach.brown

On some boards, max SDIO frequency is limited by trace lengths and other layout
choices. We would like a way to specify this limitation so the driver can
behave accordingly.

This patch set assumes that the limitation has been reported in an ACPI table
which the driver can check to get the max frequency.

The first patch creates a PCI ID and support for the Intel byt sdio where NI is
the subvendor.

If CONFIG_ACPI is set, the second patch uses the ACPI table to set f_max during
the new ni_byt_sdio_probe_slot.

rv2:
   * Use acpi_evaluate_integer() instead of
     acpi_get_handle()/acpi_evaluate_object()
pv1:
   * Removed redundant comment
   * Print info message if MXFQ not found in acpi table
pv2:
   * Changed info message to error message if MXFQ not found
   * Replaced ni_byt_sdio_probe_slot with one of two versions depending on
     whether CONFIG_ACPI is set.

Zach Brown (2):
  mmc: sdhci-pci: Add PCI ID for Intel byt sdio host controller
    sub-vended by NI
  mmc: sdhci-pci: Use ACPI to get max frequency for Intel byt sdio
    controller sub-vended by NI

 drivers/mmc/host/sdhci-pci-core.c | 52 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

--
2.7.4

^ permalink raw reply

* Re: [PATCH v2 0/7] mmc: core: Re-work CMD13 polling method for CMD6 for mmc
From: Ulf Hansson @ 2016-11-22 21:01 UTC (permalink / raw)
  To: linux-mmc@vger.kernel.org, Ulf Hansson
  Cc: Jaehoon Chung, Adrian Hunter, Linus Walleij, Chaotian Jing,
	Stephen Boyd, Michael Walle, Yong Mao, Shawn Lin
In-Reply-To: <1479848173-20881-1-git-send-email-ulf.hansson@linaro.org>

On 22 November 2016 at 21:56, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> Changes in v2:
>
>         - From discussions around the difficulties for how to support CMD13
>         polling for HS200, HS400 HS400ES, I decided to drop those patches for
>         now. It's is particularly due to the need for tuning, after a speed mode
>         switch, that makes it hard to rely on CMD13 polling for these cases.
>         Perhaps we can allow CMD13 polling when switching to the intermediate
>         speed modes, but let's deal with that outside of this series.
>
>         - Folded in a new patch, which checks the SWITCH_ERROR bit in each
>           CMD13 response when polling with CMD13. Patch v2 4/7.
>
>         - No other changes made to the rest of the series.
>
>
>
> Several changes has been made for how and when to use CMD13 as a
> polling-method, to find out when the mmc cards stops signaling busy after
> sending a CMD6. This particularly concerns the cases when switching to new bus
> speed modes, such as HS (high-speed), HS DDR, HS200, HS400 and HS400ES.
>
> Currently CMD13 polling is *not* allowed for these cases, but this was recently
> changed - and which did cause regressions for card detection for some
> platforms.
>
> A simple fix was made to solve these regressions, simply by using a default
> CMD6 generic timeout of 500ms, as to avoid using the fall-back timeout in
> __mmc_switch() of 10min. That greatly improve the situation and one could
> consider the regressions as "solved".
>
> However, this simple fix is still causing unnecessary long card initialization
> times, especially for those mmc hosts that doesn't support HW busy detection
> (using MMC_CAP_WAIT_WHILE_BUSY and/or implements the ->card_busy() host ops).
>
> This because we wait a fixed amount of time (CMD6 generic timeout) to make sure
> the card is done signaling busy, while in practice this happens a lot sooner.
>
> A couple of tests for HS and HS DDR eMMC cards, shows the card only need a few
> ms to complete the bus speed mode changes, thus it's far less than the CMD6
> generic timeout.
>
> To improve this behaviour and shorten the card initialization time, we need to
> allow using CMD13 as polling method to find out when the card stops signaling
> busy. Although, enabling CMD13 polling may also introduce other issues as
> according to the JEDEC spec, it's not the recommended method. Especially it
> mentions that CRC errors may be triggered when sending a CMD13 command during a
> bus timing change.
>
> To deal with these issues, we need to change from ignoring those CRC errors but
> instead continue to treat the card as being busy and continue to poll with
> CMD13. Perhaps this behaviour is one of reasons to why the earlier CMD13 polling
> method didn't work out well.
>
> This series requires extensive testing, please help with that!
>
> I have currently tested it with HS and HS DDR eMMC cards, and for combinations
> of an mmc hosts (mmci) supporting HW busy detection and not (local hacks in
> mmci.c).
>
>
> Ulf Hansson (9):
>   mmc: core: Retry instead of ignore at CRC errors when polling for busy
>   mmc: core: Remove redundant __mmc_send_status()
>   mmc: core: Rename ignore_crc to retry_crc_err to reflect its purpose
>   mmc: core: Enable __mmc_switch() to change bus speed timing for the
>     host
>   mmc: core: Allow CMD13 polling when switching to HS mode for mmc
>   mmc: core: Update CMD13 polling policy when switch to HS DDR mode
>   mmc: core: Allow CMD13 polling when switch to HS200 mode
>   mmc: core: Allow CMD13 polling when switch to HS400 mode
>   mmc: core: Allow CMD13 polling when switch to HS400ES mode
>
>  drivers/mmc/core/core.c    |   2 +-
>  drivers/mmc/core/mmc.c     | 156 ++++++++++++++-------------------------------
>  drivers/mmc/core/mmc_ops.c |  45 +++++++------
>  drivers/mmc/core/mmc_ops.h |   4 +-
>  4 files changed, 77 insertions(+), 130 deletions(-)

Oops, forgot to clean up the cover letter. Please ignore the summary
of changes above. It's the below changes that are the v2 series.

Apologize for the inconvenience!

Kind regards
Uffe

>
> --
> 1.9.1
>
>
>
>
>
>
> *** BLURB HERE ***
>
> Ulf Hansson (7):
>   mmc: core: Retry instead of ignore at CRC errors when polling for busy
>   mmc: core: Remove redundant __mmc_send_status()
>   mmc: core: Rename ignore_crc to retry_crc_err to reflect its purpose
>   mmc: core: Check SWITCH_ERROR bit from each CMD13 response when
>     polling
>   mmc: core: Enable __mmc_switch() to change bus speed timing for the
>     host
>   mmc: core: Allow CMD13 polling when switching to HS mode for mmc
>   mmc: core: Update CMD13 polling policy when switch to HS DDR mode
>
>  drivers/mmc/core/core.c    |  2 +-
>  drivers/mmc/core/mmc.c     | 53 +++++++++++++++++++++++-----------------------
>  drivers/mmc/core/mmc_ops.c | 51 ++++++++++++++++++++++++++------------------
>  drivers/mmc/core/mmc_ops.h |  4 ++--
>  4 files changed, 60 insertions(+), 50 deletions(-)
>
> --
> 1.9.1
>

^ permalink raw reply

* [PATCH v2 4/7] mmc: core: Check SWITCH_ERROR bit from each CMD13 response when polling
From: Ulf Hansson @ 2016-11-22 20:56 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Jaehoon Chung, Adrian Hunter, Linus Walleij, Chaotian Jing,
	Stephen Boyd, Michael Walle, Yong Mao, Shawn Lin
In-Reply-To: <1479848173-20881-1-git-send-email-ulf.hansson@linaro.org>

According to the JEDEC specification, the SWITCH_ERROR bit in the device
status from a R1 response, is an error bit which may be cleared as soon as
the response that reports the error is sent.

When polling with CMD13 to find out when the card stops signaling busy
after a CMD6 has been sent, we currently parse only the last CMD13 response
for the SWITCH_ERROR bit. Consequentially we could loose important
information about the card.

In worst case if the card stops signaling busy within the allowed timeout,
we could end up believing that the CMD6 command completed successfully,
when in fact it didn't.

To improve the behaviour, let's parse each CMD13 response to see if the
SWITCH_ERROR bit is set in the device status. In such case, we abort the
polling loop and report the error.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v2:
	- New patch.

---
 drivers/mmc/core/mmc_ops.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 214e734..fba5d29 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -496,12 +496,16 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
 			busy = host->ops->card_busy(host);
 		} else {
 			err = mmc_send_status(card, &status);
-			if (retry_crc_err && err == -EILSEQ)
+			if (retry_crc_err && err == -EILSEQ) {
 				busy = true;
-			else if (err)
+			} else if (err) {
 				return err;
-			else
+			} else {
+				err = mmc_switch_status_error(host, status);
+				if (err)
+					return err;
 				busy = R1_CURRENT_STATE(status) == R1_STATE_PRG;
+			}
 		}
 
 		/* Timeout if the device still remains busy. */
@@ -515,7 +519,7 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
 	if (host->ops->card_busy && send_status)
 		return mmc_switch_status(card);
 
-	return mmc_switch_status_error(host, status);
+	return 0;
 }
 
 /**
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 2/7] mmc: core: Remove redundant __mmc_send_status()
From: Ulf Hansson @ 2016-11-22 20:56 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Jaehoon Chung, Adrian Hunter, Linus Walleij, Chaotian Jing,
	Stephen Boyd, Michael Walle, Yong Mao, Shawn Lin
In-Reply-To: <1479848173-20881-1-git-send-email-ulf.hansson@linaro.org>

There are only one users left which calls __mmc_send_status(). Moreover,
the ignore_crc parameter isn't being used, so let's just remove these
redundant parts.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/mmc_ops.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 4773c56..0515748 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -54,8 +54,7 @@
 	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
 };
 
-static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
-				    bool ignore_crc)
+int mmc_send_status(struct mmc_card *card, u32 *status)
 {
 	int err;
 	struct mmc_command cmd = {0};
@@ -67,8 +66,6 @@ static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
 	if (!mmc_host_is_spi(card->host))
 		cmd.arg = card->rca << 16;
 	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-	if (ignore_crc)
-		cmd.flags &= ~MMC_RSP_CRC;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err)
@@ -83,11 +80,6 @@ static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
 	return 0;
 }
 
-int mmc_send_status(struct mmc_card *card, u32 *status)
-{
-	return __mmc_send_status(card, status, false);
-}
-
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
 	struct mmc_command cmd = {0};
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 1/7] mmc: core: Retry instead of ignore at CRC errors when polling for busy
From: Ulf Hansson @ 2016-11-22 20:56 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Jaehoon Chung, Adrian Hunter, Linus Walleij, Chaotian Jing,
	Stephen Boyd, Michael Walle, Yong Mao, Shawn Lin
In-Reply-To: <1479848173-20881-1-git-send-email-ulf.hansson@linaro.org>

After a CMD6 command has been sent, the __mmc_switch() function might be
advised to poll the card for busy by using CMD13 and also by ignoring CRC
errors.

In the case of ignoring CRC errors, the mmc core tells the mmc host to also
ignore these errors via masking the MMC_RSP_CRC response flag. This seems
wrong, as it leads to that the mmc host could propagate an unreliable
response, instead of a proper error code.

What we really want, is not to ignore CRC errors but instead retry the
polling attempt. So, let's change this by treating a CRC error as the card
is still being busy and thus continue to run the polling loop.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/mmc_ops.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 481bbdb..4773c56 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -503,10 +503,13 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
 		if (host->ops->card_busy) {
 			busy = host->ops->card_busy(host);
 		} else {
-			err = __mmc_send_status(card, &status, ignore_crc);
-			if (err)
+			err = mmc_send_status(card, &status);
+			if (ignore_crc && err == -EILSEQ)
+				busy = true;
+			else if (err)
 				return err;
-			busy = R1_CURRENT_STATE(status) == R1_STATE_PRG;
+			else
+				busy = R1_CURRENT_STATE(status) == R1_STATE_PRG;
 		}
 
 		/* Timeout if the device still remains busy. */
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 6/7] mmc: core: Allow CMD13 polling when switching to HS mode for mmc
From: Ulf Hansson @ 2016-11-22 20:56 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Jaehoon Chung, Adrian Hunter, Linus Walleij, Chaotian Jing,
	Stephen Boyd, Michael Walle, Yong Mao, Shawn Lin
In-Reply-To: <1479848173-20881-1-git-send-email-ulf.hansson@linaro.org>

In cases when the mmc host doesn't support HW busy detection, polling for a
card being busy by using CMD13 is beneficial. That is because, instead of
waiting a fixed amount of time, 500ms or the generic CMD6 time from
EXT_CSD, we find out a lot sooner when the card stops signaling busy. This
leads to a significant decreased total initialization time for the mmc
card.

However, to allow polling with CMD13 during a bus timing change operation,
such as switching to HS mode, we first need to update the mmc host's bus
timing before starting to poll. Deal with that, simply by providing
MMC_TIMING_MMC_HS as the timing parameter to __mmc_switch() from
mmc_select_hs().

By telling __mmc_switch() to allow polling with CMD13, also makes it
validate the CMD6 status, thus we can remove the corresponding checks.

When switching to HS400ES, the mmc_select_hs() function is called in one of
the intermediate steps. To still prevent CMD13 polling for HS400ES, let's
call the __mmc_switch() function in this path as it enables us to keep
using the existing method.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/mmc.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index cb1cf4e..15dd51c 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1012,13 +1012,8 @@ static int mmc_select_hs(struct mmc_card *card)
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
-			   card->ext_csd.generic_cmd6_time, 0,
-			   true, false, true);
-	if (!err) {
-		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-		err = mmc_switch_status(card);
-	}
-
+			   card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS,
+			   true, true, true);
 	if (err)
 		pr_warn("%s: switch to high-speed failed, err:%d\n",
 			mmc_hostname(card->host), err);
@@ -1268,16 +1263,23 @@ static int mmc_select_hs400es(struct mmc_card *card)
 		goto out_err;
 
 	/* Switch card to HS mode */
-	err = mmc_select_hs(card);
-	if (err)
+	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+			   card->ext_csd.generic_cmd6_time, 0,
+			   true, false, true);
+	if (err) {
+		pr_err("%s: switch to hs for hs400es failed, err:%d\n",
+			mmc_hostname(host), err);
 		goto out_err;
+	}
 
-	mmc_set_clock(host, card->ext_csd.hs_max_dtr);
-
+	mmc_set_timing(host, MMC_TIMING_MMC_HS);
 	err = mmc_switch_status(card);
 	if (err)
 		goto out_err;
 
+	mmc_set_clock(host, card->ext_csd.hs_max_dtr);
+
 	/* Switch card to DDR with strobe bit */
 	val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE;
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-- 
1.9.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox