Commit 0ea67fae authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC fixes from Ulf Hansson:
 "Here are some mmc fixes intended for v4.9 rc2.

  This time I have also included a few changes for a memstick driver
  which has a corresponding mmc driver. They use the same USB device as
  parent, hence both needs to play nice with runtime PM, which they
  didn't.

  MMC core:
   - Update MAINTAINERS as the mmc tree moved to kernel.org
   - A few fixes for HS400es mode
   - A few other minor fixes

  MMC host:
   - sdhci: Fix an issue when dealing with stop commands
   - sdhci-pci: Fix a bus power failure issue
   - sdhci-esdhc-imx: Correct two register accesses
   - sdhci-of-arasan: Fix the 1.8V I/O signal switch behaviour
   - rtsx_usb_sdmmc: Fix runtime PM issues

  Other: (Because of no maintainer)
   - memstick: rtsx_usb_ms: Fix runtime PM issues"

* tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  MAINTAINERS: mmc: Move the mmc tree to kernel.org
  memstick: rtsx_usb_ms: Manage runtime PM when accessing the device
  memstick: rtsx_usb_ms: Runtime resume the device when polling for cards
  mmc: rtsx_usb_sdmmc: Handle runtime PM while changing the led
  mmc: rtsx_usb_sdmmc: Avoid keeping the device runtime resumed when unused
  mmc: sdhci: cast unsigned int to unsigned long long to avoid unexpeted error
  mmc: sdhci-esdhc-imx: Correct two register accesses
  mmc: sdhci-pci: Fix bus power failing to enable for some Intel controllers
  mmc: sdhci-pci: Let devices define their own sdhci_ops
  mmc: sdhci: Rename sdhci_set_power() to sdhci_set_power_noreg()
  mmc: sdhci: Fix SDHCI_QUIRK2_STOP_WITH_TC
  mmc: core: Annotate cmd_hdr as __le32
  mmc: sdhci-of-arasan: add sdhci_arasan_voltage_switch for arasan, 5.1
  mmc: core: changes frequency to hs_max_dtr when selecting hs400es
  mmc: core: switch to 1V8 or 1V2 for hs400es mode
  mmc: block: add missing header dependencies
  mmc: sdhci-of-arasan: Fix non static symbol warning
parents a28ad14e 82bb095e
...@@ -8212,7 +8212,7 @@ F: include/linux/mfd/ ...@@ -8212,7 +8212,7 @@ F: include/linux/mfd/
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
M: Ulf Hansson <ulf.hansson@linaro.org> M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
T: git git://git.linaro.org/people/ulf.hansson/mmc.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/mmc/ F: Documentation/devicetree/bindings/mmc/
F: drivers/mmc/ F: drivers/mmc/
......
...@@ -524,6 +524,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work) ...@@ -524,6 +524,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work)
int rc; int rc;
if (!host->req) { if (!host->req) {
pm_runtime_get_sync(ms_dev(host));
do { do {
rc = memstick_next_req(msh, &host->req); rc = memstick_next_req(msh, &host->req);
dev_dbg(ms_dev(host), "next req %d\n", rc); dev_dbg(ms_dev(host), "next req %d\n", rc);
...@@ -544,6 +545,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work) ...@@ -544,6 +545,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work)
host->req->error); host->req->error);
} }
} while (!rc); } while (!rc);
pm_runtime_put(ms_dev(host));
} }
} }
...@@ -570,6 +572,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh, ...@@ -570,6 +572,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh,
dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
__func__, param, value); __func__, param, value);
pm_runtime_get_sync(ms_dev(host));
mutex_lock(&ucr->dev_mutex); mutex_lock(&ucr->dev_mutex);
err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD); err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD);
...@@ -635,6 +638,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh, ...@@ -635,6 +638,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh,
} }
out: out:
mutex_unlock(&ucr->dev_mutex); mutex_unlock(&ucr->dev_mutex);
pm_runtime_put(ms_dev(host));
/* power-on delay */ /* power-on delay */
if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON)
...@@ -681,6 +685,7 @@ static int rtsx_usb_detect_ms_card(void *__host) ...@@ -681,6 +685,7 @@ static int rtsx_usb_detect_ms_card(void *__host)
int err; int err;
for (;;) { for (;;) {
pm_runtime_get_sync(ms_dev(host));
mutex_lock(&ucr->dev_mutex); mutex_lock(&ucr->dev_mutex);
/* Check pending MS card changes */ /* Check pending MS card changes */
...@@ -703,6 +708,7 @@ static int rtsx_usb_detect_ms_card(void *__host) ...@@ -703,6 +708,7 @@ static int rtsx_usb_detect_ms_card(void *__host)
} }
poll_again: poll_again:
pm_runtime_put(ms_dev(host));
if (host->eject) if (host->eject)
break; break;
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "queue.h" #include "queue.h"
#include "block.h"
MODULE_ALIAS("mmc:block"); MODULE_ALIAS("mmc:block");
#ifdef MODULE_PARAM_PREFIX #ifdef MODULE_PARAM_PREFIX
...@@ -1786,7 +1787,7 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, ...@@ -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_blk_data *md = mq->data;
struct mmc_packed *packed = mqrq->packed; struct mmc_packed *packed = mqrq->packed;
bool do_rel_wr, do_data_tag; bool do_rel_wr, do_data_tag;
u32 *packed_cmd_hdr; __le32 *packed_cmd_hdr;
u8 hdr_blocks; u8 hdr_blocks;
u8 i = 1; u8 i = 1;
......
...@@ -31,7 +31,7 @@ enum mmc_packed_type { ...@@ -31,7 +31,7 @@ enum mmc_packed_type {
struct mmc_packed { struct mmc_packed {
struct list_head list; struct list_head list;
u32 cmd_hdr[1024]; __le32 cmd_hdr[1024];
unsigned int blocks; unsigned int blocks;
u8 nr_entries; u8 nr_entries;
u8 retries; u8 retries;
......
...@@ -1263,6 +1263,16 @@ static int mmc_select_hs400es(struct mmc_card *card) ...@@ -1263,6 +1263,16 @@ static int mmc_select_hs400es(struct mmc_card *card)
goto out_err; 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); err = mmc_select_bus_width(card);
if (err < 0) if (err < 0)
goto out_err; goto out_err;
...@@ -1272,6 +1282,8 @@ static int mmc_select_hs400es(struct mmc_card *card) ...@@ -1272,6 +1282,8 @@ static int mmc_select_hs400es(struct mmc_card *card)
if (err) if (err)
goto out_err; goto out_err;
mmc_set_clock(host, card->ext_csd.hs_max_dtr);
err = mmc_switch_status(card); err = mmc_switch_status(card);
if (err) if (err)
goto out_err; goto out_err;
......
...@@ -1138,11 +1138,6 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -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__); dev_dbg(sdmmc_dev(host), "%s\n", __func__);
mutex_lock(&ucr->dev_mutex); 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_power_mode(host, ios->power_mode);
sd_set_bus_width(host, ios->bus_width); sd_set_bus_width(host, ios->bus_width);
sd_set_timing(host, ios->timing, &host->ddr_mode); sd_set_timing(host, ios->timing, &host->ddr_mode);
...@@ -1314,6 +1309,7 @@ static void rtsx_usb_update_led(struct work_struct *work) ...@@ -1314,6 +1309,7 @@ static void rtsx_usb_update_led(struct work_struct *work)
container_of(work, struct rtsx_usb_sdmmc, led_work); container_of(work, struct rtsx_usb_sdmmc, led_work);
struct rtsx_ucr *ucr = host->ucr; struct rtsx_ucr *ucr = host->ucr;
pm_runtime_get_sync(sdmmc_dev(host));
mutex_lock(&ucr->dev_mutex); mutex_lock(&ucr->dev_mutex);
if (host->led.brightness == LED_OFF) if (host->led.brightness == LED_OFF)
...@@ -1322,6 +1318,7 @@ static void rtsx_usb_update_led(struct work_struct *work) ...@@ -1322,6 +1318,7 @@ static void rtsx_usb_update_led(struct work_struct *work)
rtsx_usb_turn_on_led(ucr); rtsx_usb_turn_on_led(ucr);
mutex_unlock(&ucr->dev_mutex); mutex_unlock(&ucr->dev_mutex);
pm_runtime_put(sdmmc_dev(host));
} }
#endif #endif
......
...@@ -346,7 +346,8 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) ...@@ -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); struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
u32 data; 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)) { if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) {
/* /*
* Clear and then set D3CD bit to avoid missing the * 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) ...@@ -555,6 +556,25 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
esdhc_clrset_le(host, 0xffff, val, 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) static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
{ {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 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) ...@@ -947,6 +967,7 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
static struct sdhci_ops sdhci_esdhc_ops = { static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le, .read_l = esdhc_readl_le,
.read_w = esdhc_readw_le, .read_w = esdhc_readw_le,
.read_b = esdhc_readb_le,
.write_l = esdhc_writel_le, .write_l = esdhc_writel_le,
.write_w = esdhc_writew_le, .write_w = esdhc_writew_le,
.write_b = esdhc_writeb_le, .write_b = esdhc_writeb_le,
......
...@@ -250,7 +250,7 @@ static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc, ...@@ -250,7 +250,7 @@ static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,
writel(vendor, host->ioaddr + SDHCI_ARASAN_VENDOR_REGISTER); 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; u8 ctrl;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
...@@ -265,6 +265,28 @@ void sdhci_arasan_reset(struct sdhci_host *host, u8 mask) ...@@ -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 = { static struct sdhci_ops sdhci_arasan_ops = {
.set_clock = sdhci_arasan_set_clock, .set_clock = sdhci_arasan_set_clock,
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
...@@ -661,6 +683,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev) ...@@ -661,6 +683,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
host->mmc_host_ops.hs400_enhanced_strobe = host->mmc_host_ops.hs400_enhanced_strobe =
sdhci_arasan_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); ret = sdhci_add_host(host);
......
...@@ -32,6 +32,14 @@ ...@@ -32,6 +32,14 @@
#include "sdhci-pci.h" #include "sdhci-pci.h"
#include "sdhci-pci-o2micro.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 * * Hardware specific quirk handling *
...@@ -390,6 +398,45 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) ...@@ -390,6 +398,45 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
return 0; 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 = { static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
.allow_runtime_pm = true, .allow_runtime_pm = true,
.probe_slot = byt_emmc_probe_slot, .probe_slot = byt_emmc_probe_slot,
...@@ -397,6 +444,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { ...@@ -397,6 +444,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 |
SDHCI_QUIRK2_STOP_WITH_TC, SDHCI_QUIRK2_STOP_WITH_TC,
.ops = &sdhci_intel_byt_ops,
}; };
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
...@@ -405,6 +453,7 @@ 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, SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.allow_runtime_pm = true, .allow_runtime_pm = true,
.probe_slot = byt_sdio_probe_slot, .probe_slot = byt_sdio_probe_slot,
.ops = &sdhci_intel_byt_ops,
}; };
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
...@@ -415,6 +464,7 @@ 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, .allow_runtime_pm = true,
.own_cd_for_runtime_pm = true, .own_cd_for_runtime_pm = true,
.probe_slot = byt_sd_probe_slot, .probe_slot = byt_sd_probe_slot,
.ops = &sdhci_intel_byt_ops,
}; };
/* Define Host controllers for Intel Merrifield platform */ /* Define Host controllers for Intel Merrifield platform */
...@@ -1648,7 +1698,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( ...@@ -1648,7 +1698,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
} }
host->hw_name = "PCI"; 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->quirks = chip->quirks;
host->quirks2 = chip->quirks2; host->quirks2 = chip->quirks2;
......
...@@ -65,6 +65,8 @@ struct sdhci_pci_fixes { ...@@ -65,6 +65,8 @@ struct sdhci_pci_fixes {
int (*suspend) (struct sdhci_pci_chip *); int (*suspend) (struct sdhci_pci_chip *);
int (*resume) (struct sdhci_pci_chip *); int (*resume) (struct sdhci_pci_chip *);
const struct sdhci_ops *ops;
}; };
struct sdhci_pci_slot { struct sdhci_pci_slot {
......
...@@ -315,7 +315,7 @@ static void pxav3_set_power(struct sdhci_host *host, unsigned char mode, ...@@ -315,7 +315,7 @@ static void pxav3_set_power(struct sdhci_host *host, unsigned char mode,
struct mmc_host *mmc = host->mmc; struct mmc_host *mmc = host->mmc;
u8 pwr = host->pwr; u8 pwr = host->pwr;
sdhci_set_power(host, mode, vdd); sdhci_set_power_noreg(host, mode, vdd);
if (host->pwr == pwr) if (host->pwr == pwr)
return; return;
......
...@@ -687,7 +687,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) ...@@ -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. * host->clock is in Hz. target_timeout is in us.
* Hence, us = 1000000 * cycles / Hz. Round up. * Hence, us = 1000000 * cycles / Hz. Round up.
*/ */
val = 1000000 * data->timeout_clks; val = 1000000ULL * data->timeout_clks;
if (do_div(val, host->clock)) if (do_div(val, host->clock))
target_timeout++; target_timeout++;
target_timeout += val; target_timeout += val;
...@@ -1077,6 +1077,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) ...@@ -1077,6 +1077,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
/* Initially, a command has no error */ /* Initially, a command has no error */
cmd->error = 0; 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 */ /* Wait max 10 ms */
timeout = 10; timeout = 10;
...@@ -1390,7 +1394,7 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, ...@@ -1390,7 +1394,7 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
} }
void sdhci_set_power(struct sdhci_host *host, unsigned char mode, void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
unsigned short vdd) unsigned short vdd)
{ {
u8 pwr = 0; u8 pwr = 0;
...@@ -1455,20 +1459,17 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode, ...@@ -1455,20 +1459,17 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
mdelay(10); 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, void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
unsigned short vdd) unsigned short vdd)
{ {
struct mmc_host *mmc = host->mmc; if (IS_ERR(host->mmc->supply.vmmc))
sdhci_set_power_noreg(host, mode, vdd);
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);
else 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) ...@@ -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) if (host->ops->platform_send_init_74_clocks)
host->ops->platform_send_init_74_clocks(host, ios->power_mode); host->ops->platform_send_init_74_clocks(host, ios->power_mode);
...@@ -2409,7 +2413,7 @@ static void sdhci_timeout_data_timer(unsigned long data) ...@@ -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) { if (!host->cmd) {
/* /*
...@@ -2453,11 +2457,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) ...@@ -2453,11 +2457,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
return; 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) if (intmask & SDHCI_INT_RESPONSE)
sdhci_finish_command(host); sdhci_finish_command(host);
} }
...@@ -2680,8 +2679,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) ...@@ -2680,8 +2679,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
} }
if (intmask & SDHCI_INT_CMD_MASK) if (intmask & SDHCI_INT_CMD_MASK)
sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
&intmask);
if (intmask & SDHCI_INT_DATA_MASK) if (intmask & SDHCI_INT_DATA_MASK)
sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
......
...@@ -683,6 +683,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, ...@@ -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_clock(struct sdhci_host *host, unsigned int clock);
void sdhci_set_power(struct sdhci_host *host, unsigned char mode, void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
unsigned short vdd); 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_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask); void sdhci_reset(struct sdhci_host *host, u8 mask);
void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment