aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-06-30 17:40:29 -0400
committerPierre Ossman <drzeus@drzeus.cx>2008-07-15 08:14:47 -0400
commitedb5a98e43682d66c98ddd1dee863d867807546e (patch)
tree32e64ccbb3669e8dfb1245de581948387567addc /drivers/mmc
parentd643b5f7e0793ef7828a35a5ea049d675ad2ad8c (diff)
MMC: S3C24XX: Add platform data for MMC/SD driver
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. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/s3cmci.c44
-rw-r--r--drivers/mmc/host/s3cmci.h1
2 files changed, 42 insertions, 3 deletions
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 774af3d7218f..684a10ca2e8f 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -21,6 +21,8 @@
21#include <asm/arch/regs-sdi.h> 21#include <asm/arch/regs-sdi.h>
22#include <asm/arch/regs-gpio.h> 22#include <asm/arch/regs-gpio.h>
23 23
24#include <asm/plat-s3c24xx/mci.h>
25
24#include "s3cmci.h" 26#include "s3cmci.h"
25 27
26#define DRIVER_NAME "s3c-mci" 28#define DRIVER_NAME "s3c-mci"
@@ -1011,6 +1013,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1011 s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2); 1013 s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
1012 s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3); 1014 s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
1013 1015
1016 if (host->pdata->set_power)
1017 host->pdata->set_power(ios->power_mode, ios->vdd);
1018
1014 if (!host->is2440) 1019 if (!host->is2440)
1015 mci_con |= S3C2410_SDICON_FIFORESET; 1020 mci_con |= S3C2410_SDICON_FIFORESET;
1016 1021
@@ -1024,6 +1029,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1024 if (host->is2440) 1029 if (host->is2440)
1025 mci_con |= S3C2440_SDICON_SDRESET; 1030 mci_con |= S3C2440_SDICON_SDRESET;
1026 1031
1032 if (host->pdata->set_power)
1033 host->pdata->set_power(ios->power_mode, ios->vdd);
1034
1027 break; 1035 break;
1028 } 1036 }
1029 1037
@@ -1072,9 +1080,25 @@ static void s3cmci_reset(struct s3cmci_host *host)
1072 writel(con, host->base + S3C2410_SDICON); 1080 writel(con, host->base + S3C2410_SDICON);
1073} 1081}
1074 1082
1083static int s3cmci_get_ro(struct mmc_host *mmc)
1084{
1085 struct s3cmci_host *host = mmc_priv(mmc);
1086
1087 if (host->pdata->gpio_wprotect == 0)
1088 return 0;
1089
1090 return s3c2410_gpio_getpin(host->pdata->gpio_wprotect);
1091}
1092
1075static struct mmc_host_ops s3cmci_ops = { 1093static struct mmc_host_ops s3cmci_ops = {
1076 .request = s3cmci_request, 1094 .request = s3cmci_request,
1077 .set_ios = s3cmci_set_ios, 1095 .set_ios = s3cmci_set_ios,
1096 .get_ro = s3cmci_get_ro,
1097};
1098
1099static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
1100 /* This is currently here to avoid a number of if (host->pdata)
1101 * checks. Any zero fields to ensure reaonable defaults are picked. */
1078}; 1102};
1079 1103
1080static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440) 1104static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
@@ -1094,6 +1118,12 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
1094 host->pdev = pdev; 1118 host->pdev = pdev;
1095 host->is2440 = is2440; 1119 host->is2440 = is2440;
1096 1120
1121 host->pdata = pdev->dev.platform_data;
1122 if (!host->pdata) {
1123 pdev->dev.platform_data = &s3cmci_def_pdata;
1124 host->pdata = &s3cmci_def_pdata;
1125 }
1126
1097 spin_lock_init(&host->complete_lock); 1127 spin_lock_init(&host->complete_lock);
1098 tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host); 1128 tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
1099 1129
@@ -1112,7 +1142,8 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
1112 host->pio_active = XFER_NONE; 1142 host->pio_active = XFER_NONE;
1113 1143
1114 host->dma = S3CMCI_DMA; 1144 host->dma = S3CMCI_DMA;
1115 host->irq_cd = IRQ_EINT2; 1145 host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
1146 s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
1116 1147
1117 host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1148 host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1118 if (!host->mem) { 1149 if (!host->mem) {
@@ -1158,7 +1189,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
1158 1189
1159 disable_irq(host->irq); 1190 disable_irq(host->irq);
1160 1191
1161 s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2); 1192 s3c2410_gpio_cfgpin(host->pdata->gpio_detect, S3C2410_GPIO_IRQ);
1162 set_irq_type(host->irq_cd, IRQT_BOTHEDGE); 1193 set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
1163 1194
1164 if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) { 1195 if (request_irq(host->irq_cd, s3cmci_irq_cd, 0, DRIVER_NAME, host)) {
@@ -1168,6 +1199,10 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
1168 goto probe_free_irq; 1199 goto probe_free_irq;
1169 } 1200 }
1170 1201
1202 if (host->pdata->gpio_wprotect)
1203 s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
1204 S3C2410_GPIO_INPUT);
1205
1171 if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) { 1206 if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {
1172 dev_err(&pdev->dev, "unable to get DMA channel.\n"); 1207 dev_err(&pdev->dev, "unable to get DMA channel.\n");
1173 ret = -EBUSY; 1208 ret = -EBUSY;
@@ -1191,11 +1226,14 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
1191 host->clk_rate = clk_get_rate(host->clk); 1226 host->clk_rate = clk_get_rate(host->clk);
1192 1227
1193 mmc->ops = &s3cmci_ops; 1228 mmc->ops = &s3cmci_ops;
1194 mmc->ocr_avail = MMC_VDD_32_33; 1229 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
1195 mmc->caps = MMC_CAP_4_BIT_DATA; 1230 mmc->caps = MMC_CAP_4_BIT_DATA;
1196 mmc->f_min = host->clk_rate / (host->clk_div * 256); 1231 mmc->f_min = host->clk_rate / (host->clk_div * 256);
1197 mmc->f_max = host->clk_rate / host->clk_div; 1232 mmc->f_max = host->clk_rate / host->clk_div;
1198 1233
1234 if (host->pdata->ocr_avail)
1235 mmc->ocr_avail = host->pdata->ocr_avail;
1236
1199 mmc->max_blk_count = 4095; 1237 mmc->max_blk_count = 4095;
1200 mmc->max_blk_size = 4095; 1238 mmc->max_blk_size = 4095;
1201 mmc->max_req_size = 4095 * 512; 1239 mmc->max_req_size = 4095 * 512;
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index 90b8af7d8a46..37d9c60010c9 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -22,6 +22,7 @@ enum s3cmci_waitfor {
22 22
23struct s3cmci_host { 23struct s3cmci_host {
24 struct platform_device *pdev; 24 struct platform_device *pdev;
25 struct s3c24xx_mci_pdata *pdata;
25 struct mmc_host *mmc; 26 struct mmc_host *mmc;
26 struct resource *mem; 27 struct resource *mem;
27 struct clk *clk; 28 struct clk *clk;