Commit 1d6bebf2 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-mmc

parents 86166f98 3eee0d03
......@@ -20,6 +20,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/scatterlist.h>
......@@ -70,6 +71,7 @@ static void mmci_stop_data(struct mmci_host *host)
static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
{
unsigned int datactrl, timeout, irqmask;
unsigned long long clks;
void __iomem *base;
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)
mmci_init_sg(host, data);
timeout = data->timeout_clks +
((unsigned long long)data->timeout_ns * host->cclk) /
1000000000ULL;
clks = (unsigned long long)data->timeout_ns * host->cclk;
do_div(clks, 1000000000UL);
timeout = data->timeout_clks + (unsigned int)clks;
base = host->base;
writel(timeout, base + MMCIDATATIMER);
......
......@@ -54,28 +54,6 @@
#define DBGF(x...) do { } while (0)
#endif
#ifdef CONFIG_MMC_DEBUG
void DBG_REG(int reg, u8 value)
{
int i;
printk(KERN_DEBUG "wbsd: Register %d: 0x%02X %3d '%c' ",
reg, (int)value, (int)value, (value < 0x20)?'.':value);
for (i = 7;i >= 0;i--)
{
if (value & (1 << i))
printk("x");
else
printk(".");
}
printk("\n");
}
#else
#define DBG_REG(r, v) do {} while (0)
#endif
/*
* Device resources
*/
......@@ -92,6 +70,13 @@ MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
#endif /* CONFIG_PNP */
static const int config_ports[] = { 0x2E, 0x4E };
static const int unlock_codes[] = { 0x83, 0x87 };
static const int valid_ids[] = {
0x7112,
};
#ifdef CONFIG_PNP
static unsigned int nopnp = 0;
#else
......@@ -1050,6 +1035,20 @@ static struct mmc_host_ops wbsd_ops = {
* *
\*****************************************************************************/
/*
* Helper function for card detection
*/
static void wbsd_detect_card(unsigned long data)
{
struct wbsd_host *host = (struct wbsd_host*)data;
BUG_ON(host == NULL);
DBG("Executing card detection\n");
mmc_detect_change(host->mmc);
}
/*
* Tasklets
*/
......@@ -1075,7 +1074,6 @@ static void wbsd_tasklet_card(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr;
int change = 0;
spin_lock(&host->lock);
......@@ -1094,14 +1092,20 @@ static void wbsd_tasklet_card(unsigned long param)
{
DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT;
change = 1;
/*
* Delay card detection to allow electrical connections
* to stabilise.
*/
mod_timer(&host->timer, jiffies + HZ/2);
}
spin_unlock(&host->lock);
}
else if (host->flags & WBSD_FCARD_PRESENT)
{
DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT;
change = 1;
if (host->mrq)
{
......@@ -1112,15 +1116,14 @@ static void wbsd_tasklet_card(unsigned long param)
host->mrq->cmd->error = MMC_ERR_FAILED;
tasklet_schedule(&host->finish_tasklet);
}
}
/*
* Unlock first since we might get a call back.
*/
spin_unlock(&host->lock);
if (change)
mmc_detect_change(host->mmc);
}
}
static void wbsd_tasklet_fifo(unsigned long param)
......@@ -1324,6 +1327,13 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
spin_lock_init(&host->lock);
/*
* Set up detection timer
*/
init_timer(&host->timer);
host->timer.data = (unsigned long)host;
host->timer.function = wbsd_detect_card;
/*
* Maximum number of segments. Worst case is one sector per segment
* so this will be 64kB/512.
......@@ -1351,11 +1361,17 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
static void __devexit wbsd_free_mmc(struct device* dev)
{
struct mmc_host* mmc;
struct wbsd_host* host;
mmc = dev_get_drvdata(dev);
if (!mmc)
return;
host = mmc_priv(mmc);
BUG_ON(host == NULL);
del_timer_sync(&host->timer);
mmc_free_host(mmc);
dev_set_drvdata(dev, NULL);
......
......@@ -8,13 +8,6 @@
* published by the Free Software Foundation.
*/
const int config_ports[] = { 0x2E, 0x4E };
const int unlock_codes[] = { 0x83, 0x87 };
const int valid_ids[] = {
0x7112,
};
#define LOCK_CODE 0xAA
#define WBSD_CONF_SWRST 0x02
......@@ -187,4 +180,6 @@ struct wbsd_host
struct tasklet_struct timeout_tasklet;
struct tasklet_struct finish_tasklet;
struct tasklet_struct block_tasklet;
struct timer_list timer; /* Card detection timer */
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment