Linux MultiMedia Card development
 help / color / mirror / Atom feed
* [v16, 2/7] dt: bindings: move guts devicetree doc out of powerpc directory
From: Yangbo Lu @ 2016-11-09  3:14 UTC (permalink / raw)
  To: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Scott Wood, Arnd Bergmann
  Cc: Mark Rutland, Greg Kroah-Hartman, Xiaobo Xie, Minghuan Lian,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, Qiang Zhao, Russell King,
	Bhupesh Sharma, Jochen Friedrich, Claudiu Manoil,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Kumar Gala, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Leo Li,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Yangbo Lu,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1478661252-42439-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>

Move guts devicetree doc to Documentation/devicetree/bindings/soc/fsl/
since it's used by not only PowerPC but also ARM. And add a specification
for 'little-endian' property.

Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Scott Wood <oss-fOR+EgIDQEHk1uMJSBkQmQ@public.gmane.org>
Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
Changes for v4:
	- Added this patch
Changes for v5:
	- Modified the description for little-endian property
Changes for v6:
	- None
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
	- Added 'Acked-by: Rob Herring'
Changes for v9:
	- None
Changes for v10:
	- None
Changes for v11:
	- None
Changes for v12:
	- None
Changes for v13:
	- None
Changes for v14:
	- None
Changes for v15:
	- None
Changes for v16:
	- Added 'Acked-by: Arnd'
---
 Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt | 3 +++
 1 file changed, 3 insertions(+)
 rename Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt (91%)

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt b/Documentation/devicetree/bindings/soc/fsl/guts.txt
similarity index 91%
rename from Documentation/devicetree/bindings/powerpc/fsl/guts.txt
rename to Documentation/devicetree/bindings/soc/fsl/guts.txt
index b71b203..07adca9 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
+++ b/Documentation/devicetree/bindings/soc/fsl/guts.txt
@@ -25,6 +25,9 @@ Recommended properties:
  - fsl,liodn-bits : Indicates the number of defined bits in the LIODN
    registers, for those SOCs that have a PAMU device.
 
+ - little-endian : Indicates that the global utilities block is little
+   endian. The default is big endian.
+
 Examples:
 	global-utilities@e0000 {	/* global utilities block */
 		compatible = "fsl,mpc8548-guts";
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [v16, 1/7] ARM64: dts: ls2080a: add device configuration node
From: Yangbo Lu @ 2016-11-09  3:14 UTC (permalink / raw)
  To: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Scott Wood, Arnd Bergmann
  Cc: Mark Rutland, Greg Kroah-Hartman, Xiaobo Xie, Minghuan Lian,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, Qiang Zhao, Russell King,
	Bhupesh Sharma, Jochen Friedrich, Claudiu Manoil,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Kumar Gala, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Leo Li,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Yangbo Lu,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1478661252-42439-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>

Add the dts node for device configuration unit that provides
general purpose configuration and status for the device.

Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
Acked-by: Scott Wood <oss-fOR+EgIDQEHk1uMJSBkQmQ@public.gmane.org>
Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
---
Changes for v5:
	- Added this patch
Changes for v6:
	- None
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
Changes for v10:
	- None
Changes for v11:
	- None
Changes for v12:
	- None
Changes for v13:
	- None
Changes for v14:
	- None
Changes for v15:
	- None
Changes for v16:
	- Added 'Acked-by: Arnd'
---
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 7f0dc13..d058e56 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -216,6 +216,12 @@
 			clocks = <&sysclk>;
 		};
 
+		dcfg: dcfg@1e00000 {
+			compatible = "fsl,ls2080a-dcfg", "syscon";
+			reg = <0x0 0x1e00000 0x0 0x10000>;
+			little-endian;
+		};
+
 		serial0: serial@21c0500 {
 			compatible = "fsl,ns16550", "ns16550a";
 			reg = <0x0 0x21c0500 0x0 0x100>;
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [v16, 0/7] Fix eSDHC host version register bug
From: Yangbo Lu @ 2016-11-09  3:14 UTC (permalink / raw)
  To: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Scott Wood, Arnd Bergmann
  Cc: Mark Rutland, Greg Kroah-Hartman, Xiaobo Xie, Minghuan Lian,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, Qiang Zhao, Russell King,
	Bhupesh Sharma, Jochen Friedrich, Claudiu Manoil,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Kumar Gala, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Leo Li,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Yangbo Lu,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ

This patchset is used to fix a host version register bug in the T4240-R1.0-R2.0
eSDHC controller. To match the SoC version and revision, 15 previous version
patchsets had tried many methods but all of them were rejected by reviewers.
Such as
	- dts compatible method
	- syscon method
	- ifdef PPC method
	- GUTS driver getting SVR method
Anrd suggested a soc_device_match method in v10, and this is the only available
method left now. This v11 patchset introduces the soc_device_match interface in
soc driver.

The first four patches of Yangbo are to add the GUTS driver. This is used to
register a soc device which contain soc version and revision information.
The other three patches introduce the soc_device_match method in soc driver
and apply it on esdhc driver to fix this bug.

---
Changes for v15:
	- Dropped patch 'dt: bindings: update Freescale DCFG compatible'
	  since the work had been done by below patch on ShawnGuo's linux tree.
	  'dt-bindings: fsl: add LS1043A/LS1046A/LS2080A compatible for SCFG
	   and DCFG'
	- Fixed error code issue in guts driver
Changes for v16:
	- Dropped patch 'powerpc/fsl: move mpc85xx.h to include/linux/fsl'
	- Added a bug-fix patch from Geert
---

Arnd Bergmann (1):
  base: soc: introduce soc_device_match() interface

Geert Uytterhoeven (1):
  base: soc: Check for NULL SoC device attributes

Yangbo Lu (5):
  ARM64: dts: ls2080a: add device configuration node
  dt: bindings: move guts devicetree doc out of powerpc directory
  soc: fsl: add GUTS driver for QorIQ platforms
  MAINTAINERS: add entry for Freescale SoC drivers
  mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0

 .../bindings/{powerpc => soc}/fsl/guts.txt         |   3 +
 MAINTAINERS                                        |  11 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     |   6 +
 drivers/base/Kconfig                               |   1 +
 drivers/base/soc.c                                 |  70 ++++++
 drivers/mmc/host/Kconfig                           |   1 +
 drivers/mmc/host/sdhci-of-esdhc.c                  |  20 ++
 drivers/soc/Kconfig                                |   3 +-
 drivers/soc/fsl/Kconfig                            |  18 ++
 drivers/soc/fsl/Makefile                           |   1 +
 drivers/soc/fsl/guts.c                             | 236 +++++++++++++++++++++
 include/linux/fsl/guts.h                           | 125 ++++++-----
 include/linux/sys_soc.h                            |   3 +
 13 files changed, 447 insertions(+), 51 deletions(-)
 rename Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt (91%)
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/guts.c

-- 
2.1.0.27.g96db324

^ permalink raw reply

* Re: [PATCH v6 05/14] mmc: sdhci-msm: Update DLL reset sequence
From: Arnd Bergmann @ 2016-11-08 23:14 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Ritesh Harjani, ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
	shawn.lin-TNX95d0MmH7DzftRWevZcw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	david.brown-QSEj5FYQhm4dnm+yROfE0A,
	andy.gross-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
	mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
	Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
	asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
	david.griego-QSEj5FYQhm4dnm+yROfE0A,
	stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	pramod.gurav-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <20161108230622.GN16026-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

On Tuesday, November 8, 2016 3:06:22 PM CET Stephen Boyd wrote:
> > +
> > +             config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
> > +             config &= ~(0xFF << 10);
> > +             config |= mclk_freq << 10;
> > +
> > +             writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
> > +             /* wait for 5us before enabling DLL clock */
> 
> Usually there's a barrier between writel_relaxed() and delay
> because we don't know when the writel will be posted out and the
> delay is there to wait for the operation to happen. Probably
> should change this to be a writel() instead.
> 

The barrier in writel() is not for posted writes, it is to synchronize
with memory accesses *before* the write.

In general, if you want to ensure that a write has made it to the
device, you need to read back from the same address (the specific
behavior may depend on the bus).

While in general, using the non-relaxed accessors should be the
default (and there should be a comment for each *_relaxed access),
but I don't think using writel() would let you skip the delay here.

	Arnd
--
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 v6 04/14] mmc: sdhci-msm: Change poor style writel/readl of registers
From: Stephen Boyd @ 2016-11-08 23:07 UTC (permalink / raw)
  To: Ritesh Harjani
  Cc: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, devicetree,
	linux-clk, david.brown, andy.gross, linux-arm-msm, georgi.djakov,
	alex.lemberg, mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman,
	david.griego, stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <1478517877-23733-5-git-send-email-riteshh@codeaurora.org>

On 11/07, Ritesh Harjani wrote:
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index 8ef44a2a..42f42aa 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -137,8 +137,9 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
>  	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>  
>  	/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
> -	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
> -			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
> +	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
> +	config |= CORE_CK_OUT_EN;
> +	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>  
>  	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
>  	rc = msm_dll_poll_ck_out_en(host, 1);
> @@ -305,6 +306,7 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>  	struct mmc_host *mmc = host->mmc;
>  	int wait_cnt = 50;
>  	unsigned long flags;
> +	u32 config = 0;

It needs to be initialized?

>  
>  	spin_lock_irqsave(&host->lock, flags);
>  
> @@ -313,33 +315,40 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>  	 * tuning is in progress. Keeping PWRSAVE ON may
>  	 * turn off the clock.
>  	 */
> -	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
> -			& ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
> +	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);

It's written here unconditionally though?

> +	config &= ~CORE_CLK_PWRSAVE;

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

^ permalink raw reply

* Re: [PATCH v6 05/14] mmc: sdhci-msm: Update DLL reset sequence
From: Stephen Boyd @ 2016-11-08 23:06 UTC (permalink / raw)
  To: Ritesh Harjani
  Cc: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, devicetree,
	linux-clk, david.brown, andy.gross, linux-arm-msm, georgi.djakov,
	alex.lemberg, mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman,
	david.griego, stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <1478517877-23733-6-git-send-email-riteshh@codeaurora.org>

On 11/07, Ritesh Harjani wrote:
> 
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index 42f42aa..32b0b79 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -58,11 +58,17 @@
>  #define CORE_DLL_CONFIG		0x100
>  #define CORE_DLL_STATUS		0x108
>  
> +#define CORE_DLL_CONFIG_2	0x1b4
> +#define CORE_FLL_CYCLE_CNT	BIT(18)
> +#define CORE_DLL_CLOCK_DISABLE	BIT(21)
> +
>  #define CORE_VENDOR_SPEC	0x10c
>  #define CORE_CLK_PWRSAVE	BIT(1)
>  
>  #define CORE_VENDOR_SPEC_CAPABILITIES0	0x11c
>  
> +#define TCXO_FREQ		19200000

TCXO_FREQ could change based on the board. For example, IPQ has
it as 25 MHz.

