Merge master.kernel.org:/home/rmk/linux-2.6-mmc
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
#include <linux/mmc/host.h>
|
#include <linux/mmc/host.h>
|
||||||
#include <linux/mmc/protocol.h>
|
#include <linux/mmc/protocol.h>
|
||||||
|
|
||||||
|
#include <asm/div64.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/scatterlist.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)
|
static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
unsigned int datactrl, timeout, irqmask;
|
unsigned int datactrl, timeout, irqmask;
|
||||||
|
unsigned long long clks;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
|
||||||
DBG(host, "blksz %04x blks %04x flags %08x\n",
|
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);
|
mmci_init_sg(host, data);
|
||||||
|
|
||||||
timeout = data->timeout_clks +
|
clks = (unsigned long long)data->timeout_ns * host->cclk;
|
||||||
((unsigned long long)data->timeout_ns * host->cclk) /
|
do_div(clks, 1000000000UL);
|
||||||
1000000000ULL;
|
|
||||||
|
timeout = data->timeout_clks + (unsigned int)clks;
|
||||||
|
|
||||||
base = host->base;
|
base = host->base;
|
||||||
writel(timeout, base + MMCIDATATIMER);
|
writel(timeout, base + MMCIDATATIMER);
|
||||||
|
@@ -54,28 +54,6 @@
|
|||||||
#define DBGF(x...) do { } while (0)
|
#define DBGF(x...) do { } while (0)
|
||||||
#endif
|
#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
|
* Device resources
|
||||||
*/
|
*/
|
||||||
@@ -92,6 +70,13 @@ MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
|
|||||||
|
|
||||||
#endif /* CONFIG_PNP */
|
#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
|
#ifdef CONFIG_PNP
|
||||||
static unsigned int nopnp = 0;
|
static unsigned int nopnp = 0;
|
||||||
#else
|
#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
|
* Tasklets
|
||||||
*/
|
*/
|
||||||
@@ -1075,7 +1074,6 @@ static void wbsd_tasklet_card(unsigned long param)
|
|||||||
{
|
{
|
||||||
struct wbsd_host* host = (struct wbsd_host*)param;
|
struct wbsd_host* host = (struct wbsd_host*)param;
|
||||||
u8 csr;
|
u8 csr;
|
||||||
int change = 0;
|
|
||||||
|
|
||||||
spin_lock(&host->lock);
|
spin_lock(&host->lock);
|
||||||
|
|
||||||
@@ -1094,14 +1092,20 @@ static void wbsd_tasklet_card(unsigned long param)
|
|||||||
{
|
{
|
||||||
DBG("Card inserted\n");
|
DBG("Card inserted\n");
|
||||||
host->flags |= WBSD_FCARD_PRESENT;
|
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)
|
else if (host->flags & WBSD_FCARD_PRESENT)
|
||||||
{
|
{
|
||||||
DBG("Card removed\n");
|
DBG("Card removed\n");
|
||||||
host->flags &= ~WBSD_FCARD_PRESENT;
|
host->flags &= ~WBSD_FCARD_PRESENT;
|
||||||
change = 1;
|
|
||||||
|
|
||||||
if (host->mrq)
|
if (host->mrq)
|
||||||
{
|
{
|
||||||
@@ -1112,15 +1116,14 @@ static void wbsd_tasklet_card(unsigned long param)
|
|||||||
host->mrq->cmd->error = MMC_ERR_FAILED;
|
host->mrq->cmd->error = MMC_ERR_FAILED;
|
||||||
tasklet_schedule(&host->finish_tasklet);
|
tasklet_schedule(&host->finish_tasklet);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/*
|
||||||
/*
|
* Unlock first since we might get a call back.
|
||||||
* Unlock first since we might get a call back.
|
*/
|
||||||
*/
|
spin_unlock(&host->lock);
|
||||||
spin_unlock(&host->lock);
|
|
||||||
|
|
||||||
if (change)
|
|
||||||
mmc_detect_change(host->mmc);
|
mmc_detect_change(host->mmc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wbsd_tasklet_fifo(unsigned long param)
|
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);
|
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
|
* Maximum number of segments. Worst case is one sector per segment
|
||||||
* so this will be 64kB/512.
|
* 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)
|
static void __devexit wbsd_free_mmc(struct device* dev)
|
||||||
{
|
{
|
||||||
struct mmc_host* mmc;
|
struct mmc_host* mmc;
|
||||||
|
struct wbsd_host* host;
|
||||||
|
|
||||||
mmc = dev_get_drvdata(dev);
|
mmc = dev_get_drvdata(dev);
|
||||||
if (!mmc)
|
if (!mmc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
host = mmc_priv(mmc);
|
||||||
|
BUG_ON(host == NULL);
|
||||||
|
|
||||||
|
del_timer_sync(&host->timer);
|
||||||
|
|
||||||
mmc_free_host(mmc);
|
mmc_free_host(mmc);
|
||||||
|
|
||||||
dev_set_drvdata(dev, NULL);
|
dev_set_drvdata(dev, NULL);
|
||||||
|
@@ -8,13 +8,6 @@
|
|||||||
* published by the Free Software Foundation.
|
* 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 LOCK_CODE 0xAA
|
||||||
|
|
||||||
#define WBSD_CONF_SWRST 0x02
|
#define WBSD_CONF_SWRST 0x02
|
||||||
@@ -187,4 +180,6 @@ struct wbsd_host
|
|||||||
struct tasklet_struct timeout_tasklet;
|
struct tasklet_struct timeout_tasklet;
|
||||||
struct tasklet_struct finish_tasklet;
|
struct tasklet_struct finish_tasklet;
|
||||||
struct tasklet_struct block_tasklet;
|
struct tasklet_struct block_tasklet;
|
||||||
|
|
||||||
|
struct timer_list timer; /* Card detection timer */
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user