From patchwork Wed Dec 10 20:58:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 5472301 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BCFF0BEEA8 for ; Wed, 10 Dec 2014 20:59:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D34502017D for ; Wed, 10 Dec 2014 20:59:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D5F6C2018E for ; Wed, 10 Dec 2014 20:59:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758237AbaLJU6b (ORCPT ); Wed, 10 Dec 2014 15:58:31 -0500 Received: from mail-ie0-f172.google.com ([209.85.223.172]:34385 "EHLO mail-ie0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758220AbaLJU63 (ORCPT ); Wed, 10 Dec 2014 15:58:29 -0500 Received: by mail-ie0-f172.google.com with SMTP id tr6so3522133ieb.17 for ; Wed, 10 Dec 2014 12:58:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=b5vGNprpqtxmgYW6KvEIFdElsN0IQZWgImgimLrZPp0=; b=k6Z2yqEyUq+Cdn+1M3mrjRoWhN4vGAgsc82gqdAhSCQnO1LKElWvhJoJ3GmjRw5QRz G+DoSJbSdM80HR0R/r2gy9x89QadAaujXsm2WHgI28KsLZ4GUeAs/WcCIobVBSfUmMfK amhmzM3wg/fdc1WtVgZ8BaWp1Y9OqTv3GlMjA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=b5vGNprpqtxmgYW6KvEIFdElsN0IQZWgImgimLrZPp0=; b=k/KD8CSQ2Dv3GJA4DJ+AyJbW0n15copfWoV6tBqRBZFAzcqBopd5ae9eycnDVHtkrs YAu+yQWOecyTzl9EIBJz/Quhrm18Glw/lsXXZs9S73vT8b3gJng72j6I9WDE1SIbdB1J XYraIzO+ESW5Wb9FFd0lTMqG1kRxFWDPq+CzMS4EKnUAJOAa5oC2SS399QIkL6OzNi8Q RlK9TAxR9NVjA11tBlJ5Kg4pBStWwiTgk584KBPSTdW3kMi/wSt+hUhX3284iqjgPu9N piRGQh/VRUZn5aZtesUQGdTJfYU70pv4AuchqP6aiypkF0k3uNF/JAo5XcJq+QxwBkbD BSDQ== X-Gm-Message-State: ALoCoQk/IKYW8U5VOwPhhcyTxXE0tn0KKA3fjrFIUfUUWaiRdD3cquSderSiir2Yw+mWPvv68cOE X-Received: by 10.50.79.135 with SMTP id j7mr10243672igx.14.1418245108273; Wed, 10 Dec 2014 12:58:28 -0800 (PST) Received: from tictac.mtv.corp.google.com ([172.22.65.76]) by mx.google.com with ESMTPSA id m15sm2091454iom.44.2014.12.10.12.58.27 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 10 Dec 2014 12:58:27 -0800 (PST) From: Doug Anderson To: Ulf Hansson , Mark Brown , Heiko Stuebner , Jaehoon Chung , Seungwon Jeon Cc: Alexandru Stan , Alim Akhtar , Sonny Rao , Andrew Bresticker , linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Doug Anderson , chris@printf.net, johan.rudholm@axis.com, tim.kryger@gmail.com, adrian.hunter@intel.com, andrew_gabbasov@mentor.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/4] mmc: core: Add mmc_regulator_set_vqmmc() Date: Wed, 10 Dec 2014 12:58:03 -0800 Message-Id: <1418245085-9754-2-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1418245085-9754-1-git-send-email-dianders@chromium.org> References: <1418245085-9754-1-git-send-email-dianders@chromium.org> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This adds logic to the MMC core to set VQMMC. This is expected to be called by MMC drivers like dw_mmc as part of (or instead of) their start_signal_voltage_switch() callback. A few notes: * When setting the signal voltage to 3.3V we do our best to make VQMMC and VMMC match. It's been reported that this makes some old cards happy since they were tested back in the day before UHS when VQMMC and VMMC were provided by the same regulator. A nice side effect of this is that we don't end up on the hairy edge of VQMMC (2.7V), which some EEs claim is a little too close to the minimum for comfort. * When setting the signal voltage to 1.8V or 1.2V we aim for that specific voltage instead of picking the lowest one in the range. * We very purposely don't print errors in mmc_regulator_set_vqmmc(). There are cases where the MMC core will try several different voltages and we don't want to pollute the logs. Signed-off-by: Doug Anderson --- drivers/mmc/core/core.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mmc/host.h | 7 +++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9584bff..d0da480 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1333,6 +1333,59 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, } EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); +static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator, + int min_uV, int ideal_uV, + int max_uV) +{ + /* + * Check if supported first to avoid errors since we may try several + * signal levels during power up and don't want to show errors. + */ + if (!regulator_is_supported_voltage(regulator, min_uV, max_uV)) + return -EINVAL; + + return regulator_set_closest_voltage(regulator, min_uV, ideal_uV, + max_uV); +} + +/** + * mmc_regulator_set_vqmmc - Set VQMMC as per the ios + * + * For 3.3V signaling, we try to match vqmmc to vmmc as closely as possible. + * That will match the behavior of old boards where vqmmc and vmmc were supplied + * by the same supply. + * + * For 1.2V and 1.8V signaling we'll try to get as close as possible to the + * requested voltage. This is definitely a good idea for UHS where there's a + * separate regulator on the card that's trying to make 1.8V and it's best if + * we match. + * + * This function is expected to be used by a controller's + * start_signal_voltage_switch() function. + */ +int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios) +{ + /* If no vqmmc supply then we can't change the voltage */ + if (IS_ERR(mmc->supply.vqmmc)) + return -EINVAL; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_120: + return mmc_regulator_set_voltage_if_supported( + mmc->supply.vqmmc, 1100000, 1200000, 1300000); + case MMC_SIGNAL_VOLTAGE_180: + return mmc_regulator_set_voltage_if_supported( + mmc->supply.vqmmc, 1700000, 1800000, 1950000); + case MMC_SIGNAL_VOLTAGE_330: + return mmc_regulator_set_voltage_if_supported( + mmc->supply.vqmmc, 2700000, + regulator_get_voltage(mmc->supply.vmmc), 3600000); + default: + return -EINVAL; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); + #endif /* CONFIG_REGULATOR */ int mmc_regulator_get_supply(struct mmc_host *mmc) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9f32270..524d6fc 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -416,6 +416,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply); int mmc_regulator_set_ocr(struct mmc_host *mmc, struct regulator *supply, unsigned short vdd_bit); +int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios); #else static inline int mmc_regulator_get_ocrmask(struct regulator *supply) { @@ -428,6 +429,12 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, { return 0; } + +static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + return -EINVAL; +} #endif int mmc_regulator_get_supply(struct mmc_host *mmc);