Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (42 commits)
  atmel-mci: fix sdc_reg typo
  tmio_mmc: add maintainer
  mmc: Add OpenFirmware bindings for SDHCI driver
  sdhci: Add quirk for forcing maximum block size to 2048 bytes
  sdhci: Add quirk for controllers that need IRQ re-init after reset
  sdhci: Add quirk for controllers that need small delays for PIO
  sdhci: Add set_clock callback and a quirk for nonstandard clocks
  sdhci: Add get_{max,timeout}_clock callbacks
  sdhci: Add support for hosts reporting inverted write-protect state
  sdhci: Add support for card-detection polling
  sdhci: Enable only relevant (DMA/PIO) interrupts during transfers
  sdhci: Split card-detection IRQs management from sdhci_init()
  sdhci: Add support for bus-specific IO memory accessors
  mmc_spi: adjust for delayed data token response
  omap_hsmmc: Wait for SDBP
  omap_hsmmc: Fix MMC3 dma
  omap_hsmmc: Disable SDBP at suspend
  omap_hsmmc: Do not prefix slot name
  omap_hsmmc: Allow cover switch to cause rescan
  omap_hsmmc: Add 8-bit bus width mode support
  ...
  • Loading branch information
Linus Torvalds committed Apr 5, 2009
2 parents 601cc11 + 32ab83a commit 0a053e8
Show file tree
Hide file tree
Showing 19 changed files with 2,109 additions and 272 deletions.
20 changes: 19 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2924,6 +2924,12 @@ M: buytenh@marvell.com
L: netdev@vger.kernel.org
S: Supported

MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
P: Nicolas Pitre
M: nico@cam.org
L: linux-kernel@vger.kernel.org
S: Maintained

MARVELL YUKON / SYSKONNECT DRIVER
P: Mirko Lindner
M: mlindner@syskonnect.de
Expand Down Expand Up @@ -3916,7 +3922,14 @@ S: Maintained
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
P: Pierre Ossman
M: drzeus-sdhci@drzeus.cx
L: sdhci-devel@list.drzeus.cx
L: sdhci-devel@lists.ossman.eu
S: Maintained

SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
P: Anton Vorontsov
M: avorontsov@ru.mvista.com
L: linuxppc-dev@ozlabs.org
L: sdhci-devel@lists.ossman.eu
S: Maintained

SECURITY SUBSYSTEM
Expand Down Expand Up @@ -4394,6 +4407,11 @@ L: tlinux-users@tce.toshiba-dme.co.jp
W: http://www.buzzard.org.uk/toshiba/
S: Maintained

TMIO MMC DRIVER
P: Ian Molton
M: ian@mnementh.co.uk
S: Maintained

TPM DEVICE DRIVER
P: Debora Velarde
M: debora@linux.vnet.ibm.com
Expand Down
2 changes: 2 additions & 0 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

#include "queue.h"

MODULE_ALIAS("mmc:block");

/*
* max 8 partitions per card
*/
Expand Down
8 changes: 8 additions & 0 deletions drivers/mmc/core/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
}

retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
if (retval)
return retval;

/*
* Request the mmc_block device. Note: that this is a direct request
* for the module it carries no information as to what is inserted.
*/
retval = add_uevent_var(env, "MODALIAS=mmc:block");

return retval;
}
Expand Down
18 changes: 18 additions & 0 deletions drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,21 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
data->timeout_clks = 0;
}
}
/*
* Some cards need very high timeouts if driven in SPI mode.
* The worst observed timeout was 900ms after writing a
* continuous stream of data until the internal logic
* overflowed.
*/
if (mmc_host_is_spi(card->host)) {
if (data->flags & MMC_DATA_WRITE) {
if (data->timeout_ns < 1000000000)
data->timeout_ns = 1000000000; /* 1s */
} else {
if (data->timeout_ns < 100000000)
data->timeout_ns = 100000000; /* 100ms */
}
}
}
EXPORT_SYMBOL(mmc_set_data_timeout);

