#include <asm/io.h>
#define DRIVER_NAME "tifm_sd"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
static int no_dma = 0;
static int fixed_timeout = 0;
enum {
FIFO_RDY = 0x0001, /* hardware dependent value */
EJECT = 0x0004,
- EJECT_DONE = 0x0008,
CARD_BUSY = 0x0010,
OPENDRAIN = 0x0040, /* hardware dependent value */
CARD_EVENT = 0x0100, /* hardware dependent value */
struct tasklet_struct finish_tasklet;
struct timer_list timer;
struct mmc_request *req;
- wait_queue_head_t notify;
size_t written_blocks;
size_t buffer_size;
}
/* Called from interrupt handler */
-static void tifm_sd_signal_irq(struct tifm_dev *sock,
- unsigned int sock_irq_status)
+static void tifm_sd_data_event(struct tifm_dev *sock)
{
struct tifm_sd *host;
- unsigned int host_status = 0, fifo_status = 0;
- int error_code = 0;
+ unsigned int fifo_status = 0;
spin_lock(&sock->lock);
host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
- if (sock_irq_status & FIFO_EVENT) {
- fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
- writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
+ fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
+ writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
+
+ host->flags |= fifo_status & FIFO_RDY;
+
+ if (host->req)
+ tifm_sd_process_cmd(sock, host, 0);
+
+ dev_dbg(&sock->dev, "fifo_status %x\n", fifo_status);
+ spin_unlock(&sock->lock);
+
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_card_event(struct tifm_dev *sock)
+{
+ struct tifm_sd *host;
+ unsigned int host_status = 0;
+ int error_code = 0;
+
+ spin_lock(&sock->lock);
+ host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
- host->flags |= fifo_status & FIFO_RDY;
- }
- if (sock_irq_status & CARD_EVENT) {
host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
host->written_blocks++;
host->flags &= ~CARD_BUSY;
}
- }
if (host->req)
tifm_sd_process_cmd(sock, host, host_status);
done:
- dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n",
- host_status, fifo_status);
+ dev_dbg(&sock->dev, "host_status %x\n", host_status);
spin_unlock(&sock->lock);
}
mmc_request_done(mmc, mrq);
}
-static void tifm_sd_terminate(struct tifm_sd *host)
-{
- struct tifm_dev *sock = host->dev;
- unsigned long flags;
-
- writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
- mmiowb();
- spin_lock_irqsave(&sock->lock, flags);
- host->flags |= EJECT;
- if (host->req) {
- writel(TIFM_FIFO_INT_SETALL,
- sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
- writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
- tasklet_schedule(&host->finish_tasklet);
- }
- spin_unlock_irqrestore(&sock->lock, flags);
-}
-
static void tifm_sd_abort(unsigned long data)
{
struct tifm_sd *host = (struct tifm_sd*)data;
printk(KERN_ERR DRIVER_NAME
- ": card failed to respond for a long period of time");
+ ": card failed to respond for a long period of time\n");
- tifm_sd_terminate(host);
tifm_eject(host->dev);
}
/* chip_select : maybe later */
//vdd
//power is set before probe / after remove
- //I believe, power_off when already marked for eject is sufficient to
- // allow removal.
- if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
- host->flags |= EJECT_DONE;
- wake_up_all(&host->notify);
- }
spin_unlock_irqrestore(&sock->lock, flags);
}
host->dev = sock;
host->timeout_jiffies = msecs_to_jiffies(1000);
- init_waitqueue_head(&host->notify);
tasklet_init(&host->finish_tasklet,
no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
(unsigned long)host);
mmc->max_blk_size = 2048;
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
mmc->max_seg_size = mmc->max_req_size;
- sock->signal_irq = tifm_sd_signal_irq;
+ sock->card_event = tifm_sd_card_event;
+ sock->data_event = tifm_sd_data_event;
rc = tifm_sd_initialize_host(host);
if (!rc)
{
struct mmc_host *mmc = tifm_get_drvdata(sock);
struct tifm_sd *host = mmc_priv(mmc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sock->lock, flags);
+ host->flags |= EJECT;
+ writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+ mmiowb();
+ spin_unlock_irqrestore(&sock->lock, flags);
- del_timer_sync(&host->timer);
- tifm_sd_terminate(host);
- wait_event_timeout(host->notify, host->flags & EJECT_DONE,
- host->timeout_jiffies);
tasklet_kill(&host->finish_tasklet);
+
+ spin_lock_irqsave(&sock->lock, flags);
+ if (host->req) {
+ writel(TIFM_FIFO_INT_SETALL,
+ sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+ writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+ host->req->cmd->error = MMC_ERR_TIMEOUT;
+ if (host->req->stop)
+ host->req->stop->error = MMC_ERR_TIMEOUT;
+ tasklet_schedule(&host->finish_tasklet);
+ }
+ spin_unlock_irqrestore(&sock->lock, flags);
mmc_remove_host(mmc);
+ dev_dbg(&sock->dev, "after remove\n");
/* The meaning of the bit majority in this constant is unknown. */
writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
sock->addr + SOCK_CONTROL);
- tifm_set_drvdata(sock, NULL);
mmc_free_host(mmc);
}
struct mmc_host *mmc = tifm_get_drvdata(sock);
struct tifm_sd *host = mmc_priv(mmc);
- if (sock->media_id != FM_SD
+ if (sock->type != TIFM_TYPE_SD
|| tifm_sd_initialize_host(host)) {
tifm_eject(sock);
return 0;
#endif /* CONFIG_PM */
-static tifm_media_id tifm_sd_id_tbl[] = {
- FM_SD, 0
+static struct tifm_device_id tifm_sd_id_tbl[] = {
+ { TIFM_TYPE_SD }, { }
};
static struct tifm_driver tifm_sd_driver = {