This patch adds platform data support to the s3mci driver. This allows flexible board-specific configuration of set_power, card detect and read only pins. Index: linux-2.6.20.4/drivers/mmc/s3cmci.c =================================================================== --- linux-2.6.20.4.orig/drivers/mmc/s3cmci.c 2007-04-02 20:37:47.000000000 +0200 +++ linux-2.6.20.4/drivers/mmc/s3cmci.c 2007-04-02 20:55:02.000000000 +0200 @@ -22,6 +22,7 @@ #include #include #include +#include #include "mmc_debug.h" #include "s3cmci.h" @@ -1012,6 +1013,9 @@ s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2); s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3); + if (host->pdata->set_power) + host->pdata->set_power(ios->power_mode, ios->vdd); + if (!host->is2440) mci_con|=S3C2410_SDICON_FIFORESET; @@ -1022,6 +1026,9 @@ s3c2410_gpio_setpin(S3C2410_GPE5, 0); s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP); + if (host->pdata->set_power) + host->pdata->set_power(ios->power_mode, ios->vdd); + if (host->is2440) mci_con|=S3C2440_SDICON_SDRESET; @@ -1075,9 +1082,26 @@ writel(con, host->base + S3C2410_SDICON); } +static int s3cmci_get_ro(struct mmc_host *mmc) +{ + struct s3cmci_host *host = mmc_priv(mmc); + + if (host->pdata->gpio_wprotect == 0) + return 0; + + return s3c2410_gpio_getpin(host->pdata->gpio_wprotect); +} + static struct mmc_host_ops s3cmci_ops = { .request = s3cmci_request, .set_ios = s3cmci_set_ios, + .get_ro = s3cmci_get_ro, +}; + +static struct s3c24xx_mci_pdata s3cmci_def_pdata = { + .gpio_detect = 0, + .set_power = NULL, + .ocr_avail = MMC_VDD_32_33, }; static int s3cmci_probe(struct platform_device *pdev, int is2440) @@ -1097,6 +1121,12 @@ host->mmc = mmc; host->pdev = pdev; + host->pdata = pdev->dev.platform_data; + if (!host->pdata) { + pdev->dev.platform_data = &s3cmci_def_pdata; + host->pdata = &s3cmci_def_pdata; + } + spin_lock_init(&host->complete_lock); tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host); if (is2440) { @@ -1115,7 +1145,8 @@ host->pio_active = XFER_NONE; host->dma = S3CMCI_DMA; - host->irq_cd = IRQ_EINT2; + host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect); + s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ); host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!host->mem) { @@ -1157,7 +1188,7 @@ disable_irq(host->irq); - s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2); + s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ); set_irq_type(host->irq_cd, IRQT_BOTHEDGE); if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) { @@ -1168,6 +1199,10 @@ goto probe_free_irq; } + if (host->pdata->gpio_wprotect) + s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect, + S3C2410_GPIO_INPUT); + if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) { dev_err(&pdev->dev, "unable to get DMA channel.\n"); ret = -EBUSY; @@ -1190,7 +1225,7 @@ host->clk_rate = clk_get_rate(host->clk); mmc->ops = &s3cmci_ops; - mmc->ocr_avail = MMC_VDD_32_33; + mmc->ocr_avail = host->pdata->ocr_avail; mmc->caps = MMC_CAP_4_BIT_DATA; mmc->f_min = host->clk_rate / (host->clk_div * 256); mmc->f_max = host->clk_rate / host->clk_div; Index: linux-2.6.20.4/drivers/mmc/s3cmci.h =================================================================== --- linux-2.6.20.4.orig/drivers/mmc/s3cmci.h 2007-04-02 20:37:44.000000000 +0200 +++ linux-2.6.20.4/drivers/mmc/s3cmci.h 2007-04-02 20:37:48.000000000 +0200 @@ -22,6 +22,7 @@ struct s3cmci_host { struct platform_device *pdev; + struct s3c24xx_mci_pdata *pdata; struct mmc_host *mmc; struct resource *mem; struct clk *clk; Index: linux-2.6.20.4/include/asm-arm/arch-s3c2410/mci.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.20.4/include/asm-arm/arch-s3c2410/mci.h 2007-04-02 20:54:16.000000000 +0200 @@ -0,0 +1,12 @@ +#ifndef _ARCH_MCI_H +#define _ARCH_MCI_H + +struct s3c24xx_mci_pdata { + unsigned int gpio_detect; + unsigned int gpio_wprotect; + unsigned long ocr_avail; + void (*set_power)(unsigned char power_mode, + unsigned short vdd); +}; + +#endif /* _ARCH_NCI_H */