diff options
author | 2016-11-04 21:04:44 +0100 | |
---|---|---|
committer | 2016-11-04 21:04:44 +0100 | |
commit | f8f93bc9d2a29c81cc6a4e6d7c87a6f712dbbeeb (patch) | |
tree | 7e07960f43f7a6c985f75ee5b629121e9799bfdb /drivers/mmc | |
parent | ALSA: usb-audio: Add quirk for Syntek STK1160 (diff) | |
parent | Merge remote-tracking branch 'asoc/fix/topology-abi' into asoc-linus (diff) | |
download | linux-dev-f8f93bc9d2a29c81cc6a4e6d7c87a6f712dbbeeb.tar.xz linux-dev-f8f93bc9d2a29c81cc6a4e6d7c87a6f712dbbeeb.zip |
Merge tag 'asoc-fix-v4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v4.9
The most important fix in here is a change which removes the #error
making the topology API unusable as-is since we have recently discovered
some production uses on Chromebooks so need to acknowledge that what
we've got there now is an ABI.
There's also a very big batch of driver specific fixes here which have
kept on being delayed due to more arriving so the update is another of
these bigger than I would like ones. There is one especially big one in
there, for the Qualcomm code which fixes simultaneous playback and
capture which was broken during the merge window. The diff for that is
large because it moves blocks of code to different functions but it's
functionally fairly simple and if it breaks it should have been very
obvious in testing.
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 3 | ||||
-rw-r--r-- | drivers/mmc/card/queue.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 12 | ||||
-rw-r--r-- | drivers/mmc/host/rtsx_usb_sdmmc.c | 7 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 23 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-of-arasan.c | 26 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 54 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci.h | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pxav3.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 42 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 2 |
11 files changed, 142 insertions, 33 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c3335112e68c..709a872ed484 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -46,6 +46,7 @@ #include <asm/uaccess.h> #include "queue.h" +#include "block.h" MODULE_ALIAS("mmc:block"); #ifdef MODULE_PARAM_PREFIX @@ -1786,7 +1787,7 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, struct mmc_blk_data *md = mq->data; struct mmc_packed *packed = mqrq->packed; bool do_rel_wr, do_data_tag; - u32 *packed_cmd_hdr; + __le32 *packed_cmd_hdr; u8 hdr_blocks; u8 i = 1; diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 3c15a75bae86..342f1e3f301e 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -31,7 +31,7 @@ enum mmc_packed_type { struct mmc_packed { struct list_head list; - u32 cmd_hdr[1024]; + __le32 cmd_hdr[1024]; unsigned int blocks; u8 nr_entries; u8 retries; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 3486bc7fbb64..39fc5b2b96c5 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1263,6 +1263,16 @@ static int mmc_select_hs400es(struct mmc_card *card) goto out_err; } + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + + if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V) + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + + /* If fails try again during next card power cycle */ + if (err) + goto out_err; + err = mmc_select_bus_width(card); if (err < 0) goto out_err; @@ -1272,6 +1282,8 @@ static int mmc_select_hs400es(struct mmc_card *card) if (err) goto out_err; + mmc_set_clock(host, card->ext_csd.hs_max_dtr); + err = mmc_switch_status(card); if (err) goto out_err; diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 4106295527b9..6e9c0f8fddb1 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -1138,11 +1138,6 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) dev_dbg(sdmmc_dev(host), "%s\n", __func__); mutex_lock(&ucr->dev_mutex); - if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) { - mutex_unlock(&ucr->dev_mutex); - return; - } - sd_set_power_mode(host, ios->power_mode); sd_set_bus_width(host, ios->bus_width); sd_set_timing(host, ios->timing, &host->ddr_mode); @@ -1314,6 +1309,7 @@ static void rtsx_usb_update_led(struct work_struct *work) container_of(work, struct rtsx_usb_sdmmc, led_work); struct rtsx_ucr *ucr = host->ucr; + pm_runtime_get_sync(sdmmc_dev(host)); mutex_lock(&ucr->dev_mutex); if (host->led.brightness == LED_OFF) @@ -1322,6 +1318,7 @@ static void rtsx_usb_update_led(struct work_struct *work) rtsx_usb_turn_on_led(ucr); mutex_unlock(&ucr->dev_mutex); + pm_runtime_put(sdmmc_dev(host)); } #endif diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1f54fd8755c8..7123ef96ed18 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -346,7 +346,8 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); u32 data; - if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { + if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE || + reg == SDHCI_INT_STATUS)) { if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) { /* * Clear and then set D3CD bit to avoid missing the @@ -555,6 +556,25 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) esdhc_clrset_le(host, 0xffff, val, reg); } +static u8 esdhc_readb_le(struct sdhci_host *host, int reg) +{ + u8 ret; + u32 val; + + switch (reg) { + case SDHCI_HOST_CONTROL: + val = readl(host->ioaddr + reg); + + ret = val & SDHCI_CTRL_LED; + ret |= (val >> 5) & SDHCI_CTRL_DMA_MASK; + ret |= (val & ESDHC_CTRL_4BITBUS); + ret |= (val & ESDHC_CTRL_8BITBUS) << 3; + return ret; + } + + return readb(host->ioaddr + reg); +} + static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -947,6 +967,7 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl_le, .read_w = esdhc_readw_le, + .read_b = esdhc_readb_le, .write_l = esdhc_writel_le, .write_w = esdhc_writew_le, .write_b = esdhc_writeb_le, diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index da8e40af6f85..410a55b1c25f 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -250,7 +250,7 @@ static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc, writel(vendor, host->ioaddr + SDHCI_ARASAN_VENDOR_REGISTER); } -void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) +static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) { u8 ctrl; struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -265,6 +265,28 @@ void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) } } +static int sdhci_arasan_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_180: + /* + * Plese don't switch to 1V8 as arasan,5.1 doesn't + * actually refer to this setting to indicate the + * signal voltage and the state machine will be broken + * actually if we force to enable 1V8. That's something + * like broken quirk but we could work around here. + */ + return 0; + case MMC_SIGNAL_VOLTAGE_330: + case MMC_SIGNAL_VOLTAGE_120: + /* We don't support 3V3 and 1V2 */ + break; + } + + return -EINVAL; +} + static struct sdhci_ops sdhci_arasan_ops = { .set_clock = sdhci_arasan_set_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock, @@ -661,6 +683,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev) host->mmc_host_ops.hs400_enhanced_strobe = sdhci_arasan_hs400_enhanced_strobe; + host->mmc_host_ops.start_signal_voltage_switch = + sdhci_arasan_voltage_switch; } ret = sdhci_add_host(host); diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 72a1f1f5180a..1d9e00a00e9f 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -32,6 +32,14 @@ #include "sdhci-pci.h" #include "sdhci-pci-o2micro.h" +static int sdhci_pci_enable_dma(struct sdhci_host *host); +static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width); +static void sdhci_pci_hw_reset(struct sdhci_host *host); +static int sdhci_pci_select_drive_strength(struct sdhci_host *host, + struct mmc_card *card, + unsigned int max_dtr, int host_drv, + int card_drv, int *drv_type); + /*****************************************************************************\ * * * Hardware specific quirk handling * @@ -390,6 +398,45 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) return 0; } +#define SDHCI_INTEL_PWR_TIMEOUT_CNT 20 +#define SDHCI_INTEL_PWR_TIMEOUT_UDELAY 100 + +static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) +{ + int cntr; + u8 reg; + + sdhci_set_power(host, mode, vdd); + + if (mode == MMC_POWER_OFF) + return; + + /* + * Bus power might not enable after D3 -> D0 transition due to the + * present state not yet having propagated. Retry for up to 2ms. + */ + for (cntr = 0; cntr < SDHCI_INTEL_PWR_TIMEOUT_CNT; cntr++) { + reg = sdhci_readb(host, SDHCI_POWER_CONTROL); + if (reg & SDHCI_POWER_ON) + break; + udelay(SDHCI_INTEL_PWR_TIMEOUT_UDELAY); + reg |= SDHCI_POWER_ON; + sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); + } +} + +static const struct sdhci_ops sdhci_intel_byt_ops = { + .set_clock = sdhci_set_clock, + .set_power = sdhci_intel_set_power, + .enable_dma = sdhci_pci_enable_dma, + .set_bus_width = sdhci_pci_set_bus_width, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, + .hw_reset = sdhci_pci_hw_reset, + .select_drive_strength = sdhci_pci_select_drive_strength, +}; + static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { .allow_runtime_pm = true, .probe_slot = byt_emmc_probe_slot, @@ -397,6 +444,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | SDHCI_QUIRK2_STOP_WITH_TC, + .ops = &sdhci_intel_byt_ops, }; static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { @@ -405,6 +453,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = byt_sdio_probe_slot, + .ops = &sdhci_intel_byt_ops, }; static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { @@ -415,6 +464,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { .allow_runtime_pm = true, .own_cd_for_runtime_pm = true, .probe_slot = byt_sd_probe_slot, + .ops = &sdhci_intel_byt_ops, }; /* Define Host controllers for Intel Merrifield platform */ @@ -1648,7 +1698,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( } host->hw_name = "PCI"; - host->ops = &sdhci_pci_ops; + host->ops = chip->fixes && chip->fixes->ops ? + chip->fixes->ops : + &sdhci_pci_ops; host->quirks = chip->quirks; host->quirks2 = chip->quirks2; diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 9c7c08b93223..6bccf56bc5ff 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -65,6 +65,8 @@ struct sdhci_pci_fixes { int (*suspend) (struct sdhci_pci_chip *); int (*resume) (struct sdhci_pci_chip *); + + const struct sdhci_ops *ops; }; struct sdhci_pci_slot { diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index dd1938d341f7..d0f5c05fbc19 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -315,7 +315,7 @@ static void pxav3_set_power(struct sdhci_host *host, unsigned char mode, struct mmc_host *mmc = host->mmc; u8 pwr = host->pwr; - sdhci_set_power(host, mode, vdd); + sdhci_set_power_noreg(host, mode, vdd); if (host->pwr == pwr) return; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 48055666c655..71654b90227f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -687,7 +687,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) * host->clock is in Hz. target_timeout is in us. * Hence, us = 1000000 * cycles / Hz. Round up. */ - val = 1000000 * data->timeout_clks; + val = 1000000ULL * data->timeout_clks; if (do_div(val, host->clock)) target_timeout++; target_timeout += val; @@ -1077,6 +1077,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) /* Initially, a command has no error */ cmd->error = 0; + if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && + cmd->opcode == MMC_STOP_TRANSMISSION) + cmd->flags |= MMC_RSP_BUSY; + /* Wait max 10 ms */ timeout = 10; @@ -1390,8 +1394,8 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); } -void sdhci_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) +void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) { u8 pwr = 0; @@ -1455,20 +1459,17 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode, mdelay(10); } } -EXPORT_SYMBOL_GPL(sdhci_set_power); +EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); -static void __sdhci_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) +void sdhci_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) { - struct mmc_host *mmc = host->mmc; - - if (host->ops->set_power) - host->ops->set_power(host, mode, vdd); - else if (!IS_ERR(mmc->supply.vmmc)) - sdhci_set_power_reg(host, mode, vdd); + if (IS_ERR(host->mmc->supply.vmmc)) + sdhci_set_power_noreg(host, mode, vdd); else - sdhci_set_power(host, mode, vdd); + sdhci_set_power_reg(host, mode, vdd); } +EXPORT_SYMBOL_GPL(sdhci_set_power); /*****************************************************************************\ * * @@ -1609,7 +1610,10 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } - __sdhci_set_power(host, ios->power_mode, ios->vdd); + if (host->ops->set_power) + host->ops->set_power(host, ios->power_mode, ios->vdd); + else + sdhci_set_power(host, ios->power_mode, ios->vdd); if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks(host, ios->power_mode); @@ -2409,7 +2413,7 @@ static void sdhci_timeout_data_timer(unsigned long data) * * \*****************************************************************************/ -static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) +static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) { if (!host->cmd) { /* @@ -2453,11 +2457,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) return; } - if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && - !(host->cmd->flags & MMC_RSP_BUSY) && !host->data && - host->cmd->opcode == MMC_STOP_TRANSMISSION) - *mask &= ~SDHCI_INT_DATA_END; - if (intmask & SDHCI_INT_RESPONSE) sdhci_finish_command(host); } @@ -2680,8 +2679,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) } if (intmask & SDHCI_INT_CMD_MASK) - sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, - &intmask); + sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); if (intmask & SDHCI_INT_DATA_MASK) sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c722cd23205c..766df17fb7eb 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -683,6 +683,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, void sdhci_set_clock(struct sdhci_host *host, unsigned int clock); void sdhci_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd); +void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, + unsigned short vdd); void sdhci_set_bus_width(struct sdhci_host *host, int width); void sdhci_reset(struct sdhci_host *host, u8 mask); void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); |