diff options
-rw-r--r-- | drivers/mmc/host/s3cmci.c | 44 | ||||
-rw-r--r-- | drivers/mmc/host/s3cmci.h | 1 | ||||
-rw-r--r-- | include/asm-arm/plat-s3c24xx/mci.h | 12 |
3 files changed, 54 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 | ||
1083 | static 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 | |||
1075 | static struct mmc_host_ops s3cmci_ops = { | 1093 | static 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 | |||
1099 | static 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 | ||
1080 | static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440) | 1104 | static 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 | ||
23 | struct s3cmci_host { | 23 | struct 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; |
diff --git a/include/asm-arm/plat-s3c24xx/mci.h b/include/asm-arm/plat-s3c24xx/mci.h new file mode 100644 index 000000000000..5be2c1449c6d --- /dev/null +++ b/include/asm-arm/plat-s3c24xx/mci.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _ARCH_MCI_H | ||
2 | #define _ARCH_MCI_H | ||
3 | |||
4 | struct s3c24xx_mci_pdata { | ||
5 | unsigned int gpio_detect; | ||
6 | unsigned int gpio_wprotect; | ||
7 | unsigned long ocr_avail; | ||
8 | void (*set_power)(unsigned char power_mode, | ||
9 | unsigned short vdd); | ||
10 | }; | ||
11 | |||
12 | #endif /* _ARCH_NCI_H */ | ||