linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
To: Olof Johansson <olof@lixom.net>, Chris Ball <chris@printf.net>
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
	pawel.moll@arm.com, linux-mmc@vger.kernel.org,
	robh+dt@kernel.org, ijc+devicetree@hellion.org.ok,
	galak@codeaurora.org, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 0/3] RFC/RFT: Powering on MMC Wifi/BT modules in MMC core
Date: Thu, 13 Feb 2014 10:36:40 +0000	[thread overview]
Message-ID: <20140213103640.GT26684@n2100.arm.linux.org.uk> (raw)
In-Reply-To: <20140201161420.GA26684@n2100.arm.linux.org.uk>

Any comments on this?

On Sat, Feb 01, 2014 at 04:14:20PM +0000, Russell King - ARM Linux wrote:
> On Thu, Jan 30, 2014 at 09:49:17PM +0000, Russell King - ARM Linux wrote:
> > On Sun, Jan 19, 2014 at 07:56:52PM -0800, Olof Johansson wrote:
> > > This is a small series enhancing the MMC core code to power on modules
> > > before the host in cases where needed, and the corresponding DT bindings
> > > changes.
> > > 
> > > I've got some other issues to debug on the Chromebook, i.e. the interface
> > > doens't actually work. So far it seems unrelated to this patch set so
> > > it's worth posting this and get things going since others need the same
> > > functionality (i.e Cubox-i).
> > > 
> > > As mentioned in the patch in the series, I haven't implemented power-down
> > > yet, I wanted to make sure that the power-on side will be adequate for
> > > those who are looking to use it right away.
> > > 
> > > Comments/test reports/etc welcome.
> > 
> > So, I thought I'd give this a go on the Cubox-i4, and... it doesn't work
> > there.  It's not your patches, it's down to sdhci-esdhc-imx.c not using
> > mmc_of_parse() at all, so those new properties have no way to be used
> > there.
> > 
> > It doesn't look like it could in its current form use mmc_of_parse(),
> > as the imx code manually parses some of the generic properties to hand
> > them into the sdhci layer.  This looks icky, and it looks like something
> > that should be fixed - why should drivers be parsing the core attributes
> > themselves?
> 
> Here's an illustration of why it's icky.
> 
> If we call mmc_of_parse() in the sdhci-esdhc-imx driver (which we'd need to
> do in order to get information on how to configure the card detection etc)
> then this fills in mmc->f_max.
> 
> However, the subsequent call to sdhci_add_host() computes the maximum clock
> from the sdhci capabilities, and then does this:
> 
>         host->max_clk *= 1000000;
>         if (host->max_clk == 0 || host->quirks &
>                         SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
>                 if (!host->ops->get_max_clock) {
>                         pr_err("%s: Hardware doesn't specify base clock "
>                                "frequency.\n", mmc_hostname(mmc));
>                         return -ENODEV;
>                 }
>                 host->max_clk = host->ops->get_max_clock(host);
>         }
> ...
>         /*
>          * Set host parameters.
>          */
>         mmc->ops = &sdhci_ops;
>         mmc->f_max = host->max_clk;
> 
> which would have the effect of overwriting a previously set f_max from
> the OF data.
> 
> There's also the whole "cd-gpios" thing which would need sorting out -
> the imx sdhci driver already parses this property itself, and sets its
> own internal data (so it knows whether it has to use the controller
> based card detect or the gpio card detect) and simply adding a call to
> mmc_of_parse() would result in the gpio slot stuff being setup twice.
> 
> The obvious solution here is to rewrite the sdhci initialisation such
> that it uses the generic infrastructure, but I don't have the motivation
> to do that (I've already plenty of patches to deal with that I don't
> need any more at the moment.)
> 
> A simpler solution would be to split mmc_of_parse() so that the new bits
> are a separate function, which the generic MMC core always calls for
> every host - taking the decision over whether this is supported completely
> away from hosts.  I think that makes a lot of sense, especially as this
> has nothing to do with the facilities found on any particular host.
> 
> There's another issue here about resets.  Let's take the case where the
> external card is powered off, but has active high resets.  At the moment,
> the sequence is this:
> 
> power: _____/~~~~~~~~~~~~
> reset: __/~~~~\__________
> 
> That's not particularly nice, as the reset signal will tend do drive power
> into the device before it's powered up via the clamping diodes in the case.
> Generally, devices are not designed to be powered in this way.  However,
> this is a relatively minor issue though compared to this one, which is what
> happens if the card uses active low reset:
> 
> power: _____/~~~~~~~~~~~~
> reset: ~~\_____/~~~~~~~~~
> 
> This is definitely not good, because it means that the reset is higher for
> longer, which may result in unacceptable dissapation in the package from
> those clamping diodes.  What we need instead is for active low reset is:
> 
> power: _____/~~~~~~~~~~~~
> reset: ________/~~~~~~~~~
> 
> So, we need the GPIO layer to tell us whether the output is active high or
> active low and adjust the initial setting accordingly.  Basically, whenever
> the attached device is powered down, GPIOs to it should be held at low level
> or high impedance (with a pull-down to reduce the risks of ESD damage.)
> 
> I've seen designs get this wrong in the past - Intel Assabet is a good one
> where the UDA1341 audio codec ends up illuminating a LED by being powered
> not via it's supply pin, but by a CPLD output driving one of the I2S pins
> high.  The result is that the CPLD output sources quite a bit of current
> into the UDA1341, which then holds other pins on the SA1110 around mid-rail,
> which is the /worst/ thing you can do with CMOS.  Powering chips via their
> inputs is basically a big no-no.
> 
> So, I think something like the below is needed on top of your patches.
> Note that I added -EPROBE_DEFER handling too (which fixes a bug, because
> regulator_get() returns pointer-errors):
> 
>  drivers/mmc/core/host.c            | 90 +++++++++++++++++++++++++++-----------
>  1 files changed, 65 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index e6b850b3241f..64942eb495b6 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -316,7 +316,7 @@ int mmc_of_parse(struct mmc_host *host)
>  	u32 bus_width;
>  	bool explicit_inv_wp, gpio_inv_wp = false;
>  	enum of_gpio_flags flags;
> -	int i, len, ret, gpio;
> +	int len, ret, gpio;
>  
>  	if (!host->parent || !host->parent->of_node)
>  		return 0;
> @@ -419,30 +419,6 @@ int mmc_of_parse(struct mmc_host *host)
>  	if (explicit_inv_wp ^ gpio_inv_wp)
>  		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
>  
> -	/* Parse card power/reset/clock control */
> -	if (of_find_property(np, "card-reset-gpios", NULL)) {
> -		struct gpio_desc *gpd;
> -		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
> -			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
> -			if (IS_ERR(gpd))
> -				break;
> -			gpiod_direction_output(gpd, 0);
> -			host->card_reset_gpios[i] = gpd;
> -		}
> -
> -		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
> -		if (!IS_ERR(gpd)) {
> -			dev_warn(host->parent, "More reset gpios than we can handle");
> -			gpiod_put(gpd);
> -		}
> -	}
> -
> -	host->card_clk = of_clk_get_by_name(np, "card_ext_clock");
> -	if (IS_ERR(host->card_clk))
> -		host->card_clk = NULL;
> -
> -	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
> -
>  	if (of_find_property(np, "cap-sd-highspeed", &len))
>  		host->caps |= MMC_CAP_SD_HIGHSPEED;
>  	if (of_find_property(np, "cap-mmc-highspeed", &len))
> @@ -467,6 +443,66 @@ int mmc_of_parse(struct mmc_host *host)
>  
>  EXPORT_SYMBOL(mmc_of_parse);
>  
> +static int mmc_of_parse_child(struct mmc_host *host)
> +{
> +	struct device_node *np;
> +	struct clk *clk;
> +	int i;
> +
> +	if (!host->parent || !host->parent->of_node)
> +		return 0;
> +
> +	np = host->parent->of_node;
> +
> +	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
> +	if (IS_ERR(host->card_regulator)) {
> +		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
> +			return PTR_ERR(host->card_regulator);
> +		host->card_regulator = NULL;
> +	}
> +
> +	/* Parse card power/reset/clock control */
> +	if (of_find_property(np, "card-reset-gpios", NULL)) {
> +		struct gpio_desc *gpd;
> +		int level = 0;
> +
> +		/*
> +		 * If the regulator is enabled, then we can hold the
> +		 * card in reset with an active high resets.  Otherwise,
> +		 * hold the resets low.
> +		 */
> +		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
> +			level = 1;
> +
> +		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
> +			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
> +			if (IS_ERR(gpd)) {
> +				if (PTR_ERR(gpd) == -EPROBE_DEFER)
> +					return PTR_ERR(gpd);
> +				break;
> +			}
> +			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
> +			host->card_reset_gpios[i] = gpd;
> +		}
> +
> +		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
> +		if (!IS_ERR(gpd)) {
> +			dev_warn(host->parent, "More reset gpios than we can handle");
> +			gpiod_put(gpd);
> +		}
> +	}
> +
> +	clk = of_clk_get_by_name(np, "card_ext_clock");
> +	if (IS_ERR(clk)) {
> +		if (PTR_ERR(clk) == -EPROBE_DEFER)
> +			return PTR_ERR(clk);
> +		clk = NULL;
> +	}
> +	host->card_clk = clk;
> +
> +	return 0;
> +}
> +
>  /**
>   *	mmc_alloc_host - initialise the per-host structure.
>   *	@extra: sizeof private data structure
> @@ -546,6 +582,10 @@ int mmc_add_host(struct mmc_host *host)
>  {
>  	int err;
>  
> +	err = mmc_of_parse_child(host);
> +	if (err)
> +		return err;
> +
>  	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
>  		!host->ops->enable_sdio_irq);
>  
> 
> -- 
> FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
> in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
> Estimate before purchase was "up to 13.2Mbit".
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

      reply	other threads:[~2014-02-13 10:36 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-20  3:56 [PATCH 0/3] RFC/RFT: Powering on MMC Wifi/BT modules in MMC core Olof Johansson
2014-01-20  3:56 ` [PATCH 1/3] mmc: add support for power-on sequencing through DT Olof Johansson
2014-01-20  8:44   ` Ulf Hansson
2014-01-20 19:13     ` Olof Johansson
2014-01-21  8:55       ` Ulf Hansson
2014-01-21 18:14         ` Olof Johansson
2014-01-22 11:30           ` Mark Brown
2014-01-20 16:36   ` Mark Brown
2014-01-20 16:48   ` Russell King - ARM Linux
2014-01-20 17:03     ` Fabio Estevam
2014-01-20 17:16       ` Russell King - ARM Linux
2014-01-20 18:47         ` Fabio Estevam
2014-01-21 19:19           ` Russell King - ARM Linux
2014-01-24 17:35     ` Fabio Estevam
2014-01-27  8:43       ` Jyri Sarha
2014-01-27  8:54         ` Chen-Yu Tsai
2014-01-27  9:48           ` Jyri Sarha
2014-01-20 18:58   ` Arnd Bergmann
     [not found]     ` <201401201958.57997.arnd-r2nGTMty4D4@public.gmane.org>
2014-01-20 19:04       ` Olof Johansson
2014-01-20 19:12         ` Arnd Bergmann
2014-01-20 19:14   ` Fabio Estevam
2014-01-20 19:14     ` Olof Johansson
2014-01-21  7:24   ` Sascha Hauer
2014-01-21  7:25     ` Sascha Hauer
2014-01-21 18:34   ` Tomasz Figa
2014-01-21 21:30     ` Olof Johansson
2014-01-21 21:39       ` Tomasz Figa
2014-01-26 17:26     ` Tomasz Figa
2014-01-27 10:19       ` Ulf Hansson
2014-01-28  0:59         ` Tomasz Figa
2014-01-28  1:08           ` Chris Ball
2014-01-28 10:06           ` Ulf Hansson
2014-01-28 10:48             ` Arnd Bergmann
2014-02-12 18:33               ` Mark Brown
2014-02-13  8:56               ` Ulf Hansson
2014-02-13  9:01                 ` Tomasz Figa
2014-02-13 10:42               ` Russell King - ARM Linux
2014-02-13 12:48                 ` Arnd Bergmann
2014-02-13 14:41                   ` Russell King - ARM Linux
2014-02-13 16:13                     ` Arnd Bergmann
2014-02-13 17:31                       ` Olof Johansson
2014-02-15 12:18                       ` Arnd Bergmann
2014-02-15 12:27                         ` Russell King - ARM Linux
2014-02-15 13:09                           ` Arnd Bergmann
2014-02-15 13:22                             ` Tomasz Figa
2014-02-15 16:21                               ` Arnd Bergmann
2014-02-15 20:52                                 ` Russell King - ARM Linux
2014-02-15 21:35                                   ` Tomasz Figa
2014-02-15 22:03                                     ` Russell King - ARM Linux
2014-02-17 13:00                                   ` Arnd Bergmann
2014-02-17 23:25                                 ` Mark Brown
2014-01-20  3:56 ` [PATCH 2/3] mmc: dw_mmc: call mmc_of_parse to fill in common options Olof Johansson
2014-01-20  4:53   ` Jaehoon Chung
2014-01-20  3:56 ` [PATCH 3/3] ARM: dts: exynos5250-snow: Enable wifi power-on Olof Johansson
2014-01-30 21:49 ` [PATCH 0/3] RFC/RFT: Powering on MMC Wifi/BT modules in MMC core Russell King - ARM Linux
2014-02-01 16:14   ` Russell King - ARM Linux
2014-02-13 10:36     ` Russell King - ARM Linux [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140213103640.GT26684@n2100.arm.linux.org.uk \
    --to=linux@arm.linux.org.uk \
    --cc=chris@printf.net \
    --cc=devicetree@vger.kernel.org \
    --cc=galak@codeaurora.org \
    --cc=ijc+devicetree@hellion.org.ok \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=olof@lixom.net \
    --cc=pawel.moll@arm.com \
    --cc=robh+dt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).