MMC host:
- rtsx_pci: Fix support for some various speed modes - sdhci-of-at91: Fix support for GPIO card detect on SAMA5D2 - sdhci-cadence: Fix support for DDR52 speed mode for eMMC on UniPhier - sdhci-acpi: Fix broken WP support on Acer Aspire Switch 10 - sdhci-acpi: Workaround FW bug for suspend on Lenovo Miix 320 -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAl5zyeEXHHVsZi5oYW5z c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCn/vA//XKlCkEtNbF9ll7FlC1e3k9OY RgG6C+C0HHgIpff2dl/7eUOYVDIE9TiP77mc+3ViiDcN4BeZpJCixp/obFUTj7tP LpbiRoop+VaCQpvoB4CB4qGfx6q1WBXWzErhupXF4JKG3sEH8cqHXTygch6fDq60 qktkBDIQRuwKKN+YxdKymSSb0kac5t9o+Lg6WDFMWWr3T2gzXQ4l61B+wJ1Zc5cN KgbbMPA9sc6DpQBuIfS9KrY+z7ofbqlJ70Ur1mnbHGByuyyri/amSSVT/vIzpiJU iSd1jxbpCuXE5Kfyf75oGfz+ijbz1JHw9lsKi9jrwjkTn40LarljOWlMB4Bbr/Ki m2Ywe4OnGWHaQpDnm4WThjFUgLaH6dh/WWOCe82W7XAWC5D2cpUH4TJfsCh6tp1z MwNQk7j0nmFU+SA87TAoAPpidMJ/fW3XAYWGmCehLGHAN/7WR5awnEpDYJD0dqN0 lFC7ptWk2Qb4tYX0R2Vxu3q/NbavA+BaE9qNPH4SLrFpINn6Hcy7uIzv+mDTgX3q QFiYl6PE3RkylMEO103LqF/p5Efg2Vlm0IdGFYrph5rrcOd5VCY/zxi9zZsLWhlo CjCd5BbNCPXhHoG7bAxSFPgyBaUNpogcYD6MTLsBTxcmZRjB9DbckdTjhKrKWBlx UyeQ3zLGVZwgt5pjMZM= =jupi -----END PGP SIGNATURE----- Merge tag 'mmc-v5.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: - rtsx_pci: Fix support for some various speed modes - sdhci-of-at91: Fix support for GPIO card detect on SAMA5D2 - sdhci-cadence: Fix support for DDR52 speed mode for eMMC on UniPhier - sdhci-acpi: Fix broken WP support on Acer Aspire Switch 10 - sdhci-acpi: Workaround FW bug for suspend on Lenovo Miix 320 * tag 'mmc-v5.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: rtsx_pci: Fix support for speed-modes that relies on tuning mmc: sdhci-of-at91: fix cd-gpios for SAMA5D2 mmc: sdhci-cadence: set SDHCI_QUIRK2_PRESET_VALUE_BROKEN for UniPhier mmc: sdhci-acpi: Disable write protect detection on Acer Aspire Switch 10 (SW5-012) mmc: sdhci-acpi: Switch signal voltage back to 3.3V on suspend on external microSD on Lenovo Miix 320
This commit is contained in:
commit
6c90b86a74
|
@ -394,7 +394,7 @@ static const struct pcr_ops rts522a_pcr_ops = {
|
|||
void rts522a_init_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rts5227_init_params(pcr);
|
||||
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 20, 11);
|
||||
pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
|
||||
|
||||
pcr->option.ocp_en = 1;
|
||||
|
|
|
@ -618,6 +618,7 @@ static const struct pcr_ops rts524a_pcr_ops = {
|
|||
void rts524a_init_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rts5249_init_params(pcr);
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 29, 11);
|
||||
pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
|
||||
pcr->option.ltr_l1off_snooze_sspwrgate =
|
||||
LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
|
||||
|
@ -733,6 +734,7 @@ static const struct pcr_ops rts525a_pcr_ops = {
|
|||
void rts525a_init_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rts5249_init_params(pcr);
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(25, 29, 11);
|
||||
pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
|
||||
pcr->option.ltr_l1off_snooze_sspwrgate =
|
||||
LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
|
||||
|
|
|
@ -662,7 +662,7 @@ void rts5260_init_params(struct rtsx_pcr *pcr)
|
|||
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 29, 11);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
|
||||
|
||||
pcr->ic_version = rts5260_get_ic_version(pcr);
|
||||
|
|
|
@ -764,7 +764,7 @@ void rts5261_init_params(struct rtsx_pcr *pcr)
|
|||
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 27, 16);
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 11);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
|
||||
|
||||
pcr->ic_version = rts5261_get_ic_version(pcr);
|
||||
|
|
|
@ -606,19 +606,22 @@ static int sd_change_phase(struct realtek_pci_sdmmc *host,
|
|||
u8 sample_point, bool rx)
|
||||
{
|
||||
struct rtsx_pcr *pcr = host->pcr;
|
||||
|
||||
u16 SD_VP_CTL = 0;
|
||||
dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n",
|
||||
__func__, rx ? "RX" : "TX", sample_point);
|
||||
|
||||
rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
|
||||
if (rx)
|
||||
if (rx) {
|
||||
SD_VP_CTL = SD_VPRX_CTL;
|
||||
rtsx_pci_write_register(pcr, SD_VPRX_CTL,
|
||||
PHASE_SELECT_MASK, sample_point);
|
||||
else
|
||||
} else {
|
||||
SD_VP_CTL = SD_VPTX_CTL;
|
||||
rtsx_pci_write_register(pcr, SD_VPTX_CTL,
|
||||
PHASE_SELECT_MASK, sample_point);
|
||||
rtsx_pci_write_register(pcr, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
|
||||
rtsx_pci_write_register(pcr, SD_VPCLK0_CTL, PHASE_NOT_RESET,
|
||||
}
|
||||
rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET, 0);
|
||||
rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET,
|
||||
PHASE_NOT_RESET);
|
||||
rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, 0);
|
||||
rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/pm.h>
|
||||
|
@ -72,9 +73,16 @@ struct sdhci_acpi_host {
|
|||
const struct sdhci_acpi_slot *slot;
|
||||
struct platform_device *pdev;
|
||||
bool use_runtime_pm;
|
||||
bool is_intel;
|
||||
bool reset_signal_volt_on_suspend;
|
||||
unsigned long private[0] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
enum {
|
||||
DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP = BIT(0),
|
||||
DMI_QUIRK_SD_NO_WRITE_PROTECT = BIT(1),
|
||||
};
|
||||
|
||||
static inline void *sdhci_acpi_priv(struct sdhci_acpi_host *c)
|
||||
{
|
||||
return (void *)c->private;
|
||||
|
@ -391,6 +399,8 @@ static int intel_probe_slot(struct platform_device *pdev, struct acpi_device *ad
|
|||
host->mmc_host_ops.start_signal_voltage_switch =
|
||||
intel_start_signal_voltage_switch;
|
||||
|
||||
c->is_intel = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -647,6 +657,36 @@ static const struct acpi_device_id sdhci_acpi_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
|
||||
|
||||
static const struct dmi_system_id sdhci_acpi_quirks[] = {
|
||||
{
|
||||
/*
|
||||
* The Lenovo Miix 320-10ICR has a bug in the _PS0 method of
|
||||
* the SHC1 ACPI device, this bug causes it to reprogram the
|
||||
* wrong LDO (DLDO3) to 1.8V if 1.8V modes are used and the
|
||||
* card is (runtime) suspended + resumed. DLDO3 is used for
|
||||
* the LCD and setting it to 1.8V causes the LCD to go black.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
|
||||
},
|
||||
.driver_data = (void *)DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* The Acer Aspire Switch 10 (SW5-012) microSD slot always
|
||||
* reports the card being write-protected even though microSD
|
||||
* cards do not have a write-protect switch at all.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
|
||||
},
|
||||
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
|
||||
},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
|
||||
static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(struct acpi_device *adev)
|
||||
{
|
||||
const struct sdhci_acpi_uid_slot *u;
|
||||
|
@ -663,17 +703,23 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
const struct sdhci_acpi_slot *slot;
|
||||
struct acpi_device *device, *child;
|
||||
const struct dmi_system_id *id;
|
||||
struct sdhci_acpi_host *c;
|
||||
struct sdhci_host *host;
|
||||
struct resource *iomem;
|
||||
resource_size_t len;
|
||||
size_t priv_size;
|
||||
int quirks = 0;
|
||||
int err;
|
||||
|
||||
device = ACPI_COMPANION(dev);
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
id = dmi_first_match(sdhci_acpi_quirks);
|
||||
if (id)
|
||||
quirks = (long)id->driver_data;
|
||||
|
||||
slot = sdhci_acpi_get_slot(device);
|
||||
|
||||
/* Power on the SDHCI controller and its children */
|
||||
|
@ -759,6 +805,12 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
|||
dev_warn(dev, "failed to setup card detect gpio\n");
|
||||
c->use_runtime_pm = false;
|
||||
}
|
||||
|
||||
if (quirks & DMI_QUIRK_RESET_SD_SIGNAL_VOLT_ON_SUSP)
|
||||
c->reset_signal_volt_on_suspend = true;
|
||||
|
||||
if (quirks & DMI_QUIRK_SD_NO_WRITE_PROTECT)
|
||||
host->mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
|
||||
}
|
||||
|
||||
err = sdhci_setup_host(host);
|
||||
|
@ -823,17 +875,39 @@ static int sdhci_acpi_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed(
|
||||
struct device *dev)
|
||||
{
|
||||
struct sdhci_acpi_host *c = dev_get_drvdata(dev);
|
||||
struct sdhci_host *host = c->host;
|
||||
|
||||
if (c->is_intel && c->reset_signal_volt_on_suspend &&
|
||||
host->mmc->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_330) {
|
||||
struct intel_host *intel_host = sdhci_acpi_priv(c);
|
||||
unsigned int fn = INTEL_DSM_V33_SWITCH;
|
||||
u32 result = 0;
|
||||
|
||||
intel_dsm(intel_host, dev, fn, &result);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int sdhci_acpi_suspend(struct device *dev)
|
||||
{
|
||||
struct sdhci_acpi_host *c = dev_get_drvdata(dev);
|
||||
struct sdhci_host *host = c->host;
|
||||
int ret;
|
||||
|
||||
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
|
||||
mmc_retune_needed(host->mmc);
|
||||
|
||||
return sdhci_suspend_host(host);
|
||||
ret = sdhci_suspend_host(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sdhci_acpi_reset_signal_voltage_if_needed(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdhci_acpi_resume(struct device *dev)
|
||||
|
@ -853,11 +927,17 @@ static int sdhci_acpi_runtime_suspend(struct device *dev)
|
|||
{
|
||||
struct sdhci_acpi_host *c = dev_get_drvdata(dev);
|
||||
struct sdhci_host *host = c->host;
|
||||
int ret;
|
||||
|
||||
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
|
||||
mmc_retune_needed(host->mmc);
|
||||
|
||||
return sdhci_runtime_suspend_host(host);
|
||||
ret = sdhci_runtime_suspend_host(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sdhci_acpi_reset_signal_voltage_if_needed(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdhci_acpi_runtime_resume(struct device *dev)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "sdhci-pltfm.h"
|
||||
|
||||
|
@ -235,6 +236,11 @@ static const struct sdhci_ops sdhci_cdns_ops = {
|
|||
.set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
|
||||
};
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_cdns_uniphier_pltfm_data = {
|
||||
.ops = &sdhci_cdns_ops,
|
||||
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
|
||||
};
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
|
||||
.ops = &sdhci_cdns_ops,
|
||||
};
|
||||
|
@ -334,6 +340,7 @@ static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
|
|||
static int sdhci_cdns_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sdhci_host *host;
|
||||
const struct sdhci_pltfm_data *data;
|
||||
struct sdhci_pltfm_host *pltfm_host;
|
||||
struct sdhci_cdns_priv *priv;
|
||||
struct clk *clk;
|
||||
|
@ -350,8 +357,12 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
data = of_device_get_match_data(dev);
|
||||
if (!data)
|
||||
data = &sdhci_cdns_pltfm_data;
|
||||
|
||||
nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node);
|
||||
host = sdhci_pltfm_init(pdev, &sdhci_cdns_pltfm_data,
|
||||
host = sdhci_pltfm_init(pdev, data,
|
||||
struct_size(priv, phy_params, nr_phy_params));
|
||||
if (IS_ERR(host)) {
|
||||
ret = PTR_ERR(host);
|
||||
|
@ -431,7 +442,10 @@ static const struct dev_pm_ops sdhci_cdns_pm_ops = {
|
|||
};
|
||||
|
||||
static const struct of_device_id sdhci_cdns_match[] = {
|
||||
{ .compatible = "socionext,uniphier-sd4hc" },
|
||||
{
|
||||
.compatible = "socionext,uniphier-sd4hc",
|
||||
.data = &sdhci_cdns_uniphier_pltfm_data,
|
||||
},
|
||||
{ .compatible = "cdns,sd4hc" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
|
|
@ -132,7 +132,8 @@ static void sdhci_at91_reset(struct sdhci_host *host, u8 mask)
|
|||
|
||||
sdhci_reset(host, mask);
|
||||
|
||||
if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
|
||||
if ((host->mmc->caps & MMC_CAP_NONREMOVABLE)
|
||||
|| mmc_gpio_get_cd(host->mmc) >= 0)
|
||||
sdhci_at91_set_force_card_detect(host);
|
||||
|
||||
if (priv->cal_always_on && (mask & SDHCI_RESET_ALL))
|
||||
|
@ -427,8 +428,11 @@ static int sdhci_at91_probe(struct platform_device *pdev)
|
|||
* detection procedure using the SDMCC_CD signal is bypassed.
|
||||
* This bit is reset when a software reset for all command is performed
|
||||
* so we need to implement our own reset function to set back this bit.
|
||||
*
|
||||
* WA: SAMA5D2 doesn't drive CMD if using CD GPIO line.
|
||||
*/
|
||||
if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
|
||||
if ((host->mmc->caps & MMC_CAP_NONREMOVABLE)
|
||||
|| mmc_gpio_get_cd(host->mmc) >= 0)
|
||||
sdhci_at91_set_force_card_detect(host);
|
||||
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
|
Loading…
Reference in New Issue