📄 full.patch
字号:
} +int sd_set_bus_width(struct mmc_host *host, u16 rca, u32 bus_width)+{+ struct mmc_command cmd;+ int err;++ cmd.opcode = MMC_ACMD_SD_SET_BUS_WIDTH;+ cmd.flags = MMC_RSP_R1;++ switch(bus_width) {+ case 1: cmd.arg = 00; break;+ case 4: cmd.arg = 10; break;+ default: return -EINVAL;+ }++ err = mmc_wait_for_acmd(host, rca, &cmd, 3);++ if(err == MMC_ERR_TIMEOUT) {+ printk(KERN_ERR "MMC: sd_set_bus_width timed out.\n");+ } else if(err == MMC_ERR_BADCRC) {+ printk(KERN_ERR "MMC: sd_set_bus_width yielded crc error.\n");+ } else {+ DBG("MMC: sd_app_op_cond done.\n");+ }++ return err;+}++EXPORT_SYMBOL(sd_set_bus_width);++static int sd_app_op_cond(struct mmc_host *host, u16 rca, u32 parameter, u32 *response)+{+ struct mmc_command cmd;+ int err;+ int retries = 10;++ cmd.opcode = MMC_ACMD_SD_APP_OP_COND;+ cmd.arg = parameter;+ cmd.flags = MMC_RSP_SHORT;++ DBG("MMC: sd_app_op_cond to %08x\n",parameter);++ while(retries--) {+ err = mmc_wait_for_acmd(host, 0, &cmd, 0);+ if(0 == (cmd.resp[0] & MMC_CARD_BUSY)) {+ err=MMC_ERR_BUSY;+ printk(KERN_ERR "MMC: sd_app_op_cond: at least one card is busy - trying again.\n");+ mmc_delay(10);+ continue;+ }++ if(err == MMC_ERR_NONE) {+ if(response)*response = cmd.resp[0];+ break;+ }+ }++ if(err == MMC_ERR_TIMEOUT) {+ printk(KERN_WARNING "MMC: sd_app_op_cond timed out. Probably no SD-Card here.\n");+ } else if(err == MMC_ERR_BUSY) {+ printk(KERN_ERR "MMC: sd_app_op_cond locked busy. Probably have broken SD-Card.\n");+ } else {+ DBG("MMC: sd_app_op_cond done. Results are: 0x%08x.\n",cmd.resp[0]);+ }++ return err;+}++ /* * Apply power to the MMC stack. */@@ -532,7 +716,7 @@ static int mmc_send_op_cond(struct mmc_h * Create a mmc_card entry for each discovered card, assigning * it an RCA, and save the raw CID for decoding later. */-static void mmc_discover_cards(struct mmc_host *host)+static void mmc_discover_cards(struct mmc_host *host, u8 sd) { struct mmc_card *card; unsigned int first_rca = 1, err;@@ -542,7 +726,7 @@ static void mmc_discover_cards(struct mm cmd.opcode = MMC_ALL_SEND_CID; cmd.arg = 0;- cmd.flags = MMC_RSP_R2;+ cmd.flags = MMC_RSP_LONG; //HACK! CRC currently not implemented err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err == MMC_ERR_TIMEOUT) {@@ -550,14 +734,13 @@ static void mmc_discover_cards(struct mm break; } if (err != MMC_ERR_NONE) {- printk(KERN_ERR "%s: error requesting CID: %d\n",- host->host_name, err);+ printk(KERN_ERR "%s: error requesting CID: %d\n", host->host_name, err); break; } card = mmc_find_card(host, cmd.resp); if (!card) {- card = mmc_alloc_card(host, cmd.resp, &first_rca);+ card = mmc_alloc_card(host, cmd.resp, sd, &first_rca); if (IS_ERR(card)) { err = PTR_ERR(card); break;@@ -574,6 +757,9 @@ static void mmc_discover_cards(struct mm err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) mmc_card_set_dead(card);++ //SD-Cards choose their adresses themselfes (yuck!)+ if(card->sd) card->rca = (cmd.resp[0] >> 16); } } @@ -590,7 +776,7 @@ static void mmc_read_csds(struct mmc_hos cmd.opcode = MMC_SEND_CSD; cmd.arg = card->rca << 16;- cmd.flags = MMC_RSP_R2;+ cmd.flags = MMC_RSP_LONG; //HACK: No CRC check as s3c-Core is broken err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) {@@ -651,63 +837,22 @@ static void mmc_check_cards(struct mmc_h } } + static void mmc_setup(struct mmc_host *host) {- if (host->ios.power_mode != MMC_POWER_ON) {- int err;- u32 ocr;-- mmc_power_up(host);- mmc_idle_cards(host);-- err = mmc_send_op_cond(host, 0, &ocr);- if (err != MMC_ERR_NONE)- return;-- host->ocr = mmc_select_voltage(host, ocr);-- /*- * Since we're changing the OCR value, we seem to- * need to tell some cards to go back to the idle- * state. We wait 1ms to give cards time to- * respond.- */- if (host->ocr)- mmc_idle_cards(host);- } else {- host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;- host->ios.clock = host->f_min;- host->ops->set_ios(host, &host->ios);-- /*- * We should remember the OCR mask from the existing- * cards, and detect the new cards OCR mask, combine- * the two and re-select the VDD. However, if we do- * change VDD, we should do an idle, and then do a- * full re-initialisation. We would need to notify- * drivers so that they can re-setup the cards as- * well, while keeping their queues at bay.- *- * For the moment, we take the easy way out - if the- * new cards don't like our currently selected VDD,- * they drop off the bus.- */- }-- if (host->ocr == 0)- return;-- /*- * Send the selected OCR multiple times... until the cards- * all get the idea that they should be ready for CMD2.- * (My SanDisk card seems to need this.)- */- mmc_send_op_cond(host, host->ocr, NULL);+ mmc_power_up(host);+ mmc_idle_cards(host); - mmc_discover_cards(host);+ // Wake and discover SD-Cards+ sd_app_op_cond(host, 0, host->ocr_avail, NULL);+ mmc_discover_cards(host, 1);++ // Wake and discover MMC-Cards+ mmc_send_op_cond(host, host->ocr_avail, NULL);+ mmc_discover_cards(host, 0); /*- * Ok, now switch to push-pull mode.+ * switch to push-pull mode. */ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; host->ops->set_ios(host, &host->ios);diff --git a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h--- a/drivers/mmc/mmc.h+++ b/drivers/mmc/mmc.h@@ -13,4 +13,5 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host); int mmc_register_card(struct mmc_card *card); void mmc_remove_card(struct mmc_card *card);+int sd_set_bus_width(struct mmc_host *host, u16 rca, u32 bus_width); #endifdiff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c--- a/drivers/mmc/mmc_block.c+++ b/drivers/mmc/mmc_block.c@@ -3,6 +3,9 @@ * * Copyright 2002 Hewlett-Packard Company *+ * SD-Card support:+ * Copyright (C) 2004 Thomas Kleffel, All Rights Reserved+ * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is * preserved in its entirety in all copies and derived works.@@ -30,11 +33,13 @@ #include <linux/devfs_fs_kernel.h> #include <linux/mmc/card.h>+#include <linux/mmc/host.h> #include <linux/mmc/protocol.h> #include <asm/system.h> #include <asm/uaccess.h> +#include "mmc.h" #include "mmc_queue.h" /*@@ -165,11 +170,17 @@ static int mmc_blk_issue_rq(struct mmc_q { struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card;+ struct mmc_host *host = md->queue.card->host; int ret; if (mmc_card_claim_host(card)) goto cmd_err; + if((card->sd) && (host->flags & MMC_HOST_WIDEMODE) && (card->bus_width != 4)) {+ if(sd_set_bus_width(host, card->rca, 4)) goto cmd_err;+ card->bus_width=4;+ }+ do { struct mmc_blk_request brq; struct mmc_command cmd;@@ -180,6 +191,7 @@ static int mmc_blk_issue_rq(struct mmc_q brq.cmd.arg = req->sector << 9; brq.cmd.flags = MMC_RSP_R1;+ brq.data.req = req; brq.data.timeout_ns = card->csd.tacc_ns * 10; brq.data.timeout_clks = card->csd.tacc_clks * 10; brq.data.blksz_bits = md->block_bits;@@ -188,6 +200,9 @@ static int mmc_blk_issue_rq(struct mmc_q brq.stop.arg = 0; brq.stop.flags = MMC_RSP_R1B; + if(card->bus_width==4)+ brq.data.flags |= MMC_DATA_WIDE;+ if (rq_data_dir(req) == READ) { brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; brq.data.flags |= MMC_DATA_READ;@@ -252,7 +267,7 @@ static int mmc_blk_issue_rq(struct mmc_q /* * The whole request completed successfully. */- add_disk_randomness(req->rq_disk);+ //add_disk_randomness(req->rq_disk); blkdev_dequeue_request(req); end_that_request_last(req); }@@ -347,7 +362,7 @@ static struct mmc_blk_data *mmc_blk_allo sprintf(md->disk->disk_name, "mmcblk%d", devidx); sprintf(md->disk->devfs_name, "mmc/blk%d", devidx); - md->block_bits = card->csd.read_blkbits;+ md->block_bits = card->csd.read_bl_len; blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); set_capacity(md->disk, card->csd.capacity);@@ -364,7 +379,7 @@ mmc_blk_set_blksize(struct mmc_blk_data mmc_card_claim_host(card); cmd.opcode = MMC_SET_BLOCKLEN;- cmd.arg = 1 << card->csd.read_blkbits;+ cmd.arg = 1 << card->csd.read_bl_len; cmd.flags = MMC_RSP_R1; err = mmc_wait_for_cmd(card->host, &cmd, 5); mmc_card_release_host(card);@@ -386,12 +401,12 @@ static int mmc_blk_probe(struct mmc_card /* * Check that the card supports the command class(es) we need. */- if (!(card->csd.cmdclass & CCC_BLOCK_READ))+ if (!(card->csd.ccc & CCC_BLOCK_READ)) return -ENODEV; - if (card->csd.read_blkbits < 9) {+ if (card->csd.read_bl_len < 9) { printk(KERN_WARNING "%s: read blocksize too small (%u)\n",- mmc_card_id(card), 1 << card->csd.read_blkbits);+ mmc_card_id(card), 1 << card->csd.read_bl_len); return -ENODEV; } @@ -405,7 +420,7 @@ static int mmc_blk_probe(struct mmc_card printk(KERN_INFO "%s: %s %s %dKiB\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),- (card->csd.capacity << card->csd.read_blkbits) / 1024);+ (card->csd.capacity << card->csd.read_bl_len) / 1024); mmc_set_drvdata(card, md); add_disk(md->disk);diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c--- a/drivers/mmc/mmc_sysfs.c+++ b/drivers/mmc/mmc_sysfs.c@@ -3,6 +3,9 @@ * * Copyright (C) 2003 Russell King, All Rights Reserved. *+ * SD-Card support:+ * Copyright (C) 2004 Thomas Kleffel, 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 * published by the Free Software Foundation.@@ -39,10 +42,13 @@ MMC_ATTR(manfid, "0x%06x\n", card->cid.m MMC_ATTR(name, "%s\n", card->cid.prod_name); MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_ATTR(serial, "0x%08x\n", card->cid.serial);+MMC_ATTR(bus_width, "%u\n", card->bus_width);+MMC_ATTR(type, "%s\n", (card->sd?"SD":"MMC")); #define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL) static struct device_attribute mmc_dev_attrs[] = {+ MMC_ATTR_RO(bus_width), MMC_ATTR_RO(cid), MMC_ATTR_RO(csd), MMC_ATTR_RO(date),@@ -52,6 +58,7 @@ static struct device_attribute mmc_dev_a MMC_ATTR_RO(name), MMC_ATTR_RO(oemid), MMC_ATTR_RO(serial),+ MMC_ATTR_RO(type), __ATTR_NULL }; @@ -97,7 +104,7 @@ mmc_bus_hotplug(struct device *dev, char }) for (i = 0; i < 12; i++)- ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';+ ccc[i] = card->csd.ccc & (1 << i) ? '1' : '0'; ccc[12] = '\0'; i = 0;diff --git a/drivers/mmc/s3c2410mci.c b/drivers/mmc/s3c2410mci.cnew file mode 100644--- /dev/null+++ b/drivers/mmc/s3c2410mci.c@@ -0,0 +1,760 @@+/*+ * linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver+ *+ * Copyright (C) 2004 Thomas Kleffel, 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+ * published by the Free Software Foundation.+ */+#include <linux/config.h>+#include <linux/module.h>+#include <linux/moduleparam.h>+#include <linux/init.h>+#include <linux/ioport.h>+#include <linux/device.h>+#include <linux/interrupt.h>+#include <linux/blkdev.h>+#include <linux/delay.h>+#include <linux/err.h>+#include <linux/dma-mapping.h>+#include <linux/mmc/host.h>+#include <linux/mmc/protocol.h>++#include <asm/dma.h>+#include <asm/dma-mapping.h>+#include <asm/arch/dma.h>++#include <asm/io.h>+#include <asm/irq.h>+#include <asm/hardware/amba.h>+#include <asm/hardware/clock.h>+#include <asm/mach/mmc.h>++#include <asm/arch/regs-sdi.h>+#include <asm/arch/regs-gpio.h>++//#define S3C2410SDI_DMA_BACKBUF++#ifdef CONFIG_MMC_DEBUG+#define DBG(x...) printk(KERN_DEBUG x)+#else+#define DBG(x...) do { } while (0)+#endif++#include "s3c2410mci.h"++#define DRIVER_NAME "mmci-s3c2410"+#define PFX DRIVER_NAME ": "++#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)++// #define KERN_DEBUG KERN_INFO++typedef enum {+ DMAP_READ,+ DMAP_WRITE,+} eDMAPurpose_t;++static struct s3c2410_dma_client s3c2410sdi_dma_client = {+ .name = "s3c2410-sdi",+};++++/*+ * ISR for SDI Interface IRQ+ * Communication between driver and ISR works as follows:+ * host->mrq points to current request+ * host->complete_what tells the ISR when the request is considered done+ * COMPLETION_CMDSENT when the command was sent+ * COMPLETION_RSPFIN when a response was received+ * COMPLETION_XFERFINISH when the data transfer is finished+ * COMPLETION_XFERFINISH_RSPFIN both of the above.+ * host->complete_request is the completion-object the driver waits for+ *+ * 1) Driver sets up host->mrq and host->complete_what+ * 2) Driver prepares the transfer+ * 3) Driver enables interrupts+ * 4) Driver starts transfer+ * 5) Driver waits for host->complete_rquest
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -