Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp803576pxb; Tue, 3 Nov 2020 13:00:24 -0800 (PST) X-Google-Smtp-Source: ABdhPJzW3DDv49+zlY135kr2YOElTQyuUr3M0yKAuHwzpyisTAIlBIoRwBl/gxwqFKqKEgri0XcM X-Received: by 2002:a17:906:1246:: with SMTP id u6mr21846922eja.432.1604437224342; Tue, 03 Nov 2020 13:00:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604437224; cv=none; d=google.com; s=arc-20160816; b=Hu2Fq+UtOed2N0SXl5Fjr/UGm3Kl7gyKSF3uJC9OsLqXkiTI/LbP7a949+eB+o0Xs6 fg0JsdKR0Qj9wg99oXyS3+1PsXX1LwWUEhfQUmNYBFKewFpEcQuwjG1h6nWiLbZW/RSp YO6Ok8kdadzwEcltY7qshTL3Qtw+EOM5m/FvJRVziT1rbm3MuYCQ5MnwTylNBov/4/6F BaESuVnTx+MYtdWK4LAwSLGAR6A1Bv2kYCdkf44gm/dAiehJDwd/bokE5grVbZiSUAVj 2p8qKFo6aCGiW5KAPb6H0ZO9sfoNE0TOZf1YmUXgM4RPq+oRr9JqsenZJ+d9HpXA4EC4 GsAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=CraTImru1WEIDI5pggkpvEBbbVcyjATLNT8iqO2Vcuc=; b=DK6bq2jwDy5iW/wWpfJ47EP7yjIFqhTk58J6R09TlGlWqu8PH/E+wH1+ZkhrtJ4lnw gxS8uqDcIXdWuP4Qr1/BwjI1fCggvZKDqJfgALyUo/tUH/+IWx9MTJw2iftW3fdSHJLA 4TPkZthQ1g7pY8jXz8VYCROJBpnqw/Jf+LQ5VI8HV4Jphc518Ij8B9U6nvr4+abLAYk9 jMGI8u480Z24TYvyYffCuNdJNhHhEHraReem879cTvvjsUaODxfIT2nk2b8Yba3DQS73 GpYqTSR/C8wjkWFe1PY97wek8JvAXx+wj54pVFWyEkCRMstZgoquw3leocDEct+d298A bwdQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=MJuK1Bv0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m30si14395446edj.103.2020.11.03.13.00.00; Tue, 03 Nov 2020 13:00:24 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=MJuK1Bv0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732726AbgKCU4a (ORCPT + 99 others); Tue, 3 Nov 2020 15:56:30 -0500 Received: from mail.kernel.org ([198.145.29.99]:58164 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731988AbgKCU42 (ORCPT ); Tue, 3 Nov 2020 15:56:28 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id ADD3F20732; Tue, 3 Nov 2020 20:56:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604436987; bh=9CXD83r7/hEiAg1O5gJNxnZkiFr/YrvW/sKfL3+bIbI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MJuK1Bv0jqnc6mAdUvXKOX352xjBM9E8NY3sA3jZba7uE5RFG5oliwH3Cmybi5Ec3 202dH+Etxvk2evudQYEcyS+jqlYTAwlzlAMVy15gbfZzFgWzKnJF3p5i4hpIxna941 ktA/ZCJOWGz9xvYNPfDi7ost0kb1sE+P63wfcRDs= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Adrian Hunter , Ulf Hansson Subject: [PATCH 5.4 097/214] mmc: sdhci: Add LTR support for some Intel BYT based controllers Date: Tue, 3 Nov 2020 21:35:45 +0100 Message-Id: <20201103203259.604544706@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201103203249.448706377@linuxfoundation.org> References: <20201103203249.448706377@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Adrian Hunter commit 46f4a69ec8ed6ab9f6a6172afe50df792c8bc1b6 upstream. Some Intel BYT based host controllers support the setting of latency tolerance. Accordingly, implement the PM QoS ->set_latency_tolerance() callback. The raw register values are also exposed via debugfs. Intel EHL controllers require this support. Signed-off-by: Adrian Hunter Fixes: cb3a7d4a0aec4e ("mmc: sdhci-pci: Add support for Intel EHL") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200818104508.7149-1-adrian.hunter@intel.com Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/sdhci-pci-core.c | 154 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -520,6 +522,8 @@ struct intel_host { bool rpm_retune_ok; u32 glk_rx_ctrl1; u32 glk_tun_val; + u32 active_ltr; + u32 idle_ltr; }; static const guid_t intel_dsm_guid = @@ -764,6 +768,108 @@ static int intel_execute_tuning(struct m return 0; } +#define INTEL_ACTIVELTR 0x804 +#define INTEL_IDLELTR 0x808 + +#define INTEL_LTR_REQ BIT(15) +#define INTEL_LTR_SCALE_MASK GENMASK(11, 10) +#define INTEL_LTR_SCALE_1US (2 << 10) +#define INTEL_LTR_SCALE_32US (3 << 10) +#define INTEL_LTR_VALUE_MASK GENMASK(9, 0) + +static void intel_cache_ltr(struct sdhci_pci_slot *slot) +{ + struct intel_host *intel_host = sdhci_pci_priv(slot); + struct sdhci_host *host = slot->host; + + intel_host->active_ltr = readl(host->ioaddr + INTEL_ACTIVELTR); + intel_host->idle_ltr = readl(host->ioaddr + INTEL_IDLELTR); +} + +static void intel_ltr_set(struct device *dev, s32 val) +{ + struct sdhci_pci_chip *chip = dev_get_drvdata(dev); + struct sdhci_pci_slot *slot = chip->slots[0]; + struct intel_host *intel_host = sdhci_pci_priv(slot); + struct sdhci_host *host = slot->host; + u32 ltr; + + pm_runtime_get_sync(dev); + + /* + * Program latency tolerance (LTR) accordingly what has been asked + * by the PM QoS layer or disable it in case we were passed + * negative value or PM_QOS_LATENCY_ANY. + */ + ltr = readl(host->ioaddr + INTEL_ACTIVELTR); + + if (val == PM_QOS_LATENCY_ANY || val < 0) { + ltr &= ~INTEL_LTR_REQ; + } else { + ltr |= INTEL_LTR_REQ; + ltr &= ~INTEL_LTR_SCALE_MASK; + ltr &= ~INTEL_LTR_VALUE_MASK; + + if (val > INTEL_LTR_VALUE_MASK) { + val >>= 5; + if (val > INTEL_LTR_VALUE_MASK) + val = INTEL_LTR_VALUE_MASK; + ltr |= INTEL_LTR_SCALE_32US | val; + } else { + ltr |= INTEL_LTR_SCALE_1US | val; + } + } + + if (ltr == intel_host->active_ltr) + goto out; + + writel(ltr, host->ioaddr + INTEL_ACTIVELTR); + writel(ltr, host->ioaddr + INTEL_IDLELTR); + + /* Cache the values into lpss structure */ + intel_cache_ltr(slot); +out: + pm_runtime_put_autosuspend(dev); +} + +static bool intel_use_ltr(struct sdhci_pci_chip *chip) +{ + switch (chip->pdev->device) { + case PCI_DEVICE_ID_INTEL_BYT_EMMC: + case PCI_DEVICE_ID_INTEL_BYT_EMMC2: + case PCI_DEVICE_ID_INTEL_BYT_SDIO: + case PCI_DEVICE_ID_INTEL_BYT_SD: + case PCI_DEVICE_ID_INTEL_BSW_EMMC: + case PCI_DEVICE_ID_INTEL_BSW_SDIO: + case PCI_DEVICE_ID_INTEL_BSW_SD: + return false; + default: + return true; + } +} + +static void intel_ltr_expose(struct sdhci_pci_chip *chip) +{ + struct device *dev = &chip->pdev->dev; + + if (!intel_use_ltr(chip)) + return; + + dev->power.set_latency_tolerance = intel_ltr_set; + dev_pm_qos_expose_latency_tolerance(dev); +} + +static void intel_ltr_hide(struct sdhci_pci_chip *chip) +{ + struct device *dev = &chip->pdev->dev; + + if (!intel_use_ltr(chip)) + return; + + dev_pm_qos_hide_latency_tolerance(dev); + dev->power.set_latency_tolerance = NULL; +} + static void byt_probe_slot(struct sdhci_pci_slot *slot) { struct mmc_host_ops *ops = &slot->host->mmc_host_ops; @@ -778,6 +884,43 @@ static void byt_probe_slot(struct sdhci_ ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; device_property_read_u32(dev, "max-frequency", &mmc->f_max); + + if (!mmc->slotno) { + slot->chip->slots[mmc->slotno] = slot; + intel_ltr_expose(slot->chip); + } +} + +static void byt_add_debugfs(struct sdhci_pci_slot *slot) +{ + struct intel_host *intel_host = sdhci_pci_priv(slot); + struct mmc_host *mmc = slot->host->mmc; + struct dentry *dir = mmc->debugfs_root; + + if (!intel_use_ltr(slot->chip)) + return; + + debugfs_create_x32("active_ltr", 0444, dir, &intel_host->active_ltr); + debugfs_create_x32("idle_ltr", 0444, dir, &intel_host->idle_ltr); + + intel_cache_ltr(slot); +} + +static int byt_add_host(struct sdhci_pci_slot *slot) +{ + int ret = sdhci_add_host(slot->host); + + if (!ret) + byt_add_debugfs(slot); + return ret; +} + +static void byt_remove_slot(struct sdhci_pci_slot *slot, int dead) +{ + struct mmc_host *mmc = slot->host->mmc; + + if (!mmc->slotno) + intel_ltr_hide(slot->chip); } static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) @@ -859,6 +1002,8 @@ static int glk_emmc_add_host(struct sdhc if (ret) goto cleanup; + byt_add_debugfs(slot); + return 0; cleanup: @@ -1036,6 +1181,8 @@ static const struct sdhci_pci_fixes sdhc #endif .allow_runtime_pm = true, .probe_slot = byt_emmc_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_NO_LED, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | @@ -1049,6 +1196,7 @@ static const struct sdhci_pci_fixes sdhc .allow_runtime_pm = true, .probe_slot = glk_emmc_probe_slot, .add_host = glk_emmc_add_host, + .remove_slot = byt_remove_slot, #ifdef CONFIG_PM_SLEEP .suspend = sdhci_cqhci_suspend, .resume = sdhci_cqhci_resume, @@ -1079,6 +1227,8 @@ static const struct sdhci_pci_fixes sdhc SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = ni_byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), }; @@ -1096,6 +1246,8 @@ static const struct sdhci_pci_fixes sdhc SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), }; @@ -1115,6 +1267,8 @@ static const struct sdhci_pci_fixes sdhc .allow_runtime_pm = true, .own_cd_for_runtime_pm = true, .probe_slot = byt_sd_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };