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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYCJimAAoJEP4mhCVzWIwpCi0P/0IQuR0GoR1DSYz6L8WXshn0 xsHyOB19/vWoQQZH41UzpqvMQq8AMSnkTPjoEYtUDzRsmyncsb4W+OV6I957RihM saKmz71hPm8AqN6IyoYIXYubDNAQ4mWcY75StkbQ1UHuFgW66Dn2Yncm1Kq4a9px e0/GKS3gAE5fG/524PwW6J8JvtkkZ8QTOun9ltZolAIZ7uqLYBL2n77d0AtO94Wf ZeUW+Ud+W5Pf1PeEvAfgAEz9FTiUQEft/KI37nX6qOD9YDJszZnN29gf+kTxIGmk b67yDHx2YaLMqP2yYO+7QtMPpIAJpmhZw9llVDJInqad8EmQIqHZU54I7F+2SoAq nE71LFSNuXk+ZPE4ty5KvnnftbOi97x0FfqslspNdvl+wnprChPKTJCw7H4cZLEs vUUiUDZg8SEfg3S/iX/9C1CdpYx0inVN8SzyG6EhVFotsHAJvK3jZ4mW/YDCaz3n RVVjE9mgFemW2Q3OW+Ow4mNgcIOevfXJZoX4vZxNU/YV7NPxUhkcxLTzaWYyon+U H52ClmLGNUhmm39vMGOC9ZhSGTlzjM/CdRBUQgUeUDDfARLg1+YABSzDAWf3WcH7 7vtxjGyCleMXU+c6MdkvlFmkuhGsZhkON+0Po5rZfYqLluKaM4U3Z4vO4oKpDFVT XpfC33TvafXmlSEcGQxp =Oy6R -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
0ea67fae9e
@ -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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
poll_again:
|
poll_again:
|
||||||
|
pm_runtime_put(ms_dev(host));
|
||||||
if (host->eject)
|
if (host->eject)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -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,
|
|||||||
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 {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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)
|
|||||||
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 = {
|
|||||||
.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 = {
|
|||||||
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 = {
|
|||||||
.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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
/* 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,8 +1394,8 @@ 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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__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)
|
|||||||
* *
|
* *
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user