diff options
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 70 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_core.c | 19 | ||||
-rw-r--r-- | drivers/mmc/host/wbsd.c | 2 |
3 files changed, 74 insertions, 17 deletions
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index cf66a3db71b8..ac678e9fb19a 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -45,6 +45,7 @@ #include <asm/cpu_device_id.h> #include <asm/intel-family.h> #include <asm/iosf_mbi.h> +#include <linux/pci.h> #endif #include "sdhci.h" @@ -134,6 +135,16 @@ static bool sdhci_acpi_byt(void) return x86_match_cpu(byt); } +static bool sdhci_acpi_cht(void) +{ + static const struct x86_cpu_id cht[] = { + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, + {} + }; + + return x86_match_cpu(cht); +} + #define BYT_IOSF_SCCEP 0x63 #define BYT_IOSF_OCP_NETCTRL0 0x1078 #define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8) @@ -178,6 +189,45 @@ static bool sdhci_acpi_byt_defer(struct device *dev) return false; } +static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device, + unsigned int slot, unsigned int parent_slot) +{ + struct pci_dev *dev, *parent, *from = NULL; + + while (1) { + dev = pci_get_device(vendor, device, from); + pci_dev_put(from); + if (!dev) + break; + parent = pci_upstream_bridge(dev); + if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot && + parent && PCI_SLOT(parent->devfn) == parent_slot && + !pci_upstream_bridge(parent)) { + pci_dev_put(dev); + return true; + } + from = dev; + } + + return false; +} + +/* + * GPDwin uses PCI wifi which conflicts with SDIO's use of + * acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is + * problematic, but since SDIO is only used for wifi, the presence of the PCI + * wifi card in the expected slot with an ACPI companion node, is used to + * indicate that acpi_device_fix_up_power() should be avoided. + */ +static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, + const char *uid) +{ + return sdhci_acpi_cht() && + !strcmp(hid, "80860F14") && + !strcmp(uid, "2") && + sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28); +} + #else static inline void sdhci_acpi_byt_setting(struct device *dev) @@ -189,6 +239,12 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev) return false; } +static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, + const char *uid) +{ + return false; +} + #endif static int bxt_get_cd(struct mmc_host *mmc) @@ -389,18 +445,20 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (acpi_bus_get_device(handle, &device)) return -ENODEV; + hid = acpi_device_hid(device); + uid = device->pnp.unique_id; + /* Power on the SDHCI controller and its children */ acpi_device_fix_up_power(device); - list_for_each_entry(child, &device->children, node) - if (child->status.present && child->status.enabled) - acpi_device_fix_up_power(child); + if (!sdhci_acpi_no_fixup_child_power(hid, uid)) { + list_for_each_entry(child, &device->children, node) + if (child->status.present && child->status.enabled) + acpi_device_fix_up_power(child); + } if (sdhci_acpi_byt_defer(dev)) return -EPROBE_DEFER; - hid = acpi_device_hid(device); - uid = device->pnp.unique_id; - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) return -ENOMEM; diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 82b80d42f7ae..88a94355ac90 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -409,30 +409,29 @@ static void tmio_mmc_transfer_data(struct tmio_mmc_host *host, * Transfer the data */ if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) { - u8 data[4] = { }; + u32 data = 0; + u32 *buf32 = (u32 *)buf; if (is_read) - sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf, + sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, buf32, count >> 2); else - sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf, + sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, buf32, count >> 2); /* if count was multiple of 4 */ if (!(count & 0x3)) return; - buf8 = (u8 *)(buf + (count >> 2)); + buf32 += count >> 2; count %= 4; if (is_read) { - sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, - (u32 *)data, 1); - memcpy(buf8, data, count); + sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, &data, 1); + memcpy(buf32, &data, count); } else { - memcpy(data, buf8, count); - sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, - (u32 *)data, 1); + memcpy(&data, buf32, count); + sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, &data, 1); } return; diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index e15a9733fcfd..9668616faf16 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1386,7 +1386,7 @@ static void wbsd_request_dma(struct wbsd_host *host, int dma) * order for ISA to be able to DMA to it. */ host->dma_buffer = kmalloc(WBSD_DMA_SIZE, - GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN); + GFP_NOIO | GFP_DMA | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); if (!host->dma_buffer) goto free; |