Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/drzeus/mmc
authorLinus Torvalds <torvalds@woody.osdl.org>
Sat, 2 Dec 2006 16:29:04 +0000 (08:29 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Sat, 2 Dec 2006 16:29:04 +0000 (08:29 -0800)
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/drzeus/mmc:
  mmc: correct request error handling
  mmc: Flush block queue when removing card
  mmc: sdhci high speed support
  mmc: Support for high speed SD cards
  mmc: Fix mmc_delay() function
  mmc: Add support for mmc v4 wide-bus modes
  [PATCH] mmc: Add support for mmc v4 high speed mode
  trivial change for mmc/Kconfig: MMC_PXA does not mean only PXA255
  Make general code cleanups
  Add MMC_CAP_{MULTIWRITE,BYTEBLOCK} flags
  Platform device error handling cleanup
  Move register definitions away from the header file
  Change OMAP_MMC_{READ,WRITE} macros to use the host pointer
  Replace base with virt_base and phys_base
  mmc: constify mmc_host_ops vectors
  mmc: remove kernel_thread()

17 files changed:
drivers/mmc/Kconfig
drivers/mmc/at91_mci.c
drivers/mmc/au1xmmc.c
drivers/mmc/imxmmc.c
drivers/mmc/mmc.c
drivers/mmc/mmc_block.c
drivers/mmc/mmc_queue.c
drivers/mmc/mmc_queue.h
drivers/mmc/mmci.c
drivers/mmc/omap.c
drivers/mmc/omap.h [deleted file]
drivers/mmc/pxamci.c
drivers/mmc/sdhci.c
drivers/mmc/sdhci.h
drivers/mmc/wbsd.c
include/linux/mmc/card.h
include/linux/mmc/protocol.h

index ea41852ec8cd33f945eb942519fe90b680de7920..f4f8ccaf5455c789bb723fb956fb08639225825f 100644 (file)
@@ -40,7 +40,7 @@ config MMC_ARMMMCI
          If unsure, say N.
 
 config MMC_PXA
-       tristate "Intel PXA255 Multimedia Card Interface support"
+       tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
        depends on ARCH_PXA && MMC
        help
          This selects the Intel(R) PXA(R) Multimedia card Interface.
index 494b23fb0a01930503c35e6e42336f65f06f7234..6495cd8a9306687478d9e03d6d471edf0973242c 100644 (file)
@@ -793,7 +793,7 @@ int at91_mci_get_ro(struct mmc_host *mmc)
        return read_only;
 }
 
-static struct mmc_host_ops at91_mci_ops = {
+static const struct mmc_host_ops at91_mci_ops = {
        .request        = at91_mci_request,
        .set_ios        = at91_mci_set_ios,
        .get_ro         = at91_mci_get_ro,
index 53ffcbb14a97cf14da80d8de359da8516f63062a..447fba5825fd10854484452004455419fa1cd3a2 100644 (file)
@@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host)
        host->rx_chan = rxchan;
 }
 
-struct mmc_host_ops au1xmmc_ops = {
+struct const mmc_host_ops au1xmmc_ops = {
        .request        = au1xmmc_request,
        .set_ios        = au1xmmc_set_ios,
 };
index 659d4a822cc5d6bf8852516d428b9394e1eff27a..06e7fcd192217317bef3d0159c5823144ca6619a 100644 (file)
@@ -877,7 +877,7 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        }
 }
 
-static struct mmc_host_ops imxmci_ops = {
+static const struct mmc_host_ops imxmci_ops = {
        .request        = imxmci_request,
        .set_ios        = imxmci_set_ios,
 };
index 766bc54406e5864111ded440d722eb694bd03d3d..9d190022a4905f8d3682699ab2c87ec67e693ff6 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
  *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
  *
  * 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
@@ -396,23 +397,23 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
                return err;
 
        /*
-        * Default bus width is 1 bit.
-        */
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-
-       /*
-        * We can only change the bus width of the selected
-        * card so therefore we have to put the handling
+        * We can only change the bus width of SD cards when
+        * they are selected so we have to put the handling
         * here.
+        *
+        * The card is in 1 bit mode by default so
+        * we only need to change if it supports the
+        * wider version.
         */
-       if (host->caps & MMC_CAP_4_BIT_DATA) {
+       if (mmc_card_sd(card) &&
+               (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+
                /*
-                * The card is in 1 bit mode by default so
-                * we only need to change if it supports the
-                * wider version.
-                */
-               if (mmc_card_sd(card) &&
-                       (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+               * Default bus width is 1 bit.
+               */
+               host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+               if (host->caps & MMC_CAP_4_BIT_DATA) {
                        struct mmc_command cmd;
                        cmd.opcode = SD_APP_SET_BUS_WIDTH;
                        cmd.arg = SD_BUS_WIDTH_4;
@@ -453,11 +454,11 @@ static void mmc_deselect_cards(struct mmc_host *host)
 
 static inline void mmc_delay(unsigned int ms)
 {
-       if (ms < HZ / 1000) {
-               yield();
+       if (ms < 1000 / HZ) {
+               cond_resched();
                mdelay(ms);
        } else {
-               msleep_interruptible (ms);
+               msleep(ms);
        }
 }
 
@@ -953,6 +954,137 @@ static void mmc_read_csds(struct mmc_host *host)
        }
 }
 
+static void mmc_process_ext_csds(struct mmc_host *host)
+{
+       int err;
+       struct mmc_card *card;
+
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+
+       struct scatterlist sg;
+
+       /*
+        * As the ext_csd is so large and mostly unused, we don't store the
+        * raw block in mmc_card.
+        */
+       u8 *ext_csd;
+       ext_csd = kmalloc(512, GFP_KERNEL);
+       if (!ext_csd) {
+               printk("%s: could not allocate a buffer to receive the ext_csd."
+                      "mmc v4 cards will be treated as v3.\n",
+                       mmc_hostname(host));
+               return;
+       }
+
+       list_for_each_entry(card, &host->cards, node) {
+               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+                       continue;
+               if (mmc_card_sd(card))
+                       continue;
+               if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+                       continue;
+
+               err = mmc_select_card(host, card);
+               if (err != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               memset(&cmd, 0, sizeof(struct mmc_command));
+
+               cmd.opcode = MMC_SEND_EXT_CSD;
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+               memset(&data, 0, sizeof(struct mmc_data));
+
+               mmc_set_data_timeout(&data, card, 0);
+
+               data.blksz = 512;
+               data.blocks = 1;
+               data.flags = MMC_DATA_READ;
+               data.sg = &sg;
+               data.sg_len = 1;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               mrq.cmd = &cmd;
+               mrq.data = &data;
+
+               sg_init_one(&sg, ext_csd, 512);
+
+               mmc_wait_for_req(host, &mrq);
+
+               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+               case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+                       card->ext_csd.hs_max_dtr = 52000000;
+                       break;
+               case EXT_CSD_CARD_TYPE_26:
+                       card->ext_csd.hs_max_dtr = 26000000;
+                       break;
+               default:
+                       /* MMC v4 spec says this cannot happen */
+                       printk("%s: card is mmc v4 but doesn't support "
+                              "any high-speed modes.\n",
+                               mmc_hostname(card->host));
+                       mmc_card_set_bad(card);
+                       continue;
+               }
+
+               /* Activate highspeed support. */
+               cmd.opcode = MMC_SWITCH;
+               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                         (EXT_CSD_HS_TIMING << 16) |
+                         (1 << 8) |
+                         EXT_CSD_CMD_SET_NORMAL;
+               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+               if (err != MMC_ERR_NONE) {
+                       printk("%s: failed to switch card to mmc v4 "
+                              "high-speed mode.\n",
+                              mmc_hostname(card->host));
+                       continue;
+               }
+
+               mmc_card_set_highspeed(card);
+
+               /* Check for host support for wide-bus modes. */
+               if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
+                       continue;
+               }
+
+               /* Activate 4-bit support. */
+               cmd.opcode = MMC_SWITCH;
+               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                         (EXT_CSD_BUS_WIDTH << 16) |
+                         (EXT_CSD_BUS_WIDTH_4 << 8) |
+                         EXT_CSD_CMD_SET_NORMAL;
+               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+               if (err != MMC_ERR_NONE) {
+                       printk("%s: failed to switch card to "
+                              "mmc v4 4-bit bus mode.\n",
+                              mmc_hostname(card->host));
+                       continue;
+               }
+
+               host->ios.bus_width = MMC_BUS_WIDTH_4;
+       }
+
+       kfree(ext_csd);
+
+       mmc_deselect_cards(host);
+}
+
 static void mmc_read_scrs(struct mmc_host *host)
 {
        int err;
@@ -1025,14 +1157,133 @@ static void mmc_read_scrs(struct mmc_host *host)
        mmc_deselect_cards(host);
 }
 
+static void mmc_read_switch_caps(struct mmc_host *host)
+{
+       int err;
+       struct mmc_card *card;
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       unsigned char *status;
+       struct scatterlist sg;
+
+       status = kmalloc(64, GFP_KERNEL);
+       if (!status) {
+               printk(KERN_WARNING "%s: Unable to allocate buffer for "
+                       "reading switch capabilities.\n",
+                       mmc_hostname(host));
+               return;
+       }
+
+       list_for_each_entry(card, &host->cards, node) {
+               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+                       continue;
+               if (!mmc_card_sd(card))
+                       continue;
+               if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+                       continue;
+
+               err = mmc_select_card(host, card);
+               if (err != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               memset(&cmd, 0, sizeof(struct mmc_command));
+
+               cmd.opcode = SD_SWITCH;
+               cmd.arg = 0x00FFFFF1;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+               memset(&data, 0, sizeof(struct mmc_data));
+
+               mmc_set_data_timeout(&data, card, 0);
+
+               data.blksz = 64;
+               data.blocks = 1;
+               data.flags = MMC_DATA_READ;
+               data.sg = &sg;
+               data.sg_len = 1;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               mrq.cmd = &cmd;
+               mrq.data = &data;
+
+               sg_init_one(&sg, status, 64);
+
+               mmc_wait_for_req(host, &mrq);
+
+               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               if (status[13] & 0x02)
+                       card->sw_caps.hs_max_dtr = 50000000;
+
+               memset(&cmd, 0, sizeof(struct mmc_command));
+
+               cmd.opcode = SD_SWITCH;
+               cmd.arg = 0x80FFFFF1;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+               memset(&data, 0, sizeof(struct mmc_data));
+
+               mmc_set_data_timeout(&data, card, 0);
+
+               data.blksz = 64;
+               data.blocks = 1;
+               data.flags = MMC_DATA_READ;
+               data.sg = &sg;
+               data.sg_len = 1;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               mrq.cmd = &cmd;
+               mrq.data = &data;
+
+               sg_init_one(&sg, status, 64);
+
+               mmc_wait_for_req(host, &mrq);
+
+               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               if ((status[16] & 0xF) != 1) {
+                       printk(KERN_WARNING "%s: Problem switching card "
+                               "into high-speed mode!\n",
+                               mmc_hostname(host));
+                       continue;
+               }
+
+               mmc_card_set_highspeed(card);
+       }
+
+       kfree(status);
+
+       mmc_deselect_cards(host);
+}
+
 static unsigned int mmc_calculate_clock(struct mmc_host *host)
 {
        struct mmc_card *card;
        unsigned int max_dtr = host->f_max;
 
        list_for_each_entry(card, &host->cards, node)
-               if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
-                       max_dtr = card->csd.max_dtr;
+               if (!mmc_card_dead(card)) {
+                       if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
+                               if (max_dtr > card->sw_caps.hs_max_dtr)
+                                       max_dtr = card->sw_caps.hs_max_dtr;
+                       } else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
+                               if (max_dtr > card->ext_csd.hs_max_dtr)
+                                       max_dtr = card->ext_csd.hs_max_dtr;
+                       } else if (max_dtr > card->csd.max_dtr) {
+                               max_dtr = card->csd.max_dtr;
+                       }
+               }
 
        pr_debug("%s: selected %d.%03dMHz transfer rate\n",
                 mmc_hostname(host),
@@ -1150,8 +1401,11 @@ static void mmc_setup(struct mmc_host *host)
 
        mmc_read_csds(host);
 
-       if (host->mode == MMC_MODE_SD)
+       if (host->mode == MMC_MODE_SD) {
                mmc_read_scrs(host);
+               mmc_read_switch_caps(host);
+       } else
+               mmc_process_ext_csds(host);
 }
 
 
index f9027c8db79226250a0e0fced80633be29d16cba..87713572293f0d3044e077e1b9944617dc14ce1f 100644 (file)
@@ -83,7 +83,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
        md->usage--;
        if (md->usage == 0) {
                put_disk(md->disk);
-               mmc_cleanup_queue(&md->queue);
                kfree(md);
        }
        mutex_unlock(&open_lock);
@@ -225,10 +224,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        struct mmc_blk_data *md = mq->data;
        struct mmc_card *card = md->queue.card;
        struct mmc_blk_request brq;
-       int ret;
+       int ret = 1;
 
        if (mmc_card_claim_host(card))
-               goto cmd_err;
+               goto flush_queue;
 
        do {
                struct mmc_command cmd;
@@ -345,8 +344,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        return 1;
 
  cmd_err:
-       ret = 1;
-
        /*
         * If this is an SD card and we're writing, we can first
         * mark the known good sectors as ok.
@@ -380,6 +377,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
        mmc_card_release_host(card);
 
+flush_queue:
        spin_lock_irq(&md->lock);
        while (ret) {
                ret = end_that_request_chunk(req, 0,
@@ -553,12 +551,11 @@ static void mmc_blk_remove(struct mmc_card *card)
        if (md) {
                int devidx;
 
+               /* Stop new requests from getting into the queue */
                del_gendisk(md->disk);
 
-               /*
-                * I think this is needed.
-                */
-               md->disk->queue = NULL;
+               /* Then flush out any already in there */
+               mmc_cleanup_queue(&md->queue);
 
                devidx = md->disk->first_minor >> MMC_SHIFT;
                __clear_bit(devidx, dev_use);
index 61a1de85cb23c96f83134c7672bd63f693e91e85..a17423a4ed8fb9cbcc4b41e3ea0fcd7a4a7cb744 100644 (file)
  */
 #include <linux/module.h>
 #include <linux/blkdev.h>
+#include <linux/kthread.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include "mmc_queue.h"
 
-#define MMC_QUEUE_EXIT         (1 << 0)
-#define MMC_QUEUE_SUSPENDED    (1 << 1)
+#define MMC_QUEUE_SUSPENDED    (1 << 0)
 
 /*
  * Prepare a MMC request.  Essentially, this means passing the
@@ -59,7 +59,6 @@ static int mmc_queue_thread(void *d)
 {
        struct mmc_queue *mq = d;
        struct request_queue *q = mq->queue;
-       DECLARE_WAITQUEUE(wait, current);
 
        /*
         * Set iothread to ensure that we aren't put to sleep by
@@ -67,12 +66,7 @@ static int mmc_queue_thread(void *d)
         */
        current->flags |= PF_MEMALLOC|PF_NOFREEZE;
 
-       daemonize("mmcqd");
-
-       complete(&mq->thread_complete);
-
        down(&mq->thread_sem);
-       add_wait_queue(&mq->thread_wq, &wait);
        do {
                struct request *req = NULL;
 
@@ -84,7 +78,7 @@ static int mmc_queue_thread(void *d)
                spin_unlock_irq(q->queue_lock);
 
                if (!req) {
-                       if (mq->flags & MMC_QUEUE_EXIT)
+                       if (kthread_should_stop())
                                break;
                        up(&mq->thread_sem);
                        schedule();
@@ -95,10 +89,8 @@ static int mmc_queue_thread(void *d)
 
                mq->issue_fn(mq, req);
        } while (1);
-       remove_wait_queue(&mq->thread_wq, &wait);
        up(&mq->thread_sem);
 
-       complete_and_exit(&mq->thread_complete, 0);
        return 0;
 }
 
@@ -111,9 +103,22 @@ static int mmc_queue_thread(void *d)
 static void mmc_request(request_queue_t *q)
 {
        struct mmc_queue *mq = q->queuedata;
+       struct request *req;
+       int ret;
+
+       if (!mq) {
+               printk(KERN_ERR "MMC: killing requests for dead queue\n");
+               while ((req = elv_next_request(q)) != NULL) {
+                       do {
+                               ret = end_that_request_chunk(req, 0,
+                                       req->current_nr_sectors << 9);
+                       } while (ret);
+               }
+               return;
+       }
 
        if (!mq->req)
-               wake_up(&mq->thread_wq);
+               wake_up_process(mq->thread);
 }
 
 /**
@@ -152,36 +157,40 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
                         GFP_KERNEL);
        if (!mq->sg) {
                ret = -ENOMEM;
-               goto cleanup;
+               goto cleanup_queue;
        }
 
-       init_completion(&mq->thread_complete);
-       init_waitqueue_head(&mq->thread_wq);
        init_MUTEX(&mq->thread_sem);
 
-       ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL);
-       if (ret >= 0) {
-               wait_for_completion(&mq->thread_complete);
-               init_completion(&mq->thread_complete);
-               ret = 0;
-               goto out;
+       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
+       if (IS_ERR(mq->thread)) {
+               ret = PTR_ERR(mq->thread);
+               goto free_sg;
        }
 
- cleanup:
+       return 0;
+
+ free_sg:
        kfree(mq->sg);
        mq->sg = NULL;
-
+ cleanup_queue:
        blk_cleanup_queue(mq->queue);
- out:
        return ret;
 }
 EXPORT_SYMBOL(mmc_init_queue);
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
-       mq->flags |= MMC_QUEUE_EXIT;
-       wake_up(&mq->thread_wq);
-       wait_for_completion(&mq->thread_complete);
+       request_queue_t *q = mq->queue;
+       unsigned long flags;
+
+       /* Mark that we should start throwing out stragglers */
+       spin_lock_irqsave(q->queue_lock, flags);
+       q->queuedata = NULL;
+       spin_unlock_irqrestore(q->queue_lock, flags);
+
+       /* Then terminate our worker thread */
+       kthread_stop(mq->thread);
 
        kfree(mq->sg);
        mq->sg = NULL;
index 7182d2f69b4e0d65fc899e6e07b1ba48a4422f49..c9f139e764f6cecdd3ac409160f077b79e73e74d 100644 (file)
@@ -6,8 +6,7 @@ struct task_struct;
 
 struct mmc_queue {
        struct mmc_card         *card;
-       struct completion       thread_complete;
-       wait_queue_head_t       thread_wq;
+       struct task_struct      *thread;
        struct semaphore        thread_sem;
        unsigned int            flags;
        struct request          *req;
index 828503c4ee62b509763a0dd0f722de70bfbad727..e9b80e9202664bbfa8cd84a6b302b48ae9154560 100644 (file)
@@ -443,7 +443,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        }
 }
 
-static struct mmc_host_ops mmci_ops = {
+static const struct mmc_host_ops mmci_ops = {
        .request        = mmci_request,
        .set_ios        = mmci_set_ios,
 };
index d593ef342e759f1a551e8303d250f981fd5f4fd6..435d331e772ada91a03a37517c35663bfefdf042 100644 (file)
 #include <asm/arch/fpga.h>
 #include <asm/arch/tps65010.h>
 
-#include "omap.h"
+#define        OMAP_MMC_REG_CMD        0x00
+#define        OMAP_MMC_REG_ARGL       0x04
+#define        OMAP_MMC_REG_ARGH       0x08
+#define        OMAP_MMC_REG_CON        0x0c
+#define        OMAP_MMC_REG_STAT       0x10
+#define        OMAP_MMC_REG_IE         0x14
+#define        OMAP_MMC_REG_CTO        0x18
+#define        OMAP_MMC_REG_DTO        0x1c
+#define        OMAP_MMC_REG_DATA       0x20
+#define        OMAP_MMC_REG_BLEN       0x24
+#define        OMAP_MMC_REG_NBLK       0x28
+#define        OMAP_MMC_REG_BUF        0x2c
+#define OMAP_MMC_REG_SDIO      0x34
+#define        OMAP_MMC_REG_REV        0x3c
+#define        OMAP_MMC_REG_RSP0       0x40
+#define        OMAP_MMC_REG_RSP1       0x44
+#define        OMAP_MMC_REG_RSP2       0x48
+#define        OMAP_MMC_REG_RSP3       0x4c
+#define        OMAP_MMC_REG_RSP4       0x50
+#define        OMAP_MMC_REG_RSP5       0x54
+#define        OMAP_MMC_REG_RSP6       0x58
+#define        OMAP_MMC_REG_RSP7       0x5c
+#define        OMAP_MMC_REG_IOSR       0x60
+#define        OMAP_MMC_REG_SYSC       0x64
+#define        OMAP_MMC_REG_SYSS       0x68
+
+#define        OMAP_MMC_STAT_CARD_ERR          (1 << 14)
+#define        OMAP_MMC_STAT_CARD_IRQ          (1 << 13)
+#define        OMAP_MMC_STAT_OCR_BUSY          (1 << 12)
+#define        OMAP_MMC_STAT_A_EMPTY           (1 << 11)
+#define        OMAP_MMC_STAT_A_FULL            (1 << 10)
+#define        OMAP_MMC_STAT_CMD_CRC           (1 <<  8)
+#define        OMAP_MMC_STAT_CMD_TOUT          (1 <<  7)
+#define        OMAP_MMC_STAT_DATA_CRC          (1 <<  6)
+#define        OMAP_MMC_STAT_DATA_TOUT         (1 <<  5)
+#define        OMAP_MMC_STAT_END_BUSY          (1 <<  4)
+#define        OMAP_MMC_STAT_END_OF_DATA       (1 <<  3)
+#define        OMAP_MMC_STAT_CARD_BUSY         (1 <<  2)
+#define        OMAP_MMC_STAT_END_OF_CMD        (1 <<  0)
+
+#define OMAP_MMC_READ(host, reg)       __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC    0
+#define OMAP_MMC_CMDTYPE_BCR   1
+#define OMAP_MMC_CMDTYPE_AC    2
+#define OMAP_MMC_CMDTYPE_ADTC  3
+
 
 #define DRIVER_NAME "mmci-omap"
 #define RSP_TYPE(x)    ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
@@ -60,8 +110,9 @@ struct mmc_omap_host {
        unsigned char           id; /* 16xx chips have 2 MMC blocks */
        struct clk *            iclk;
        struct clk *            fclk;
-       struct resource         *res;
-       void __iomem            *base;
+       struct resource         *mem_res;
+       void __iomem            *virt_base;
+       unsigned int            phys_base;
        int                     irq;
        unsigned char           bus_mode;
        unsigned char           hw_bus_mode;
@@ -191,16 +242,16 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
 
        clk_enable(host->fclk);
 
-       OMAP_MMC_WRITE(host->base, CTO, 200);
-       OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff);
-       OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16);
-       OMAP_MMC_WRITE(host->base, IE,
+       OMAP_MMC_WRITE(host, CTO, 200);
+       OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
+       OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
+       OMAP_MMC_WRITE(host, IE,
                       OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
                       OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
                       OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
                       OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
                       OMAP_MMC_STAT_END_OF_DATA);
-       OMAP_MMC_WRITE(host->base, CMD, cmdreg);
+       OMAP_MMC_WRITE(host, CMD, cmdreg);
 }
 
 static void
@@ -296,22 +347,22 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
                if (cmd->flags & MMC_RSP_136) {
                        /* response type 2 */
                        cmd->resp[3] =
-                               OMAP_MMC_READ(host->base, RSP0) |
-                               (OMAP_MMC_READ(host->base, RSP1) << 16);
+                               OMAP_MMC_READ(host, RSP0) |
+                               (OMAP_MMC_READ(host, RSP1) << 16);
                        cmd->resp[2] =
-                               OMAP_MMC_READ(host->base, RSP2) |
-                               (OMAP_MMC_READ(host->base, RSP3) << 16);
+                               OMAP_MMC_READ(host, RSP2) |
+                               (OMAP_MMC_READ(host, RSP3) << 16);
                        cmd->resp[1] =
-                               OMAP_MMC_READ(host->base, RSP4) |
-                               (OMAP_MMC_READ(host->base, RSP5) << 16);
+                               OMAP_MMC_READ(host, RSP4) |
+                               (OMAP_MMC_READ(host, RSP5) << 16);
                        cmd->resp[0] =
-                               OMAP_MMC_READ(host->base, RSP6) |
-                               (OMAP_MMC_READ(host->base, RSP7) << 16);
+                               OMAP_MMC_READ(host, RSP6) |
+                               (OMAP_MMC_READ(host, RSP7) << 16);
                } else {
                        /* response types 1, 1b, 3, 4, 5, 6 */
                        cmd->resp[0] =
-                               OMAP_MMC_READ(host->base, RSP6) |
-                               (OMAP_MMC_READ(host->base, RSP7) << 16);
+                               OMAP_MMC_READ(host, RSP6) |
+                               (OMAP_MMC_READ(host, RSP7) << 16);
                }
        }
 
@@ -354,9 +405,9 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
        host->data->bytes_xfered += n;
 
        if (write) {
-               __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+               __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
        } else {
-               __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+               __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
        }
 }
 
@@ -386,11 +437,11 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
        int transfer_error;
 
        if (host->cmd == NULL && host->data == NULL) {
-               status = OMAP_MMC_READ(host->base, STAT);
+               status = OMAP_MMC_READ(host, STAT);
                dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
                if (status != 0) {
-                       OMAP_MMC_WRITE(host->base, STAT, status);
-                       OMAP_MMC_WRITE(host->base, IE, 0);
+                       OMAP_MMC_WRITE(host, STAT, status);
+                       OMAP_MMC_WRITE(host, IE, 0);
                }
                return IRQ_HANDLED;
        }
@@ -399,8 +450,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
        end_transfer = 0;
        transfer_error = 0;
 
-       while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) {
-               OMAP_MMC_WRITE(host->base, STAT, status);
+       while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
+               OMAP_MMC_WRITE(host, STAT, status);
 #ifdef CONFIG_MMC_DEBUG
                dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
                        status, host->cmd != NULL ? host->cmd->opcode : -1);
@@ -470,8 +521,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 
                if (status & OMAP_MMC_STAT_CARD_ERR) {
                        if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
-                               u32 response = OMAP_MMC_READ(host->base, RSP6)
-                                       | (OMAP_MMC_READ(host->base, RSP7) << 16);
+                               u32 response = OMAP_MMC_READ(host, RSP6)
+                                       | (OMAP_MMC_READ(host, RSP7) << 16);
                                /* STOP sometimes sets must-ignore bits */
                                if (!(response & (R1_CC_ERROR
                                                                | R1_ILLEGAL_COMMAND
@@ -530,12 +581,6 @@ static void mmc_omap_switch_timer(unsigned long arg)
        schedule_work(&host->switch_work);
 }
 
-/* FIXME: Handle card insertion and removal properly. Maybe use a mask
- * for MMC state? */
-static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask)
-{
-}
-
 static void mmc_omap_switch_handler(void *data)
 {
        struct mmc_omap_host *host = (struct mmc_omap_host *) data;
@@ -581,7 +626,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
        int dst_port = 0;
        int sync_dev = 0;
 
-       data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA;
+       data_addr = host->phys_base + OMAP_MMC_REG_DATA;
        frame = data->blksz;
        count = sg_dma_len(sg);
 
@@ -642,7 +687,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
        /* Max limit for DMA frame count is 0xffff */
        BUG_ON(count > 0xffff);
 
-       OMAP_MMC_WRITE(host->base, BUF, buf);
+       OMAP_MMC_WRITE(host, BUF, buf);
        omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
                                     frame, count, OMAP_DMA_SYNC_FRAME,
                                     sync_dev, 0);
@@ -727,11 +772,11 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques
 {
        u16 reg;
 
-       reg = OMAP_MMC_READ(host->base, SDIO);
+       reg = OMAP_MMC_READ(host, SDIO);
        reg &= ~(1 << 5);
-       OMAP_MMC_WRITE(host->base, SDIO, reg);
+       OMAP_MMC_WRITE(host, SDIO, reg);
        /* Set maximum timeout */
-       OMAP_MMC_WRITE(host->base, CTO, 0xff);
+       OMAP_MMC_WRITE(host, CTO, 0xff);
 }
 
 static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
@@ -745,14 +790,14 @@ static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_reque
        timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
 
        /* Check if we need to use timeout multiplier register */
-       reg = OMAP_MMC_READ(host->base, SDIO);
+       reg = OMAP_MMC_READ(host, SDIO);
        if (timeout > 0xffff) {
                reg |= (1 << 5);
                timeout /= 1024;
        } else
                reg &= ~(1 << 5);
-       OMAP_MMC_WRITE(host->base, SDIO, reg);
-       OMAP_MMC_WRITE(host->base, DTO, timeout);
+       OMAP_MMC_WRITE(host, SDIO, reg);
+       OMAP_MMC_WRITE(host, DTO, timeout);
 }
 
 static void
@@ -764,19 +809,18 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 
        host->data = data;
        if (data == NULL) {
-               OMAP_MMC_WRITE(host->base, BLEN, 0);
-               OMAP_MMC_WRITE(host->base, NBLK, 0);
-               OMAP_MMC_WRITE(host->base, BUF, 0);
+               OMAP_MMC_WRITE(host, BLEN, 0);
+               OMAP_MMC_WRITE(host, NBLK, 0);
+               OMAP_MMC_WRITE(host, BUF, 0);
                host->dma_in_use = 0;
                set_cmd_timeout(host, req);
                return;
        }
 
-
        block_size = data->blksz;
 
-       OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
-       OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
+       OMAP_MMC_WRITE(host, NBLK, data->blocks - 1);
+       OMAP_MMC_WRITE(host, BLEN, block_size - 1);
        set_data_timeout(host, req);
 
        /* cope with calling layer confusion; it issues "single
@@ -818,7 +862,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 
        /* Revert to PIO? */
        if (!use_dma) {
-               OMAP_MMC_WRITE(host->base, BUF, 0x1f1f);
+               OMAP_MMC_WRITE(host, BUF, 0x1f1f);
                host->total_bytes_left = data->blocks * block_size;
                host->sg_len = sg_len;
                mmc_omap_sg_to_buf(host);
@@ -844,7 +888,6 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
 static void innovator_fpga_socket_power(int on)
 {
 #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
-
        if (on) {
                fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
                     OMAP1510_FPGA_POWER);
@@ -870,8 +913,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
                        /* GPIO 4 of TPS65010 sends SD_EN signal */
                        tps65010_set_gpio_out_value(GPIO4, HIGH);
                else if (cpu_is_omap24xx()) {
-                       u16 reg = OMAP_MMC_READ(host->base, CON);
-                       OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11));
+                       u16 reg = OMAP_MMC_READ(host, CON);
+                       OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
                } else
                        if (host->power_pin >= 0)
                                omap_set_gpio_dataout(host->power_pin, 1);
@@ -883,8 +926,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
                else if (machine_is_omap_h3())
                        tps65010_set_gpio_out_value(GPIO4, LOW);
                else if (cpu_is_omap24xx()) {
-                       u16 reg = OMAP_MMC_READ(host->base, CON);
-                       OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11));
+                       u16 reg = OMAP_MMC_READ(host, CON);
+                       OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
                } else
                        if (host->power_pin >= 0)
                                omap_set_gpio_dataout(host->power_pin, 0);
@@ -926,7 +969,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        case MMC_POWER_UP:
        case MMC_POWER_ON:
                mmc_omap_power(host, 1);
-               dsor |= 1<<11;
+               dsor |= 1 << 11;
                break;
        }
 
@@ -940,14 +983,14 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
         * which results in the while loop below getting stuck.
         * Writing to the CON register twice seems to do the trick. */
        for (i = 0; i < 2; i++)
-               OMAP_MMC_WRITE(host->base, CON, dsor);
+               OMAP_MMC_WRITE(host, CON, dsor);
        if (ios->power_mode == MMC_POWER_UP) {
                /* Send clock cycles, poll completion */
-               OMAP_MMC_WRITE(host->base, IE, 0);
-               OMAP_MMC_WRITE(host->base, STAT, 0xffff);
-               OMAP_MMC_WRITE(host->base, CMD, 1<<7);
-               while (0 == (OMAP_MMC_READ(host->base, STAT) & 1));
-               OMAP_MMC_WRITE(host->base, STAT, 1);
+               OMAP_MMC_WRITE(host, IE, 0);
+               OMAP_MMC_WRITE(host, STAT, 0xffff);
+               OMAP_MMC_WRITE(host, CMD, 1 << 7);
+               while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
+               OMAP_MMC_WRITE(host, STAT, 1);
        }
        clk_disable(host->fclk);
 }
@@ -959,7 +1002,7 @@ static int mmc_omap_get_ro(struct mmc_host *mmc)
        return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
 }
 
-static struct mmc_host_ops mmc_omap_ops = {
+static const struct mmc_host_ops mmc_omap_ops = {
        .request        = mmc_omap_request,
        .set_ios        = mmc_omap_set_ios,
        .get_ro         = mmc_omap_get_ro,
@@ -970,25 +1013,29 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
        struct omap_mmc_conf *minfo = pdev->dev.platform_data;
        struct mmc_host *mmc;
        struct mmc_omap_host *host = NULL;
-       struct resource *r;
+       struct resource *res;
        int ret = 0;
        int irq;
-       
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (minfo == NULL) {
+               dev_err(&pdev->dev, "platform data missing\n");
+               return -ENXIO;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!r || irq < 0)
+       if (res == NULL || irq < 0)
                return -ENXIO;
 
-       r = request_mem_region(pdev->resource[0].start,
-                               pdev->resource[0].end - pdev->resource[0].start + 1,
-                              pdev->name);
-       if (!r)
+       res = request_mem_region(res->start, res->end - res->start + 1,
+                                pdev->name);
+       if (res == NULL)
                return -EBUSY;
 
        mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
-       if (!mmc) {
+       if (mmc == NULL) {
                ret = -ENOMEM;
-               goto out;
+               goto err_free_mem_region;
        }
 
        host = mmc_priv(mmc);
@@ -1000,13 +1047,13 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
        host->dma_timer.data = (unsigned long) host;
 
        host->id = pdev->id;
-       host->res = r;
+       host->mem_res = res;
        host->irq = irq;
 
        if (cpu_is_omap24xx()) {
                host->iclk = clk_get(&pdev->dev, "mmc_ick");
                if (IS_ERR(host->iclk))
-                       goto out;
+                       goto err_free_mmc_host;
                clk_enable(host->iclk);
        }
 
@@ -1017,7 +1064,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
 
        if (IS_ERR(host->fclk)) {
                ret = PTR_ERR(host->fclk);
-               goto out;
+               goto err_free_iclk;
        }
 
        /* REVISIT:
@@ -1030,14 +1077,15 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
        host->use_dma = 1;
        host->dma_ch = -1;
 
-       host->irq = pdev->resource[1].start;
-       host->base = (void __iomem*)IO_ADDRESS(r->start);
+       host->irq = irq;
+       host->phys_base = host->mem_res->start;
+       host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
 
        mmc->ops = &mmc_omap_ops;
        mmc->f_min = 400000;
        mmc->f_max = 24000000;
-       mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_BYTEBLOCK;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
        if (minfo->wire4)
                 mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1055,20 +1103,18 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
                if ((ret = omap_request_gpio(host->power_pin)) != 0) {
                        dev_err(mmc_dev(host->mmc),
                                "Unable to get GPIO pin for MMC power\n");
-                       goto out;
+                       goto err_free_fclk;
                }
                omap_set_gpio_direction(host->power_pin, 0);
        }
 
        ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
        if (ret)
-               goto out;
+               goto err_free_power_gpio;
 
        host->dev = &pdev->dev;
        platform_set_drvdata(pdev, host);
 
-       mmc_add_host(mmc);
-
        if (host->switch_pin >= 0) {
                INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
                init_timer(&host->switch_timer);
@@ -1106,10 +1152,11 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
                        schedule_work(&host->switch_work);
        }
 
-no_switch:
+       mmc_add_host(mmc);
+
        return 0;
 
-out:
+no_switch:
        /* FIXME: Free other resources too. */
        if (host) {
                if (host->iclk && !IS_ERR(host->iclk))
@@ -1118,6 +1165,20 @@ out:
                        clk_put(host->fclk);
                mmc_free_host(host->mmc);
        }
+err_free_power_gpio:
+       if (host->power_pin >= 0)
+               omap_free_gpio(host->power_pin);
+err_free_fclk:
+       clk_put(host->fclk);
+err_free_iclk:
+       if (host->iclk != NULL) {
+               clk_disable(host->iclk);
+               clk_put(host->iclk);
+       }
+err_free_mmc_host:
+       mmc_free_host(host->mmc);
+err_free_mem_region:
+       release_mem_region(res->start, res->end - res->start + 1);
        return ret;
 }
 
@@ -1127,30 +1188,31 @@ static int mmc_omap_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       if (host) {
-               mmc_remove_host(host->mmc);
-               free_irq(host->irq, host);
-
-               if (host->power_pin >= 0)
-                       omap_free_gpio(host->power_pin);
-               if (host->switch_pin >= 0) {
-                       device_remove_file(&pdev->dev, &dev_attr_enable_poll);
-                       device_remove_file(&pdev->dev, &dev_attr_cover_switch);
-                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
-                       omap_free_gpio(host->switch_pin);
-                       host->switch_pin = -1;
-                       del_timer_sync(&host->switch_timer);
-                       flush_scheduled_work();
-               }
-               if (host->iclk && !IS_ERR(host->iclk))
-                       clk_put(host->iclk);
-               if (host->fclk && !IS_ERR(host->fclk))
-                       clk_put(host->fclk);
-               mmc_free_host(host->mmc);
+       BUG_ON(host == NULL);
+
+       mmc_remove_host(host->mmc);
+       free_irq(host->irq, host);
+
+       if (host->power_pin >= 0)
+               omap_free_gpio(host->power_pin);
+       if (host->switch_pin >= 0) {
+               device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+               device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+               free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+               omap_free_gpio(host->switch_pin);
+               host->switch_pin = -1;
+               del_timer_sync(&host->switch_timer);
+               flush_scheduled_work();
        }
+       if (host->iclk && !IS_ERR(host->iclk))
+               clk_put(host->iclk);
+       if (host->fclk && !IS_ERR(host->fclk))
+               clk_put(host->fclk);
 
        release_mem_region(pdev->resource[0].start,
-                       pdev->resource[0].end - pdev->resource[0].start + 1);
+                          pdev->resource[0].end - pdev->resource[0].start + 1);
+
+       mmc_free_host(host->mmc);
 
        return 0;
 }
diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h
deleted file mode 100644 (file)
index c954d35..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef        DRIVERS_MEDIA_MMC_OMAP_H
-#define        DRIVERS_MEDIA_MMC_OMAP_H
-
-#define        OMAP_MMC_REG_CMD        0x00
-#define        OMAP_MMC_REG_ARGL       0x04
-#define        OMAP_MMC_REG_ARGH       0x08
-#define        OMAP_MMC_REG_CON        0x0c
-#define        OMAP_MMC_REG_STAT       0x10
-#define        OMAP_MMC_REG_IE         0x14
-#define        OMAP_MMC_REG_CTO        0x18
-#define        OMAP_MMC_REG_DTO        0x1c
-#define        OMAP_MMC_REG_DATA       0x20
-#define        OMAP_MMC_REG_BLEN       0x24
-#define        OMAP_MMC_REG_NBLK       0x28
-#define        OMAP_MMC_REG_BUF        0x2c
-#define OMAP_MMC_REG_SDIO      0x34
-#define        OMAP_MMC_REG_REV        0x3c
-#define        OMAP_MMC_REG_RSP0       0x40
-#define        OMAP_MMC_REG_RSP1       0x44
-#define        OMAP_MMC_REG_RSP2       0x48
-#define        OMAP_MMC_REG_RSP3       0x4c
-#define        OMAP_MMC_REG_RSP4       0x50
-#define        OMAP_MMC_REG_RSP5       0x54
-#define        OMAP_MMC_REG_RSP6       0x58
-#define        OMAP_MMC_REG_RSP7       0x5c
-#define        OMAP_MMC_REG_IOSR       0x60
-#define        OMAP_MMC_REG_SYSC       0x64
-#define        OMAP_MMC_REG_SYSS       0x68
-
-#define        OMAP_MMC_STAT_CARD_ERR          (1 << 14)
-#define        OMAP_MMC_STAT_CARD_IRQ          (1 << 13)
-#define        OMAP_MMC_STAT_OCR_BUSY          (1 << 12)
-#define        OMAP_MMC_STAT_A_EMPTY           (1 << 11)
-#define        OMAP_MMC_STAT_A_FULL            (1 << 10)
-#define        OMAP_MMC_STAT_CMD_CRC           (1 <<  8)
-#define        OMAP_MMC_STAT_CMD_TOUT          (1 <<  7)
-#define        OMAP_MMC_STAT_DATA_CRC          (1 <<  6)
-#define        OMAP_MMC_STAT_DATA_TOUT         (1 <<  5)
-#define        OMAP_MMC_STAT_END_BUSY          (1 <<  4)
-#define        OMAP_MMC_STAT_END_OF_DATA       (1 <<  3)
-#define        OMAP_MMC_STAT_CARD_BUSY         (1 <<  2)
-#define        OMAP_MMC_STAT_END_OF_CMD        (1 <<  0)
-
-#define OMAP_MMC_READ(base, reg)       __raw_readw((base) + OMAP_MMC_REG_##reg)
-#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg)
-
-/*
- * Command types
- */
-#define OMAP_MMC_CMDTYPE_BC    0
-#define OMAP_MMC_CMDTYPE_BCR   1
-#define OMAP_MMC_CMDTYPE_AC    2
-#define OMAP_MMC_CMDTYPE_ADTC  3
-
-#endif
index a526698b8c91b41b701e0dee517adf5323f79cb3..471e9f4e05306e7574469d87af2fcdfabe84ce3c 100644 (file)
@@ -393,7 +393,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                 host->clkrt, host->cmdat);
 }
 
-static struct mmc_host_ops pxamci_ops = {
+static const struct mmc_host_ops pxamci_ops = {
        .request        = pxamci_request,
        .get_ro         = pxamci_get_ro,
        .set_ios        = pxamci_set_ios,
index 9a7d39b7cdbf43ae3b24df6eed03b8e4c511148b..cd98117632d38e66687ad8aa91185c5dccf9a067 100644 (file)
@@ -616,6 +616,7 @@ static void sdhci_finish_command(struct sdhci_host *host)
 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        int div;
+       u8 ctrl;
        u16 clk;
        unsigned long timeout;
 
@@ -624,6 +625,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 
        writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
 
+       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       if (clock > 25000000)
+               ctrl |= SDHCI_CTRL_HISPD;
+       else
+               ctrl &= ~SDHCI_CTRL_HISPD;
+       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
        if (clock == 0)
                goto out;
 
@@ -784,7 +792,7 @@ static int sdhci_get_ro(struct mmc_host *mmc)
        return !(present & SDHCI_WRITE_PROTECT);
 }
 
-static struct mmc_host_ops sdhci_ops = {
+static const struct mmc_host_ops sdhci_ops = {
        .request        = sdhci_request,
        .set_ios        = sdhci_set_ios,
        .get_ro         = sdhci_get_ro,
@@ -1291,6 +1299,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        else if (caps & SDHCI_CAN_VDD_180)
                mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
+       if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
+               printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
+                       " but no high speed support.\n",
+                       host->slot_descr);
+               mmc->f_max = 25000000;
+       }
+
        if (mmc->ocr_avail == 0) {
                printk(KERN_ERR "%s: Hardware doesn't report any "
                        "support voltages.\n", host->slot_descr);
index 72a67937afe0edc83fe8289116c1e61304367b3f..f9d1a0a6f03a97fae3e0b1ebd7a129999877c42a 100644 (file)
@@ -71,6 +71,7 @@
 #define SDHCI_HOST_CONTROL     0x28
 #define  SDHCI_CTRL_LED                0x01
 #define  SDHCI_CTRL_4BITBUS    0x02
+#define  SDHCI_CTRL_HISPD      0x04
 
 #define SDHCI_POWER_CONTROL    0x29
 #define  SDHCI_POWER_ON                0x01
 #define  SDHCI_CLOCK_BASE_SHIFT        8
 #define  SDHCI_MAX_BLOCK_MASK  0x00030000
 #define  SDHCI_MAX_BLOCK_SHIFT  16
+#define  SDHCI_CAN_DO_HISPD    0x00200000
 #define  SDHCI_CAN_DO_DMA      0x00400000
 #define  SDHCI_CAN_VDD_330     0x01000000
 #define  SDHCI_CAN_VDD_300     0x02000000
index 682e62b0b09db65d0539742f3f7c804dc0aaba82..7a282672f8e9037d9995859e9fbdb31504ecbf94 100644 (file)
@@ -1021,7 +1021,7 @@ static int wbsd_get_ro(struct mmc_host *mmc)
        return csr & WBSD_WRPT;
 }
 
-static struct mmc_host_ops wbsd_ops = {
+static const struct mmc_host_ops wbsd_ops = {
        .request        = wbsd_request,
        .set_ios        = wbsd_set_ios,
        .get_ro         = wbsd_get_ro,
index 991a37382a22e84ec1e15894688046a9e77a077e..d0e6a5497614f7ead6dcb62ac5e9167cb591785d 100644 (file)
@@ -39,6 +39,10 @@ struct mmc_csd {
                                write_misalign:1;
 };
 
+struct mmc_ext_csd {
+       unsigned int            hs_max_dtr;
+};
+
 struct sd_scr {
        unsigned char           sda_vsn;
        unsigned char           bus_widths;
@@ -46,6 +50,10 @@ struct sd_scr {
 #define SD_SCR_BUS_WIDTH_4     (1<<2)
 };
 
+struct sd_switch_caps {
+       unsigned int            hs_max_dtr;
+};
+
 struct mmc_host;
 
 /*
@@ -62,12 +70,15 @@ struct mmc_card {
 #define MMC_STATE_BAD          (1<<2)          /* unrecognised device */
 #define MMC_STATE_SDCARD       (1<<3)          /* is an SD card */
 #define MMC_STATE_READONLY     (1<<4)          /* card is read-only */
+#define MMC_STATE_HIGHSPEED    (1<<5)          /* card is in high speed mode */
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
        u32                     raw_scr[2];     /* raw card SCR */
        struct mmc_cid          cid;            /* card identification */
        struct mmc_csd          csd;            /* card specific */
+       struct mmc_ext_csd      ext_csd;        /* mmc v4 extended card specific */
        struct sd_scr           scr;            /* extra SD information */
+       struct sd_switch_caps   sw_caps;        /* switch (CMD6) caps */
 };
 
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
@@ -75,12 +86,14 @@ struct mmc_card {
 #define mmc_card_bad(c)                ((c)->state & MMC_STATE_BAD)
 #define mmc_card_sd(c)         ((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
+#define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)   ((c)->state |= MMC_STATE_DEAD)
 #define mmc_card_set_bad(c)    ((c)->state |= MMC_STATE_BAD)
 #define mmc_card_set_sd(c)     ((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
 
 #define mmc_card_name(c)       ((c)->cid.prod_name)
 #define mmc_card_id(c)         ((c)->dev.bus_id)
index 08dec8d9e7038a09fbeb1fbe64973a16f590ab94..2dce60c43f4b2892538fe7d27fed55fa23db796e 100644 (file)
 #ifndef MMC_MMC_PROTOCOL_H
 #define MMC_MMC_PROTOCOL_H
 
-/* Standard MMC commands (3.1)           type  argument     response */
+/* Standard MMC commands (4.1)           type  argument     response */
    /* class 1 */
 #define        MMC_GO_IDLE_STATE         0   /* bc                          */
 #define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
 #define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
 #define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
 #define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
 #define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
 #define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
 #define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
 #define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
@@ -80,6 +82,7 @@
   /* class 8 */
 /* This is basically the same command as for MMC with some quirks. */
 #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
 
   /* Application commands */
 #define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
 #define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
 #define SD_APP_SEND_SCR          51   /* adtc                    R1  */
 
+/*
+ * MMC_SWITCH argument format:
+ *
+ *     [31:26] Always 0
+ *     [25:24] Access Mode
+ *     [23:16] Location of target Byte in EXT_CSD
+ *     [15:08] Value Byte
+ *     [07:03] Always 0
+ *     [02:00] Command Set
+ */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ *      [31] Check (0) or switch (1)
+ *      [30:24] Reserved (0)
+ *      [23:20] Function group 6
+ *      [19:16] Function group 5
+ *      [15:12] Function group 4
+ *      [11:8] Function group 3
+ *      [7:4] Function group 2
+ *      [3:0] Function group 1
+ */
+
 /*
   MMC status in R1
   Type
@@ -230,13 +257,54 @@ struct _mmc_csd {
 
 #define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
 #define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1       */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
 
 #define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
 #define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
 #define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH      183     /* R/W */
+#define EXT_CSD_HS_TIMING      185     /* R/W */
+#define EXT_CSD_CARD_TYPE      196     /* RO */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL         (1<<0)
+#define EXT_CSD_CMD_SET_SECURE         (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET                0x00    /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS       0x01    /* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS     0x02    /* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE     0x03    /* Set target to value */
+
+/*
+ * SCR field definitions
+ */
 
+#define SCR_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1      1           /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2      2           /* Implements system specification 2.00 */
 
 /*
  * SD bus widths