diff options
| -rw-r--r-- | drivers/mmc/mmci.c | 9 | ||||
| -rw-r--r-- | drivers/mmc/wbsd.c | 80 | ||||
| -rw-r--r-- | drivers/mmc/wbsd.h | 9 |
3 files changed, 56 insertions, 42 deletions
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 3a5f6ac5b364..7a42966d755b 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
| 21 | #include <linux/mmc/protocol.h> | 21 | #include <linux/mmc/protocol.h> |
| 22 | 22 | ||
| 23 | #include <asm/div64.h> | ||
| 23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 24 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
| 25 | #include <asm/scatterlist.h> | 26 | #include <asm/scatterlist.h> |
| @@ -70,6 +71,7 @@ static void mmci_stop_data(struct mmci_host *host) | |||
| 70 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | 71 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) |
| 71 | { | 72 | { |
| 72 | unsigned int datactrl, timeout, irqmask; | 73 | unsigned int datactrl, timeout, irqmask; |
| 74 | unsigned long long clks; | ||
| 73 | void __iomem *base; | 75 | void __iomem *base; |
| 74 | 76 | ||
| 75 | DBG(host, "blksz %04x blks %04x flags %08x\n", | 77 | DBG(host, "blksz %04x blks %04x flags %08x\n", |
| @@ -81,9 +83,10 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
| 81 | 83 | ||
| 82 | mmci_init_sg(host, data); | 84 | mmci_init_sg(host, data); |
| 83 | 85 | ||
| 84 | timeout = data->timeout_clks + | 86 | clks = (unsigned long long)data->timeout_ns * host->cclk; |
| 85 | ((unsigned long long)data->timeout_ns * host->cclk) / | 87 | do_div(clks, 1000000000UL); |
| 86 | 1000000000ULL; | 88 | |
| 89 | timeout = data->timeout_clks + (unsigned int)clks; | ||
| 87 | 90 | ||
| 88 | base = host->base; | 91 | base = host->base; |
| 89 | writel(timeout, base + MMCIDATATIMER); | 92 | writel(timeout, base + MMCIDATATIMER); |
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index b7fbd30b49a0..0c41d4b41a65 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
| @@ -54,28 +54,6 @@ | |||
| 54 | #define DBGF(x...) do { } while (0) | 54 | #define DBGF(x...) do { } while (0) |
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | #ifdef CONFIG_MMC_DEBUG | ||
| 58 | void DBG_REG(int reg, u8 value) | ||
| 59 | { | ||
| 60 | int i; | ||
| 61 | |||
| 62 | printk(KERN_DEBUG "wbsd: Register %d: 0x%02X %3d '%c' ", | ||
| 63 | reg, (int)value, (int)value, (value < 0x20)?'.':value); | ||
| 64 | |||
| 65 | for (i = 7;i >= 0;i--) | ||
| 66 | { | ||
| 67 | if (value & (1 << i)) | ||
| 68 | printk("x"); | ||
| 69 | else | ||
| 70 | printk("."); | ||
| 71 | } | ||
| 72 | |||
| 73 | printk("\n"); | ||
| 74 | } | ||
| 75 | #else | ||
| 76 | #define DBG_REG(r, v) do {} while (0) | ||
| 77 | #endif | ||
| 78 | |||
| 79 | /* | 57 | /* |
| 80 | * Device resources | 58 | * Device resources |
| 81 | */ | 59 | */ |
| @@ -92,6 +70,13 @@ MODULE_DEVICE_TABLE(pnp, pnp_dev_table); | |||
| 92 | 70 | ||
| 93 | #endif /* CONFIG_PNP */ | 71 | #endif /* CONFIG_PNP */ |
| 94 | 72 | ||
| 73 | static const int config_ports[] = { 0x2E, 0x4E }; | ||
| 74 | static const int unlock_codes[] = { 0x83, 0x87 }; | ||
| 75 | |||
| 76 | static const int valid_ids[] = { | ||
| 77 | 0x7112, | ||
| 78 | }; | ||
| 79 | |||
| 95 | #ifdef CONFIG_PNP | 80 | #ifdef CONFIG_PNP |
| 96 | static unsigned int nopnp = 0; | 81 | static unsigned int nopnp = 0; |
| 97 | #else | 82 | #else |
| @@ -1051,6 +1036,20 @@ static struct mmc_host_ops wbsd_ops = { | |||
| 1051 | \*****************************************************************************/ | 1036 | \*****************************************************************************/ |
| 1052 | 1037 | ||
| 1053 | /* | 1038 | /* |
| 1039 | * Helper function for card detection | ||
| 1040 | */ | ||
| 1041 | static void wbsd_detect_card(unsigned long data) | ||
| 1042 | { | ||
| 1043 | struct wbsd_host *host = (struct wbsd_host*)data; | ||
| 1044 | |||
| 1045 | BUG_ON(host == NULL); | ||
| 1046 | |||
| 1047 | DBG("Executing card detection\n"); | ||
| 1048 | |||
| 1049 | mmc_detect_change(host->mmc); | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | /* | ||
| 1054 | * Tasklets | 1053 | * Tasklets |
| 1055 | */ | 1054 | */ |
| 1056 | 1055 | ||
| @@ -1075,7 +1074,6 @@ static void wbsd_tasklet_card(unsigned long param) | |||
| 1075 | { | 1074 | { |
| 1076 | struct wbsd_host* host = (struct wbsd_host*)param; | 1075 | struct wbsd_host* host = (struct wbsd_host*)param; |
| 1077 | u8 csr; | 1076 | u8 csr; |
| 1078 | int change = 0; | ||
| 1079 | 1077 | ||
| 1080 | spin_lock(&host->lock); | 1078 | spin_lock(&host->lock); |
| 1081 | 1079 | ||
| @@ -1094,14 +1092,20 @@ static void wbsd_tasklet_card(unsigned long param) | |||
| 1094 | { | 1092 | { |
| 1095 | DBG("Card inserted\n"); | 1093 | DBG("Card inserted\n"); |
| 1096 | host->flags |= WBSD_FCARD_PRESENT; | 1094 | host->flags |= WBSD_FCARD_PRESENT; |
| 1097 | change = 1; | 1095 | |
| 1096 | /* | ||
| 1097 | * Delay card detection to allow electrical connections | ||
| 1098 | * to stabilise. | ||
| 1099 | */ | ||
| 1100 | mod_timer(&host->timer, jiffies + HZ/2); | ||
| 1098 | } | 1101 | } |
| 1102 | |||
| 1103 | spin_unlock(&host->lock); | ||
| 1099 | } | 1104 | } |
| 1100 | else if (host->flags & WBSD_FCARD_PRESENT) | 1105 | else if (host->flags & WBSD_FCARD_PRESENT) |
| 1101 | { | 1106 | { |
| 1102 | DBG("Card removed\n"); | 1107 | DBG("Card removed\n"); |
| 1103 | host->flags &= ~WBSD_FCARD_PRESENT; | 1108 | host->flags &= ~WBSD_FCARD_PRESENT; |
| 1104 | change = 1; | ||
| 1105 | 1109 | ||
| 1106 | if (host->mrq) | 1110 | if (host->mrq) |
| 1107 | { | 1111 | { |
| @@ -1112,15 +1116,14 @@ static void wbsd_tasklet_card(unsigned long param) | |||
| 1112 | host->mrq->cmd->error = MMC_ERR_FAILED; | 1116 | host->mrq->cmd->error = MMC_ERR_FAILED; |
| 1113 | tasklet_schedule(&host->finish_tasklet); | 1117 | tasklet_schedule(&host->finish_tasklet); |
| 1114 | } | 1118 | } |
| 1115 | } | 1119 | |
| 1116 | 1120 | /* | |
| 1117 | /* | 1121 | * Unlock first since we might get a call back. |
| 1118 | * Unlock first since we might get a call back. | 1122 | */ |
| 1119 | */ | 1123 | spin_unlock(&host->lock); |
| 1120 | spin_unlock(&host->lock); | ||
| 1121 | 1124 | ||
| 1122 | if (change) | ||
| 1123 | mmc_detect_change(host->mmc); | 1125 | mmc_detect_change(host->mmc); |
| 1126 | } | ||
| 1124 | } | 1127 | } |
| 1125 | 1128 | ||
| 1126 | static void wbsd_tasklet_fifo(unsigned long param) | 1129 | static void wbsd_tasklet_fifo(unsigned long param) |
| @@ -1325,6 +1328,13 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) | |||
| 1325 | spin_lock_init(&host->lock); | 1328 | spin_lock_init(&host->lock); |
| 1326 | 1329 | ||
| 1327 | /* | 1330 | /* |
| 1331 | * Set up detection timer | ||
| 1332 | */ | ||
| 1333 | init_timer(&host->timer); | ||
| 1334 | host->timer.data = (unsigned long)host; | ||
| 1335 | host->timer.function = wbsd_detect_card; | ||
| 1336 | |||
| 1337 | /* | ||
| 1328 | * Maximum number of segments. Worst case is one sector per segment | 1338 | * Maximum number of segments. Worst case is one sector per segment |
| 1329 | * so this will be 64kB/512. | 1339 | * so this will be 64kB/512. |
| 1330 | */ | 1340 | */ |
| @@ -1351,11 +1361,17 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) | |||
| 1351 | static void __devexit wbsd_free_mmc(struct device* dev) | 1361 | static void __devexit wbsd_free_mmc(struct device* dev) |
| 1352 | { | 1362 | { |
| 1353 | struct mmc_host* mmc; | 1363 | struct mmc_host* mmc; |
| 1364 | struct wbsd_host* host; | ||
| 1354 | 1365 | ||
| 1355 | mmc = dev_get_drvdata(dev); | 1366 | mmc = dev_get_drvdata(dev); |
| 1356 | if (!mmc) | 1367 | if (!mmc) |
| 1357 | return; | 1368 | return; |
| 1358 | 1369 | ||
| 1370 | host = mmc_priv(mmc); | ||
| 1371 | BUG_ON(host == NULL); | ||
| 1372 | |||
| 1373 | del_timer_sync(&host->timer); | ||
| 1374 | |||
| 1359 | mmc_free_host(mmc); | 1375 | mmc_free_host(mmc); |
| 1360 | 1376 | ||
| 1361 | dev_set_drvdata(dev, NULL); | 1377 | dev_set_drvdata(dev, NULL); |
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index 864f30828d01..661a9f6a6e6f 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h | |||
| @@ -8,13 +8,6 @@ | |||
| 8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | const int config_ports[] = { 0x2E, 0x4E }; | ||
| 12 | const int unlock_codes[] = { 0x83, 0x87 }; | ||
| 13 | |||
| 14 | const int valid_ids[] = { | ||
| 15 | 0x7112, | ||
| 16 | }; | ||
| 17 | |||
| 18 | #define LOCK_CODE 0xAA | 11 | #define LOCK_CODE 0xAA |
| 19 | 12 | ||
| 20 | #define WBSD_CONF_SWRST 0x02 | 13 | #define WBSD_CONF_SWRST 0x02 |
| @@ -187,4 +180,6 @@ struct wbsd_host | |||
| 187 | struct tasklet_struct timeout_tasklet; | 180 | struct tasklet_struct timeout_tasklet; |
| 188 | struct tasklet_struct finish_tasklet; | 181 | struct tasklet_struct finish_tasklet; |
| 189 | struct tasklet_struct block_tasklet; | 182 | struct tasklet_struct block_tasklet; |
| 183 | |||
| 184 | struct timer_list timer; /* Card detection timer */ | ||
| 190 | }; | 185 | }; |