Expand Down Expand Up @@ -915,6 +930,7 @@ void mmc_stop_host(struct mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
#endif

cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();

mmc_bus_get(host);
Expand Down Expand Up @@ -942,6 +958,7 @@ void mmc_stop_host(struct mmc_host *host)
*/
int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
{
cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();

mmc_bus_get(host);
Expand Down Expand Up @@ -975,6 +992,7 @@ int mmc_resume_host(struct mmc_host *host)
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
mmc_power_up(host);
mmc_select_voltage(host, host->ocr);
BUG_ON(!host->bus_ops->resume);
host->bus_ops->resume(host);
}
Expand Down
67 changes: 67 additions & 0 deletions drivers/mmc/core/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,68 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
NULL, "%08llx\n");

#define EXT_CSD_STR_LEN 1025

static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
{
struct mmc_card *card = inode->i_private;
char *buf;
ssize_t n = 0;
u8 *ext_csd;
int err, i;

buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
if (!buf)
return -ENOMEM;

ext_csd = kmalloc(512, GFP_KERNEL);
if (!ext_csd) {
err = -ENOMEM;
goto out_free;
}

mmc_claim_host(card->host);
err = mmc_send_ext_csd(card, ext_csd);
mmc_release_host(card->host);
if (err)
goto out_free;

for (i = 511; i >= 0; i--)
n += sprintf(buf + n, "%02x", ext_csd[i]);
n += sprintf(buf + n, "\n");
BUG_ON(n != EXT_CSD_STR_LEN);

filp->private_data = buf;
kfree(ext_csd);
return 0;

out_free:
kfree(buf);
kfree(ext_csd);
return err;
}

static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
char *buf = filp->private_data;

return simple_read_from_buffer(ubuf, cnt, ppos,
buf, EXT_CSD_STR_LEN);
}

static int mmc_ext_csd_release(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}

static struct file_operations mmc_dbg_ext_csd_fops = {
.open = mmc_ext_csd_open,
.read = mmc_ext_csd_read,
.release = mmc_ext_csd_release,
};

void mmc_add_card_debugfs(struct mmc_card *card)
{
struct mmc_host *host = card->host;
Expand Down Expand Up @@ -211,6 +273,11 @@ void mmc_add_card_debugfs(struct mmc_card *card)
&mmc_dbg_card_status_fops))
goto err;

if (mmc_card_mmc(card))
if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
&mmc_dbg_ext_csd_fops))
goto err;

return;

err:
Expand Down
8 changes: 8 additions & 0 deletions drivers/mmc/core/sdio_cis.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,18 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
if (tpl_code == 0xff)
break;

/* null entries have no link field or data */
if (tpl_code == 0x00)
continue;

ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
if (ret)
break;

/* a size of 0xff also means we're done */
if (tpl_link == 0xff)
break;

this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
if (!this)
return -ENOMEM;
Expand Down
8 changes: 8 additions & 0 deletions drivers/mmc/core/sdio_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
BUG_ON(!card);
BUG_ON(fn > 7);

/* sanity check */
if (addr & ~0x1FFFF)
return -EINVAL;

memset(&cmd, 0, sizeof(struct mmc_command));

cmd.opcode = SD_IO_RW_DIRECT;
Expand Down Expand Up @@ -125,6 +129,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
WARN_ON(blocks == 0);
WARN_ON(blksz == 0);

/* sanity check */
if (addr & ~0x1FFFF)
return -EINVAL;

memset(&mrq, 0, sizeof(struct mmc_request));
memset(&cmd, 0, sizeof(struct mmc_command));
memset(&data, 0, sizeof(struct mmc_data));
Expand Down
29 changes: 29 additions & 0 deletions drivers/mmc/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ config MMC_SDHCI

If unsure, say N.

config MMC_SDHCI_IO_ACCESSORS
bool
depends on MMC_SDHCI
help
This is silent Kconfig symbol that is selected by the drivers that
need to overwrite SDHCI IO memory accessors.

config MMC_SDHCI_PCI
tristate "SDHCI support on PCI bus"
depends on MMC_SDHCI && PCI
Expand Down Expand Up @@ -65,6 +72,17 @@ config MMC_RICOH_MMC

If unsure, say Y.

config MMC_SDHCI_OF
tristate "SDHCI support on OpenFirmware platforms"
depends on MMC_SDHCI && PPC_OF
select MMC_SDHCI_IO_ACCESSORS
help
This selects the OF support for Secure Digital Host Controller
Interfaces. So far, only the Freescale eSDHC controller is known
to exist on OF platforms.

If unsure, say N.

config MMC_OMAP
tristate "TI OMAP Multimedia Card Interface support"
depends on ARCH_OMAP
Expand Down Expand Up @@ -171,6 +189,17 @@ config MMC_TIFM_SD
To compile this driver as a module, choose M here: the
module will be called tifm_sd.

config MMC_MVSDIO
tristate "Marvell MMC/SD/SDIO host driver"
depends on PLAT_ORION
---help---
This selects the Marvell SDIO host driver.
SDIO may currently be found on the Kirkwood 88F6281 and 88F6192
SoC controllers.

To compile this driver as a module, choose M here: the
module will be called mvsdio.

config MMC_SPI
tristate "MMC/SD/SDIO over SPI"
depends on SPI_MASTER && !HIGHMEM && HAS_DMA
Expand Down
2 changes: 2 additions & 0 deletions drivers/mmc/host/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o
obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
obj-$(CONFIG_MMC_AT91) += at91_mci.o
obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
ifeq ($(CONFIG_OF),y)
obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o
Expand Down
2 changes: 1 addition & 1 deletion drivers/mmc/host/atmel-mci.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
slot->sdc_reg |= MCI_SDCBUS_1BIT;
break;
case MMC_BUS_WIDTH_4:
slot->sdc_reg = MCI_SDCBUS_4BIT;
slot->sdc_reg |= MCI_SDCBUS_4BIT;
break;
}

Expand Down
40 changes: 33 additions & 7 deletions drivers/mmc/host/mmc_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,11 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
* so it can always DMA directly into the target buffer.
* It'd probably be better to memcpy() the first chunk and
* avoid extra i/o calls...
*
* Note we check for more than 8 bytes, because in practice,
* some SD cards are slow...
*/
for (i = 2; i < 9; i++) {
for (i = 2; i < 16; i++) {
value = mmc_spi_readbytes(host, 1);
if (value < 0)
goto done;
Expand Down Expand Up @@ -609,6 +612,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
struct spi_device *spi = host->spi;
int status, i;
struct scratch *scratch = host->data;
u32 pattern;

if (host->mmc->use_spi_crc)
scratch->crc_val = cpu_to_be16(
Expand Down Expand Up @@ -636,8 +640,27 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
* doesn't necessarily tell whether the write operation succeeded;
* it just says if the transmission was ok and whether *earlier*
* writes succeeded; see the standard.
*
* In practice, there are (even modern SDHC-)cards which are late
* in sending the response, and miss the time frame by a few bits,
* so we have to cope with this situation and check the response
* bit-by-bit. Arggh!!!
*/
switch (SPI_MMC_RESPONSE_CODE(scratch->status[0])) {
pattern = scratch->status[0] << 24;
pattern |= scratch->status[1] << 16;
pattern |= scratch->status[2] << 8;
pattern |= scratch->status[3];

/* First 3 bit of pattern are undefined */
pattern |= 0xE0000000;

/* left-adjust to leading 0 bit */
while (pattern & 0x80000000)
pattern <<= 1;
/* right-adjust for pattern matching. Code is in bit 4..0 now. */
pattern >>= 27;

switch (pattern) {
case SPI_RESPONSE_ACCEPTED:
status = 0;
break;
Expand Down Expand Up @@ -668,8 +691,9 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
/* Return when not busy. If we didn't collect that status yet,
* we'll need some more I/O.
*/
for (i = 1; i < sizeof(scratch->status); i++) {
if (scratch->status[i] != 0)
for (i = 4; i < sizeof(scratch->status); i++) {
/* card is non-busy if the most recent bit is 1 */
if (scratch->status[i] & 0x01)
return 0;
}
return mmc_spi_wait_unbusy(host, timeout);
Expand Down Expand Up @@ -1204,10 +1228,12 @@ static int mmc_spi_probe(struct spi_device *spi)

/* MMC and SD specs only seem to care that sampling is on the
* rising edge ... meaning SPI modes 0 or 3. So either SPI mode
* should be legit. We'll use mode 0 since it seems to be a
* bit less troublesome on some hardware ... unclear why.
* should be legit. We'll use mode 0 since the steady state is 0,
* which is appropriate for hotplugging, unless the platform data
* specify mode 3 (if hardware is not compatible to mode 0).
*/
spi->mode = SPI_MODE_0;
if (spi->mode != SPI_MODE_3)
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;

status = spi_setup(spi);
Expand Down
Loading

0 comments on commit 0a053e8

Please sign in to comment.