diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2005-09-06 18:18:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:51 -0400 |
commit | 65ae2118e84616680dce37b951ffc366dcce7cf0 (patch) | |
tree | e4148db8d317b895575cb362e208ff17c1150dd0 /drivers/mmc/wbsd.c | |
parent | e619524fe5f5b0c13db34ed0f6320d2dcccf6e8d (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/wbsd.c')
-rw-r--r-- | drivers/mmc/wbsd.c | 60 |
1 files changed, 54 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 | ||
1055 | static 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 | |||
1031 | static struct mmc_host_ops wbsd_ops = { | 1077 | static 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 | ||