summaryrefslogtreecommitdiff
path: root/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/kexecboot/linux-kexecboot-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch')
-rw-r--r--packages/kexecboot/linux-kexecboot-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch891
1 files changed, 0 insertions, 891 deletions
diff --git a/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch b/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch
deleted file mode 100644
index 6ff752d1ff..0000000000
--- a/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0011-MMC-driver-for-TMIO-devices.patch
+++ /dev/null
@@ -1,891 +0,0 @@
-From b358a64c1fdd1eb80da57f919c893d910db95e37 Mon Sep 17 00:00:00 2001
-From: Ian Molton <spyro@f2s.com>
-Date: Sat, 29 Dec 2007 15:26:19 +0000
-Subject: [PATCH 11/64] MMC driver for TMIO devices
-
----
- drivers/mmc/host/Kconfig | 6 +
- drivers/mmc/host/Makefile | 1 +
- drivers/mmc/host/tmio_mmc.c | 633 +++++++++++++++++++++++++++++++++++++++++++
- drivers/mmc/host/tmio_mmc.h | 205 ++++++++++++++
- 4 files changed, 845 insertions(+), 0 deletions(-)
- create mode 100644 drivers/mmc/host/tmio_mmc.c
- create mode 100644 drivers/mmc/host/tmio_mmc.h
-
-diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
-index 5fef678..f8f9b7e 100644
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -130,3 +130,9 @@ config MMC_SPI
-
- If unsure, or if your system has no SPI master driver, say N.
-
-+config MMC_TMIO
-+ tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
-+ depends on MMC
-+ help
-+ This provides support for the SD/MMC cell found in TC6393XB,
-+ T7L66XB and also ipaq ASIC3
-diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
-index 3877c87..7ac956b 100644
---- a/drivers/mmc/host/Makefile
-+++ b/drivers/mmc/host/Makefile
-@@ -17,4 +17,5 @@ obj-$(CONFIG_MMC_OMAP) += omap.o
- obj-$(CONFIG_MMC_AT91) += at91_mci.o
- obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
- obj-$(CONFIG_MMC_SPI) += mmc_spi.o
-+obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
-
-diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
-new file mode 100644
-index 0000000..735c386
---- /dev/null
-+++ b/drivers/mmc/host/tmio_mmc.c
-@@ -0,0 +1,633 @@
-+/*
-+ * linux/drivers/mmc/tmio_mmc.c
-+ *
-+ * Copyright (C) 2004 Ian Molton
-+ * Copyright (C) 2007 Ian Molton
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Driver for the MMC / SD / SDIO cell found in:
-+ *
-+ * TC6393XB TC6391XB TC6387XB T7L66XB
-+ *
-+ * This driver draws mainly on scattered spec sheets, Reverse engineering
-+ * of the toshiba e800 SD driver and some parts of the 2.4 ASIC3 driver (4 bit
-+ * support). (Further 4 bit support from a later datasheet).
-+ *
-+ * TODO:
-+ * Investigate using a workqueue for PIO transfers
-+ * Eliminate FIXMEs
-+ * SDIO support
-+ * Better Power management
-+ * Handle MMC errors better
-+ * double buffer support
-+ *
-+ */
-+#include <linux/module.h>
-+#include <linux/irq.h>
-+#include <linux/device.h>
-+#include <linux/delay.h>
-+#include <linux/mmc/mmc.h>
-+#include <linux/mmc/host.h>
-+#include <linux/mfd-core.h>
-+#include <linux/mfd/tmio.h>
-+
-+#include "tmio_mmc.h"
-+
-+/*
-+ * Fixme - documentation conflicts on what the clock values are for the
-+ * various dividers.
-+ * One document I have says that its a divisor of a 24MHz clock, another 33.
-+ * This probably depends on HCLK for a given platform, so we may need to
-+ * require HCLK be passed to us from the MFD core.
-+ *
-+ */
-+
-+static void tmio_mmc_set_clock (struct tmio_mmc_host *host, int new_clock) {
-+ struct tmio_mmc_cnf __iomem *cnf = host->cnf;
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+ u32 clk = 0, clock;
-+
-+ if (new_clock) {
-+ for(clock = 46875, clk = 0x100; new_clock >= (clock<<1); ){
-+ clock <<= 1;
-+ clk >>= 1;
-+ }
-+ if(clk & 0x1)
-+ clk = 0x20000;
-+
-+ clk >>= 2;
-+ if(clk & 0x8000) /* For full speed we disable the divider. */
-+ writeb(0, &cnf->sd_clk_mode);
-+ else
-+ writeb(1, &cnf->sd_clk_mode);
-+ clk |= 0x100;
-+ }
-+
-+ writew(clk, &ctl->sd_card_clk_ctl);
-+}
-+
-+static void tmio_mmc_clk_stop (struct tmio_mmc_host *host) {
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+
-+ writew(0x0000, &ctl->clk_and_wait_ctl);
-+ msleep(10);
-+ writew(readw(&ctl->sd_card_clk_ctl) & ~0x0100, &ctl->sd_card_clk_ctl);
-+ msleep(10);
-+}
-+
-+static void tmio_mmc_clk_start (struct tmio_mmc_host *host) {
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+
-+ writew(readw(&ctl->sd_card_clk_ctl) | 0x0100, &ctl->sd_card_clk_ctl);
-+ msleep(10);
-+ writew(0x0100, &ctl->clk_and_wait_ctl);
-+ msleep(10);
-+}
-+
-+static void reset(struct tmio_mmc_host *host) {
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+
-+ /* FIXME - should we set stop clock reg here */
-+ writew(0x0000, &ctl->reset_sd);
-+ writew(0x0000, &ctl->reset_sdio);
-+ msleep(10);
-+ writew(0x0001, &ctl->reset_sd);
-+ writew(0x0001, &ctl->reset_sdio);
-+ msleep(10);
-+}
-+
-+static void
-+tmio_mmc_finish_request(struct tmio_mmc_host *host)
-+{
-+ struct mmc_request *mrq = host->mrq;
-+
-+ host->mrq = NULL;
-+ host->cmd = NULL;
-+ host->data = NULL;
-+
-+ mmc_request_done(host->mmc, mrq);
-+}
-+
-+/* These are the bitmasks the tmio chip requires to implement the MMC response
-+ * types. Note that R1 and R6 are the same in this scheme. */
-+#define APP_CMD 0x0040
-+#define RESP_NONE 0x0300
-+#define RESP_R1 0x0400
-+#define RESP_R1B 0x0500
-+#define RESP_R2 0x0600
-+#define RESP_R3 0x0700
-+#define DATA_PRESENT 0x0800
-+#define TRANSFER_READ 0x1000
-+#define TRANSFER_MULTI 0x2000
-+#define SECURITY_CMD 0x4000
-+
-+static void
-+tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
-+{
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+ struct mmc_data *data = host->data;
-+ int c = cmd->opcode;
-+
-+ if(cmd->opcode == MMC_STOP_TRANSMISSION) {
-+ writew(0x001, &ctl->stop_internal_action);
-+ return;
-+ }
-+
-+ switch(mmc_resp_type(cmd)) {
-+ case MMC_RSP_NONE: c |= RESP_NONE; break;
-+ case MMC_RSP_R1: c |= RESP_R1; break;
-+ case MMC_RSP_R1B: c |= RESP_R1B; break;
-+ case MMC_RSP_R2: c |= RESP_R2; break;
-+ case MMC_RSP_R3: c |= RESP_R3; break;
-+ default:
-+ DBG("Unknown response type %d\n", mmc_resp_type(cmd));
-+ }
-+
-+ host->cmd = cmd;
-+
-+/* FIXME - this seems to be ok comented out but the spec suggest this bit should
-+ * be set when issuing app commands.
-+ * if(cmd->flags & MMC_FLAG_ACMD)
-+ * c |= APP_CMD;
-+ */
-+ if(data) {
-+ c |= DATA_PRESENT;
-+ if(data->blocks > 1) {
-+ writew(0x100, &ctl->stop_internal_action);
-+ c |= TRANSFER_MULTI;
-+ }
-+ if(data->flags & MMC_DATA_READ)
-+ c |= TRANSFER_READ;
-+ }
-+
-+ enable_mmc_irqs(ctl, TMIO_MASK_CMD);
-+
-+ /* Fire off the command */
-+ tmio_iowrite32(cmd->arg, ctl->arg_reg);
-+ writew(c, &ctl->sd_cmd);
-+}
-+
-+/* This chip always returns (at least?) as much data as you ask for.
-+ * Im unsure what happens if you ask for less than a block. This should be
-+ * looked into to ensure that a funny length read doesnt hose the controller.
-+ *
-+ * FIXME - this chip cannot do 1 and 2 byte data requests in 4 bit mode
-+ */
-+static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host) {
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+ struct mmc_data *data = host->data;
-+ unsigned short *buf;
-+ unsigned int count;
-+ unsigned long flags;
-+
-+ if(!data){
-+ DBG("Spurious PIO IRQ\n");
-+ return;
-+ }
-+
-+ buf = (unsigned short *)(tmio_mmc_kmap_atomic(host, &flags) +
-+ host->sg_off);
-+
-+ /* Ensure we dont read more than one block. The chip will interrupt us
-+ * When the next block is available.
-+ * FIXME - this is probably not true now IRQ handling is fixed
-+ */
-+ count = host->sg_ptr->length - host->sg_off;
-+ if(count > data->blksz)
-+ count = data->blksz;
-+
-+ DBG("count: %08x offset: %08x flags %08x\n",
-+ count, host->sg_off, data->flags);
-+
-+ /* Transfer the data */
-+ if(data->flags & MMC_DATA_READ)
-+ readsw(&ctl->sd_data_port[0], buf, count >> 1);
-+ else
-+ writesw(&ctl->sd_data_port[0], buf, count >> 1);
-+
-+ host->sg_off += count;
-+
-+ tmio_mmc_kunmap_atomic(host, &flags);
-+
-+ if(host->sg_off == host->sg_ptr->length)
-+ tmio_mmc_next_sg(host);
-+
-+ return;
-+}
-+
-+static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host) {
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+ struct mmc_data *data = host->data;
-+
-+ host->data = NULL;
-+
-+ if(!data){
-+ DBG("Spurious data end IRQ\n");
-+ return;
-+ }
-+
-+ /* FIXME - return correct transfer count on errors */
-+ if (!data->error)
-+ data->bytes_xfered = data->blocks * data->blksz;
-+ else
-+ data->bytes_xfered = 0;
-+
-+ DBG("Completed data request\n");
-+
-+ /*FIXME - other drivers allow an optional stop command of any given type
-+ * which we dont do, as the chip can auto generate them.
-+ * Perhaps we can be smarter about when to use auto CMD12 and
-+ * only issue the auto request when we know this is the desired
-+ * stop command, allowing fallback to the stop command the
-+ * upper layers expect. For now, we do what works.
-+ */
-+
-+ writew(0x000, &ctl->stop_internal_action);
-+
-+ if(data->flags & MMC_DATA_READ)
-+ disable_mmc_irqs(ctl, TMIO_MASK_READOP);
-+ else
-+ disable_mmc_irqs(ctl, TMIO_MASK_WRITEOP);
-+
-+ tmio_mmc_finish_request(host);
-+}
-+
-+static inline void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, unsigned int stat) {
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+ struct mmc_command *cmd = host->cmd;
-+
-+ if(!host->cmd) {
-+ DBG("Spurious CMD irq\n");
-+ return;
-+ }
-+
-+ host->cmd = NULL;
-+
-+ /* This controller is sicker than the PXA one. not only do we need to
-+ * drop the top 8 bits of the first response word, we also need to
-+ * modify the order of the response for short response command types.
-+ */
-+
-+ /* FIXME - this works but readl is wrong and will break on asic3... */
-+ cmd->resp[3] = tmio_ioread32(&ctl->response[0]);
-+ cmd->resp[2] = tmio_ioread32(&ctl->response[2]);
-+ cmd->resp[1] = tmio_ioread32(&ctl->response[4]);
-+ cmd->resp[0] = tmio_ioread32(&ctl->response[6]);
-+
-+ if(cmd->flags & MMC_RSP_136) {
-+ cmd->resp[0] = (cmd->resp[0] <<8) | (cmd->resp[1] >>24);
-+ cmd->resp[1] = (cmd->resp[1] <<8) | (cmd->resp[2] >>24);
-+ cmd->resp[2] = (cmd->resp[2] <<8) | (cmd->resp[3] >>24);
-+ cmd->resp[3] <<= 8;
-+ }
-+ else if(cmd->flags & MMC_RSP_R3) {
-+ cmd->resp[0] = cmd->resp[3];
-+ }
-+
-+ if (stat & TMIO_STAT_CMDTIMEOUT)
-+ cmd->error = -ETIMEDOUT;
-+ else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
-+ cmd->error = -EILSEQ;
-+
-+ /* If there is data to handle we enable data IRQs here, and
-+ * we will ultimatley finish the request in the data_end handler.
-+ * If theres no data or we encountered an error, finish now.
-+ */
-+ if(host->data && !cmd->error){
-+ if(host->data->flags & MMC_DATA_READ)
-+ enable_mmc_irqs(ctl, TMIO_MASK_READOP);
-+ else
-+ enable_mmc_irqs(ctl, TMIO_MASK_WRITEOP);
-+ }
-+ else {
-+ tmio_mmc_finish_request(host);
-+ }
-+
-+ return;
-+}
-+
-+
-+static irqreturn_t tmio_mmc_irq(int irq, void *devid)
-+{
-+ struct tmio_mmc_host *host = devid;
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+ unsigned int ireg, irq_mask, status;
-+
-+ DBG("MMC IRQ begin\n");
-+
-+ status = tmio_ioread32(ctl->status);
-+ irq_mask = tmio_ioread32(ctl->irq_mask);
-+ ireg = status & TMIO_MASK_IRQ & ~irq_mask;
-+
-+#ifdef CONFIG_MMC_DEBUG
-+ debug_status(status);
-+ debug_status(ireg);
-+#endif
-+ if (!ireg) {
-+ disable_mmc_irqs(ctl, status & ~irq_mask);
-+#ifdef CONFIG_MMC_DEBUG
-+ WARN("tmio_mmc: Spurious MMC irq, disabling! 0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
-+ debug_status(status);
-+#endif
-+ goto out;
-+ }
-+
-+ while (ireg) {
-+ /* Card insert / remove attempts */
-+ if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)){
-+ ack_mmc_irqs(ctl, TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE);
-+ mmc_detect_change(host->mmc,0);
-+ }
-+
-+ /* CRC and other errors */
-+/* if (ireg & TMIO_STAT_ERR_IRQ)
-+ * handled |= tmio_error_irq(host, irq, stat);
-+ */
-+
-+ /* Command completion */
-+ if (ireg & TMIO_MASK_CMD) {
-+ tmio_mmc_cmd_irq(host, status);
-+ ack_mmc_irqs(ctl, TMIO_MASK_CMD);
-+ }
-+
-+ /* Data transfer */
-+ if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
-+ ack_mmc_irqs(ctl, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
-+ tmio_mmc_pio_irq(host);
-+ }
-+
-+ /* Data transfer completion */
-+ if (ireg & TMIO_STAT_DATAEND) {
-+ tmio_mmc_data_irq(host);
-+ ack_mmc_irqs(ctl, TMIO_STAT_DATAEND);
-+ }
-+
-+ /* Check status - keep going until we've handled it all */
-+ status = tmio_ioread32(ctl->status);
-+ irq_mask = tmio_ioread32(ctl->irq_mask);
-+ ireg = status & TMIO_MASK_IRQ & ~irq_mask;
-+
-+#ifdef CONFIG_MMC_DEBUG
-+ DBG("Status at end of loop: %08x\n", status);
-+ debug_status(status);
-+#endif
-+ }
-+ DBG("MMC IRQ end\n");
-+
-+out:
-+ return IRQ_HANDLED;
-+}
-+
-+static void tmio_mmc_start_data(struct tmio_mmc_host *host, struct mmc_data *data)
-+{
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+
-+ DBG("setup data transfer: blocksize %08x nr_blocks %d\n",
-+ data->blksz, data->blocks);
-+
-+ tmio_mmc_init_sg(host, data);
-+ host->data = data;
-+
-+ /* Set transfer length / blocksize */
-+ writew(data->blksz, &ctl->sd_xfer_len);
-+ writew(data->blocks, &ctl->xfer_blk_count);
-+}
-+
-+/* Process requests from the MMC layer */
-+static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
-+{
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+
-+ WARN_ON(host->mrq != NULL);
-+
-+ host->mrq = mrq;
-+
-+ /* If we're performing a data request we need to setup some
-+ extra information */
-+ if (mrq->data)
-+ tmio_mmc_start_data(host, mrq->data);
-+
-+ tmio_mmc_start_command(host, mrq->cmd);
-+}
-+
-+/* Set MMC clock / power.
-+ * Note: This controller uses a simple divider scheme therefore it cannot
-+ * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
-+ * MMC wont run that fast, it has to be clocked at 12MHz which is the next
-+ * slowest setting.
-+ */
-+static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-+{
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ struct tmio_mmc_cnf __iomem *cnf = host->cnf;
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+
-+ if(ios->clock)
-+ tmio_mmc_set_clock (host, ios->clock);
-+
-+ /* Power sequence - OFF -> ON -> UP */
-+ switch (ios->power_mode) {
-+ case MMC_POWER_OFF:
-+ writeb(0x00, &cnf->pwr_ctl[1]); /* power down SD bus */
-+ tmio_mmc_clk_stop(host);
-+ break;
-+ case MMC_POWER_ON:
-+ writeb(0x02, &cnf->pwr_ctl[1]); /* power up SD bus */
-+ break;
-+ case MMC_POWER_UP:
-+ tmio_mmc_clk_start(host); /* start bus clock */
-+ break;
-+ }
-+
-+ switch (ios->bus_width) {
-+ case MMC_BUS_WIDTH_1:
-+ writew(0x80e0, &ctl->sd_mem_card_opt);
-+ break;
-+ case MMC_BUS_WIDTH_4:
-+ writew(0x00e0, &ctl->sd_mem_card_opt);
-+ break;
-+ }
-+
-+ /* Potentially we may need a 140us pause here. FIXME */
-+ udelay(140);
-+}
-+
-+static int tmio_mmc_get_ro(struct mmc_host *mmc) {
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ struct tmio_mmc_ctl __iomem *ctl = host->ctl;
-+
-+ return (readw(&ctl->status[0]) & TMIO_STAT_WRPROTECT)?0:1;
-+}
-+
-+static struct mmc_host_ops tmio_mmc_ops = {
-+ .request = tmio_mmc_request,
-+ .set_ios = tmio_mmc_set_ios,
-+ .get_ro = tmio_mmc_get_ro,
-+};
-+
-+static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) {
-+ struct mfd_cell *cell = mfd_get_cell(dev);
-+ struct mmc_host *mmc = platform_get_drvdata(dev);
-+ int ret;
-+
-+ ret = mmc_suspend_host(mmc, state);
-+
-+ /* Tell MFD core it can disable us now.*/
-+ if(!ret && cell->disable)
-+ cell->disable(dev);
-+
-+ return ret;
-+}
-+
-+static int tmio_mmc_resume(struct platform_device *dev) {
-+ struct mfd_cell *cell = mfd_get_cell(dev);
-+ struct mmc_host *mmc = platform_get_drvdata(dev);
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ struct tmio_mmc_cnf __iomem *cnf = host->cnf;
-+
-+ /* Enable the MMC/SD Control registers */
-+ writew(SDCREN, &cnf->cmd);
-+ writel(dev->resource[0].start & 0xfffe, &cnf->ctl_base);
-+
-+ /* Tell the MFD core we are ready to be enabled */
-+ if(cell->enable)
-+ cell->enable(dev);
-+
-+ mmc_resume_host(mmc);
-+
-+ return 0;
-+}
-+
-+static int __devinit tmio_mmc_probe(struct platform_device *dev)
-+{
-+ struct mfd_cell *cell = mfd_get_cell(dev);
-+ struct tmio_mmc_cnf __iomem *cnf;
-+ struct tmio_mmc_ctl __iomem *ctl;
-+ struct tmio_mmc_host *host;
-+ struct mmc_host *mmc;
-+ int ret = -ENOMEM;
-+
-+ mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
-+ if (!mmc) {
-+ goto out;
-+ }
-+
-+ host = mmc_priv(mmc);
-+ host->mmc = mmc;
-+ platform_set_drvdata(dev, mmc); /* Used so we can de-init safely. */
-+
-+ host->cnf = cnf = ioremap((unsigned long)dev->resource[1].start,
-+ (unsigned long)dev->resource[1].end -
-+ (unsigned long)dev->resource[1].start);
-+ if(!host->cnf)
-+ goto host_free;
-+
-+ host->ctl = ctl = ioremap((unsigned long)dev->resource[0].start,
-+ (unsigned long)dev->resource[0].end -
-+ (unsigned long)dev->resource[0].start);
-+ if (!host->ctl) {
-+ goto unmap_cnf;
-+ }
-+
-+ mmc->ops = &tmio_mmc_ops;
-+ mmc->caps = MMC_CAP_4_BIT_DATA;
-+ mmc->f_min = 46875;
-+ mmc->f_max = 24000000;
-+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-+
-+ /* Enable the MMC/SD Control registers */
-+ writew(SDCREN, &cnf->cmd);
-+ writel(dev->resource[0].start & 0xfffe, &cnf->ctl_base);
-+
-+ /* Tell the MFD core we are ready to be enabled */
-+ if(cell->enable)
-+ cell->enable(dev);
-+
-+ writeb(0x01,&cnf->pwr_ctl[2]); /* Disable SD power during suspend */
-+ writeb(0x1f, &cnf->stop_clk_ctl); /* Route clock to SDIO??? FIXME */
-+ writeb(0x0, &cnf->pwr_ctl[1]); /* Power down SD bus*/
-+ tmio_mmc_clk_stop(host); /* Stop bus clock */
-+ reset(host); /* Reset MMC HC */
-+
-+ host->irq = (unsigned long)dev->resource[2].start;
-+ ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED, "tmio-mmc", host);
-+ if (ret){
-+ ret = -ENODEV;
-+ DBG("Failed to allocate IRQ.\n");
-+ goto unmap_ctl;
-+ }
-+ set_irq_type(host->irq, IRQT_FALLING);
-+
-+ mmc_add_host(mmc);
-+
-+ printk(KERN_INFO "%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
-+ (unsigned long)host->ctl, host->irq);
-+
-+ /* Lets unmask the IRQs we want to know about */
-+ disable_mmc_irqs(ctl, TMIO_MASK_ALL);
-+ enable_mmc_irqs(ctl, TMIO_MASK_IRQ);
-+
-+ return 0;
-+
-+unmap_ctl:
-+ iounmap(host->ctl);
-+unmap_cnf:
-+ iounmap(host->cnf);
-+host_free:
-+ mmc_free_host(mmc);
-+out:
-+ return ret;
-+}
-+
-+static int __devexit tmio_mmc_remove(struct platform_device *dev)
-+{
-+ struct mmc_host *mmc = platform_get_drvdata(dev);
-+
-+ platform_set_drvdata(dev, NULL);
-+
-+ if (mmc) {
-+ struct tmio_mmc_host *host = mmc_priv(mmc);
-+ mmc_remove_host(mmc);
-+ free_irq(host->irq, host);
-+ /* FIXME - we might want to consider stopping the chip here. */
-+ iounmap(host->ctl);
-+ iounmap(host->cnf);
-+ mmc_free_host(mmc); /* FIXME - why does this call hang ? */
-+ }
-+ return 0;
-+}
-+
-+/* ------------------- device registration ----------------------- */
-+
-+static struct platform_driver tmio_mmc_driver = {
-+ .driver = {
-+ .name = "tmio-mmc",
-+ },
-+ .probe = tmio_mmc_probe,
-+ .remove = __devexit_p(tmio_mmc_remove),
-+#ifdef CONFIG_PM
-+ .suspend = tmio_mmc_suspend,
-+ .resume = tmio_mmc_resume,
-+#endif
-+};
-+
-+
-+static int __init tmio_mmc_init(void)
-+{
-+ return platform_driver_register (&tmio_mmc_driver);
-+}
-+
-+static void __exit tmio_mmc_exit(void)
-+{
-+ platform_driver_unregister (&tmio_mmc_driver);
-+}
-+
-+module_init(tmio_mmc_init);
-+module_exit(tmio_mmc_exit);
-+
-+MODULE_DESCRIPTION("Toshiba TMIO SD/MMC driver");
-+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
-+MODULE_LICENSE("GPLv2");
-diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
-new file mode 100644
-index 0000000..d4d9f8f
---- /dev/null
-+++ b/drivers/mmc/host/tmio_mmc.h
-@@ -0,0 +1,205 @@
-+/* Definitons for use with the tmio_mmc.c
-+ *
-+ * (c) 2005 Ian Molton <spyro@f2s.com>
-+ * (c) 2007 Ian Molton <spyro@f2s.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+struct tmio_mmc_cnf {
-+ u8 x00[4];
-+ u16 cmd;
-+ u8 x01[10];
-+ u32 ctl_base;
-+ u8 x02[41];
-+ u8 int_pin;
-+ u8 x03[2];
-+ u8 stop_clk_ctl;
-+ u8 gclk_ctl; /* Gated Clock Control */
-+ u8 sd_clk_mode; /* 0x42 */
-+ u8 x04;
-+ u16 pin_status;
-+ u8 x05[2];
-+ u8 pwr_ctl[3];
-+ u8 x06;
-+ u8 card_detect_mode;
-+ u8 x07[3];
-+ u8 sd_slot;
-+ u8 x08[159];
-+ u8 ext_gclk_ctl_1; /* Extended Gated Clock Control 1 */
-+ u8 ext_gclk_ctl_2; /* Extended Gated Clock Control 2 */
-+ u8 x09[7];
-+ u8 ext_gclk_ctl_3; /* Extended Gated Clock Control 3 */
-+ u8 sd_led_en_1;
-+ u8 x10[3];
-+ u8 sd_led_en_2;
-+ u8 x11;
-+} __attribute__ ((packed));
-+
-+#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
-+
-+struct tmio_mmc_ctl {
-+ u16 sd_cmd;
-+ u16 x00;
-+ u16 arg_reg[2];
-+ u16 stop_internal_action;
-+ u16 xfer_blk_count;
-+ u16 response[8];
-+ u16 status[2];
-+ u16 irq_mask[2];
-+ u16 sd_card_clk_ctl;
-+ u16 sd_xfer_len;
-+ u16 sd_mem_card_opt;
-+ u16 x01;
-+ u16 sd_error_detail_status[2];
-+ u16 sd_data_port[2];
-+ u16 transaction_ctl;
-+ u16 x02[85];
-+ u16 reset_sd;
-+ u16 x03[15];
-+ u16 sdio_regs[28];
-+ u16 clk_and_wait_ctl;
-+ u16 x04[83];
-+ u16 reset_sdio;
-+ u16 x05[15];
-+} __attribute__ ((packed));
-+
-+/* Definitions for values the CTRL_STATUS register can take. */
-+#define TMIO_STAT_CMDRESPEND 0x00000001
-+#define TMIO_STAT_DATAEND 0x00000004
-+#define TMIO_STAT_CARD_REMOVE 0x00000008
-+#define TMIO_STAT_CARD_INSERT 0x00000010
-+#define TMIO_STAT_SIGSTATE 0x00000020
-+#define TMIO_STAT_WRPROTECT 0x00000080
-+#define TMIO_STAT_CARD_REMOVE_A 0x00000100
-+#define TMIO_STAT_CARD_INSERT_A 0x00000200
-+#define TMIO_STAT_SIGSTATE_A 0x00000400
-+#define TMIO_STAT_CMD_IDX_ERR 0x00010000
-+#define TMIO_STAT_CRCFAIL 0x00020000
-+#define TMIO_STAT_STOPBIT_ERR 0x00040000
-+#define TMIO_STAT_DATATIMEOUT 0x00080000
-+#define TMIO_STAT_RXOVERFLOW 0x00100000
-+#define TMIO_STAT_TXUNDERRUN 0x00200000
-+#define TMIO_STAT_CMDTIMEOUT 0x00400000
-+#define TMIO_STAT_RXRDY 0x01000000
-+#define TMIO_STAT_TXRQ 0x02000000
-+#define TMIO_STAT_ILL_FUNC 0x20000000
-+#define TMIO_STAT_CMD_BUSY 0x40000000
-+#define TMIO_STAT_ILL_ACCESS 0x80000000
-+
-+/* Define some IRQ masks */
-+/* This is the mask used at reset by the chip */
-+#define TMIO_MASK_ALL 0x837f031d
-+#define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND | \
-+ TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-+#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND | \
-+ TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-+#define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
-+ TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-+#define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
-+
-+#define enable_mmc_irqs(ctl, i) \
-+ do { \
-+ u32 mask;\
-+ mask = tmio_ioread32((ctl)->irq_mask); \
-+ mask &= ~((i) & TMIO_MASK_IRQ); \
-+ tmio_iowrite32(mask, (ctl)->irq_mask); \
-+ } while (0)
-+
-+#define disable_mmc_irqs(ctl, i) \
-+ do { \
-+ u32 mask;\
-+ mask = tmio_ioread32((ctl)->irq_mask); \
-+ mask |= ((i) & TMIO_MASK_IRQ); \
-+ tmio_iowrite32(mask, (ctl)->irq_mask); \
-+ } while (0)
-+
-+#define ack_mmc_irqs(ctl, i) \
-+ do { \
-+ u32 mask;\
-+ mask = tmio_ioread32((ctl)->status); \
-+ mask &= ~((i) & TMIO_MASK_IRQ); \
-+ tmio_iowrite32(mask, (ctl)->status); \
-+ } while (0)
-+
-+
-+struct tmio_mmc_host {
-+ struct tmio_mmc_cnf __iomem *cnf;
-+ struct tmio_mmc_ctl __iomem *ctl;
-+ struct mmc_command *cmd;
-+ struct mmc_request *mrq;
-+ struct mmc_data *data;
-+ struct mmc_host *mmc;
-+ int irq;
-+
-+ /* pio related stuff */
-+ struct scatterlist *sg_ptr;
-+ unsigned int sg_len;
-+ unsigned int sg_off;
-+};
-+
-+#include <linux/scatterlist.h>
-+#include <linux/blkdev.h>
-+
-+static inline void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data)
-+{
-+ host->sg_len = data->sg_len;
-+ host->sg_ptr = data->sg;
-+ host->sg_off = 0;
-+}
-+
-+static inline int tmio_mmc_next_sg(struct tmio_mmc_host *host)
-+{
-+ host->sg_ptr++;
-+ host->sg_off = 0;
-+ return --host->sg_len;
-+}
-+
-+static inline char *tmio_mmc_kmap_atomic(struct tmio_mmc_host *host, unsigned long *flags)
-+{
-+ struct scatterlist *sg = host->sg_ptr;
-+
-+ local_irq_save(*flags);
-+ return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-+}
-+
-+static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host, unsigned long *flags)
-+{
-+ kunmap_atomic(sg_page(host->sg_ptr), KM_BIO_SRC_IRQ);
-+ local_irq_restore(*flags);
-+}
-+
-+#ifdef CONFIG_MMC_DEBUG
-+#define DBG(args...) printk(args)
-+
-+void debug_status(u32 status){
-+ printk("status: %08x = ", status);
-+ if(status & TMIO_STAT_CARD_REMOVE) printk("Card_removed ");
-+ if(status & TMIO_STAT_CARD_INSERT) printk("Card_insert ");
-+ if(status & TMIO_STAT_SIGSTATE) printk("Sigstate ");
-+ if(status & TMIO_STAT_WRPROTECT) printk("Write_protect ");
-+ if(status & TMIO_STAT_CARD_REMOVE_A) printk("Card_remove_A ");
-+ if(status & TMIO_STAT_CARD_INSERT_A) printk("Card_insert_A ");
-+ if(status & TMIO_STAT_SIGSTATE_A) printk("Sigstate_A ");
-+ if(status & TMIO_STAT_CMD_IDX_ERR) printk("Cmd_IDX_Err ");
-+ if(status & TMIO_STAT_STOPBIT_ERR) printk("Stopbit_ERR ");
-+ if(status & TMIO_STAT_ILL_FUNC) printk("ILLEGAL_FUNC ");
-+ if(status & TMIO_STAT_CMD_BUSY) printk("CMD_BUSY ");
-+ if(status & TMIO_STAT_CMDRESPEND) printk("Response_end ");
-+ if(status & TMIO_STAT_DATAEND) printk("Data_end ");
-+ if(status & TMIO_STAT_CRCFAIL) printk("CRC_failure ");
-+ if(status & TMIO_STAT_DATATIMEOUT) printk("Data_timeout ");
-+ if(status & TMIO_STAT_CMDTIMEOUT) printk("Command_timeout ");
-+ if(status & TMIO_STAT_RXOVERFLOW) printk("RX_OVF ");
-+ if(status & TMIO_STAT_TXUNDERRUN) printk("TX_UND ");
-+ if(status & TMIO_STAT_RXRDY) printk("RX_rdy ");
-+ if(status & TMIO_STAT_TXRQ) printk("TX_req ");
-+ if(status & TMIO_STAT_ILL_ACCESS) printk("ILLEGAL_ACCESS ");
-+ printk("\n");
-+}
-+#else
-+#define DBG(fmt,args...) do { } while (0)
-+#endif
---
-1.5.3.8
-