diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2016-09-16 13:17:18 -0700 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2016-09-29 13:58:03 -0700 |
commit | cd89f007101ad44dc318b2aca826b5754c5ccfa9 (patch) | |
tree | 75cddcca3c07f8c06e053398eeb618f3da458169 /drivers/mmc | |
parent | 45de59e3f1511606433c294e9ec85c5b9d4f637f (diff) | |
parent | 1d074db69c46d62ce82b331c2080e2fcb710bf4a (diff) |
Merge tag 'v4.4.21' into toradex_vf_4.4-next
This is the 4.4.21 stable release
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 12 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 81 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 35 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 21 |
5 files changed, 115 insertions, 35 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c641c202fe7e..64950035613b 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1767,8 +1767,8 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, packed_cmd_hdr = packed->cmd_hdr; memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr)); - packed_cmd_hdr[0] = (packed->nr_entries << 16) | - (PACKED_CMD_WR << 8) | PACKED_CMD_VER; + packed_cmd_hdr[0] = cpu_to_le32((packed->nr_entries << 16) | + (PACKED_CMD_WR << 8) | PACKED_CMD_VER); hdr_blocks = mmc_large_sector(card) ? 8 : 1; /* @@ -1782,14 +1782,14 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, ((brq->data.blocks * brq->data.blksz) >= card->ext_csd.data_tag_unit_size); /* Argument of CMD23 */ - packed_cmd_hdr[(i * 2)] = + packed_cmd_hdr[(i * 2)] = cpu_to_le32( (do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) | (do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) | - blk_rq_sectors(prq); + blk_rq_sectors(prq)); /* Argument of CMD18 or CMD25 */ - packed_cmd_hdr[((i * 2)) + 1] = + packed_cmd_hdr[((i * 2)) + 1] = cpu_to_le32( mmc_card_blockaddr(card) ? - blk_rq_pos(prq) : blk_rq_pos(prq) << 9; + blk_rq_pos(prq) : blk_rq_pos(prq) << 9); packed->blocks += blk_rq_sectors(prq); i++; } diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1dee533634c9..2e6d2fff1096 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -97,6 +97,7 @@ config MMC_RICOH_MMC config MMC_SDHCI_ACPI tristate "SDHCI support for ACPI enumerated SDHCI controllers" depends on MMC_SDHCI && ACPI + select IOSF_MBI if X86 help This selects support for ACPI enumerated SDHCI controllers, identified by ACPI Compatibility ID PNP0D40 or specific diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 8aea3fa6938b..5a05bf400ca8 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -41,6 +41,11 @@ #include <linux/mmc/pm.h> #include <linux/mmc/slot-gpio.h> +#ifdef CONFIG_X86 +#include <asm/cpu_device_id.h> +#include <asm/iosf_mbi.h> +#endif + #include "sdhci.h" enum { @@ -146,6 +151,75 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { .ops = &sdhci_acpi_ops_int, }; +#ifdef CONFIG_X86 + +static bool sdhci_acpi_byt(void) +{ + static const struct x86_cpu_id byt[] = { + { X86_VENDOR_INTEL, 6, 0x37 }, + {} + }; + + return x86_match_cpu(byt); +} + +#define BYT_IOSF_SCCEP 0x63 +#define BYT_IOSF_OCP_NETCTRL0 0x1078 +#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8) + +static void sdhci_acpi_byt_setting(struct device *dev) +{ + u32 val = 0; + + if (!sdhci_acpi_byt()) + return; + + if (iosf_mbi_read(BYT_IOSF_SCCEP, 0x06, BYT_IOSF_OCP_NETCTRL0, + &val)) { + dev_err(dev, "%s read error\n", __func__); + return; + } + + if (!(val & BYT_IOSF_OCP_TIMEOUT_BASE)) + return; + + val &= ~BYT_IOSF_OCP_TIMEOUT_BASE; + + if (iosf_mbi_write(BYT_IOSF_SCCEP, 0x07, BYT_IOSF_OCP_NETCTRL0, + val)) { + dev_err(dev, "%s write error\n", __func__); + return; + } + + dev_dbg(dev, "%s completed\n", __func__); +} + +static bool sdhci_acpi_byt_defer(struct device *dev) +{ + if (!sdhci_acpi_byt()) + return false; + + if (!iosf_mbi_available()) + return true; + + sdhci_acpi_byt_setting(dev); + + return false; +} + +#else + +static inline void sdhci_acpi_byt_setting(struct device *dev) +{ +} + +static inline bool sdhci_acpi_byt_defer(struct device *dev) +{ + return false; +} + +#endif + static int bxt_get_cd(struct mmc_host *mmc) { int gpio_cd = mmc_gpio_get_cd(mmc); @@ -337,6 +411,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (acpi_bus_get_status(device) || !device->status.present) return -ENODEV; + if (sdhci_acpi_byt_defer(dev)) + return -EPROBE_DEFER; + hid = acpi_device_hid(device); uid = device->pnp.unique_id; @@ -460,6 +537,8 @@ static int sdhci_acpi_resume(struct device *dev) { struct sdhci_acpi_host *c = dev_get_drvdata(dev); + sdhci_acpi_byt_setting(&c->pdev->dev); + return sdhci_resume_host(c->host); } @@ -483,6 +562,8 @@ static int sdhci_acpi_runtime_resume(struct device *dev) { struct sdhci_acpi_host *c = dev_get_drvdata(dev); + sdhci_acpi_byt_setting(&c->pdev->dev); + return sdhci_runtime_resume_host(c->host); } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1a802af827ed..552a34dc4f82 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -492,7 +492,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, host->align_buffer, host->align_buffer_sz, direction); if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) goto fail; - BUG_ON(host->align_addr & host->align_mask); + BUG_ON(host->align_addr & SDHCI_ADMA2_MASK); host->sg_count = sdhci_pre_dma_transfer(host, data); if (host->sg_count < 0) @@ -514,8 +514,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, * the (up to three) bytes that screw up the * alignment. */ - offset = (host->align_sz - (addr & host->align_mask)) & - host->align_mask; + offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) & + SDHCI_ADMA2_MASK; if (offset) { if (data->flags & MMC_DATA_WRITE) { buffer = sdhci_kmap_atomic(sg, &flags); @@ -529,8 +529,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, BUG_ON(offset > 65536); - align += host->align_sz; - align_addr += host->align_sz; + align += SDHCI_ADMA2_ALIGN; + align_addr += SDHCI_ADMA2_ALIGN; desc += host->desc_sz; @@ -611,7 +611,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host, /* Do a quick scan of the SG list for any unaligned mappings */ has_unaligned = false; for_each_sg(data->sg, sg, host->sg_count, i) - if (sg_dma_address(sg) & host->align_mask) { + if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { has_unaligned = true; break; } @@ -623,15 +623,15 @@ static void sdhci_adma_table_post(struct sdhci_host *host, align = host->align_buffer; for_each_sg(data->sg, sg, host->sg_count, i) { - if (sg_dma_address(sg) & host->align_mask) { - size = host->align_sz - - (sg_dma_address(sg) & host->align_mask); + if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) { + size = SDHCI_ADMA2_ALIGN - + (sg_dma_address(sg) & SDHCI_ADMA2_MASK); buffer = sdhci_kmap_atomic(sg, &flags); memcpy(buffer, align, size); sdhci_kunmap_atomic(buffer, &flags); - align += host->align_sz; + align += SDHCI_ADMA2_ALIGN; } } } @@ -1315,7 +1315,9 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode, pwr = SDHCI_POWER_330; break; default: - BUG(); + WARN(1, "%s: Invalid vdd %#x\n", + mmc_hostname(host->mmc), vdd); + break; } } @@ -2983,24 +2985,17 @@ int sdhci_add_host(struct sdhci_host *host) if (host->flags & SDHCI_USE_64_BIT_DMA) { host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * SDHCI_ADMA2_64_DESC_SZ; - host->align_buffer_sz = SDHCI_MAX_SEGS * - SDHCI_ADMA2_64_ALIGN; host->desc_sz = SDHCI_ADMA2_64_DESC_SZ; - host->align_sz = SDHCI_ADMA2_64_ALIGN; - host->align_mask = SDHCI_ADMA2_64_ALIGN - 1; } else { host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * SDHCI_ADMA2_32_DESC_SZ; - host->align_buffer_sz = SDHCI_MAX_SEGS * - SDHCI_ADMA2_32_ALIGN; host->desc_sz = SDHCI_ADMA2_32_DESC_SZ; - host->align_sz = SDHCI_ADMA2_32_ALIGN; - host->align_mask = SDHCI_ADMA2_32_ALIGN - 1; } host->adma_table = dma_alloc_coherent(mmc_dev(mmc), host->adma_table_sz, &host->adma_addr, GFP_KERNEL); + host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL); if (!host->adma_table || !host->align_buffer) { if (host->adma_table) @@ -3014,7 +3009,7 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; host->adma_table = NULL; host->align_buffer = NULL; - } else if (host->adma_addr & host->align_mask) { + } else if (host->adma_addr & (SDHCI_ADMA2_DESC_ALIGN - 1)) { pr_warn("%s: unable to allocate aligned ADMA descriptor\n", mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 9c331ac5ad6b..0115e9907bf8 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -272,22 +272,27 @@ /* ADMA2 32-bit DMA descriptor size */ #define SDHCI_ADMA2_32_DESC_SZ 8 -/* ADMA2 32-bit DMA alignment */ -#define SDHCI_ADMA2_32_ALIGN 4 - /* ADMA2 32-bit descriptor */ struct sdhci_adma2_32_desc { __le16 cmd; __le16 len; __le32 addr; -} __packed __aligned(SDHCI_ADMA2_32_ALIGN); +} __packed __aligned(4); + +/* ADMA2 data alignment */ +#define SDHCI_ADMA2_ALIGN 4 +#define SDHCI_ADMA2_MASK (SDHCI_ADMA2_ALIGN - 1) + +/* + * ADMA2 descriptor alignment. Some controllers (e.g. Intel) require 8 byte + * alignment for the descriptor table even in 32-bit DMA mode. Memory + * allocation is at least 8 byte aligned anyway, so just stipulate 8 always. + */ +#define SDHCI_ADMA2_DESC_ALIGN 8 /* ADMA2 64-bit DMA descriptor size */ #define SDHCI_ADMA2_64_DESC_SZ 12 -/* ADMA2 64-bit DMA alignment */ -#define SDHCI_ADMA2_64_ALIGN 8 - /* * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte * aligned. @@ -483,8 +488,6 @@ struct sdhci_host { dma_addr_t align_addr; /* Mapped bounce buffer */ unsigned int desc_sz; /* ADMA descriptor size */ - unsigned int align_sz; /* ADMA alignment */ - unsigned int align_mask; /* ADMA alignment mask */ struct tasklet_struct finish_tasklet; /* Tasklet structures */ |