?? hho-sd.patch
字號:
diff -Nbur linux26-cvs/drivers/mmc/au1xmmc.c linux26-cvs.SD/drivers/mmc/au1xmmc.c--- linux26-cvs/drivers/mmc/au1xmmc.c 2005-09-06 10:01:29.000000000 -0500+++ linux26-cvs.SD/drivers/mmc/au1xmmc.c 2005-09-06 09:58:25.000000000 -0500@@ -66,6 +66,12 @@ #define DRIVER_NAME "au1xxx-mmc" + /* If this is defined, then support the additional SD options+ * This requires the SD patch from handhelds.org+ */++#define AU1XMMC_DO_SD+ /* Set this to enable special debugging macros */ /* #define MMC_DEBUG */ @@ -122,15 +128,22 @@ au_sync(); } -static inline void FLUSH_FIFO(struct au1xmmc_host *host) {+/* Turn on the FIFO flush - the fifo will be returned to active right+ * before data transfer+ */++static inline void FLUSH_FIFO_ON(struct au1xmmc_host *host) { u32 val = au_readl(HOST_CONFIG2(host));+ val |= SD_CONFIG2_FF;+ au_writel(val, HOST_CONFIG2(host));+ au_sync();+} - au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));- au_sync_delay(1);+static inline void FIFO_ACTIVE(struct au1xmmc_host *host) {+ u32 val = au_readl(HOST_CONFIG2(host)); /* SEND_STOP will turn off clock control - this re-enables it */- val &= ~SD_CONFIG2_DF;-+ val &= ~(SD_CONFIG2_DF | SD_CONFIG2_FF); au_writel(val, HOST_CONFIG2(host)); au_sync(); }@@ -144,8 +157,8 @@ static inline void SEND_STOP(struct au1xmmc_host *host) { - /* We know the value of CONFIG2, so avoid a read we don't need */- u32 mask = SD_CONFIG2_EN;+ /* Penalty box for Jordan - NEVER ASSUME! */+ u32 mask = au_readl(HOST_CONFIG2(host)); WARN_ON(host->status != HOST_S_DATA); host->status = HOST_S_STOP;@@ -185,7 +198,7 @@ host->flags &= HOST_F_ACTIVE; host->dma.len = 0;- host->dma.dir = 0;+ host->dma.dir = DMA_BIDIRECTIONAL; host->pio.index = 0; host->pio.offset = 0;@@ -195,6 +208,9 @@ bcsr->disk_leds |= (1 << 8); + /* Flush the FIFO until our next request */+ FLUSH_FIFO_ON(host);+ mmc_request_done(host->mmc, mrq); } @@ -210,6 +226,11 @@ switch(cmd->flags) { case MMC_RSP_R1:+#ifdef AU1XMMC_DO_SD+ if (cmd->opcode == 0x03 && host->mmc->mode == MMC_MODE_SD)+ mmccmd |= SD_CMD_RT_6;+ else+#endif mmccmd |= SD_CMD_RT_1; break; case MMC_RSP_R1B:@@ -510,8 +531,8 @@ r[3] = au_readl(host->iobase + SD_RESP0); /* The CRC is omitted from the response, so really we only got- * 120 bytes, but the engine expects 128 bits, so we have to shift- * things up + * 120 bytes, but the engine expects 128 bits, so we have to + * shift things up */ for(i = 0; i < 4; i++) {@@ -580,9 +601,8 @@ struct mmc_data *data) { int datalen = data->blocks * (1 << data->blksz_bits);-- if (dma != 0) - host->flags |= HOST_F_DMA;+ int i = 0;+ u32 channel; if (data->flags & MMC_DATA_READ) host->flags |= HOST_F_RECV;@@ -592,8 +612,6 @@ if (host->mrq->stop) host->flags |= HOST_F_STOP; - host->dma.dir = DMA_BIDIRECTIONAL;- host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir); @@ -602,9 +620,21 @@ au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host)); - if (host->flags & HOST_F_DMA) {- int i;- u32 channel = DMA_CHANNEL(host);+ if (dma == 0) {+ host->pio.index = 0;+ host->pio.offset = 0;+ host->pio.len = datalen;+ + if (host->flags & HOST_F_XMIT)+ IRQ_ON(host, SD_CONFIG_TH);+ else + IRQ_ON(host, SD_CONFIG_NE);++ return MMC_ERR_NONE;+ }++ host->flags |= HOST_F_DMA;+ channel = DMA_CHANNEL(host); au1xxx_dbdma_stop(channel); @@ -614,7 +644,7 @@ int sg_len = sg_dma_len(&data->sg[i]); int len = (datalen > sg_len) ? sg_len : datalen; - if (i == host->dma.len - 1)+ if (i == (host->dma.len - 1)) flags = DDMA_FLAGS_IE; if (host->flags & HOST_F_XMIT)@@ -626,23 +656,11 @@ (void *) phys_to_virt(sg_addr), len, flags); - if (!ret) + if (ret == 0) goto dataerr; datalen -= len; }- }- else {- host->pio.index = 0;- host->pio.offset = 0;- host->pio.len = datalen;- - if (host->flags & HOST_F_XMIT)- IRQ_ON(host, SD_CONFIG_TH);- else - IRQ_ON(host, SD_CONFIG_NE);- //IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);- } return MMC_ERR_NONE; @@ -669,7 +687,7 @@ bcsr->disk_leds &= ~(1 << 8); if (mrq->data) {- FLUSH_FIFO(host);+ FIFO_ACTIVE(host); ret = au1xmmc_prepare_data(host, mrq->data); } @@ -730,11 +748,26 @@ au1xmmc_set_clock(host, ios->clock); host->clock = ios->clock; }++#ifdef AU1XMMC_DO_SD+ /* Set the bus width for SD */++ if (ios->bus_width != host->bus_width) {+ u32 val;+ val = au_readl(HOST_CONFIG2(host));+ val &= ~(SD_CONFIG2_WB);+ val |= (ios->bus_width == MMC_BUS_WIDTH_4) ? SD_CONFIG2_WB : 0;++ au_writel(val, HOST_CONFIG2(host));+ au_sync();++ host->bus_width = ios->bus_width;+ }+#endif } static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs) { struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;- u32 status; /* Avoid spurious interrupts */ @@ -773,24 +806,8 @@ /* In PIO mode, interrupts might still be enabled */ IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);-- //IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF); tasklet_schedule(&host->finish_task); }-#if 0- else if (status & SD_STATUS_DD) {-- /* Sometimes we get a DD before a NE in PIO mode */-- if (!(host->flags & HOST_F_DMA) && - (status & SD_STATUS_NE))- au1xmmc_receive_pio(host);- else {- au1xmmc_data_complete(host, status);- //tasklet_schedule(&host->data_task);- }- }-#endif else if (status & (SD_STATUS_CR)) { if (host->status == HOST_S_CMD) au1xmmc_cmd_complete(host,status);@@ -830,10 +847,13 @@ mmc_detect_change(host->mmc); } ++#ifdef MMC_DEBUG if (host->mrq != NULL) { u32 status = au_readl(HOST_STATUS(host)); DEBUG("PENDING - %8.8x\n", host->id, status); }+#endif mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT); }@@ -872,9 +892,19 @@ host->rx_chan = rxchan; } +#ifdef AU1XMMC_DO_SD+static int au1xmmc_get_ro(struct mmc_host *mmc) {+ struct au1xmmc_host *host = mmc_priv(mmc);+ return au1xmmc_card_readonly(host);+}+#endif+ struct mmc_host_ops au1xmmc_ops = { .request = au1xmmc_request, .set_ios = au1xmmc_set_ios,+#ifdef AU1XMMC_DO_SD+ .get_ro = au1xmmc_get_ro, +#endif }; static int au1xmmc_probe(struct device *dev) {@@ -909,6 +939,9 @@ mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; +#ifdef AU1XMMC_DO_SD+ mmc->caps = MMC_CAP_4_BIT_DATA;+#endif mmc->ocr_avail = AU1XMMC_OCR; host = mmc_priv(mmc);@@ -919,6 +952,9 @@ host->clock = 0; host->power_mode = MMC_POWER_OFF; +#ifdef AU1XMMC_DO_SD+ host->bus_width = MMC_BUS_WIDTH_1;+#endif host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0; host->status = HOST_S_IDLE; diff -Nbur linux26-cvs/drivers/mmc/Kconfig linux26-cvs.SD/drivers/mmc/Kconfig--- linux26-cvs/drivers/mmc/Kconfig 2005-09-06 10:01:29.000000000 -0500+++ linux26-cvs.SD/drivers/mmc/Kconfig 2005-09-06 09:58:25.000000000 -0500@@ -60,13 +60,31 @@ If unsure, 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++config MMC_SAMCOP+ tristate "SAMCOP MMC/SD function support"+ depends on MMC+ help+ This provides support for the SD/MMC cell found in SAMCOP.++config MMC_ASIC3+ tristate "HTC ASIC3 SD/MMC support"+ depends on MMC+ help+ This provides support for the ASIC3 SD/MMC controller, used+ in the iPAQ hx4700 and others.+ config MMC_AU1X tristate "Alchemy AU1XX0 MMC Card Interface support" depends on SOC_AU1X00 && MMC help This selects the AMD Alchemy(R) Multimedia card interface.- iIf you have a Alchemy platform with a MMC slot, say Y or M here.-- If unsure, say N.+ If you have a Alchemy platform with a MMC slot, say Y or M here. endmenudiff -Nbur linux26-cvs/drivers/mmc/Makefile linux26-cvs.SD/drivers/mmc/Makefile--- linux26-cvs/drivers/mmc/Makefile 2005-09-06 10:01:29.000000000 -0500+++ linux26-cvs.SD/drivers/mmc/Makefile 2005-09-06 09:58:25.000000000 -0500@@ -18,6 +18,9 @@ obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o+obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o+obj-$(CONFIG_MMC_SAMCOP) += samcop_sdi.o+obj-$(CONFIG_MMC_ASIC3) += asic3_mmc.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.odiff -Nbur linux26-cvs/drivers/mmc/mmc_block.c linux26-cvs.SD/drivers/mmc/mmc_block.c--- linux26-cvs/drivers/mmc/mmc_block.c 2005-09-06 10:00:07.000000000 -0500+++ linux26-cvs.SD/drivers/mmc/mmc_block.c 2005-09-06 09:58:49.000000000 -0500@@ -95,6 +95,10 @@ if (md->usage == 2) check_disk_change(inode->i_bdev); ret = 0;+ + if ((filp->f_mode & FMODE_WRITE) &&+ mmc_card_readonly(md->queue.card))+ ret = -EROFS; } return ret;@@ -202,7 +206,10 @@ brq.data.sg = mq->sg; brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg); +#if 0 mmc_wait_for_req(card->host, &brq.mrq);+#endif+ mmc_uninterruptible_wait_for_req(card->host, &brq.mrq); if (brq.cmd.error) { printk(KERN_ERR "%s: error %d sending read/write command\n", req->rq_disk->disk_name, brq.cmd.error);@@ -227,7 +234,10 @@ cmd.opcode = MMC_SEND_STATUS; cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_R1;+#if 0 err = mmc_wait_for_cmd(card->host, &cmd, 5);+#endif+ err = mmc_uninterruptible_cmd(card->host, &cmd, 5); if (err) { printk(KERN_ERR "%s: error %d requesting status\n", req->rq_disk->disk_name, err);@@ -383,7 +393,7 @@ struct mmc_blk_data *md; int err; - if (card->csd.cmdclass & ~0x1ff)+ if (card->csd.cmdclass & ~0x5ff) return -ENODEV; if (card->csd.read_blkbits < 9) {@@ -400,9 +410,10 @@ if (err) goto out; - printk(KERN_INFO "%s: %s %s %dKiB\n",+ printk(KERN_INFO "%s: %s %s %dKiB %s\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_blkbits) / 1024,+ mmc_card_readonly(card)?"(ro)":""); mmc_set_drvdata(card, md); add_disk(md->disk);diff -Nbur linux26-cvs/drivers/mmc/mmc.c linux26-cvs.SD/drivers/mmc/mmc.c--- linux26-cvs/drivers/mmc/mmc.c 2005-09-06 10:00:07.000000000 -0500+++ linux26-cvs.SD/drivers/mmc/mmc.c 2005-09-06 09:58:25.000000000 -0500@@ -3,6 +3,8 @@ * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. *+ * SD support (c) 2004 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -