[PATCH] Re: Toshiba TC6371AF PCI SD card controller (SD TypA) driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've manged to fix the Richards' driver - it now compiles with 3.13-rc3 and
works - it reads&writes both SD and SDHC cards. See the (ugly) patch below.
It still needs a lot of work.

The chip on the board is T7L65XB (can be seen after removing keyboard).


diff --git a/drivers/mmc/host/toshsd.c b/drivers/mmc/host/toshsd.c
index 85bd5641..d7667f6 100644
--- a/drivers/mmc/host/toshsd.c
+++ b/drivers/mmc/host/toshsd.c
@@ -14,12 +14,14 @@
 
 #include <linux/delay.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/interrupt.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include "toshsd.h"
 
@@ -51,12 +53,6 @@ MODULE_DEVICE_TABLE(pci, pci_ids);
 static int toshsd_init(struct toshsd_host *host);
 
 static void
-toshsd_dumpregs(struct toshsd_host *host)
-{
-        printk(KERN_DEBUG DRIVER_NAME "0x%08x\n", 0x00);
-}
-
-static void
 toshsd_mmc_finish_request(struct toshsd_host *host)
 {
         struct mmc_request *mrq = host->mrq;
@@ -80,6 +76,7 @@ toshsd_mmc_data_transfer(unsigned long h)
 {
         struct toshsd_host *host = (struct toshsd_host *) h;
         struct mmc_data *data = host->data;
+        void *sg_virt;
         unsigned short *buf;
         int count;
         unsigned long flags;
@@ -88,10 +85,10 @@ toshsd_mmc_data_transfer(unsigned long h)
                 DBG("Spurious Data IRQ\n");
                 return;
         }
-//      spin_lock(&host->lock);
+	spin_lock_irqsave(&host->lock, flags);
 
-        buf = kmap(host->sg_ptr->page);
-        buf += host->sg_ptr->offset / 2 + host->sg_off / 2;
+  	sg_virt = kmap_atomic(sg_page(host->sg_ptr)) + host->sg_ptr->offset;
+        buf = (unsigned short *)(sg_virt + host->sg_off);
 
         /* Ensure we dont read more than one block. The chip will interrupt us
          * When the next block is available.
@@ -101,8 +98,8 @@ toshsd_mmc_data_transfer(unsigned long h)
                 count = data->blksz;
         }
 
-        DBG("count: %08x, page: %p, offset: %08x flags %08x\n", count,
-            host->sg_ptr->page, host->sg_off, data->flags);
+        DBG("count: %08x, offset: %08x flags %08x\n", count,
+            host->sg_off, data->flags);
 
         host->sg_off += count;
 
@@ -123,15 +120,14 @@ toshsd_mmc_data_transfer(unsigned long h)
                 }
         }
 
-        flush_dcache_page(host->sg_ptr->page);
-        kunmap(host->sg_ptr->page);
+	kunmap_atomic(sg_virt - host->sg_ptr->offset);
 
         if (host->sg_off == host->sg_ptr->length) {
-                host->sg_ptr++;
+                host->sg_ptr = sg_next(host->sg_ptr);
                 host->sg_off = 0;
                 --host->sg_len;
         }
-//      spin_unlock(&host->lock);
+        spin_unlock_irqrestore(&host->lock, flags);
 
         return;
 }
@@ -188,11 +184,11 @@ toshsd_mmc_cmd_irq(struct toshsd_host *host, unsigned int buffer_stat)
         }
 
         if (buffer_stat & SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT) {
-                cmd->error = MMC_ERR_TIMEOUT;
+                cmd->error = -ETIMEDOUT;
                 DBG("Timeout\n");
         } else if ((buffer_stat & SD_CTRL_BUFFERSTATUS_CRC_ERROR)
                    && (cmd->flags & MMC_RSP_CRC)) {
-                cmd->error = MMC_ERR_BADCRC;
+                cmd->error = -EIO;
                 DBG("BadCRC\n");
         } else if (buffer_stat & (SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS
                                   | SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR
@@ -206,13 +202,13 @@ toshsd_mmc_cmd_irq(struct toshsd_host *host, unsigned int buffer_stat)
                     READ_TOSHSD(SD_CTRL_ErrorStatus0));
                 DBG("detail1 error status 0x%04x\n",
                     READ_TOSHSD(SD_CTRL_ErrorStatus1));
-                cmd->error = MMC_ERR_FAILED;
+                cmd->error = -EIO;
         }
 
         DBG("Command IRQ complete %d %d %x\n", cmd->opcode, cmd->error,
             cmd->flags);
 
-        if (cmd->error == MMC_ERR_NONE) {
+        if (cmd->error == 0) {
                 switch (cmd->opcode) {
                 case SD_APP_SET_BUS_WIDTH:
                         if (cmd->arg == SD_BUS_WIDTH_4) {
@@ -258,7 +254,7 @@ toshsd_mmc_cmd_irq(struct toshsd_host *host, unsigned int buffer_stat)
 
         /* If there is data to handle we enable data IRQs here, and we will
          * ultimatley finish the request in the mmc_data_end_irq handler.*/
-        if (host->data && (cmd->error == MMC_ERR_NONE)) {
+        if (host->data && (cmd->error == 0)) {
                 bmask = READ_TOSHSD(SD_CTRL_IntMaskBuffer);
 
                 if (host->data->flags & MMC_DATA_READ) {
@@ -297,7 +293,7 @@ toshsd_mmc_data_end_irq(struct toshsd_host *host)
                 return;
         }
 
-        if (data->error == MMC_ERR_NONE) {
+        if (data->error == 0) {
                 data->bytes_xfered = data->blocks * data->blksz;
         } else {
                 data->bytes_xfered = 0;
@@ -342,17 +338,8 @@ toshsd_irq(int irq, void *dev_id)
 
 //    DBG("IRQ bstatus:%x bmask:%x cstatus:%x cmask:%x\n", bstatus, bmask, cstatus, cmask);
 
-        if (!breg && !creg) {
-                /* This occurs sometimes for no known reason.  It doesn't hurt anything, so I don't print it.  */
-                spin_lock(&host->lock);
-                WRITE_TOSHSD(SD_CTRL_IntMaskBuffer, bmask & ~breg);
-                WRITE_TOSHSD(SD_CTRL_IntMaskCard, cmask & ~creg);
-                spin_unlock(&host->lock);
-
-                result = IRQ_NONE;
-
-                goto out;
-        }
+        if (!breg && !creg)
+                return IRQ_NONE;
 
         while (breg || creg) {
 
@@ -436,8 +423,6 @@ toshsd_irq(int irq, void *dev_id)
       out:
         /* Ensure all interrupt sources are cleared */
         spin_lock(&host->lock);
-        WRITE_TOSHSD(SD_CTRL_BufferCtrl, 0);
-        WRITE_TOSHSD(SD_CTRL_CardStatus, 0);
 
         if (reset && 0) {
                 DBG("Resetting device\n");
@@ -467,7 +452,6 @@ toshsd_mmc_start_command(struct toshsd_host *host, struct mmc_command *cmd)
                 cmd->resp[1] = 0;
                 cmd->resp[2] = 0;
                 cmd->resp[3] = 0;
-                cmd->resp[4] = 0;
 
                 return;
         }
@@ -529,9 +513,9 @@ toshsd_mmc_start_command(struct toshsd_host *host, struct mmc_command *cmd)
                                             |
                                             SD_CTRL_INTMASKCARD_CARD_INSERTED_0));
 
-        WRITE_TOSHSD(SD_CTRL_IntMaskBuffer, ~(SD_CTRL_INTMASKBUFFER_UNK7
+        WRITE_TOSHSD(SD_CTRL_IntMaskBuffer, SD_CTRL_INTMASKBUFFER_UNK7
                                               |
-                                              SD_CTRL_INTMASKBUFFER_CMD_BUSY));
+                                              SD_CTRL_INTMASKBUFFER_CMD_BUSY);
 
         /* Send the command */
         WRITE_TOSHSD(SD_CTRL_Arg1, cmd->arg >> 16);
@@ -542,7 +526,7 @@ toshsd_mmc_start_command(struct toshsd_host *host, struct mmc_command *cmd)
 static void
 toshsd_mmc_start_data(struct toshsd_host *host, struct mmc_data *data)
 {
-        DBG("setup data transfer: blocksize %08x  nr_blocks %d, page: %08x, offset: %08x\n", data->blksz, data->blocks, (unsigned int) data->sg->page, data->sg->offset);
+        DBG("setup data transfer: blocksize %08x  nr_blocks %d, offset: %08x\n", data->blksz, data->blocks, data->sg->offset);
 
         host->sg_len = data->sg_len;
         host->sg_ptr = data->sg;
@@ -729,14 +713,14 @@ toshsd_suspend(struct pci_dev *pdev, pm_message_t state)
                     pci_write_config_word(host->chip->pdev, SD_CONFIG_Command,
                                           0);
 
-                ret = mmc_suspend_host(host->mmc, state);
-                if (ret) {
-                        for (i--; i >= 0; i--) {
-                                mmc_resume_host(chip->hosts[i]->mmc);
-                        }
-
-                        return ret;
-                }
+//                ret = mmc_suspend_host(host->mmc, state);
+//                if (ret) {
+//                        for (i--; i >= 0; i--) {
+//                                mmc_resume_host(chip->hosts[i]->mmc);
+//                        }
+//
+//                        return ret;
+//                }
         }
 
         pci_save_state(pdev);
@@ -772,10 +756,10 @@ toshsd_resume(struct pci_dev *pdev)
                 toshsd_init(chip->hosts[i]);
 //              mmiowb();
 
-                ret = mmc_resume_host(chip->hosts[i]->mmc);
-                if (ret) {
-                        return ret;
-                }
+//                ret = mmc_resume_host(chip->hosts[i]->mmc);
+//                if (ret) {
+//                        return ret;
+//                }
         }
 
         return 0;
@@ -954,7 +938,7 @@ toshsd_probe_slot(struct pci_dev *pdev, int slot)
         }
 
         ret =
-            request_irq(host->irq, toshsd_irq, SA_SHIRQ, host->slot_descr,
+            request_irq(host->irq, toshsd_irq, IRQF_SHARED, host->slot_descr,
                         host);
         if (ret) {
                 goto untasklet;
diff --git a/drivers/mmc/host/toshsd.h b/drivers/mmc/host/toshsd.h
index bbb0e32..5057902 100644
--- a/drivers/mmc/host/toshsd.h
+++ b/drivers/mmc/host/toshsd.h
@@ -56,8 +56,8 @@
 #define SD_CTRL_Response7            0x1a
 #define SD_CTRL_CardStatus           0x1c
 #define SD_CTRL_BufferCtrl           0x1e
-#define SD_CTRL_IntMaskBuffer        0x20
-#define SD_CTRL_IntMaskCard          0x22
+#define SD_CTRL_IntMaskCard          0x20
+#define SD_CTRL_IntMaskBuffer        0x22
 #define SD_CTRL_CardClockCtrl        0x24
 #define SD_CTRL_MemCardXferDataLen   0x26
 #define SD_CTRL_MemCardOptionSetup   0x28


-- 
Ondrej Zary
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux