aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/wbsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/wbsd.c')
-rw-r--r--drivers/mmc/wbsd.c118
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
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
1024 spin_unlock_bh(&host->lock); 1072 spin_unlock_bh(&host->lock);
1073
1074 return csr & WBSD_WRPT;
1025} 1075}
1026 1076
1027static struct mmc_host_ops wbsd_ops = { 1077static 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
1093static 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 */
1041static void wbsd_detect_card(unsigned long data) 1117static 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
1129static void wbsd_tasklet_fifo(unsigned long param) 1207static 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