Received: by 10.223.185.111 with SMTP id b44csp77203wrg; Fri, 9 Mar 2018 01:14:40 -0800 (PST) X-Google-Smtp-Source: AG47ELvblTzQflPORsSYB11T4TcHWOCoPcGIBgD+ZP/8IK2Ita3+eSp0Em7oqsEipK2W8I7qU1Wc X-Received: by 2002:a17:902:788e:: with SMTP id q14-v6mr27144926pll.396.1520586879909; Fri, 09 Mar 2018 01:14:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520586879; cv=none; d=google.com; s=arc-20160816; b=mWbqjbEItvHGILK/OUc7Rg72s3dwhyHOj/i1CesC0QRjTRRzccVtNwC+zk9C6qetbc R2rIIOPqIl68HVvLiJxYvufzFqDEWqIuALoOQ6FWHQ1f0BdzSB1BvyL3h2yrKh8qCCTA 2YHcmDqy9OepXcVB0KYh2stm3UCXJFu0JJx5YvTIZZuJE2GDelrXC62r0M8l6CgS52eN iZu8E0PBM1x3tERFUFgk7gwJhs6Z63+FzjRhmGcaHA1SoiVJGS3+Zu6BYR1t2IlXozUa fp8yPS7wlW5YcLeGFCT8nlZHTqTXZD4Wd+oRAGhvqRVnAuTzK0rg83JJajhb+q3+ksTx qCkA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:organization:from:references:cc:to:subject :arc-authentication-results; bh=KOEpyUr51b3iEMMqLDLLDZD/nQm5o3S2dwMen9LOrLA=; b=zVpJuypVE1DjDphX9nR91Q475gRq7rTh2TbBHk82DM7fVDm8L9nQruNAeV12Rs/OBK 8N7A8xG1b+Zfl6Ycj/Q8h71GnWOTRm1cdRjfFMMpX8MJEUFa2Htuj/6fZA7LR/JEZXBy av9vNA4MANvZMN08MBWb4EfXSW0FzdvFu26NY7/7tdxrauPVb7Ww8HNfYRlJ+TeXYAs7 asObBV6pXLshbeQnQa+ms5uJOxdDGVgKa2X7YZzlrL1TTxCi8Bbw6shKJrQhn7MM8KdD Yp29IaiXZ5aj0rvL+8XrD/7GVraA0xF504xHQbSxZSg+xkyz2ZwmQ8zlWn8iUWdfHx88 v96g== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c7-v6si526238plo.432.2018.03.09.01.14.25; Fri, 09 Mar 2018 01:14:39 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751279AbeCIJNG (ORCPT + 99 others); Fri, 9 Mar 2018 04:13:06 -0500 Received: from mx1.redhat.com ([209.132.183.28]:53376 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750996AbeCIJNC (ORCPT ); Fri, 9 Mar 2018 04:13:02 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 68FE381DE1; Fri, 9 Mar 2018 09:13:02 +0000 (UTC) Received: from ovpn-116-42.phx2.redhat.com (ovpn-116-42.phx2.redhat.com [10.3.116.42]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BC0805D760; Fri, 9 Mar 2018 09:12:58 +0000 (UTC) Subject: Re: [PATCH V2 2/2] mmc: sdhci-msm: support voltage pad switching To: Doug Anderson , 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 References: <1518415278-59062-1-git-send-email-vviswana@codeaurora.org> <1518415278-59062-3-git-send-email-vviswana@codeaurora.org> From: Jeremy McNicoll Organization: Red Hat Message-ID: Date: Fri, 9 Mar 2018 01:12:58 -0800 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 09 Mar 2018 09:13:02 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2018-03-02 10:25 AM, Doug Anderson wrote: > 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? > > > Looking forward to reviewing and testing V3. -jeremy