diff options
Diffstat (limited to 'drivers/mmc/wbsd.c')
-rw-r--r-- | drivers/mmc/wbsd.c | 118 |
1 files changed, 101 insertions, 17 deletions
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 402c2d661fb2..dec01d38c782 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "wbsd.h" | 42 | #include "wbsd.h" |
43 | 43 | ||
44 | #define DRIVER_NAME "wbsd" | 44 | #define DRIVER_NAME "wbsd" |
45 | #define DRIVER_VERSION "1.3" | 45 | #define DRIVER_VERSION "1.4" |
46 | 46 | ||
47 | #ifdef CONFIG_MMC_DEBUG | 47 | #ifdef CONFIG_MMC_DEBUG |
48 | #define DBG(x...) \ | 48 | #define DBG(x...) \ |
@@ -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,8 +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 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->vdd); | 981 | ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, |
982 | ios->vdd, ios->bus_width); | ||
965 | 983 | ||
966 | spin_lock_bh(&host->lock); | 984 | spin_lock_bh(&host->lock); |
967 | 985 | ||
@@ -1003,30 +1021,63 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
1003 | 1021 | ||
1004 | /* | 1022 | /* |
1005 | * MMC cards need to have pin 1 high during init. | 1023 | * MMC cards need to have pin 1 high during init. |
1006 | * Init time corresponds rather nicely with the bus mode. | ||
1007 | * It wreaks havoc with the card detection though so | 1024 | * It wreaks havoc with the card detection though so |
1008 | * that needs to be disabed. | 1025 | * that needs to be disabled. |
1009 | */ | 1026 | */ |
1010 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); | 1027 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); |
1011 | if ((ios->power_mode == MMC_POWER_ON) && | 1028 | if (ios->chip_select == MMC_CS_HIGH) |
1012 | (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)) | ||
1013 | { | 1029 | { |
1030 | BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1); | ||
1014 | setup |= WBSD_DAT3_H; | 1031 | setup |= WBSD_DAT3_H; |
1015 | host->flags |= WBSD_FIGNORE_DETECT; | 1032 | host->flags |= WBSD_FIGNORE_DETECT; |
1016 | } | 1033 | } |
1017 | else | 1034 | else |
1018 | { | 1035 | { |
1019 | setup &= ~WBSD_DAT3_H; | 1036 | setup &= ~WBSD_DAT3_H; |
1020 | host->flags &= ~WBSD_FIGNORE_DETECT; | 1037 | |
1038 | /* | ||
1039 | * We cannot resume card detection immediatly | ||
1040 | * because of capacitance and delays in the chip. | ||
1041 | */ | ||
1042 | mod_timer(&host->ignore_timer, jiffies + HZ/100); | ||
1021 | } | 1043 | } |
1022 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | 1044 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); |
1023 | 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 | |||
1052 | spin_unlock_bh(&host->lock); | ||
1053 | } | ||
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 | |||
1024 | spin_unlock_bh(&host->lock); | 1072 | spin_unlock_bh(&host->lock); |
1073 | |||
1074 | return csr & WBSD_WRPT; | ||
1025 | } | 1075 | } |
1026 | 1076 | ||
1027 | static struct mmc_host_ops wbsd_ops = { | 1077 | static struct mmc_host_ops wbsd_ops = { |
1028 | .request = wbsd_request, | 1078 | .request = wbsd_request, |
1029 | .set_ios = wbsd_set_ios, | 1079 | .set_ios = wbsd_set_ios, |
1080 | .get_ro = wbsd_get_ro, | ||
1030 | }; | 1081 | }; |
1031 | 1082 | ||
1032 | /*****************************************************************************\ | 1083 | /*****************************************************************************\ |
@@ -1036,6 +1087,31 @@ static struct mmc_host_ops wbsd_ops = { | |||
1036 | \*****************************************************************************/ | 1087 | \*****************************************************************************/ |
1037 | 1088 | ||
1038 | /* | 1089 | /* |
1090 | * Helper function to reset detection ignore | ||
1091 | */ | ||
1092 | |||
1093 | static void wbsd_reset_ignore(unsigned long data) | ||
1094 | { | ||
1095 | struct wbsd_host *host = (struct wbsd_host*)data; | ||
1096 | |||
1097 | BUG_ON(host == NULL); | ||
1098 | |||
1099 | DBG("Resetting card detection ignore\n"); | ||
1100 | |||
1101 | spin_lock_bh(&host->lock); | ||
1102 | |||
1103 | host->flags &= ~WBSD_FIGNORE_DETECT; | ||
1104 | |||
1105 | /* | ||
1106 | * Card status might have changed during the | ||
1107 | * blackout. | ||
1108 | */ | ||
1109 | tasklet_schedule(&host->card_tasklet); | ||
1110 | |||
1111 | spin_unlock_bh(&host->lock); | ||
1112 | } | ||
1113 | |||
1114 | /* | ||
1039 | * Helper function for card detection | 1115 | * Helper function for card detection |
1040 | */ | 1116 | */ |
1041 | static void wbsd_detect_card(unsigned long data) | 1117 | static void wbsd_detect_card(unsigned long data) |
@@ -1097,7 +1173,7 @@ static void wbsd_tasklet_card(unsigned long param) | |||
1097 | * Delay card detection to allow electrical connections | 1173 | * Delay card detection to allow electrical connections |
1098 | * to stabilise. | 1174 | * to stabilise. |
1099 | */ | 1175 | */ |
1100 | mod_timer(&host->timer, jiffies + HZ/2); | 1176 | mod_timer(&host->detect_timer, jiffies + HZ/2); |
1101 | } | 1177 | } |
1102 | 1178 | ||
1103 | spin_unlock(&host->lock); | 1179 | spin_unlock(&host->lock); |
@@ -1124,6 +1200,8 @@ static void wbsd_tasklet_card(unsigned long param) | |||
1124 | 1200 | ||
1125 | mmc_detect_change(host->mmc); | 1201 | mmc_detect_change(host->mmc); |
1126 | } | 1202 | } |
1203 | else | ||
1204 | spin_unlock(&host->lock); | ||
1127 | } | 1205 | } |
1128 | 1206 | ||
1129 | static void wbsd_tasklet_fifo(unsigned long param) | 1207 | static void wbsd_tasklet_fifo(unsigned long param) |
@@ -1324,15 +1402,20 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) | |||
1324 | mmc->f_min = 375000; | 1402 | mmc->f_min = 375000; |
1325 | mmc->f_max = 24000000; | 1403 | mmc->f_max = 24000000; |
1326 | 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; | ||
1327 | 1406 | ||
1328 | spin_lock_init(&host->lock); | 1407 | spin_lock_init(&host->lock); |
1329 | 1408 | ||
1330 | /* | 1409 | /* |
1331 | * Set up detection timer | 1410 | * Set up timers |
1332 | */ | 1411 | */ |
1333 | init_timer(&host->timer); | 1412 | init_timer(&host->detect_timer); |
1334 | host->timer.data = (unsigned long)host; | 1413 | host->detect_timer.data = (unsigned long)host; |
1335 | host->timer.function = wbsd_detect_card; | 1414 | host->detect_timer.function = wbsd_detect_card; |
1415 | |||
1416 | init_timer(&host->ignore_timer); | ||
1417 | host->ignore_timer.data = (unsigned long)host; | ||
1418 | host->ignore_timer.function = wbsd_reset_ignore; | ||
1336 | 1419 | ||
1337 | /* | 1420 | /* |
1338 | * Maximum number of segments. Worst case is one sector per segment | 1421 | * Maximum number of segments. Worst case is one sector per segment |
@@ -1370,7 +1453,8 @@ static void __devexit wbsd_free_mmc(struct device* dev) | |||
1370 | host = mmc_priv(mmc); | 1453 | host = mmc_priv(mmc); |
1371 | BUG_ON(host == NULL); | 1454 | BUG_ON(host == NULL); |
1372 | 1455 | ||
1373 | del_timer_sync(&host->timer); | 1456 | del_timer_sync(&host->ignore_timer); |
1457 | del_timer_sync(&host->detect_timer); | ||
1374 | 1458 | ||
1375 | mmc_free_host(mmc); | 1459 | mmc_free_host(mmc); |
1376 | 1460 | ||