diff options
| -rw-r--r-- | arch/arm/mach-pxa/lubbock.c | 16 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/mainstone.c | 58 | ||||
| -rw-r--r-- | drivers/mmc/pxamci.c | 35 | ||||
| -rw-r--r-- | drivers/mmc/pxamci.h | 30 |
4 files changed, 126 insertions, 13 deletions
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index dac8de8d3b6a..87fd729c35bb 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -33,6 +33,7 @@ #include <asm/arch/lubbock.h> #include <asm/arch/udc.h> #include <asm/arch/pxafb.h> +#include <asm/arch/mmc.h> #include <asm/hardware/sa1111.h> #include "generic.h" @@ -183,10 +184,25 @@ static struct pxafb_mach_info sharp_lm8v31 __initdata = { .lccr3 = LCCR3_PCP | LCCR3_Acb(255), }; +static int lubbock_mci_init(struct device *dev, irqreturn_t (*lubbock_detect_int)(int, void *, struct pt_regs *), void *data) +{ + /* setup GPIO for PXA25x MMC controller */ + pxa_gpio_mode(GPIO6_MMCCLK_MD); + pxa_gpio_mode(GPIO8_MMCCS0_MD); + + return 0; +} + +static struct pxamci_platform_data lubbock_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = lubbock_mci_init, +}; + static void __init lubbock_init(void) { pxa_set_udc_info(&udc_info); set_pxa_fb_info(&sharp_lm8v31); + pxa_set_mci_info(&lubbock_mci_platform_data); (void) platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index d57920f58d69..2c8d7c826267 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -34,6 +34,7 @@ #include <asm/arch/pxa-regs.h> #include <asm/arch/mainstone.h> #include <asm/arch/pxafb.h> +#include <asm/arch/mmc.h> #include "generic.h" @@ -170,6 +171,61 @@ static struct pxafb_mach_info toshiba_ltm035a776c __initdata = { .pxafb_backlight_power = mainstone_backlight_power, }; +static int mainstone_mci_init(struct device *dev, irqreturn_t (*mstone_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + + /* + * setup GPIO for PXA27x MMC controller + */ + pxa_gpio_mode(GPIO32_MMCCLK_MD); + pxa_gpio_mode(GPIO112_MMCCMD_MD); + pxa_gpio_mode(GPIO92_MMCDAT0_MD); + pxa_gpio_mode(GPIO109_MMCDAT1_MD); + pxa_gpio_mode(GPIO110_MMCDAT2_MD); + pxa_gpio_mode(GPIO111_MMCDAT3_MD); + + /* make sure SD/Memory Stick multiplexer's signals + * are routed to MMC controller + */ + MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL; + + err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, SA_INTERRUPT, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "mainstone_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + + return 0; +} + +static void mainstone_mci_setpower(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) { + printk(KERN_DEBUG "%s: on\n", __FUNCTION__); + MST_MSCWR1 |= MST_MSCWR1_MMC_ON; + MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL; + } else { + printk(KERN_DEBUG "%s: off\n", __FUNCTION__); + MST_MSCWR1 &= ~MST_MSCWR1_MMC_ON; + } +} + +static void mainstone_mci_exit(struct device *dev, void *data) +{ + free_irq(MAINSTONE_MMC_IRQ, data); +} + +static struct pxamci_platform_data mainstone_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = mainstone_mci_init, + .setpower = mainstone_mci_setpower, + .exit = mainstone_mci_exit, +}; + static void __init mainstone_init(void) { platform_device_register(&smc91x_device); @@ -180,6 +236,8 @@ static void __init mainstone_init(void) set_pxa_fb_info(&toshiba_ltm04c380k); else set_pxa_fb_info(&toshiba_ltm035a776c); + + pxa_set_mci_info(&mainstone_mci_platform_data); } diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 78a5e5304a62..cadaa1efdab2 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -72,11 +72,6 @@ struct pxamci_host { unsigned int dma_dir; }; -/* - * The base MMC clock rate - */ -#define CLOCKRATE 20000000 - static inline unsigned int ns_to_clocks(unsigned int ns) { return (ns * (CLOCKRATE / 1000000) + 999) / 1000; @@ -244,7 +239,24 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) if (stat & STAT_TIME_OUT_RESPONSE) { cmd->error = MMC_ERR_TIMEOUT; } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { +#ifdef CONFIG_PXA27x + /* + * workaround for erratum #42: + * Intel PXA27x Family Processor Specification Update Rev 001 + */ + if (cmd->opcode == MMC_ALL_SEND_CID || + cmd->opcode == MMC_SEND_CSD || + cmd->opcode == MMC_SEND_CID) { + /* a bogus CRC error can appear if the msb of + the 15 byte response is a one */ + if ((cmd->resp[0] & 0x80000000) == 0) + cmd->error = MMC_ERR_BADCRC; + } else { + DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode); + } +#else cmd->error = MMC_ERR_BADCRC; +#endif } pxamci_disable_irq(host, END_CMD_RES); @@ -429,8 +441,8 @@ static int pxamci_probe(struct device *dev) } mmc->ops = &pxamci_ops; - mmc->f_min = 312500; - mmc->f_max = 20000000; + mmc->f_min = CLOCKRATE_MIN; + mmc->f_max = CLOCKRATE_MAX; /* * We can do SG-DMA, but we don't because we never know how much @@ -460,8 +472,7 @@ static int pxamci_probe(struct device *dev) spin_lock_init(&host->lock); host->res = r; host->irq = irq; - host->imask = TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| - END_CMD_RES|PRG_DONE|DATA_TRAN_DONE; + host->imask = MMC_I_MASK_ALL; host->base = ioremap(r->start, SZ_4K); if (!host->base) { @@ -478,10 +489,6 @@ static int pxamci_probe(struct device *dev) writel(64, host->base + MMC_RESTO); writel(host->imask, host->base + MMC_I_MASK); - pxa_gpio_mode(GPIO6_MMCCLK_MD); - pxa_gpio_mode(GPIO8_MMCCS0_MD); - pxa_set_cken(CKEN12_MMC, 1); - host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW, pxamci_dma_irq, host); if (host->dma < 0) { @@ -498,6 +505,8 @@ static int pxamci_probe(struct device *dev) if (host->pdata && host->pdata->init) host->pdata->init(dev, pxamci_detect_irq, mmc); + pxa_set_cken(CKEN12_MMC, 1); + mmc_add_host(mmc); return 0; diff --git a/drivers/mmc/pxamci.h b/drivers/mmc/pxamci.h index a80b24db9734..1b163220df2b 100644 --- a/drivers/mmc/pxamci.h +++ b/drivers/mmc/pxamci.h @@ -70,6 +70,16 @@ #define BUF_PART_FULL (1 << 0) #define MMC_I_MASK 0x0028 + +/*PXA27x MMC interrupts*/ +#define SDIO_SUSPEND_ACK (1 << 12) +#define SDIO_INT (1 << 11) +#define RD_STALLED (1 << 10) +#define RES_ERR (1 << 9) +#define DAT_ERR (1 << 8) +#define TINT (1 << 7) + +/*PXA2xx MMC interrupts*/ #define TXFIFO_WR_REQ (1 << 6) #define RXFIFO_RD_REQ (1 << 5) #define CLK_IS_OFF (1 << 4) @@ -78,6 +88,12 @@ #define PRG_DONE (1 << 1) #define DATA_TRAN_DONE (1 << 0) +#ifdef CONFIG_PXA27x +#define MMC_I_MASK_ALL 0x00001fff +#else +#define MMC_I_MASK_ALL 0x0000007f +#endif + #define MMC_I_REG 0x002c /* same as MMC_I_MASK */ @@ -92,3 +108,17 @@ #define MMC_RXFIFO 0x0040 /* 8 bit */ #define MMC_TXFIFO 0x0044 /* 8 bit */ + +/* + * The base MMC clock rate + */ +#ifdef CONFIG_PXA27x +#define CLOCKRATE_MIN 304688 +#define CLOCKRATE_MAX 19500000 +#else +#define CLOCKRATE_MIN 312500 +#define CLOCKRATE_MAX 20000000 +#endif + +#define CLOCKRATE CLOCKRATE_MAX + |
