Received: by 10.223.185.116 with SMTP id b49csp34149wrg; Fri, 2 Mar 2018 13:06:09 -0800 (PST) X-Google-Smtp-Source: AG47ELt0lk17Ov+g6ywt40E7JCyBFiT9USt5Y2a8/B0VIR4oGk56S/6AbNxKD9DlYKBIwm+YREKs X-Received: by 2002:a17:902:a50d:: with SMTP id s13-v6mr6455855plq.191.1520024769389; Fri, 02 Mar 2018 13:06:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520024769; cv=none; d=google.com; s=arc-20160816; b=rhvRLa/kkaQwUfQQDXCZRRik9Eanjb5LWqxB1zIukoHuH/pRHDJU+Gk39SEnSfcK8X /9gYchurV7Hz3c15WS8h4b2u6sGLivHDpzScwA41voc43bqepCSlyHvR8gOps2dt8G8k jE6mEjCKNsLPQWMjg6CtrFKXWI/aYQB7sSNgNhS2VajJwlIprfMF5KaHxSatlHtMvsqj UXs8ssQA+Yv9bXESIi92pHcd9w3zmottR8xOhVzeDyFLMfb/Z2dy53bKtBcM/djR9uGt jxzJAqqtbKdMYLSMEgAoIEy00ecmdT23iNw8Ldq3ECOGOEZq75dpV7imcRFOR9FOjGia au+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=Y78Pd896GBXRO2weg0KG8s2Nu+iayDvYELPi+gjwpXU=; b=QRQ/ccZSlZLU9B48qMSesb5mc7cP2qfbxclLopmq6POBPpgyLbqhNpQRTneOEEuYzT 2dwUOCHwtRVo7YjLJLUkcdQLXxZYQ/VteL+tUGDgBCSPfrW5TZcwiBkjc2qm7sEyhDrU GfIF7sXaZvxTO1MqjErgY/wTKakcjRPNOrkvkm2fiFXRivvhpm3mImdad1tLHvOT42q5 +I3bUspWtff1+M/FMjY8kzx0e/DngBSFff/4ht2XLNet5S3/kiJBc4nH4jOdZAMO0tzp RE0CQcgA8YgLbAOHvG+1QIbJCJJpmeUqL2Sg70g/77h4KvxTGawVedMv0RU1+Hu34SIC Y6fA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=fFmoYrQs; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h6-v6si3815801pls.39.2018.03.02.13.05.54; Fri, 02 Mar 2018 13:06:09 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=fFmoYrQs; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1165109AbeCBSZn (ORCPT + 99 others); Fri, 2 Mar 2018 13:25:43 -0500 Received: from mail-vk0-f66.google.com ([209.85.213.66]:45847 "EHLO mail-vk0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1162994AbeCBSZk (ORCPT ); Fri, 2 Mar 2018 13:25:40 -0500 Received: by mail-vk0-f66.google.com with SMTP id k187so6258193vke.12 for ; Fri, 02 Mar 2018 10:25:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=Y78Pd896GBXRO2weg0KG8s2Nu+iayDvYELPi+gjwpXU=; b=fFmoYrQsPmptTK2+EKARc6eNtut5qaNJFn203MJwnrO1hi8JBA352C7K7hmdYG/eP/ patEi9dnaEY4CaEANgiNaV6Nrrwn6IBiy2UnYL5nDuRnkENS0/wh0nJT40stwu5cUvJ6 luKFVDpH7piTQ8sAb/1dxPaFtgRBipgRX9989q8fXqG93dTGNj97wcVqD05pVrySVAFY QUf5dATm/3/Ax54QqNiBwXR7okIcIjGtFwZSfCBLVZ//w+SGye4IraI1OrGcXBpJd+9S +WtoAw4sOUeV8m9kCceC327MmEnccWQsI+ZJ36K7o/wLQwdQPU/MaPkDnr7S5TX+ZA3a jj/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=Y78Pd896GBXRO2weg0KG8s2Nu+iayDvYELPi+gjwpXU=; b=bGVn5i97Z08PQ/LlqqdoeV8ASfCp//UjdMQ+yHJcKz6Yeq8qbwDztJpyqK/Aynq3XI t9+0dLkHVYYwAE937MP0pmzFB4vWfUKG2wu+NDw1PkuAjmdFH6yJJ/HVPNKo4NNf6gxf nghcEho1VoBuMV5e815KrT6jrcH9txlQFzhzgnsLY+iLCbpY1mmRCznTX6YvfZ3kNzYw Vz42jTm8CVZA6D9wVWeGu6Bv8L/+fbos263vgWst0NHi7zY4E42AnJfsNSXL5+tn7PE+ Mpb112r0IvMyXjibB+R6KC2V/46Fw5x0QLYl/M+Ys5GoXuyAOtgKrlV3svSjj4IGNQAI qf5w== X-Gm-Message-State: AElRT7Hv+vX27UG/0Ptmqd3fuiEWiI8jayxgG6zcbiYhDsydvUFnnVKO 9+7jsYpIMwahd30RJ9iGMizbuLI6h/gH7vjsTPjjgw== X-Received: by 10.31.140.5 with SMTP id o5mr4415693vkd.157.1520015139205; Fri, 02 Mar 2018 10:25:39 -0800 (PST) MIME-Version: 1.0 Received: by 10.31.151.1 with HTTP; Fri, 2 Mar 2018 10:25:38 -0800 (PST) In-Reply-To: <1518415278-59062-3-git-send-email-vviswana@codeaurora.org> References: <1518415278-59062-1-git-send-email-vviswana@codeaurora.org> <1518415278-59062-3-git-send-email-vviswana@codeaurora.org> From: Doug Anderson Date: Fri, 2 Mar 2018 10:25:38 -0800 Message-ID: Subject: Re: [PATCH V2 2/2] mmc: sdhci-msm: support voltage pad switching To: Vijay Viswanath Cc: Adrian Hunter , Ulf Hansson , linux-mmc@vger.kernel.org, LKML , Shawn Lin , linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org, asutoshd@codeaurora.org, stummala@codeaurora.org, venkatg@codeaurora.org, pramod.gurav@linaro.org, jeremymc@redhat.com, Krishna Konda , evgreen@chromium.org Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On Sun, Feb 11, 2018 at 10:01 PM, Vijay Viswanath wrote: > From: Krishna Konda > > The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs > have a control signal (io_pad_pwr_switch/mode18 ) that indicates > whether the PAD works in 3v or 1.8v. > > SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset > based on actual voltage used for IO lines. So when power irq is > triggered for io high or io low, the driver should check the voltages > supported and set the pad accordingly. > > Signed-off-by: Krishna Konda > Signed-off-by: Venkat Gopalakrishnan > Signed-off-by: Vijay Viswanath > --- > drivers/mmc/host/sdhci-msm.c | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c > index 5c23e92..96c81df 100644 > --- a/drivers/mmc/host/sdhci-msm.c > +++ b/drivers/mmc/host/sdhci-msm.c > @@ -78,6 +78,8 @@ > #define CORE_HC_MCLK_SEL_DFLT (2 << 8) > #define CORE_HC_MCLK_SEL_HS400 (3 << 8) > #define CORE_HC_MCLK_SEL_MASK (3 << 8) > +#define CORE_IO_PAD_PWR_SWITCH_EN (1 << 15) > +#define CORE_IO_PAD_PWR_SWITCH (1 << 16) > #define CORE_HC_SELECT_IN_EN BIT(18) > #define CORE_HC_SELECT_IN_HS400 (6 << 19) > #define CORE_HC_SELECT_IN_MASK (7 << 19) > @@ -1109,6 +1111,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq) > u32 irq_status, irq_ack = 0; > int retry = 10; > int pwr_state = 0, io_level = 0; > + u32 config = 0; Don't init things to 0 unless you're relying on it (you're not). Doing so tends to bypass compiler warnings about "use before init" and leads to uncaught bugs. > irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS); > @@ -1166,6 +1169,30 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq) > */ > writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL); > > + /* Ensure order between core_mem and hc_mem */ > + mb(); I spent a bit of time brushing up on my memory barriers and (as far as I understand) I agree that in general mb() between accesses of core_mem and hc_mem is technically needed since, as you say, there are two separate io-mapped devices here and you're using relaxed accessors. Oh, but hold on. In this particular case they're truly not needed, right? The value stored in CORE_VENDOR_SPEC should be exactly the value you wrote last to it, right? ...and you're just reading it back. There should be no need for any sort of barrier here... ...and, if you wanted to be _truly_ efficient (maybe you do since you're going through all this trouble of using readl_relaxed) you could just cache this value in "struct sdhci_msm_host" and you don't even have to read it back at all. > + /* > + * We should unset IO PAD PWR switch only if the register write can > + * set IO lines high and the regulator also switches to 3 V. > + * Else, we should keep the IO PAD PWR switch set. > + * This is applicable to certain targets where eMMC vccq supply is only > + * 1.8V. In such targets, even during REQ_IO_HIGH, the IO PAD PWR > + * switch must be kept set to reflect actual regulator voltage. This > + * way, during initialization of controllers with only 1.8V, we will > + * set the IO PAD bit without waiting for a REQ_IO_LOW. > + */ > + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > + > + if ((io_level & REQ_IO_HIGH) && (msm_host->caps_0 & CORE_3_0V_SUPPORT)) > + config &= ~CORE_IO_PAD_PWR_SWITCH; > + else if ((io_level & REQ_IO_LOW) || > + (msm_host->caps_0 & CORE_1_8V_SUPPORT)) > + config |= CORE_IO_PAD_PWR_SWITCH; Part of me thinks that this would all be much cleaner using the same solution as "drivers/power/avs/rockchip-io-domain.c". AKA: register to be notified about changes to vqmmc and set the bit whenever it flips. ...but I won't insist on that. I don't know a whole lot about the whole "REQ_IO_HIGH" bug I guess it's a sane place to do this... ...but I will say that the fact that sometimes "config" isn't set to anything at all here confuses me (IOW if you don't hit either the "if" or "else if" then config is unchanged). I think the comment block above tries to explain it, but I still don't really get it. Maybe more examples? If I was describing the current algorithm, I'd give these examples: * If vqmmc can only be 1.8V then at init time we'll have set PAD_PWR_SWITCH_EN and leave the PAD_PWR_SWITCH set to 3.3V, but then upon the first "REQ_IO_LOW" we'll transition down to 1.8V and stay there forever. * If vqmmc can only be 3.3V then at init time we'll have set PAD_PWR_SWITCH_EN and leave the PAD_PWR_SWITCH set to 3.3V always. * If vqmmc can be either 3.3V or 1.8V then at init time we'll have set PAD_PWR_SWITCH_EN and leave the PAD_PWR_SWITCH set to 3.3V, but then we'll honor REQ_IO_LOW / REQ_IO_HIGH. * If vqmmc has an unknown range (or ins't provided) then we'll behave like the 3.3V case (because earlier code initted PAD_PWR_SWITCH_EN to 0 when it wrote CORE_VENDOR_SPEC_POR_VAL and then we never change it). > + > + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > + /* Ensure IO pad update before any further register read/writes */ > + mb(); I agree that (to the best of my understanding) this mb() ought to be there, but maybe mention that the reason is that you have two separate IO ranges for registers and that's why you need it. Also: if you truly care about avoiding mb() calls (and since you're using _relaxed variants I assume you do), you should avoid writing the config and doing the "mb" if you didn't actually make a change. > + > if (pwr_state) > msm_host->curr_pwr_state = pwr_state; > if (io_level) > @@ -1518,6 +1545,13 @@ static int sdhci_msm_probe(struct platform_device *pdev) > } > > /* > + * Set the PAD_PWR_SWITCH_EN bit so that the PAD_PWR_SWITCH bit can > + * be used as required later on. > + */ > + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > + config |= CORE_IO_PAD_PWR_SWITCH_EN; > + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); If this is going to be unconditional (as you've written it) should this be combined with the statement earlier in the same function where we write "CORE_VENDOR_SPEC_POR_VAL" to this same register? Seems like you could write: #define CORE_VENDOR_SPEC_INIT_VAL (CORE_VENDOR_SPEC_POR_VAL | \ CORE_IO_PAD_PWR_SWITCH_EN) ...then just change the init line to use "CORE_VENDOR_SPEC_INIT_VAL" instead of "CORE_VENDOR_SPEC_POR_VAL". --- ...but it seems like it might be even better just leave the "en" bit off for now and just turn it on when you actually need it. BTW: All I have is a very terse register spec in front of me, but do you happen to know why "HC_IO_PAD_PWR_SWITCH_EN" even exists at all? Is there some difference between "enabled but choose 3.3 V" and "not enabled?" Also: do all versions of the controller supported by this driver support this bit? One last thing: on SDM845 one of the two SD controllers doesn't support 1.8V, though the register description still describes these bits. Presumably for that controller it's better to just not set "enabled" at all? -Doug