Commit 5c350d93 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:
  pxamci: enable DMA for write ops after CMD/RESP
  pxamci: replace #ifdef CONFIG_PXA27x with if (cpu_is_pxa27x())
  ricoh_mmc: Use suspend_late/resume_early
  mmci: Add support for ST Micro derivate
  mmc: Add a MX2/MX3 specific SDHC driver
parents 017f5178 b6018958
#ifndef ASMARM_ARCH_MMC_H
#define ASMARM_ARCH_MMC_H
#include <linux/mmc/host.h>
struct device;
/* board specific SDHC data, optional.
* If not present, a writable card with 3,3V is assumed.
*/
struct imxmmc_platform_data {
/* Return values for the get_ro callback should be:
* 0 for a read/write card
* 1 for a read-only card
* -ENOSYS when not supported (equal to NULL callback)
* or a negative errno value when something bad happened
*/
int (*get_ro)(struct device *);
/* board specific hook to (de)initialize the SD slot.
* The board code can call 'handler' on a card detection
* change giving data as argument.
*/
int (*init)(struct device *dev, irq_handler_t handler, void *data);
void (*exit)(struct device *dev, void *data);
/* available voltages. If not given, assume
* MMC_VDD_32_33 | MMC_VDD_33_34
*/
unsigned int ocr_avail;
/* adjust slot voltage */
void (*setpower)(struct device *, unsigned int vdd);
};
#endif
...@@ -145,6 +145,16 @@ config MMC_IMX ...@@ -145,6 +145,16 @@ config MMC_IMX
If unsure, say N. If unsure, say N.
config MMC_MXC
tristate "Freescale i.MX2/3 Multimedia Card Interface support"
depends on ARCH_MXC
help
This selects the Freescale i.MX2/3 Multimedia card Interface.
If you have a i.MX platform with a Multimedia Card slot,
say Y or M here.
If unsure, say N.
config MMC_TIFM_SD config MMC_TIFM_SD
tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)" tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI depends on EXPERIMENTAL && PCI
......
...@@ -9,6 +9,7 @@ endif ...@@ -9,6 +9,7 @@ endif
obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_PXA) += pxamci.o
obj-$(CONFIG_MMC_IMX) += imxmmc.o obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
......
...@@ -430,6 +430,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -430,6 +430,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
clk = 255; clk = 255;
host->cclk = host->mclk / (2 * (clk + 1)); host->cclk = host->mclk / (2 * (clk + 1));
} }
if (host->hw_designer == 0x80)
clk |= MCI_FCEN; /* Bug fix in ST IP block */
clk |= MCI_CLK_ENABLE; clk |= MCI_CLK_ENABLE;
} }
...@@ -440,15 +442,27 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -440,15 +442,27 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_OFF: case MMC_POWER_OFF:
break; break;
case MMC_POWER_UP: case MMC_POWER_UP:
pwr |= MCI_PWR_UP; /* The ST version does not have this, fall through to POWER_ON */
break; if (host->hw_designer != 0x80) {
pwr |= MCI_PWR_UP;
break;
}
case MMC_POWER_ON: case MMC_POWER_ON:
pwr |= MCI_PWR_ON; pwr |= MCI_PWR_ON;
break; break;
} }
if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
pwr |= MCI_ROD; if (host->hw_designer != 0x80)
pwr |= MCI_ROD;
else {
/*
* The ST Micro variant use the ROD bit for something
* else and only has OD (Open Drain).
*/
pwr |= MCI_OD;
}
}
writel(clk, host->base + MMCICLOCK); writel(clk, host->base + MMCICLOCK);
...@@ -500,6 +514,12 @@ static int mmci_probe(struct amba_device *dev, void *id) ...@@ -500,6 +514,12 @@ static int mmci_probe(struct amba_device *dev, void *id)
} }
host = mmc_priv(mmc); host = mmc_priv(mmc);
/* Bits 12 thru 19 is the designer */
host->hw_designer = (dev->periphid >> 12) & 0xff;
/* Bits 20 thru 23 is the revison */
host->hw_revision = (dev->periphid >> 20) & 0xf;
DBG(host, "designer ID = 0x%02x\n", host->hw_designer);
DBG(host, "revision = 0x%01x\n", host->hw_revision);
host->clk = clk_get(&dev->dev, NULL); host->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(host->clk)) { if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk); ret = PTR_ERR(host->clk);
...@@ -693,6 +713,15 @@ static struct amba_id mmci_ids[] = { ...@@ -693,6 +713,15 @@ static struct amba_id mmci_ids[] = {
.id = 0x00041181, .id = 0x00041181,
.mask = 0x000fffff, .mask = 0x000fffff,
}, },
/* ST Micro variants */
{
.id = 0x00180180,
.mask = 0x00ffffff,
},
{
.id = 0x00280180,
.mask = 0x00ffffff,
},
{ 0, 0 }, { 0, 0 },
}; };
......
...@@ -11,13 +11,23 @@ ...@@ -11,13 +11,23 @@
#define MCI_PWR_OFF 0x00 #define MCI_PWR_OFF 0x00
#define MCI_PWR_UP 0x02 #define MCI_PWR_UP 0x02
#define MCI_PWR_ON 0x03 #define MCI_PWR_ON 0x03
#define MCI_DATA2DIREN (1 << 2)
#define MCI_CMDDIREN (1 << 3)
#define MCI_DATA0DIREN (1 << 4)
#define MCI_DATA31DIREN (1 << 5)
#define MCI_OD (1 << 6) #define MCI_OD (1 << 6)
#define MCI_ROD (1 << 7) #define MCI_ROD (1 << 7)
/* The ST Micro version does not have ROD */
#define MCI_FBCLKEN (1 << 7)
#define MCI_DATA74DIREN (1 << 8)
#define MMCICLOCK 0x004 #define MMCICLOCK 0x004
#define MCI_CLK_ENABLE (1 << 8) #define MCI_CLK_ENABLE (1 << 8)
#define MCI_CLK_PWRSAVE (1 << 9) #define MCI_CLK_PWRSAVE (1 << 9)
#define MCI_CLK_BYPASS (1 << 10) #define MCI_CLK_BYPASS (1 << 10)
#define MCI_WIDE_BUS (1 << 11)
/* HW flow control on the ST Micro version */
#define MCI_FCEN (1 << 13)
#define MMCIARGUMENT 0x008 #define MMCIARGUMENT 0x008
#define MMCICOMMAND 0x00c #define MMCICOMMAND 0x00c
...@@ -26,6 +36,10 @@ ...@@ -26,6 +36,10 @@
#define MCI_CPSM_INTERRUPT (1 << 8) #define MCI_CPSM_INTERRUPT (1 << 8)
#define MCI_CPSM_PENDING (1 << 9) #define MCI_CPSM_PENDING (1 << 9)
#define MCI_CPSM_ENABLE (1 << 10) #define MCI_CPSM_ENABLE (1 << 10)
#define MCI_SDIO_SUSP (1 << 11)
#define MCI_ENCMD_COMPL (1 << 12)
#define MCI_NIEN (1 << 13)
#define MCI_CE_ATACMD (1 << 14)
#define MMCIRESPCMD 0x010 #define MMCIRESPCMD 0x010
#define MMCIRESPONSE0 0x014 #define MMCIRESPONSE0 0x014
...@@ -39,6 +53,11 @@ ...@@ -39,6 +53,11 @@
#define MCI_DPSM_DIRECTION (1 << 1) #define MCI_DPSM_DIRECTION (1 << 1)
#define MCI_DPSM_MODE (1 << 2) #define MCI_DPSM_MODE (1 << 2)
#define MCI_DPSM_DMAENABLE (1 << 3) #define MCI_DPSM_DMAENABLE (1 << 3)
#define MCI_DPSM_BLOCKSIZE (1 << 4)
#define MCI_DPSM_RWSTART (1 << 8)
#define MCI_DPSM_RWSTOP (1 << 9)
#define MCI_DPSM_RWMOD (1 << 10)
#define MCI_DPSM_SDIOEN (1 << 11)
#define MMCIDATACNT 0x030 #define MMCIDATACNT 0x030
#define MMCISTATUS 0x034 #define MMCISTATUS 0x034
...@@ -63,6 +82,8 @@ ...@@ -63,6 +82,8 @@
#define MCI_RXFIFOEMPTY (1 << 19) #define MCI_RXFIFOEMPTY (1 << 19)
#define MCI_TXDATAAVLBL (1 << 20) #define MCI_TXDATAAVLBL (1 << 20)
#define MCI_RXDATAAVLBL (1 << 21) #define MCI_RXDATAAVLBL (1 << 21)
#define MCI_SDIOIT (1 << 22)
#define MCI_CEATAEND (1 << 23)
#define MMCICLEAR 0x038 #define MMCICLEAR 0x038
#define MCI_CMDCRCFAILCLR (1 << 0) #define MCI_CMDCRCFAILCLR (1 << 0)
...@@ -75,6 +96,8 @@ ...@@ -75,6 +96,8 @@
#define MCI_CMDSENTCLR (1 << 7) #define MCI_CMDSENTCLR (1 << 7)
#define MCI_DATAENDCLR (1 << 8) #define MCI_DATAENDCLR (1 << 8)
#define MCI_DATABLOCKENDCLR (1 << 10) #define MCI_DATABLOCKENDCLR (1 << 10)
#define MCI_SDIOITC (1 << 22)
#define MCI_CEATAENDC (1 << 23)
#define MMCIMASK0 0x03c #define MMCIMASK0 0x03c
#define MCI_CMDCRCFAILMASK (1 << 0) #define MCI_CMDCRCFAILMASK (1 << 0)
...@@ -98,6 +121,8 @@ ...@@ -98,6 +121,8 @@
#define MCI_RXFIFOEMPTYMASK (1 << 19) #define MCI_RXFIFOEMPTYMASK (1 << 19)
#define MCI_TXDATAAVLBLMASK (1 << 20) #define MCI_TXDATAAVLBLMASK (1 << 20)
#define MCI_RXDATAAVLBLMASK (1 << 21) #define MCI_RXDATAAVLBLMASK (1 << 21)
#define MCI_SDIOITMASK (1 << 22)
#define MCI_CEATAENDMASK (1 << 23)
#define MMCIMASK1 0x040 #define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048 #define MMCIFIFOCNT 0x048
...@@ -136,6 +161,9 @@ struct mmci_host { ...@@ -136,6 +161,9 @@ struct mmci_host {
u32 pwr; u32 pwr;
struct mmc_platform_data *plat; struct mmc_platform_data *plat;
u8 hw_designer;
u8 hw_revision:4;
struct timer_list timer; struct timer_list timer;
unsigned int oldstat; unsigned int oldstat;
......
This diff is collapsed.
...@@ -180,7 +180,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) ...@@ -180,7 +180,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
else else
DALGN &= ~(1 << host->dma); DALGN &= ~(1 << host->dma);
DDADR(host->dma) = host->sg_dma; DDADR(host->dma) = host->sg_dma;
DCSR(host->dma) = DCSR_RUN;
/*
* workaround for erratum #91:
* only start DMA now if we are doing a read,
* otherwise we wait until CMD/RESP has finished
* before starting DMA.
*/
if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ)
DCSR(host->dma) = DCSR_RUN;
} }
static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
...@@ -251,23 +259,28 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) ...@@ -251,23 +259,28 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
if (stat & STAT_TIME_OUT_RESPONSE) { if (stat & STAT_TIME_OUT_RESPONSE) {
cmd->error = -ETIMEDOUT; cmd->error = -ETIMEDOUT;
} else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
#ifdef CONFIG_PXA27x
/* /*
* workaround for erratum #42: * workaround for erratum #42:
* Intel PXA27x Family Processor Specification Update Rev 001 * Intel PXA27x Family Processor Specification Update Rev 001
* A bogus CRC error can appear if the msb of a 136 bit * A bogus CRC error can appear if the msb of a 136 bit
* response is a one. * response is a one.
*/ */
if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) { if (cpu_is_pxa27x() &&
(cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000))
pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode);
} else else
#endif cmd->error = -EILSEQ;
cmd->error = -EILSEQ;
} }
pxamci_disable_irq(host, END_CMD_RES); pxamci_disable_irq(host, END_CMD_RES);
if (host->data && !cmd->error) { if (host->data && !cmd->error) {
pxamci_enable_irq(host, DATA_TRAN_DONE); pxamci_enable_irq(host, DATA_TRAN_DONE);
/*
* workaround for erratum #91, if doing write
* enable DMA late
*/
if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE)
DCSR(host->dma) = DCSR_RUN;
} else { } else {
pxamci_finish_request(host, host->mrq); pxamci_finish_request(host, host->mrq);
} }
......
...@@ -196,7 +196,7 @@ static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) ...@@ -196,7 +196,7 @@ static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
} }
static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) static int ricoh_mmc_suspend_late(struct pci_dev *pdev, pm_message_t state)
{ {
struct pci_dev *fw_dev = NULL; struct pci_dev *fw_dev = NULL;
...@@ -210,7 +210,7 @@ static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -210,7 +210,7 @@ static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state)
return 0; return 0;
} }
static int ricoh_mmc_resume(struct pci_dev *pdev) static int ricoh_mmc_resume_early(struct pci_dev *pdev)
{ {
struct pci_dev *fw_dev = NULL; struct pci_dev *fw_dev = NULL;
...@@ -229,8 +229,8 @@ static struct pci_driver ricoh_mmc_driver = { ...@@ -229,8 +229,8 @@ static struct pci_driver ricoh_mmc_driver = {
.id_table = pci_ids, .id_table = pci_ids,
.probe = ricoh_mmc_probe, .probe = ricoh_mmc_probe,
.remove = __devexit_p(ricoh_mmc_remove), .remove = __devexit_p(ricoh_mmc_remove),
.suspend = ricoh_mmc_suspend, .suspend_late = ricoh_mmc_suspend_late,
.resume = ricoh_mmc_resume, .resume_early = ricoh_mmc_resume_early,
}; };
/*****************************************************************************\ /*****************************************************************************\
......
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