> +
>  #define CDR_SELEXT_SHIFT	20
>  #define CDR_SELEXT_MASK		(0xf << CDR_SELEXT_SHIFT)
>  #define CMUX_SHIFT_PHASE_SHIFT	24
> @@ -330,6 +349,24 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>  	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>  	msm_cm_dll_set_freq(host);
>  
> +	if (msm_host->use_14lpp_dll_reset) {
> +		u32 mclk_freq = 0;
> +
> +		if ((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
> +					& CORE_FLL_CYCLE_CNT))

I suggest you grow a local variable.

> +			mclk_freq = (u32)((host->clock / TCXO_FREQ) * 8);

Is the cast necessary?

> +		else
> +			mclk_freq = (u32)((host->clock / TCXO_FREQ) * 4);

Ditto

> +
> +		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
> +		config &= ~(0xFF << 10);
> +		config |= mclk_freq << 10;
> +
> +		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
> +		/* wait for 5us before enabling DLL clock */

Usually there's a barrier between writel_relaxed() and delay
because we don't know when the writel will be posted out and the
delay is there to wait for the operation to happen. Probably
should change this to be a writel() instead.

> +		udelay(5);
> +	}
> +
>  	/* Write 0 to DLL_RST bit of DLL_CONFIG register */
>  	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
>  	config &= ~CORE_DLL_RST;
> @@ -340,6 +377,14 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>  	config &= ~CORE_DLL_PDN;
>  	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>  
> +	if (msm_host->use_14lpp_dll_reset) {
> +		msm_cm_dll_set_freq(host);
> +		/* Enable the DLL clock */
> +		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
> +		config &= ~CORE_DLL_CLOCK_DISABLE;
> +		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
> +	}
> +
>  	/* Set DLL_EN bit to 1. */
>  	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
>  	config |= CORE_DLL_EN;
> @@ -641,6 +686,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>  	dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
>  		core_version, core_major, core_minor);
>  
> +	if ((core_major == 1) && (core_minor >= 0x42))

Why so many parenthesis?

> +		msm_host->use_14lpp_dll_reset = true;
> +
>  	/*

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

^ permalink raw reply

* Re: [PATCH v6 02/14] clk: qcom: Add rcg ops to return floor value closest to the requested rate
From: Stephen Boyd @ 2016-11-08 23:02 UTC (permalink / raw)
  To: Ritesh Harjani
  Cc: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	adrian.hunter-ral2JQCrhuEAvxtiuMwx3w,
	shawn.lin-TNX95d0MmH7DzftRWevZcw,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	david.brown-QSEj5FYQhm4dnm+yROfE0A,
	andy.gross-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
	mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
	Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
	asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
	david.griego-QSEj5FYQhm4dnm+yROfE0A,
	stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	pramod.gurav-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1478517877-23733-3-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

On 11/07, Ritesh Harjani wrote:
> diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
> index b904c33..1b3e8d2 100644
> --- a/drivers/clk/qcom/clk-rcg.h
> +++ b/drivers/clk/qcom/clk-rcg.h
> @@ -173,6 +173,7 @@ struct clk_rcg2 {
>  #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
>  
>  extern const struct clk_ops clk_rcg2_ops;
> +extern const struct clk_ops clk_rcg2_floor_ops;
>  extern const struct clk_ops clk_rcg2_shared_ops;
>  extern const struct clk_ops clk_edp_pixel_ops;
>  extern const struct clk_ops clk_byte_ops;
> diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
> index a071bba..04433a6 100644
> --- a/drivers/clk/qcom/clk-rcg2.c
> +++ b/drivers/clk/qcom/clk-rcg2.c
> @@ -47,6 +47,11 @@
>  #define N_REG			0xc
>  #define D_REG			0x10
>  
> +enum {
> +	FLOOR,
> +	CEIL,
> +};

Give it a name.

> +
>  static int clk_rcg2_is_enabled(struct clk_hw *hw)
>  {
>  	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
> @@ -176,15 +181,25 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
>  	return calc_rate(parent_rate, m, n, mode, hid_div);
>  }
>  
> -static int _freq_tbl_determine_rate(struct clk_hw *hw,
> -		const struct freq_tbl *f, struct clk_rate_request *req)
> +static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
> +				    struct clk_rate_request *req, bool match)

Use the enum please. Also name it something besides match.
policy?

>  {
>  	unsigned long clk_flags, rate = req->rate;
>  	struct clk_hw *p;
>  	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
>  	int index;
>  
> -	f = qcom_find_freq(f, rate);
> +	switch (match) {
> +	case FLOOR:
> +		f = qcom_find_freq_floor(f, rate);
> +		break;
> +	case CEIL:
> +		f = qcom_find_freq(f, rate);
> +		break;
> +	default:
> +		return -EINVAL;
> +	};
> +
>  	if (!f)
>  		return -EINVAL;
>  
> diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
> index fffcbaf..cf6b87f 100644
> --- a/drivers/clk/qcom/common.c
> +++ b/drivers/clk/qcom/common.c
> @@ -46,6 +46,32 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
>  }
>  EXPORT_SYMBOL_GPL(qcom_find_freq);
>  
> +const
> +struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,

We can't put const and struct on the same line?

> +				      unsigned long rate)
> +{
> +	int size = 0;
> +
> +	if (!f)
> +		return NULL;
> +
> +	/*
> +	 * The freq table has entries in the ascending order of frequencies
> +	 * To find the floor for a given frequency, we need to do a reverse
> +	 * lookup of the table
> +	 */
> +	for (; f->freq; f++, size++)
> +		;
> +
> +	for (f--; size; f--, size--)
> +		if (rate >= f->freq)
> +			return f;

I don't understand why we can't do this while iterating through
the table. We shouldn't need to size up the frequency table first.

	const struct freq_tbl *best = NULL;

	for ( ; f->freq; f++) {
		if (rate >= f->freq)
			best = f->freq;
		else
			break;
	}
	
	return best;

> +
> +	/* could not find any rates lower than *rate* */

> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(qcom_find_freq_floor);

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
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

* [RFC 1/2] mmc: sdhci-pci: Add PCI ID for Intel byt sdio host controller sub-vended by NI
From: Zach Brown @ 2016-11-08 20:07 UTC (permalink / raw)
  To: ulf.hansson; +Cc: adrian.hunter, linux-mmc, linux-kernel, zach.brown
In-Reply-To: <1478635635-14953-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 | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 1d9e00a..c333ce2 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -375,6 +375,12 @@ 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;
+	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 +453,12 @@ 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 = {
+	.quirks2	= SDHCI_QUIRK2_HOST_OFF_CARD_ON,
+	.allow_runtime_pm = true,
+	.probe_slot	= ni_byt_sdio_probe_slot,
+};
+
 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 +1091,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

* [RFC 2/2] mmc: sdhci-pci: Use ACPI to get max frequency for Intel byt sdio host controller sub-vended by NI
From: Zach Brown @ 2016-11-08 20:07 UTC (permalink / raw)
  To: ulf.hansson; +Cc: adrian.hunter, linux-mmc, linux-kernel, zach.brown
In-Reply-To: <1478635635-14953-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, as MXFQ.

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

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 | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index c333ce2..4ac7f16 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"
@@ -377,6 +378,35 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 
 static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
+#ifdef CONFIG_ACPI
+	/* Get max freq from ACPI for NI hardware */
+	acpi_handle acpi_hdl;
+	acpi_status status;
+	struct acpi_buffer acpi_result = {
+		ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *acpi_buffer;
+	int max_freq;
+
+	status = acpi_get_handle(ACPI_HANDLE(&slot->chip->pdev->dev), "MXFQ",
+				 &acpi_hdl);
+	if (ACPI_FAILURE(status))
+		return  -ENODEV;
+
+	status = acpi_evaluate_object(acpi_hdl, NULL,
+				      NULL, &acpi_result);
+	if (ACPI_FAILURE(status))
+		return -EINVAL;
+
+	acpi_buffer = (union acpi_object *)acpi_result.pointer;
+
+	if (acpi_buffer->type != ACPI_TYPE_INTEGER)
+		return -EINVAL;
+
+	max_freq = acpi_buffer->integer.value;
+
+	slot->host->mmc->f_max = max_freq * 1000000;
+#endif
+
 	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related

* [RFC 0/2] mmc: sdhci-pci: Use ACPI to set max frequency of sdio host
From: Zach Brown @ 2016-11-08 20:07 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.

The second patch uses the ACPI table to set f_max during the new
ni_byt_sdio_probe_slot.


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
    host controller sub-vended by NI

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

--
2.7.4

^ permalink raw reply

* Re: [PATCH 2/9] mmc: mmci: add support for not-amba, but still compatible, variants
From: kbuild test robot @ 2016-11-08 17:39 UTC (permalink / raw)
  Cc: kbuild-all, ulf.hansson, mcoquelin.stm32, alexandre.torgue,
	linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-3-git-send-email-andrea.merello@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 8792 bytes --]

Hi Andrea,

[auto build test ERROR on ulf.hansson-mmc/next]
[also build test ERROR on v4.9-rc4 next-20161108]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Andrea-Merello/mmc-mmci-add-support-for-STM32-SD-controller/20161108-234358
base:   https://git.linaro.org/people/ulf.hansson/mmc next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

   drivers/mmc/host/mmci.c: In function 'mmci_probe_amba':
   drivers/mmc/host/mmci.c:1849:21: error: 'pdev' undeclared (first use in this function)
     host = mmci_probe(&pdev->dev, variant, &dev->res,
                        ^~~~
   drivers/mmc/host/mmci.c:1849:21: note: each undeclared identifier is reported only once for each function it appears in
   drivers/mmc/host/mmci.c:1851:13: error: 'ret' undeclared (first use in this function)
     if (IS_ERR(ret))
                ^~~
   In file included from drivers/mmc/host/mmci.c:12:0:
   drivers/mmc/host/mmci.c: At top level:
>> include/linux/module.h:130:27: error: redefinition of '__inittest'
     static inline initcall_t __inittest(void)  \
                              ^
   include/linux/device.h:1353:1: note: in expansion of macro 'module_init'
    module_init(__driver##_init); \
    ^~~~~~~~~~~
>> include/linux/platform_device.h:228:2: note: in expansion of macro 'module_driver'
     module_driver(__platform_driver, platform_driver_register, \
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:2032:1: note: in expansion of macro 'module_platform_driver'
    module_platform_driver(mmci_pltfm_driver);
    ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/module.h:130:27: note: previous definition of '__inittest' was here
     static inline initcall_t __inittest(void)  \
                              ^
   include/linux/device.h:1353:1: note: in expansion of macro 'module_init'
    module_init(__driver##_init); \
    ^~~~~~~~~~~
>> include/linux/amba/bus.h:170:2: note: in expansion of macro 'module_driver'
     module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:1938:1: note: in expansion of macro 'module_amba_driver'
    module_amba_driver(mmci_driver);
    ^~~~~~~~~~~~~~~~~~
>> include/linux/module.h:132:6: error: redefinition of 'init_module'
     int init_module(void) __attribute__((alias(#initfn)));
         ^
   include/linux/device.h:1353:1: note: in expansion of macro 'module_init'
    module_init(__driver##_init); \
    ^~~~~~~~~~~
>> include/linux/platform_device.h:228:2: note: in expansion of macro 'module_driver'
     module_driver(__platform_driver, platform_driver_register, \
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:2032:1: note: in expansion of macro 'module_platform_driver'
    module_platform_driver(mmci_pltfm_driver);
    ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/module.h:132:6: note: previous definition of 'init_module' was here
     int init_module(void) __attribute__((alias(#initfn)));
         ^
   include/linux/device.h:1353:1: note: in expansion of macro 'module_init'
    module_init(__driver##_init); \
    ^~~~~~~~~~~
>> include/linux/amba/bus.h:170:2: note: in expansion of macro 'module_driver'
     module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:1938:1: note: in expansion of macro 'module_amba_driver'
    module_amba_driver(mmci_driver);
    ^~~~~~~~~~~~~~~~~~
>> include/linux/module.h:136:27: error: redefinition of '__exittest'
     static inline exitcall_t __exittest(void)  \
                              ^
   include/linux/device.h:1358:1: note: in expansion of macro 'module_exit'
    module_exit(__driver##_exit);
    ^~~~~~~~~~~
>> include/linux/platform_device.h:228:2: note: in expansion of macro 'module_driver'
     module_driver(__platform_driver, platform_driver_register, \
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:2032:1: note: in expansion of macro 'module_platform_driver'
    module_platform_driver(mmci_pltfm_driver);
    ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/module.h:136:27: note: previous definition of '__exittest' was here
     static inline exitcall_t __exittest(void)  \
                              ^
   include/linux/device.h:1358:1: note: in expansion of macro 'module_exit'
    module_exit(__driver##_exit);
    ^~~~~~~~~~~
>> include/linux/amba/bus.h:170:2: note: in expansion of macro 'module_driver'
     module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:1938:1: note: in expansion of macro 'module_amba_driver'
    module_amba_driver(mmci_driver);
    ^~~~~~~~~~~~~~~~~~
>> include/linux/module.h:138:7: error: redefinition of 'cleanup_module'
     void cleanup_module(void) __attribute__((alias(#exitfn)));
          ^
   include/linux/device.h:1358:1: note: in expansion of macro 'module_exit'
    module_exit(__driver##_exit);
    ^~~~~~~~~~~
>> include/linux/platform_device.h:228:2: note: in expansion of macro 'module_driver'
     module_driver(__platform_driver, platform_driver_register, \
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:2032:1: note: in expansion of macro 'module_platform_driver'
    module_platform_driver(mmci_pltfm_driver);
    ^~~~~~~~~~~~~~~~~~~~~~
   include/linux/module.h:138:7: note: previous definition of 'cleanup_module' was here
     void cleanup_module(void) __attribute__((alias(#exitfn)));
          ^
   include/linux/device.h:1358:1: note: in expansion of macro 'module_exit'
    module_exit(__driver##_exit);
    ^~~~~~~~~~~
>> include/linux/amba/bus.h:170:2: note: in expansion of macro 'module_driver'
     module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
     ^~~~~~~~~~~~~
>> drivers/mmc/host/mmci.c:1938:1: note: in expansion of macro 'module_amba_driver'
    module_amba_driver(mmci_driver);
    ^~~~~~~~~~~~~~~~~~

vim +/module_driver +228 include/linux/platform_device.h

71d642908 Marc Kleine-Budde  2011-02-16  212  {
71d642908 Marc Kleine-Budde  2011-02-16  213  	return dev_get_drvdata(&pdev->dev);
71d642908 Marc Kleine-Budde  2011-02-16  214  }
71d642908 Marc Kleine-Budde  2011-02-16  215  
6ae07f27a Fabio Porcedda     2013-03-26  216  static inline void platform_set_drvdata(struct platform_device *pdev,
6ae07f27a Fabio Porcedda     2013-03-26  217  					void *data)
71d642908 Marc Kleine-Budde  2011-02-16  218  {
71d642908 Marc Kleine-Budde  2011-02-16  219  	dev_set_drvdata(&pdev->dev, data);
71d642908 Marc Kleine-Budde  2011-02-16  220  }
00d3dcdd9 Russell King       2005-11-09  221  
940ab8896 Grant Likely       2011-10-05  222  /* module_platform_driver() - Helper macro for drivers that don't do
940ab8896 Grant Likely       2011-10-05  223   * anything special in module init/exit.  This eliminates a lot of
940ab8896 Grant Likely       2011-10-05  224   * boilerplate.  Each module may only use this macro once, and
940ab8896 Grant Likely       2011-10-05  225   * calling it replaces module_init() and module_exit()
940ab8896 Grant Likely       2011-10-05  226   */
940ab8896 Grant Likely       2011-10-05  227  #define module_platform_driver(__platform_driver) \
907d0ed1c Lars-Peter Clausen 2011-11-16 @228  	module_driver(__platform_driver, platform_driver_register, \
907d0ed1c Lars-Peter Clausen 2011-11-16  229  			platform_driver_unregister)
940ab8896 Grant Likely       2011-10-05  230  
f309d4443 Paul Gortmaker     2015-05-01  231  /* builtin_platform_driver() - Helper macro for builtin drivers that
f309d4443 Paul Gortmaker     2015-05-01  232   * don't do anything special in driver init.  This eliminates some
f309d4443 Paul Gortmaker     2015-05-01  233   * boilerplate.  Each driver may only use this macro once, and
f309d4443 Paul Gortmaker     2015-05-01  234   * calling it replaces device_initcall().  Note this is meant to be
f309d4443 Paul Gortmaker     2015-05-01  235   * a parallel of module_platform_driver() above, but w/o _exit stuff.
f309d4443 Paul Gortmaker     2015-05-01  236   */

:::::: The code at line 228 was first introduced by commit
:::::: 907d0ed1c84114d4e8dafd66af982515d3739c90 drivercore: Generalize module_platform_driver

:::::: TO: Lars-Peter Clausen <lars@metafoo.de>
:::::: CC: Greg Kroah-Hartman <gregkh@suse.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 59383 bytes --]

^ permalink raw reply

* Re: [PATCH 2/9] mmc: mmci: add support for not-amba, but still compatible, variants
From: kbuild test robot @ 2016-11-08 17:41 UTC (permalink / raw)
  Cc: kbuild-all, ulf.hansson, mcoquelin.stm32, alexandre.torgue,
	linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-3-git-send-email-andrea.merello@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2652 bytes --]

Hi Andrea,

[auto build test ERROR on ulf.hansson-mmc/next]
[also build test ERROR on v4.9-rc4 next-20161108]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Andrea-Merello/mmc-mmci-add-support-for-STM32-SD-controller/20161108-234358
base:   https://git.linaro.org/people/ulf.hansson/mmc next
config: alpha-allyesconfig (attached as .config)
compiler: alpha-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=alpha 

All errors (new ones prefixed by >>):

   drivers/mmc/host/mmci.c: In function 'mmci_runtime_resume_pltfm':
>> drivers/mmc/host/mmci.c:2002:9: error: implicit declaration of function 'mmci_runtime_resume' [-Werror=implicit-function-declaration]
     return mmci_runtime_resume(mmc);
            ^~~~~~~~~~~~~~~~~~~
   drivers/mmc/host/mmci.c: In function 'mmci_runtime_suspend_pltfm':
>> drivers/mmc/host/mmci.c:2010:9: error: implicit declaration of function 'mmci_runtime_suspend' [-Werror=implicit-function-declaration]
     return mmci_runtime_suspend(mmc);
            ^~~~~~~~~~~~~~~~~~~~
   At top level:
   drivers/mmc/host/mmci.c:2005:12: warning: 'mmci_runtime_suspend_pltfm' defined but not used [-Wunused-function]
    static int mmci_runtime_suspend_pltfm(struct device *dev)
               ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mmc/host/mmci.c:1997:12: warning: 'mmci_runtime_resume_pltfm' defined but not used [-Wunused-function]
    static int mmci_runtime_resume_pltfm(struct device *dev)
               ^~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/mmci_runtime_resume +2002 drivers/mmc/host/mmci.c

  1996	
  1997	static int mmci_runtime_resume_pltfm(struct device *dev)
  1998	{
  1999		struct platform_device *pdev = to_platform_device(dev);
  2000		struct mmc_host *mmc = platform_get_drvdata(pdev);
  2001	
> 2002		return mmci_runtime_resume(mmc);
  2003	}
  2004	
  2005	static int mmci_runtime_suspend_pltfm(struct device *dev)
  2006	{
  2007		struct platform_device *pdev = to_platform_device(dev);
  2008		struct mmc_host *mmc = platform_get_drvdata(pdev);
  2009	
> 2010		return mmci_runtime_suspend(mmc);
  2011	}
  2012	
  2013	MODULE_DEVICE_TABLE(of, mmci_pltfm_match);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47827 bytes --]

^ permalink raw reply

* Re: [v15, 3/7] powerpc/fsl: move mpc85xx.h to include/linux/fsl
From: Arnd Bergmann @ 2016-11-08 15:47 UTC (permalink / raw)
  To: Y.B. Lu
  Cc: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org, Scott Wood,
	Mark Rutland, Greg Kroah-Hartman, X.B. Xie, M.H. Lian,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Qiang Zhao,
	Russell King, Bhupesh Sharma, Joerg Roedel, Claudiu Manoil,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring
In-Reply-To: <DB6PR0401MB25366BC8FF59C68E2823245EF8A60-2mNvjAGDOPkZcyyZo0JLBI3W/0Ik+aLCnBOFsp37pqbUKgpGm//BTAC/G2K4zDHf@public.gmane.org>

On Tuesday, November 8, 2016 6:49:51 AM CET Y.B. Lu wrote:
> Hi Arnd,
> 
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > Sent: Tuesday, November 08, 2016 5:20 AM
> > To: Y.B. Lu
> > Cc: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org; linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org; Scott Wood; Mark Rutland; Greg Kroah-Hartman; X.B.
> > Xie; M.H. Lian; linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > Qiang Zhao; Russell King; Bhupesh Sharma; Joerg Roedel; Claudiu Manoil;
> > devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Rob Herring; Santosh Shilimkar; linux-arm-
> > kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-
> > kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Leo Li; iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org; Kumar
> > Gala
> > Subject: Re: [v15, 3/7] powerpc/fsl: move mpc85xx.h to include/linux/fsl
> > 
> > On Monday, October 31, 2016 9:35:33 AM CET Y.B. Lu wrote:
> > > >
> > > > I don't see any of the contents of this header referenced by the soc
> > > > driver any more. I think you can just drop this patch.
> > > >
> > >
> > > [Lu Yangbo-B47093] This header file was included by guts.c.
> > > The guts driver used macro SVR_MAJ/SVR_MIN for calculation.
> > >
> > > This header file was for powerpc arch before. And this patch is to
> > > made it as common header file for both ARM and PPC.
> > > Sooner or later this is needed.
> > 
> > Let's discuss it once we actually need the header then, ok?
> 
> [Lu Yangbo-B47093] As I said, this header file was included by guts.c in patch 4.

Ah sorry, I misread your earlier reply, thinking you meant a potential
future patch.

> The guts driver used macro SVR_MAJ/SVR_MIN for calculation which were
> defined in this header file.
> Did you suggest we dropped this patch and just calculated them in driver?

That is probably nicer here: there is not that much value in sharing
the two one-line macro definitions, and the driver already hardcodes
the numeric per-chip IDs that make up most of the header file.

	Arnd
--
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

* [PATCH 9/9] Documentation: document mmci STM32 DT binding
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 Documentation/devicetree/bindings/mmc/mmci.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/mmci.txt b/Documentation/devicetree/bindings/mmc/mmci.txt
index 03796cf..d6b5127 100644
--- a/Documentation/devicetree/bindings/mmc/mmci.txt
+++ b/Documentation/devicetree/bindings/mmc/mmci.txt
@@ -8,7 +8,7 @@ by mmc.txt and the properties used by the mmci driver. Using "st" as
 the prefix for a property, indicates support by the ST Micro variant.
 
 Required properties:
-- compatible             : contains "arm,pl18x", "arm,primecell".
+- compatible             : contains "arm,pl18x", "arm,primecell" or "st,stm32f4xx-sdio"
 - vmmc-supply            : phandle to the regulator device tree node, mentioned
                            as the VCC/VDD supply in the eMMC/SD specs.
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH 8/9] DT: stm32f469-disco: add node for SDIO controller
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 arch/arm/boot/dts/stm32f429.dtsi      |  2 +-
 arch/arm/boot/dts/stm32f469-disco.dts | 30 ++++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index d6d0548..23e6a5e 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -185,7 +185,7 @@
 			interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
 		};
 
-		pin-controller {
+		pinctrl:pin-controller {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "st,stm32f429-pinctrl";
diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
index e911af8..e16dfc3 100644
--- a/arch/arm/boot/dts/stm32f469-disco.dts
+++ b/arch/arm/boot/dts/stm32f469-disco.dts
@@ -64,12 +64,42 @@
 	aliases {
 		serial0 = &usart3;
 	};
+
+	mmc_vcard: mmc_vcard {
+		compatible = "regulator-fixed";
+		regulator-name = "mmc_vcard";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+	};
 };
 
 &clk_hse {
 	clock-frequency = <8000000>;
 };
 
+&pinctrl {
+	sdio-cd {
+		sdio_cd: sdio-cd {
+			pins {
+				pinmux = <STM32F429_PG2_FUNC_GPIO>;
+				bias-pull-up;
+			};
+		};
+	};
+};
+
+&sdio {
+	status = "okay";
+	vmmc-supply = <&mmc_vcard>;
+	cd-gpios = <&gpiog 2 0>;
+	cd-inverted;
+	pinctrl-names = "default", "opendrain", "cd";
+	pinctrl-0 = <&sdio_pins>, <&sdio_cd>;
+	pinctrl-1 = <&sdio_pins_od>, <&sdio_cd>;
+	bus-width = <4>;
+};
+
 &usart3 {
 	status = "okay";
 };
-- 
2.7.4


^ permalink raw reply related

* [PATCH 7/9] DT: stm32f429: add node for SDIO controller
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 arch/arm/boot/dts/stm32f429.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 961bc0c..d6d0548 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -365,6 +365,18 @@
 			};
 		};
 
+		sdio: sdio@40012c00 {
+			compatible = "st,stm32f4xx-sdio";
+			reg = <0x40012c00 0x400>;
+			clocks = <&rcc 0 171>;
+			interrupts = <49>;
+			status = "disabled";
+			pinctrl-0 = <&sdio_pins>;
+			pinctrl-1 = <&sdio_pins_od>;
+			pinctrl-names = "default", "opendrain";
+			max-frequency = <48000000>;
+		};
+
 		rcc: rcc@40023810 {
 			#reset-cells = <1>;
 			#clock-cells = <2>;
-- 
2.7.4


^ permalink raw reply related

* [PATCH 6/9] DT: stm32f429: add pin map for SDIO controller
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 arch/arm/boot/dts/stm32f429.dtsi | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 336ee4f..961bc0c 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -313,6 +313,37 @@
 				};
 			};
 
+			sdio_pins:sdio_pins@0 {
+				pins {
+					pinmux = <STM32F429_PC8_FUNC_SDIO_D0>,
+						 <STM32F429_PC9_FUNC_SDIO_D1>,
+						 <STM32F429_PC10_FUNC_SDIO_D2>,
+						 <STM32F429_PC11_FUNC_SDIO_D3>,
+						 <STM32F429_PC12_FUNC_SDIO_CK>,
+						 <STM32F429_PD2_FUNC_SDIO_CMD>;
+					drive-push-pull;
+					slew-rate = <2>;
+				};
+			};
+
+			sdio_pins_od:sdio_pins_od@0 {
+				pins {
+					pinmux = <STM32F429_PC8_FUNC_SDIO_D0>,
+						 <STM32F429_PC9_FUNC_SDIO_D1>,
+						 <STM32F429_PC10_FUNC_SDIO_D2>,
+						 <STM32F429_PC11_FUNC_SDIO_D3>,
+						 <STM32F429_PC12_FUNC_SDIO_CK>;
+					drive-push-pull;
+					slew-rate = <2>;
+				};
+
+				pins_od {
+					pinmux = <STM32F429_PD2_FUNC_SDIO_CMD>;
+					drive-open-drain;
+					slew-rate = <2>;
+				};
+			};
+
 			ethernet0_mii: mii@0 {
 				pins {
 					pinmux = <STM32F429_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0>,
-- 
2.7.4


^ permalink raw reply related

* [PATCH 2/9] mmc: mmci: add support for not-amba, but still compatible, variants
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

The STM32F4xx family contain a SDIO IP that looks like a variant of
the PL180, however, inspite it's actually attached to a APB bus, it
cannot be handled by the AMBA bus code, because it lacks of the ID
registers that AMBA primecell IPs have.

This patch prepares for supporting the STM32 variant by letting the
driver register also as a platform driver, that can be matched from
the OF with specific "compatible" strings

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 drivers/mmc/host/Kconfig |   8 +-
 drivers/mmc/host/mmci.c  | 259 +++++++++++++++++++++++++++++++++++------------
 2 files changed, 199 insertions(+), 68 deletions(-)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5cf7eba..0f51de3 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -5,12 +5,12 @@
 comment "MMC/SD/SDIO Host Controller Drivers"
 
 config MMC_ARMMMCI
-	tristate "ARM AMBA Multimedia Card Interface support"
-	depends on ARM_AMBA
+	tristate "ARM AMBA Multimedia Card Interface and compatible support"
 	help
 	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
-	  Interface (PL180 and PL181) support.  If you have an ARM(R)
-	  platform with a Multimedia Card slot, say Y or M here.
+	  Interface (PL180, PL181 and compatible) support.
+	  If you have an ARM(R) platform with a Multimedia Card slot,
+	  say Y or M here.
 
 	  If unsure, say N.
 
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b826a3a..b1dfde3 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1,5 +1,6 @@
 /*
- *  linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver
+ *  linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 and
+ *  comaptible driver
  *
  *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
  *  Copyright (C) 2010 ST-Ericsson SA
@@ -37,6 +38,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/types.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -105,7 +108,7 @@ struct variant_data {
 	bool			reversed_irq_handling;
 };
 
-static struct variant_data variant_arm = {
+static __maybe_unused struct variant_data variant_arm = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
 	.datalength_bits	= 16,
@@ -114,7 +117,7 @@ static struct variant_data variant_arm = {
 	.reversed_irq_handling	= true,
 };
 
-static struct variant_data variant_arm_extended_fifo = {
+static __maybe_unused struct variant_data variant_arm_extended_fifo = {
 	.fifosize		= 128 * 4,
 	.fifohalfsize		= 64 * 4,
 	.datalength_bits	= 16,
@@ -122,7 +125,7 @@ static struct variant_data variant_arm_extended_fifo = {
 	.f_max			= 100000000,
 };
 
-static struct variant_data variant_arm_extended_fifo_hwfc = {
+static __maybe_unused struct variant_data variant_arm_extended_fifo_hwfc = {
 	.fifosize		= 128 * 4,
 	.fifohalfsize		= 64 * 4,
 	.clkreg_enable		= MCI_ARM_HWFCEN,
@@ -131,7 +134,7 @@ static struct variant_data variant_arm_extended_fifo_hwfc = {
 	.f_max			= 100000000,
 };
 
-static struct variant_data variant_u300 = {
+static __maybe_unused struct variant_data variant_u300 = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
 	.clkreg_enable		= MCI_ST_U300_HWFCEN,
@@ -146,7 +149,7 @@ static struct variant_data variant_u300 = {
 	.pwrreg_nopower		= true,
 };
 
-static struct variant_data variant_nomadik = {
+static __maybe_unused struct variant_data variant_nomadik = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
@@ -162,7 +165,7 @@ static struct variant_data variant_nomadik = {
 	.pwrreg_nopower		= true,
 };
 
-static struct variant_data variant_ux500 = {
+static __maybe_unused struct variant_data variant_ux500 = {
 	.fifosize		= 30 * 4,
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
@@ -181,7 +184,7 @@ static struct variant_data variant_ux500 = {
 	.pwrreg_nopower		= true,
 };
 
-static struct variant_data variant_ux500v2 = {
+static __maybe_unused struct variant_data variant_ux500v2 = {
 	.fifosize		= 30 * 4,
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
@@ -202,7 +205,7 @@ static struct variant_data variant_ux500v2 = {
 	.pwrreg_nopower		= true,
 };
 
-static struct variant_data variant_qcom = {
+static __maybe_unused struct variant_data variant_qcom = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
@@ -1483,31 +1486,32 @@ static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
 	return 0;
 }
 
-static int mmci_probe(struct amba_device *dev,
-	const struct amba_id *id)
+static struct mmci_host *mmci_probe(struct device *dev,
+				    struct variant_data *variant,
+				    struct resource *res,
+				    unsigned int irq0, unsigned int irq1)
 {
-	struct mmci_platform_data *plat = dev->dev.platform_data;
-	struct device_node *np = dev->dev.of_node;
-	struct variant_data *variant = id->data;
-	struct mmci_host *host;
+	struct device_node *np = dev->of_node;
+	struct mmci_platform_data *plat = dev->platform_data;
 	struct mmc_host *mmc;
+	struct mmci_host *host;
 	int ret;
 
 	/* Must have platform data or Device Tree. */
 	if (!plat && !np) {
-		dev_err(&dev->dev, "No plat data or DT found\n");
-		return -EINVAL;
+		dev_err(dev, "No plat data or DT found\n");
+		return ERR_PTR(-EINVAL);
 	}
 
 	if (!plat) {
-		plat = devm_kzalloc(&dev->dev, sizeof(*plat), GFP_KERNEL);
+		plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
 		if (!plat)
-			return -ENOMEM;
+			return ERR_PTR(-ENOMEM);
 	}
 
-	mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
+	mmc = mmc_alloc_host(sizeof(struct mmci_host), dev);
 	if (!mmc)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	ret = mmci_of_parse(np, mmc);
 	if (ret)
@@ -1516,12 +1520,7 @@ static int mmci_probe(struct amba_device *dev,
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 
-	host->hw_designer = amba_manf(dev);
-	host->hw_revision = amba_rev(dev);
-	dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
-	dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision);
-
-	host->clk = devm_clk_get(&dev->dev, NULL);
+	host->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
 		goto host_free;
@@ -1553,8 +1552,8 @@ static int mmci_probe(struct amba_device *dev,
 			host->mclk);
 	}
 
-	host->phybase = dev->res.start;
-	host->base = devm_ioremap_resource(&dev->dev, &dev->res);
+	host->phybase = res->start;
+	host->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(host->base)) {
 		ret = PTR_ERR(host->base);
 		goto clk_disable;
@@ -1688,49 +1687,41 @@ static int mmci_probe(struct amba_device *dev,
 		}
 	}
 
-	ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED,
-			DRIVER_NAME " (cmd)", host);
+	ret = devm_request_irq(dev, irq0, mmci_irq, IRQF_SHARED,
+			       DRIVER_NAME " (cmd)", host);
 	if (ret)
 		goto clk_disable;
 
-	if (!dev->irq[1])
+	if (!irq1) {
 		host->singleirq = true;
-	else {
-		ret = devm_request_irq(&dev->dev, dev->irq[1], mmci_pio_irq,
-				IRQF_SHARED, DRIVER_NAME " (pio)", host);
+	} else {
+		ret = devm_request_irq(dev, irq1, mmci_pio_irq,
+				       IRQF_SHARED, DRIVER_NAME " (pio)", host);
 		if (ret)
 			goto clk_disable;
 	}
 
 	writel(MCI_IRQENABLE, host->base + MMCIMASK0);
 
-	amba_set_drvdata(dev, mmc);
-
-	dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n",
-		 mmc_hostname(mmc), amba_part(dev), amba_manf(dev),
-		 amba_rev(dev), (unsigned long long)dev->res.start,
-		 dev->irq[0], dev->irq[1]);
-
 	mmci_dma_setup(host);
 
-	pm_runtime_set_autosuspend_delay(&dev->dev, 50);
-	pm_runtime_use_autosuspend(&dev->dev);
+	pm_runtime_set_autosuspend_delay(dev, 50);
+	pm_runtime_use_autosuspend(dev);
 
 	mmc_add_host(mmc);
 
-	pm_runtime_put(&dev->dev);
-	return 0;
+	pm_runtime_put(dev);
+	return host;
 
  clk_disable:
 	clk_disable_unprepare(host->clk);
  host_free:
 	mmc_free_host(mmc);
-	return ret;
+	return ERR_PTR(ret);
 }
 
-static int mmci_remove(struct amba_device *dev)
+static int mmc_remove(struct mmc_host *mmc)
 {
-	struct mmc_host *mmc = amba_get_drvdata(dev);
 
 	if (mmc) {
 		struct mmci_host *host = mmc_priv(mmc);
@@ -1739,7 +1730,7 @@ static int mmci_remove(struct amba_device *dev)
 		 * Undo pm_runtime_put() in probe.  We use the _sync
 		 * version here so that we can access the primecell.
 		 */
-		pm_runtime_get_sync(&dev->dev);
+		pm_runtime_get_sync(mmc->parent);
 
 		mmc_remove_host(mmc);
 
@@ -1793,14 +1784,11 @@ static void mmci_restore(struct mmci_host *host)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int mmci_runtime_suspend(struct device *dev)
+static int mmci_runtime_suspend(struct mmc_host *mmc)
 {
-	struct amba_device *adev = to_amba_device(dev);
-	struct mmc_host *mmc = amba_get_drvdata(adev);
-
 	if (mmc) {
 		struct mmci_host *host = mmc_priv(mmc);
-		pinctrl_pm_select_sleep_state(dev);
+		pinctrl_pm_select_sleep_state(mmc->parent);
 		mmci_save(host);
 		clk_disable_unprepare(host->clk);
 	}
@@ -1808,28 +1796,77 @@ static int mmci_runtime_suspend(struct device *dev)
 	return 0;
 }
 
-static int mmci_runtime_resume(struct device *dev)
+static int mmci_runtime_resume(struct mmc_host *mmc)
 {
-	struct amba_device *adev = to_amba_device(dev);
-	struct mmc_host *mmc = amba_get_drvdata(adev);
 
 	if (mmc) {
 		struct mmci_host *host = mmc_priv(mmc);
 		clk_prepare_enable(host->clk);
 		mmci_restore(host);
-		pinctrl_pm_select_default_state(dev);
+		pinctrl_pm_select_default_state(mmc->parent);
 	}
 
 	return 0;
 }
 #endif
 
-static const struct dev_pm_ops mmci_dev_pm_ops = {
+#ifdef CONFIG_ARM_AMBA
+static int mmci_remove_amba(struct amba_device *dev)
+{
+	struct mmc_host *mmc = amba_get_drvdata(dev);
+
+	return mmc_remove(mmc);
+}
+
+static int mmci_runtime_resume_amba(struct device *dev)
+{
+	struct amba_device *adev = to_amba_device(dev);
+	struct mmc_host *mmc = amba_get_drvdata(adev);
+
+	return mmci_runtime_resume(mmc);
+}
+
+static int mmci_runtime_suspend_amba(struct device *dev)
+{
+	struct amba_device *adev = to_amba_device(dev);
+	struct mmc_host *mmc = amba_get_drvdata(adev);
+
+	return mmci_runtime_suspend(mmc);
+}
+
+static const struct dev_pm_ops mmci_dev_pm_ops_amba = {
 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
 				pm_runtime_force_resume)
-	SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
+	SET_RUNTIME_PM_OPS(mmci_runtime_suspend_amba, mmci_runtime_resume_amba,
+			   NULL)
 };
 
+static int mmci_probe_amba(struct amba_device *dev, const struct amba_id *id)
+{
+	struct mmci_host *host;
+	struct variant_data *variant = id->data;
+
+	host = mmci_probe(&pdev->dev, variant, &dev->res,
+			  dev->irq[0], dev->irq[1]);
+	if (IS_ERR(ret))
+		return PTR_ERR(host);
+
+	host->hw_designer = amba_manf(dev);
+	host->hw_revision = amba_rev(dev);
+	dev_dbg(mmc_dev(host->mmc), "designer ID = 0x%02x\n",
+		host->hw_designer);
+	dev_dbg(mmc_dev(host->mmc), "revision = 0x%01x\n", host->hw_revision);
+
+	amba_set_drvdata(dev, host->mmc);
+
+	dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n",
+		 mmc_hostname(host->mmc), amba_part(dev), amba_manf(dev),
+		 amba_rev(dev), (unsigned long long)dev->res.start,
+		 dev->irq[0], dev->irq[1]);
+
+	return 0;
+}
+
 static struct amba_id mmci_ids[] = {
 	{
 		.id	= 0x00041180,
@@ -1891,14 +1928,108 @@ MODULE_DEVICE_TABLE(amba, mmci_ids);
 static struct amba_driver mmci_driver = {
 	.drv		= {
 		.name	= DRIVER_NAME,
-		.pm	= &mmci_dev_pm_ops,
+		.pm	= &mmci_dev_pm_ops_amba,
 	},
-	.probe		= mmci_probe,
-	.remove		= mmci_remove,
+	.probe		= mmci_probe_amba,
+	.remove		= mmci_remove_amba,
 	.id_table	= mmci_ids,
 };
 
 module_amba_driver(mmci_driver);
+#endif
+
+static const struct of_device_id mmci_pltfm_match[] = {
+	{},
+};
+
+static int mmci_probe_pltfm(struct platform_device *pdev)
+{
+	struct mmci_host *host;
+	struct variant_data *variant;
+	const struct of_device_id *match;
+	int irq0, irq1;
+	struct resource *res;
+
+	irq0 = platform_get_irq(pdev, 0);
+	if (irq0 < 0) {
+		dev_err(&pdev->dev, "Can't get IRQ");
+		return -EINVAL;
+	}
+
+	irq1 = platform_get_irq(pdev, 1);
+	/* optional. set to 0 to be compatible with original amba probe code */
+	if (irq1 < 0)
+		irq1 = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Can't get MMIO range");
+		return -EINVAL;
+	}
+
+	match = of_match_device(mmci_pltfm_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Can't get variant data\n");
+		return -EINVAL;
+	}
+	variant = (struct variant_data *)match->data;
+
+	host = mmci_probe(&pdev->dev, variant, res,
+			  irq0, irq1);
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	platform_set_drvdata(pdev, host->mmc);
+	dev_info(&pdev->dev, "%s: PL81x compatible SDIO at 0x%08llx irq %d,%d (pio)\n",
+		 mmc_hostname(host->mmc),
+		 (unsigned long long)res->start, irq0, irq1);
+
+	return 0;
+}
+
+static int mmci_remove_pltfm(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+	return mmc_remove(mmc);
+}
+
+static int mmci_runtime_resume_pltfm(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+	return mmci_runtime_resume(mmc);
+}
+
+static int mmci_runtime_suspend_pltfm(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+	return mmci_runtime_suspend(mmc);
+}
+
+MODULE_DEVICE_TABLE(of, mmci_pltfm_match);
+
+static const struct dev_pm_ops mmci_dev_pm_ops_pltfm = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(mmci_runtime_suspend_pltfm,
+			   mmci_runtime_resume_pltfm, NULL)
+};
+
+static struct platform_driver mmci_pltfm_driver = {
+	.probe		= mmci_probe_pltfm,
+	.remove		= mmci_remove_pltfm,
+	.driver		= {
+		.name		= DRIVER_NAME,
+		.of_match_table	= mmci_pltfm_match,
+		.pm		= &mmci_dev_pm_ops_pltfm,
+	},
+};
+
+module_platform_driver(mmci_pltfm_driver);
 
 module_param(fmax, uint, 0444);
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH 5/9] mmc: mmci: add STM32 variant
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

STM32 mcu has a SDIO controller that looks like an ARM pl810.
This patch adds the STM32 variant so that mmci driver supports it.

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 drivers/mmc/host/mmci.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 170c78a..3e67cdd 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -221,6 +221,23 @@ static __maybe_unused struct variant_data variant_ux500v2 = {
 	.has_pad_config		= true,
 };
 
+static __maybe_unused struct variant_data variant_stm32 = {
+	.fifosize		= 32 * 4,
+	.fifohalfsize		= 8 * 4,
+	.clkreg			= MCI_CLK_ENABLE,
+	.clkreg_enable		= MCI_ST_UX500_HWFCEN,
+	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
+	.clkreg_neg_edge_enable	= MCI_ST_UX500_NEG_EDGE,
+	.datalength_bits	= 24,
+	.datactrl_mask_sdio	= MCI_ST_DPSM_SDIOEN,
+	.st_sdio		= true,
+	.st_clkdiv		= true,
+	.pwrreg_powerup		= MCI_PWR_ON,
+	.f_max			= 48000000,
+	.pwrreg_clkgate		= true,
+	.pwrreg_nopower		= true,
+};
+
 static __maybe_unused struct variant_data variant_qcom = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
@@ -1981,6 +1998,7 @@ module_amba_driver(mmci_driver);
 #endif
 
 static const struct of_device_id mmci_pltfm_match[] = {
+	{ .compatible = "st,stm32f4xx-sdio", .data = &variant_stm32},
 	{},
 };
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH 4/9] mmc: mmci: add support for setting pad type via pinctrl
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

The STM32 variant  hasn't the control bit to switch pads in opendrain mode.
In this case we can achive the same result by askint to the pinmux driver
to configure pins for us.

This patch make the mmci driver able to do this whenever needed.

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 drivers/mmc/host/mmci.c | 52 +++++++++++++++++++++++++++++++++++++++----------
 drivers/mmc/host/mmci.h |  7 +++++--
 2 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 0c629e3..170c78a 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -107,6 +107,7 @@ struct variant_data {
 	bool			qcom_dml;
 	bool			reversed_irq_handling;
 	bool			has_start_err;
+	bool			has_pad_config;
 };
 
 static __maybe_unused struct variant_data variant_arm = {
@@ -117,6 +118,7 @@ static __maybe_unused struct variant_data variant_arm = {
 	.f_max			= 100000000,
 	.reversed_irq_handling	= true,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_arm_extended_fifo = {
@@ -126,6 +128,7 @@ static __maybe_unused struct variant_data variant_arm_extended_fifo = {
 	.pwrreg_powerup		= MCI_PWR_UP,
 	.f_max			= 100000000,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_arm_extended_fifo_hwfc = {
@@ -136,6 +139,7 @@ static __maybe_unused struct variant_data variant_arm_extended_fifo_hwfc = {
 	.pwrreg_powerup		= MCI_PWR_UP,
 	.f_max			= 100000000,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_u300 = {
@@ -152,6 +156,7 @@ static __maybe_unused struct variant_data variant_u300 = {
 	.pwrreg_clkgate		= true,
 	.pwrreg_nopower		= true,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_nomadik = {
@@ -169,6 +174,7 @@ static __maybe_unused struct variant_data variant_nomadik = {
 	.pwrreg_clkgate		= true,
 	.pwrreg_nopower		= true,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_ux500 = {
@@ -189,6 +195,7 @@ static __maybe_unused struct variant_data variant_ux500 = {
 	.busy_detect		= true,
 	.pwrreg_nopower		= true,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_ux500v2 = {
@@ -211,6 +218,7 @@ static __maybe_unused struct variant_data variant_ux500v2 = {
 	.busy_detect		= true,
 	.pwrreg_nopower		= true,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static __maybe_unused struct variant_data variant_qcom = {
@@ -230,6 +238,7 @@ static __maybe_unused struct variant_data variant_qcom = {
 	.qcom_fifo		= true,
 	.qcom_dml		= true,
 	.has_start_err		= true,
+	.has_pad_config		= true,
 };
 
 static int mmci_card_busy(struct mmc_host *mmc)
@@ -1317,6 +1326,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	u32 pwr = 0;
 	unsigned long flags;
 	int ret;
+	struct pinctrl_state *pins;
+	bool is_opendrain;
 
 	if (host->plat->ios_handler &&
 		host->plat->ios_handler(mmc_dev(mmc), ios))
@@ -1375,16 +1386,31 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 				~MCI_ST_DATA2DIREN);
 	}
 
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
-		if (host->hw_designer != AMBA_VENDOR_ST)
-			pwr |= MCI_ROD;
-		else {
-			/*
-			 * The ST Micro variant use the ROD bit for something
-			 * else and only has OD (Open Drain).
-			 */
-			pwr |= MCI_OD;
+	if (host->variant->has_pad_config) {
+		if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+			if (host->hw_designer != AMBA_VENDOR_ST) {
+				pwr |= MCI_ROD;
+			} else {
+				/*
+				 * The ST Micro variant use the ROD bit for
+				 * something else and only has OD (Open Drain).
+				 */
+				pwr |= MCI_OD;
+			}
 		}
+	} else {
+		/*
+		 * If the variant cannot configure the pads by its own, then we
+		 * expect the pinctrl to be able to do that for us
+		 */
+		is_opendrain = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN);
+		pins = pinctrl_lookup_state(host->pinctrl, is_opendrain ?
+					MMCI_PINCTRL_STATE_OPENDRAIN :
+					MMCI_PINCTRL_STATE_PUSHPULL);
+		if (IS_ERR(pins))
+			dev_warn(mmc_dev(mmc), "Cannot select pin drive type via pinctrl\n");
+		else
+			pinctrl_select_state(host->pinctrl, pins);
 	}
 
 	/*
@@ -1492,7 +1518,6 @@ static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
 		mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
 	if (of_get_property(np, "mmc-cap-sd-highspeed", NULL))
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
-
 	return 0;
 }
 
@@ -1530,6 +1555,13 @@ static struct mmci_host *mmci_probe(struct device *dev,
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 
+	if (!variant->has_pad_config) {
+		host->pinctrl = devm_pinctrl_get(dev);
+		if (IS_ERR(host->pinctrl)) {
+			dev_err(dev, "failed to get pinctrl");
+			goto host_free;
+		}
+	}
 	host->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a1f5e4f..d06c048 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -185,6 +185,10 @@
 
 #define NR_SG		128
 
+/* pinctrl configs */
+#define MMCI_PINCTRL_STATE_PUSHPULL "default"
+#define MMCI_PINCTRL_STATE_OPENDRAIN "opendrain"
+
 struct clk;
 struct variant_data;
 struct dma_chan;
@@ -219,7 +223,7 @@ struct mmci_host {
 	bool			vqmmc_enabled;
 	struct mmci_platform_data *plat;
 	struct variant_data	*variant;
-
+	struct pinctrl		*pinctrl;
 	u8			hw_designer;
 	u8			hw_revision:4;
 
@@ -244,4 +248,3 @@ struct mmci_host {
 #define dma_inprogress(host)	(0)
 #endif
 };
-
-- 
2.7.4


^ permalink raw reply related

* [PATCH 3/9] mmc: mmci: don't pretend all variants to have MCI_STARBITERR flag
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

This patch prepares for supporting the STM32 variant, that has no such bit
in the status register.

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 drivers/mmc/host/mmci.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b1dfde3..0c629e3 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -106,6 +106,7 @@ struct variant_data {
 	bool			qcom_fifo;
 	bool			qcom_dml;
 	bool			reversed_irq_handling;
+	bool			has_start_err;
 };
 
 static __maybe_unused struct variant_data variant_arm = {
@@ -115,6 +116,7 @@ static __maybe_unused struct variant_data variant_arm = {
 	.pwrreg_powerup		= MCI_PWR_UP,
 	.f_max			= 100000000,
 	.reversed_irq_handling	= true,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_arm_extended_fifo = {
@@ -123,6 +125,7 @@ static __maybe_unused struct variant_data variant_arm_extended_fifo = {
 	.datalength_bits	= 16,
 	.pwrreg_powerup		= MCI_PWR_UP,
 	.f_max			= 100000000,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_arm_extended_fifo_hwfc = {
@@ -132,6 +135,7 @@ static __maybe_unused struct variant_data variant_arm_extended_fifo_hwfc = {
 	.datalength_bits	= 16,
 	.pwrreg_powerup		= MCI_PWR_UP,
 	.f_max			= 100000000,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_u300 = {
@@ -147,6 +151,7 @@ static __maybe_unused struct variant_data variant_u300 = {
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.pwrreg_nopower		= true,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_nomadik = {
@@ -163,6 +168,7 @@ static __maybe_unused struct variant_data variant_nomadik = {
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.pwrreg_nopower		= true,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_ux500 = {
@@ -182,6 +188,7 @@ static __maybe_unused struct variant_data variant_ux500 = {
 	.pwrreg_clkgate		= true,
 	.busy_detect		= true,
 	.pwrreg_nopower		= true,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_ux500v2 = {
@@ -203,6 +210,7 @@ static __maybe_unused struct variant_data variant_ux500v2 = {
 	.pwrreg_clkgate		= true,
 	.busy_detect		= true,
 	.pwrreg_nopower		= true,
+	.has_start_err		= true,
 };
 
 static __maybe_unused struct variant_data variant_qcom = {
@@ -221,6 +229,7 @@ static __maybe_unused struct variant_data variant_qcom = {
 	.explicit_mclk_control	= true,
 	.qcom_fifo		= true,
 	.qcom_dml		= true,
+	.has_start_err		= true,
 };
 
 static int mmci_card_busy(struct mmc_host *mmc)
@@ -909,8 +918,9 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
 		return;
 
 	/* First check for errors */
-	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
-		      MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+	if (status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT |
+			(host->variant->has_start_err ? MCI_STARTBITERR : 0) |
+			MCI_TXUNDERRUN | MCI_RXOVERRUN)) {
 		u32 remain, success;
 
 		/* Terminate the DMA transfer */
-- 
2.7.4


^ permalink raw reply related

* [PATCH 1/9] mmc: mmci: don't pretend IP variants with only one IRQ to have two mask regs
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello
In-Reply-To: <1478612625-23256-1-git-send-email-andrea.merello@gmail.com>

Currently the driver supports both devices with one and two IRQ lines.

Two mask registers are used in order to select which events have to
actually generate an interrupt on each IRQ line.

It seems that in the single-IRQ case it's assumed that the IRQs lines
are simply OR-ed, while the two mask registers are still present. The
driver still programs the two mask registers separately.

However the STM32 variant has only one IRQ, and also has only one mask
register.

This patch prepares for STM32 variant support by making the driver using
only one mask register when only one IRQ is available.

Tested only on STM32 variant. RFT for variants other than STM32

Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
 drivers/mmc/host/mmci.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index df990bb..b826a3a 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -389,9 +389,9 @@ static void mmci_set_mask1(struct mmci_host *host, unsigned int mask)
 		mask0 |= mask;
 
 		writel(mask0, base + MMCIMASK0);
+	} else {
+		writel(mask, base + MMCIMASK1);
 	}
-
-	writel(mask, base + MMCIMASK1);
 }
 
 static void mmci_stop_data(struct mmci_host *host)
@@ -1231,12 +1231,10 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
 
 	do {
 		status = readl(host->base + MMCISTATUS);
+		status &= readl(host->base + MMCIMASK0);
 
 		if (host->singleirq) {
-			if (status & readl(host->base + MMCIMASK1))
-				mmci_pio_irq(irq, dev_id);
-
-			status &= ~MCI_IRQ1MASK;
+			mmci_pio_irq(irq, dev_id);
 		}
 
 		/*
@@ -1244,7 +1242,6 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
 		 * enabled) since the HW seems to be triggering the IRQ on both
 		 * edges while monitoring DAT0 for busy completion.
 		 */
-		status &= readl(host->base + MMCIMASK0);
 		writel(status, host->base + MMCICLEAR);
 
 		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
@@ -1656,7 +1653,8 @@ static int mmci_probe(struct amba_device *dev,
 	spin_lock_init(&host->lock);
 
 	writel(0, host->base + MMCIMASK0);
-	writel(0, host->base + MMCIMASK1);
+	if (!host->singleirq)
+		writel(0, host->base + MMCIMASK1);
 	writel(0xfff, host->base + MMCICLEAR);
 
 	/*
@@ -1746,7 +1744,8 @@ static int mmci_remove(struct amba_device *dev)
 		mmc_remove_host(mmc);
 
 		writel(0, host->base + MMCIMASK0);
-		writel(0, host->base + MMCIMASK1);
+		if (!host->singleirq)
+			writel(0, host->base + MMCIMASK1);
 
 		writel(0, host->base + MMCICOMMAND);
 		writel(0, host->base + MMCIDATACTRL);
-- 
2.7.4


^ permalink raw reply related

* [PATCH 0/9] mmc: mmci: add support for STM32 SD controller
From: Andrea Merello @ 2016-11-08 13:43 UTC (permalink / raw)
  To: ulf.hansson, mcoquelin.stm32, alexandre.torgue; +Cc: linux-mmc, Andrea Merello

The SD controller found in STM32 MCUs happens to be yet another variant
of the ARM PrimeCell PL18x SD host controller, for which the mmci driver
exists.

This series adds support for it to the mmci driver.

As other varians, this one need some specific quirks, that this series
address. Most notably this variant has not AMBA PrimeCell id registers,
so we can't probe it using the AMBA PrimeCell generic "compatible" and
mechanism; rather this series adds support to the mmci driver for
register itself also as platform driver, so that specific "copatible"
strings can also be used.

I tested this on my STM32F469-disco board, that is able to boot from an
SD card, and write/read to/from it.

RFT for other variants (to check I didn't broke anything) and with MMC
cards. In particular I tried to implement also support for open-collector
communication mode, that AFAICT is used only on MMC cards, but I couldn't
test it.

Andrea Merello (9):
  mmc: mmci: don't pretend IP variants with only one IRQ to have two
    mask regs
  mmc: mmci: add support for not-amba, but still compatible, variants
  mmc: mmci: don't pretend all variants to have MCI_STARBITERR flag
  mmc: mmci: add support for setting pad type via pinctrl
  mmc: mmci: add STM32 variant
  DT: stm32f429: add pin map for SDIO controller
  DT: stm32f429: add node for SDIO controller
  DT: stm32f469-disco: add node for SDIO controller
  Documentation: document mmci STM32 DT binding

 Documentation/devicetree/bindings/mmc/mmci.txt |   2 +-
 arch/arm/boot/dts/stm32f429.dtsi               |  45 +++-
 arch/arm/boot/dts/stm32f469-disco.dts          |  30 +++
 drivers/mmc/host/Kconfig                       |   8 +-
 drivers/mmc/host/mmci.c                        | 360 +++++++++++++++++++------
 drivers/mmc/host/mmci.h                        |   7 +-
 6 files changed, 359 insertions(+), 93 deletions(-)

--
2.7.4

^ permalink raw reply

* Re: [PATCH v6 14/14] sdhci: sdhci-msm: update dll configuration
From: Adrian Hunter @ 2016-11-08 12:57 UTC (permalink / raw)
  To: Ritesh Harjani, ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	shawn.lin-TNX95d0MmH7DzftRWevZcw, sboyd-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	david.brown-QSEj5FYQhm4dnm+yROfE0A,
	andy.gross-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	georgi.djakov-QSEj5FYQhm4dnm+yROfE0A,
	alex.lemberg-XdAiOPVOjttBDgjK7y7TUQ,
	mateusz.nowak-ral2JQCrhuEAvxtiuMwx3w,
	Yuliy.Izrailov-XdAiOPVOjttBDgjK7y7TUQ,
	asutoshd-sgV2jX0FEOL9JmXXK+q4OQ, kdorfman-sgV2jX0FEOL9JmXXK+q4OQ,
	david.griego-QSEj5FYQhm4dnm+yROfE0A,
	stummala-sgV2jX0FEOL9JmXXK+q4OQ, venkatg-sgV2jX0FEOL9JmXXK+q4OQ,
	rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
	pramod.gurav-QSEj5FYQhm4dnm+yROfE0A, Krishna Konda
In-Reply-To: <1478517877-23733-15-git-send-email-riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

On 07/11/16 13:24, Ritesh Harjani wrote:
> The newer msm sdhci's cores use a different DLL hardware for HS400.
> Update the configuration and calibration of the newer DLL block.
> 
> The HS400 DLL block used previously is CDC LP 533 and requires
> programming multiple registers and waiting for configuration to
> complete and then enable it. It has about 18 register writes and
> two register reads.
> 
> The newer HS400 DLL block is SDC4 DLL and requires two register
> writes for configuration and one register read to confirm that it
> is initialized. There is an additional register write to enable
> the power save mode for SDC4 DLL block.
> 
> Signed-off-by: Ritesh Harjani <riteshh-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Signed-off-by: Krishna Konda <kkonda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Acked-by: Adrian Hunter <adrian.hunter-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

> ---
>  drivers/mmc/host/sdhci-msm.c | 132 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 130 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index ae19d1a..84812e6 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -51,6 +51,7 @@
>  #define INT_MASK		0xf
>  #define MAX_PHASES		16
>  #define CORE_DLL_LOCK		BIT(7)
> +#define CORE_DDR_DLL_LOCK	BIT(11)
>  #define CORE_DLL_EN		BIT(16)
>  #define CORE_CDR_EN		BIT(17)
>  #define CORE_CK_OUT_EN		BIT(18)
> @@ -62,6 +63,7 @@
>  #define CORE_DLL_STATUS		0x108
>  
>  #define CORE_DLL_CONFIG_2	0x1b4
> +#define CORE_DDR_CAL_EN		BIT(0)
>  #define CORE_FLL_CYCLE_CNT	BIT(18)
>  #define CORE_DLL_CLOCK_DISABLE	BIT(21)
>  
> @@ -100,6 +102,11 @@
>  #define CORE_DDR_200_CFG		0x184
>  #define CORE_CDC_T4_DLY_SEL		BIT(0)
>  #define CORE_START_CDC_TRAFFIC		BIT(6)
> +#define CORE_VENDOR_SPEC3	0x1b0
> +#define CORE_PWRSAVE_DLL	BIT(3)
> +
> +#define CORE_DDR_CONFIG		0x1b8
> +#define DDR_CONFIG_POR_VAL	0x80040853
>  
>  #define CORE_VENDOR_SPEC_CAPABILITIES0	0x11c
>  
> @@ -126,6 +133,7 @@ struct sdhci_msm_host {
>  	bool tuning_done;
>  	bool calibration_done;
>  	u8 saved_tuning_phase;
> +	bool use_cdclp533;
>  };
>  
>  /* Platform specific tuning */
> @@ -583,6 +591,93 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
>  	return ret;
>  }
>  
> +static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
> +{
> +	u32 dll_status, config;
> +	int ret;
> +
> +	pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
> +
> +	/*
> +	 * Currently the CORE_DDR_CONFIG register defaults to desired
> +	 * configuration on reset. Currently reprogramming the power on
> +	 * reset (POR) value in case it might have been modified by
> +	 * bootloaders. In the future, if this changes, then the desired
> +	 * values will need to be programmed appropriately.
> +	 */
> +	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG);
> +
> +	/* Write 1 to DDR_CAL_EN field in CORE_DLL_CONFIG_2 */
> +	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
> +	config |= CORE_DDR_CAL_EN;
> +	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
> +
> +	/* Poll on DDR_DLL_LOCK bit in CORE_DLL_STATUS to be set */
> +	ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_DLL_STATUS,
> +					 dll_status,
> +					 (dll_status & CORE_DDR_DLL_LOCK),
> +					 10, 1000);
> +
> +	if (ret == -ETIMEDOUT) {
> +		pr_err("%s: %s: CM_DLL_SDC4 calibration was not completed\n",
> +		       mmc_hostname(host->mmc), __func__);
> +		goto out;
> +	}
> +
> +	/* set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3 */
> +	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3);
> +	config |= CORE_PWRSAVE_DLL;
> +	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC3);
> +
> +	/*
> +	 * Drain writebuffer to ensure above DLL calibration
> +	 * and PWRSAVE DLL is enabled.
> +	 */
> +	wmb();
> +out:
> +	pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
> +		 __func__, ret);
> +	return ret;
> +}
> +
> +static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
> +	int ret;
> +	u32 config;
> +
> +	pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
> +
> +	/*
> +	 * Retuning in HS400 (DDR mode) will fail, just reset the
> +	 * tuning block and restore the saved tuning phase.
> +	 */
> +	ret = msm_init_cm_dll(host);
> +	if (ret)
> +		goto out;
> +
> +	/* Set the selected phase in delay line hw block */
> +	ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
> +	if (ret)
> +		goto out;
> +
> +	/* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */
> +	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
> +	config |= CORE_CMD_DAT_TRACK_SEL;
> +	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
> +	if (msm_host->use_cdclp533)
> +		/* Calibrate CDCLP533 DLL HW */
> +		ret = sdhci_msm_cdclp533_calibration(host);
> +	else
> +		/* Calibrate CM_DLL_SDC4 HW */
> +		ret = sdhci_msm_cm_dll_sdc4_calibration(host);
> +out:
> +	pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
> +		 __func__, ret);
> +	return ret;
> +}
> +
>  static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
>  {
>  	int tuning_seq_cnt = 3;
> @@ -731,7 +826,7 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
>  	if (host->clock > CORE_FREQ_100MHZ &&
>  	    msm_host->tuning_done && !msm_host->calibration_done &&
>  	    (mmc->ios.timing == MMC_TIMING_MMC_HS400))
> -		if (!sdhci_msm_cdclp533_calibration(host))
> +		if (!sdhci_msm_hs400_dll_calibration(host))
>  			msm_host->calibration_done = true;
>  	spin_lock_irq(&host->lock);
>  }
> @@ -842,7 +937,7 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
>  	struct mmc_ios curr_ios = host->mmc->ios;
> -	u32 config;
> +	u32 config, dll_lock;
>  	int rc;
>  
>  	if (!clock) {
> @@ -899,7 +994,33 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
>  			config |= CORE_HC_SELECT_IN_EN;
>  			writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
>  		}
> +		if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
> +			/*
> +			 * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
> +			 * CORE_DLL_STATUS to be set.  This should get set
> +			 * within 15 us at 200 MHz.
> +			 */
> +			rc = readl_relaxed_poll_timeout(host->ioaddr +
> +							CORE_DLL_STATUS,
> +							dll_lock,
> +							(dll_lock &
> +							(CORE_DLL_LOCK |
> +							CORE_DDR_DLL_LOCK)), 10,
> +							1000);
> +			if (rc == -ETIMEDOUT)
> +				pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
> +				       mmc_hostname(host->mmc), dll_lock);
> +		}
>  	} else {
> +		if (!msm_host->use_cdclp533) {
> +			/* set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3 */
> +			config = readl_relaxed(host->ioaddr +
> +					CORE_VENDOR_SPEC3);
> +			config &= ~CORE_PWRSAVE_DLL;
> +			writel_relaxed(config, host->ioaddr +
> +					CORE_VENDOR_SPEC3);
> +		}
> +
>  		/* Select the default clock (free running MCLK) */
>  		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
>  		config &= ~CORE_HC_MCLK_SEL_MASK;
> @@ -1086,6 +1207,13 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>  		msm_host->use_14lpp_dll_reset = true;
>  
>  	/*
> +	 * SDCC 5 controller with major version 1, minor version 0x34 and later
> +	 * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL.
> +	 */
> +	if ((core_major == 1) && (core_minor < 0x34))
> +		msm_host->use_cdclp533 = true;
> +
> +	/*
>  	 * Support for some capabilities is not advertised by newer
>  	 * controller versions and must be explicitly enabled.
>  	 */
> 

--
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 v6 13/14] mmc: sdhci-msm: Add calibration tuning for CDCLP533 circuit
From: Adrian Hunter @ 2016-11-08 12:50 UTC (permalink / raw)
  To: Ritesh Harjani, ulf.hansson, linux-mmc, shawn.lin, sboyd
  Cc: devicetree, linux-clk, david.brown, andy.gross, linux-arm-msm,
	georgi.djakov, alex.lemberg, mateusz.nowak, Yuliy.Izrailov,
	asutoshd, kdorfman, david.griego, stummala, venkatg, rnayak,
	pramod.gurav
In-Reply-To: <1478517877-23733-14-git-send-email-riteshh@codeaurora.org>

On 07/11/16 13:24, Ritesh Harjani wrote:
> In HS400 mode a new RCLK is introduced on the interface for read data
> transfers. The eMMC5.0 device transmits the read data to the host with
> respect to rising and falling edges of RCLK. In order to ensure correct
> operation of read data transfers in HS400 mode, the incoming RX data
> needs to be sampled by delayed version of RCLK.
> 
> The CDCLP533 delay circuit shifts the RCLK by T/4. It needs to be
> initialized, configured and enabled once during HS400 mode switch and
> when operational voltage/clock is changed.
> 
> Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
> Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org>

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

> ---
>  drivers/mmc/host/sdhci-msm.c | 163 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 163 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index 6431bb8..ae19d1a 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -19,6 +19,7 @@
>  #include <linux/delay.h>
>  #include <linux/mmc/mmc.h>
>  #include <linux/slab.h>
> +#include <linux/iopoll.h>
>  
>  #include "sdhci-pltfm.h"
>  
> @@ -57,6 +58,7 @@
>  #define CORE_DLL_PDN		BIT(29)
>  #define CORE_DLL_RST		BIT(30)
>  #define CORE_DLL_CONFIG		0x100
> +#define CORE_CMD_DAT_TRACK_SEL	BIT(0)
>  #define CORE_DLL_STATUS		0x108
>  
>  #define CORE_DLL_CONFIG_2	0x1b4
> @@ -72,6 +74,33 @@
>  #define CORE_HC_SELECT_IN_HS400	(6 << 19)
>  #define CORE_HC_SELECT_IN_MASK	(7 << 19)
>  
> +#define CORE_CSR_CDC_CTLR_CFG0		0x130
> +#define CORE_SW_TRIG_FULL_CALIB		BIT(16)
> +#define CORE_HW_AUTOCAL_ENA		BIT(17)
> +
> +#define CORE_CSR_CDC_CTLR_CFG1		0x134
> +#define CORE_CSR_CDC_CAL_TIMER_CFG0	0x138
> +#define CORE_TIMER_ENA			BIT(16)
> +
> +#define CORE_CSR_CDC_CAL_TIMER_CFG1	0x13C
> +#define CORE_CSR_CDC_REFCOUNT_CFG	0x140
> +#define CORE_CSR_CDC_COARSE_CAL_CFG	0x144
> +#define CORE_CDC_OFFSET_CFG		0x14C
> +#define CORE_CSR_CDC_DELAY_CFG		0x150
> +#define CORE_CDC_SLAVE_DDA_CFG		0x160
> +#define CORE_CSR_CDC_STATUS0		0x164
> +#define CORE_CALIBRATION_DONE		BIT(0)
> +
> +#define CORE_CDC_ERROR_CODE_MASK	0x7000000
> +
> +#define CORE_CSR_CDC_GEN_CFG		0x178
> +#define CORE_CDC_SWITCH_BYPASS_OFF	BIT(0)
> +#define CORE_CDC_SWITCH_RC_EN		BIT(1)
> +
> +#define CORE_DDR_200_CFG		0x184
> +#define CORE_CDC_T4_DLY_SEL		BIT(0)
> +#define CORE_START_CDC_TRAFFIC		BIT(6)
> +
>  #define CORE_VENDOR_SPEC_CAPABILITIES0	0x11c
>  
>  #define INVALID_TUNING_PHASE	-1
> @@ -429,6 +458,131 @@ static int msm_init_cm_dll(struct sdhci_host *host)
>  	return 0;
>  }
>  
> +static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
> +	u32 config, calib_done;
> +	int ret;
> +
> +	pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
> +
> +	/*
> +	 * Retuning in HS400 (DDR mode) will fail, just reset the
> +	 * tuning block and restore the saved tuning phase.
> +	 */
> +	ret = msm_init_cm_dll(host);
> +	if (ret)
> +		goto out;
> +
> +	/* Set the selected phase in delay line hw block */
> +	ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
> +	if (ret)
> +		goto out;
> +
> +	/* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */
> +	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
> +	config |= CORE_CMD_DAT_TRACK_SEL;
> +	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
> +
> +	/* Write 0 to CDC_T4_DLY_SEL field in VENDOR_SPEC_DDR200_CFG */
> +	config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
> +	config &= ~CORE_CDC_T4_DLY_SEL;
> +	writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
> +
> +	/* Write 0 to CDC_SWITCH_BYPASS_OFF field in CORE_CSR_CDC_GEN_CFG */
> +	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
> +	config &= ~CORE_CDC_SWITCH_BYPASS_OFF;
> +	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
> +
> +	/* Write 1 to CDC_SWITCH_RC_EN field in CORE_CSR_CDC_GEN_CFG */
> +	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
> +	config |= CORE_CDC_SWITCH_RC_EN;
> +	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
> +
> +	/* Write 0 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
> +	config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
> +	config &= ~CORE_START_CDC_TRAFFIC;
> +	writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
> +
> +	/*
> +	 * Perform CDC Register Initialization Sequence
> +	 *
> +	 * CORE_CSR_CDC_CTLR_CFG0	0x11800EC
> +	 * CORE_CSR_CDC_CTLR_CFG1	0x3011111
> +	 * CORE_CSR_CDC_CAL_TIMER_CFG0	0x1201000
> +	 * CORE_CSR_CDC_CAL_TIMER_CFG1	0x4
> +	 * CORE_CSR_CDC_REFCOUNT_CFG	0xCB732020
> +	 * CORE_CSR_CDC_COARSE_CAL_CFG	0xB19
> +	 * CORE_CSR_CDC_DELAY_CFG	0x3AC
> +	 * CORE_CDC_OFFSET_CFG		0x0
> +	 * CORE_CDC_SLAVE_DDA_CFG	0x16334
> +	 */
> +
> +	writel_relaxed(0x11800EC, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +	writel_relaxed(0x3011111, host->ioaddr + CORE_CSR_CDC_CTLR_CFG1);
> +	writel_relaxed(0x1201000, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
> +	writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
> +	writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
> +	writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
> +	writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
> +	writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
> +	writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
> +
> +	/* CDC HW Calibration */
> +
> +	/* Write 1 to SW_TRIG_FULL_CALIB field in CORE_CSR_CDC_CTLR_CFG0 */
> +	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +	config |= CORE_SW_TRIG_FULL_CALIB;
> +	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +
> +	/* Write 0 to SW_TRIG_FULL_CALIB field in CORE_CSR_CDC_CTLR_CFG0 */
> +	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +	config &= ~CORE_SW_TRIG_FULL_CALIB;
> +	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +
> +	/* Write 1 to HW_AUTOCAL_ENA field in CORE_CSR_CDC_CTLR_CFG0 */
> +	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +	config |= CORE_HW_AUTOCAL_ENA;
> +	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
> +
> +	/* Write 1 to TIMER_ENA field in CORE_CSR_CDC_CAL_TIMER_CFG0 */
> +	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
> +	config |= CORE_TIMER_ENA;
> +	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
> +
> +	/* Poll on CALIBRATION_DONE field in CORE_CSR_CDC_STATUS0 to be 1 */
> +	ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_CSR_CDC_STATUS0,
> +					 calib_done,
> +					 (calib_done & CORE_CALIBRATION_DONE),
> +					 1, 50);
> +
> +	if (ret == -ETIMEDOUT) {
> +		pr_err("%s: %s: CDC calibration was not completed\n",
> +		       mmc_hostname(host->mmc), __func__);
> +		goto out;
> +	}
> +
> +	/* Verify CDC_ERROR_CODE field in CORE_CSR_CDC_STATUS0 is 0 */
> +	ret = readl_relaxed(host->ioaddr + CORE_CSR_CDC_STATUS0)
> +			& CORE_CDC_ERROR_CODE_MASK;
> +	if (ret) {
> +		pr_err("%s: %s: CDC error code %d\n",
> +		       mmc_hostname(host->mmc), __func__, ret);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Write 1 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
> +	config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
> +	config |= CORE_START_CDC_TRAFFIC;
> +	writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
> +out:
> +	pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
> +		 __func__, ret);
> +	return ret;
> +}
> +
>  static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
>  {
>  	int tuning_seq_cnt = 3;
> @@ -571,6 +725,15 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
>  	dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
>  		mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
>  	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> +
> +	spin_unlock_irq(&host->lock);
> +	/* CDCLP533 HW calibration is only required for HS400 mode*/
> +	if (host->clock > CORE_FREQ_100MHZ &&
> +	    msm_host->tuning_done && !msm_host->calibration_done &&
> +	    (mmc->ios.timing == MMC_TIMING_MMC_HS400))
> +		if (!sdhci_msm_cdclp533_calibration(host))
> +			msm_host->calibration_done = true;
> +	spin_lock_irq(&host->lock);
>  }
>  
>  static void sdhci_msm_voltage_switch(struct sdhci_host *host)
> 


^ permalink raw reply


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