Commit f234012f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  sdhci: remove needless double parenthesis
  sdhci: Specific quirk vor VIA SDHCI controller in VX855ES
  s3cmci: fix dma configuration call
  mmc: Add new via-sdmmc host controller driver
  sdhci: Add support for hosts that are only capable of 1-bit transfers
  MAINTAINERS: add myself as atmel-mci maintainer (sd/mmc interface)
  sdhci: Add SDHCI_QUIRK_NO_MULTIBLOCK quirk
  sdhci: Add better ADMA error reporting
  sdhci-s3c: Samsung S3C based SDHCI controller glue
parents 00d94a6a 11a2f1b7
...@@ -10,6 +10,8 @@ Required properties: ...@@ -10,6 +10,8 @@ Required properties:
- interrupts : should contain eSDHC interrupt. - interrupts : should contain eSDHC interrupt.
- interrupt-parent : interrupt source phandle. - interrupt-parent : interrupt source phandle.
- clock-frequency : specifies eSDHC base clock frequency. - clock-frequency : specifies eSDHC base clock frequency.
- sdhci,1-bit-only : (optional) specifies that a controller can
only handle 1-bit data transfers.
Example: Example:
......
...@@ -1010,6 +1010,13 @@ W: http://www.at91.com/ ...@@ -1010,6 +1010,13 @@ W: http://www.at91.com/
S: Maintained S: Maintained
F: drivers/mmc/host/at91_mci.c F: drivers/mmc/host/at91_mci.c
ATMEL AT91 / AT32 MCI DRIVER
P: Nicolas Ferre
M: nicolas.ferre@atmel.com
S: Maintained
F: drivers/mmc/host/atmel-mci.c
F: drivers/mmc/host/atmel-mci-regs.h
ATMEL AT91 / AT32 SERIAL DRIVER ATMEL AT91 / AT32 SERIAL DRIVER
P: Haavard Skinnemoen P: Haavard Skinnemoen
M: hskinnemoen@atmel.com M: hskinnemoen@atmel.com
...@@ -5094,6 +5101,13 @@ L: sdhci-devel@lists.ossman.eu ...@@ -5094,6 +5101,13 @@ L: sdhci-devel@lists.ossman.eu
S: Maintained S: Maintained
F: drivers/mmc/host/sdhci.* F: drivers/mmc/host/sdhci.*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
P: Ben Dooks
M: ben-linux@fluff.org
L: sdhci-devel@lists.ossman.eu
S: Maintained
F: drivers/mmc/host/sdhci-s3c.c
SECURITY SUBSYSTEM SECURITY SUBSYSTEM
P: James Morris P: James Morris
M: jmorris@namei.org M: jmorris@namei.org
...@@ -6216,6 +6230,14 @@ S: Maintained ...@@ -6216,6 +6230,14 @@ S: Maintained
F: Documentation/i2c/busses/i2c-viapro F: Documentation/i2c/busses/i2c-viapro
F: drivers/i2c/busses/i2c-viapro.c F: drivers/i2c/busses/i2c-viapro.c
VIA SD/MMC CARD CONTROLLER DRIVER
P: Joseph Chan
M: JosephChan@via.com.tw
P: Harald Welte
M: HaraldWelte@viatech.com
S: Maintained
F: drivers/mmc/host/via-sdmmc.c
VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
P: Joseph Chan P: Joseph Chan
M: JosephChan@via.com.tw M: JosephChan@via.com.tw
......
...@@ -94,6 +94,31 @@ config MMC_SDHCI_PLTFM ...@@ -94,6 +94,31 @@ config MMC_SDHCI_PLTFM
If unsure, say N. If unsure, say N.
config MMC_SDHCI_S3C
tristate "SDHCI support on Samsung S3C SoC"
depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)
help
This selects the Secure Digital Host Controller Interface (SDHCI)
often referrered to as the HSMMC block in some of the Samsung S3C
range of SoC.
Note, due to the problems with DMA, the DMA support is only
available with CONFIG_EXPERIMENTAL is selected.
If you have a controller with this interface, say Y or M here.
If unsure, say N.
config MMC_SDHCI_S3C_DMA
bool "DMA support on S3C SDHCI"
depends on MMC_SDHCI_S3C && EXPERIMENTAL
help
Enable DMA support on the Samsung S3C SDHCI glue. The DMA
has proved to be problematic if the controller encounters
certain errors, and thus should be treated with care.
YMMV.
config MMC_OMAP config MMC_OMAP
tristate "TI OMAP Multimedia Card Interface support" tristate "TI OMAP Multimedia Card Interface support"
depends on ARCH_OMAP depends on ARCH_OMAP
...@@ -265,3 +290,14 @@ config MMC_CB710 ...@@ -265,3 +290,14 @@ config MMC_CB710
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called cb710-mmc. will be called cb710-mmc.
config MMC_VIA_SDMMC
tristate "VIA SD/MMC Card Reader Driver"
depends on PCI
help
This selects the VIA SD/MMC Card Reader driver, say Y or M here.
VIA provides one multi-functional card reader which integrated into
some motherboards manufactured by VIA. This card reader supports
SD/MMC/SDHC.
If you have a controller with this interface, say Y or M here.
If unsure, say N.
...@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o ...@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o obj-$(CONFIG_MMC_OMAP) += omap.o
...@@ -31,6 +32,7 @@ obj-$(CONFIG_MMC_S3C) += s3cmci.o ...@@ -31,6 +32,7 @@ obj-$(CONFIG_MMC_S3C) += s3cmci.o
obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
ifeq ($(CONFIG_CB710_DEBUG),y) ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG CFLAGS-cb710-mmc += -DDEBUG
......
...@@ -794,7 +794,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, ...@@ -794,7 +794,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host,
host->mem->start + host->sdidata); host->mem->start + host->sdidata);
if (!setup_ok) { if (!setup_ok) {
s3c2410_dma_config(host->dma, 4, 0); s3c2410_dma_config(host->dma, 4);
s3c2410_dma_set_buffdone_fn(host->dma, s3c2410_dma_set_buffdone_fn(host->dma,
s3cmci_dma_done_callback); s3cmci_dma_done_callback);
s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
......
...@@ -250,6 +250,9 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev, ...@@ -250,6 +250,9 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev,
host->ops = &sdhci_of_data->ops; host->ops = &sdhci_of_data->ops;
} }
if (of_get_property(np, "sdhci,1-bit-only", NULL))
host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
clk = of_get_property(np, "clock-frequency", &size); clk = of_get_property(np, "clock-frequency", &size);
if (clk && size == sizeof(*clk) && *clk) if (clk && size == sizeof(*clk) && *clk)
of_host->clock = *clk; of_host->clock = *clk;
......
...@@ -284,6 +284,18 @@ static const struct sdhci_pci_fixes sdhci_jmicron = { ...@@ -284,6 +284,18 @@ static const struct sdhci_pci_fixes sdhci_jmicron = {
.resume = jmicron_resume, .resume = jmicron_resume,
}; };
static int via_probe(struct sdhci_pci_chip *chip)
{
if (chip->pdev->revision == 0x10)
chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
return 0;
}
static const struct sdhci_pci_fixes sdhci_via = {
.probe = via_probe,
};
static const struct pci_device_id pci_ids[] __devinitdata = { static const struct pci_device_id pci_ids[] __devinitdata = {
{ {
.vendor = PCI_VENDOR_ID_RICOH, .vendor = PCI_VENDOR_ID_RICOH,
...@@ -349,6 +361,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { ...@@ -349,6 +361,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.driver_data = (kernel_ulong_t)&sdhci_jmicron, .driver_data = (kernel_ulong_t)&sdhci_jmicron,
}, },
{
.vendor = PCI_VENDOR_ID_VIA,
.device = 0x95d0,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (kernel_ulong_t)&sdhci_via,
},
{ /* Generic SD host controller */ { /* Generic SD host controller */
PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
}, },
......
This diff is collapsed.
...@@ -584,7 +584,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) ...@@ -584,7 +584,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
* longer to time out, but that's much better than having a too-short * longer to time out, but that's much better than having a too-short
* timeout value. * timeout value.
*/ */
if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)) if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
return 0xE; return 0xE;
/* timeout in us */ /* timeout in us */
...@@ -1051,12 +1051,19 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) ...@@ -1051,12 +1051,19 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
* At least the Marvell CaFe chip gets confused if we set the voltage * At least the Marvell CaFe chip gets confused if we set the voltage
* and set turn on power at the same time, so set the voltage first. * and set turn on power at the same time, so set the voltage first.
*/ */
if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
pwr |= SDHCI_POWER_ON; pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
/*
* Some controllers need an extra 10ms delay of 10ms before they
* can apply clock after applying power
*/
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
mdelay(10);
} }
/*****************************************************************************\ /*****************************************************************************\
...@@ -1382,6 +1389,35 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) ...@@ -1382,6 +1389,35 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
sdhci_finish_command(host); sdhci_finish_command(host);
} }
#ifdef DEBUG
static void sdhci_show_adma_error(struct sdhci_host *host)
{
const char *name = mmc_hostname(host->mmc);
u8 *desc = host->adma_desc;
__le32 *dma;
__le16 *len;
u8 attr;
sdhci_dumpregs(host);
while (true) {
dma = (__le32 *)(desc + 4);
len = (__le16 *)(desc + 2);
attr = *desc;
DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr);
desc += 8;
if (attr & 2)
break;
}
}
#else
static void sdhci_show_adma_error(struct sdhci_host *host) { }
#endif
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{ {
BUG_ON(intmask == 0); BUG_ON(intmask == 0);
...@@ -1411,8 +1447,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) ...@@ -1411,8 +1447,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
host->data->error = -ETIMEDOUT; host->data->error = -ETIMEDOUT;
else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
host->data->error = -EILSEQ; host->data->error = -EILSEQ;
else if (intmask & SDHCI_INT_ADMA_ERROR) else if (intmask & SDHCI_INT_ADMA_ERROR) {
printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO; host->data->error = -EIO;
}
if (host->data->error) if (host->data->error)
sdhci_finish_data(host); sdhci_finish_data(host);
...@@ -1729,7 +1768,10 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -1729,7 +1768,10 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->ops = &sdhci_ops; mmc->ops = &sdhci_ops;
mmc->f_min = host->max_clk / 256; mmc->f_min = host->max_clk / 256;
mmc->f_max = host->max_clk; mmc->f_max = host->max_clk;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; mmc->caps = MMC_CAP_SDIO_IRQ;
if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
mmc->caps |= MMC_CAP_4_BIT_DATA;
if (caps & SDHCI_CAN_DO_HISPD) if (caps & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED; mmc->caps |= MMC_CAP_SD_HIGHSPEED;
...@@ -1802,7 +1844,7 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -1802,7 +1844,7 @@ int sdhci_add_host(struct sdhci_host *host)
/* /*
* Maximum block count. * Maximum block count.
*/ */
mmc->max_blk_count = 65535; mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
/* /*
* Init tasklets. * Init tasklets.
......
...@@ -226,6 +226,12 @@ struct sdhci_host { ...@@ -226,6 +226,12 @@ struct sdhci_host {
#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19)
/* Controller has to be forced to use block size of 2048 bytes */ /* Controller has to be forced to use block size of 2048 bytes */
#define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20)
/* Controller cannot do multi-block transfers */
#define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21)
/* Controller can only handle 1-bit data transfers */
#define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22)
/* Controller needs 10ms delay between applying power and clock */
#define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23)
int irq; /* Device IRQ */ int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */ void __iomem * ioaddr; /* Mapped address */
......
This diff is collapsed.
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