aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2005-09-06 18:18:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:51 -0400
commit65ae2118e84616680dce37b951ffc366dcce7cf0 (patch)
treee4148db8d317b895575cb362e208ff17c1150dd0 /drivers/mmc
parente619524fe5f5b0c13db34ed0f6320d2dcccf6e8d (diff)
[PATCH] mmc: wbsd Secure Digital support
Add support for Secure Digital specific features in the wbsd driver. Adds support for read-only switch and wide bus transfers. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/wbsd.c60
-rw-r--r--drivers/mmc/wbsd.h3
2 files changed, 57 insertions, 6 deletions
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 08ae22aed9e8..dec01d38c782 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -720,11 +720,28 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
720 * calculate CRC. 720 * calculate CRC.
721 * 721 *
722 * Space for CRC must be included in the size. 722 * Space for CRC must be included in the size.
723 * Two bytes are needed for each data line.
723 */ 724 */
724 blksize = (1 << data->blksz_bits) + 2; 725 if (host->bus_width == MMC_BUS_WIDTH_1)
726 {
727 blksize = (1 << data->blksz_bits) + 2;
728
729 wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
730 wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
731 }
732 else if (host->bus_width == MMC_BUS_WIDTH_4)
733 {
734 blksize = (1 << data->blksz_bits) + 2 * 4;
725 735
726 wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0); 736 wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
727 wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); 737 | WBSD_DATA_WIDTH);
738 wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
739 }
740 else
741 {
742 data->error = MMC_ERR_INVALID;
743 return;
744 }
728 745
729 /* 746 /*
730 * Clear the FIFO. This is needed even for DMA 747 * Clear the FIFO. This is needed even for DMA
@@ -960,9 +977,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
960 struct wbsd_host* host = mmc_priv(mmc); 977 struct wbsd_host* host = mmc_priv(mmc);
961 u8 clk, setup, pwr; 978 u8 clk, setup, pwr;
962 979
963 DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n", 980 DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
964 ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, 981 ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
965 ios->vdd); 982 ios->vdd, ios->bus_width);
966 983
967 spin_lock_bh(&host->lock); 984 spin_lock_bh(&host->lock);
968 985
@@ -1010,6 +1027,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
1010 setup = wbsd_read_index(host, WBSD_IDX_SETUP); 1027 setup = wbsd_read_index(host, WBSD_IDX_SETUP);
1011 if (ios->chip_select == MMC_CS_HIGH) 1028 if (ios->chip_select == MMC_CS_HIGH)
1012 { 1029 {
1030 BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
1013 setup |= WBSD_DAT3_H; 1031 setup |= WBSD_DAT3_H;
1014 host->flags |= WBSD_FIGNORE_DETECT; 1032 host->flags |= WBSD_FIGNORE_DETECT;
1015 } 1033 }
@@ -1025,12 +1043,41 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
1025 } 1043 }
1026 wbsd_write_index(host, WBSD_IDX_SETUP, setup); 1044 wbsd_write_index(host, WBSD_IDX_SETUP, setup);
1027 1045
1046 /*
1047 * Store bus width for later. Will be used when
1048 * setting up the data transfer.
1049 */
1050 host->bus_width = ios->bus_width;
1051
1028 spin_unlock_bh(&host->lock); 1052 spin_unlock_bh(&host->lock);
1029} 1053}
1030 1054
1055static int wbsd_get_ro(struct mmc_host* mmc)
1056{
1057 struct wbsd_host* host = mmc_priv(mmc);
1058 u8 csr;
1059
1060 spin_lock_bh(&host->lock);
1061
1062 csr = inb(host->base + WBSD_CSR);
1063 csr |= WBSD_MSLED;
1064 outb(csr, host->base + WBSD_CSR);
1065
1066 mdelay(1);
1067
1068 csr = inb(host->base + WBSD_CSR);
1069 csr &= ~WBSD_MSLED;
1070 outb(csr, host->base + WBSD_CSR);
1071
1072 spin_unlock_bh(&host->lock);
1073
1074 return csr & WBSD_WRPT;
1075}
1076
1031static struct mmc_host_ops wbsd_ops = { 1077static struct mmc_host_ops wbsd_ops = {
1032 .request = wbsd_request, 1078 .request = wbsd_request,
1033 .set_ios = wbsd_set_ios, 1079 .set_ios = wbsd_set_ios,
1080 .get_ro = wbsd_get_ro,
1034}; 1081};
1035 1082
1036/*****************************************************************************\ 1083/*****************************************************************************\
@@ -1355,6 +1402,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
1355 mmc->f_min = 375000; 1402 mmc->f_min = 375000;
1356 mmc->f_max = 24000000; 1403 mmc->f_max = 24000000;
1357 mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; 1404 mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
1405 mmc->caps = MMC_CAP_4_BIT_DATA;
1358 1406
1359 spin_lock_init(&host->lock); 1407 spin_lock_init(&host->lock);
1360 1408
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index 8af43549f5d5..9005b5241b3c 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -106,6 +106,8 @@
106#define WBSD_CLK_16M 0x02 106#define WBSD_CLK_16M 0x02
107#define WBSD_CLK_24M 0x03 107#define WBSD_CLK_24M 0x03
108 108
109#define WBSD_DATA_WIDTH 0x01
110
109#define WBSD_DAT3_H 0x08 111#define WBSD_DAT3_H 0x08
110#define WBSD_FIFO_RESET 0x04 112#define WBSD_FIFO_RESET 0x04
111#define WBSD_SOFT_RESET 0x02 113#define WBSD_SOFT_RESET 0x02
@@ -164,6 +166,7 @@ struct wbsd_host
164 int firsterr; /* See fifo functions */ 166 int firsterr; /* See fifo functions */
165 167
166 u8 clk; /* Current clock speed */ 168 u8 clk; /* Current clock speed */
169 unsigned char bus_width; /* Current bus width */
167 170
168 int config; /* Config port */ 171 int config; /* Config port */
169 u8 unlock_code; /* Code to unlock config */ 172 u8 unlock_code; /* Code to unlock config */