Эх сурвалжийг харах

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (24 commits)
  MMC: Use timeout values from CSR
  MMC: CSD and CID timeout values
  sdhci: 'scratch' may be used uninitialized
  mmc: explicitly mention SDIO support in Kconfig
  mmc: remove redundant "depends on"
  Fix comment in include/linux/mmc/host.h
  sdio: high-speed support
  mmc_block: hard code 512 byte block size
  sdhci: force high speed capability on some controllers
  mmc_block: filter out PC requests
  mmc_block: indicate strict ordering
  mmc_block: inform block layer about sector count restriction
  sdio: give sdio irq thread a host specific name
  sdio: make sleep on error interruptable
  sdhci: reduce card detection delay
  sdhci: let the controller wait for busy state to end
  atmel-mci: Add missing flush_dcache_page() in PIO transfer code
  atmel-mci: Don't overwrite error bits when NOTBUSY is set
  atmel-mci: Add experimental DMA support
  atmel-mci: support multiple mmc slots
  ...
Linus Torvalds 16 жил өмнө
parent
commit
46b5e34029

+ 5 - 2
arch/avr32/boards/atngw100/setup.c

@@ -53,8 +53,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
 };
 };
 
 
 static struct mci_platform_data __initdata mci0_data = {
 static struct mci_platform_data __initdata mci0_data = {
-	.detect_pin	= GPIO_PIN_PC(25),
-	.wp_pin		= GPIO_PIN_PE(0),
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= GPIO_PIN_PC(25),
+		.wp_pin		= GPIO_PIN_PE(0),
+	},
 };
 };
 
 
 /*
 /*

+ 11 - 7
arch/avr32/boards/atstk1000/atstk1002.c

@@ -264,16 +264,20 @@ void __init setup_board(void)
 
 
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 
 
+static struct mci_platform_data __initdata mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+
 /* MMC card detect requires MACB0 *NOT* be used */
 /* MMC card detect requires MACB0 *NOT* be used */
 #ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
 #ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
-static struct mci_platform_data __initdata mci0_data = {
-	.detect_pin	= GPIO_PIN_PC(14),	/* gpio30/sdcd */
-	.wp_pin		= GPIO_PIN_PC(15),	/* gpio31/sdwp */
-};
-#define MCI_PDATA	&mci0_data
+		.detect_pin	= GPIO_PIN_PC(14), /* gpio30/sdcd */
+		.wp_pin		= GPIO_PIN_PC(15), /* gpio31/sdwp */
 #else
 #else
-#define MCI_PDATA	NULL
+		.detect_pin	= -ENODEV,
+		.wp_pin		= -ENODEV,
 #endif	/* SW6 for sd{cd,wp} routing */
 #endif	/* SW6 for sd{cd,wp} routing */
+	},
+};
 
 
 #endif	/* SW2 for MMC signal routing */
 #endif	/* SW2 for MMC signal routing */
 
 
@@ -326,7 +330,7 @@ static int __init atstk1002_init(void)
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #endif
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
-	at32_add_device_mci(0, MCI_PDATA);
+	at32_add_device_mci(0, &mci0_pdata);
 #endif
 #endif
 #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
 #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
 	set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
 	set_hw_addr(at32_add_device_eth(1, &eth_data[1]));

+ 11 - 1
arch/avr32/boards/atstk1000/atstk1003.c

@@ -66,6 +66,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
 } };
 } };
 #endif
 #endif
 
 
+#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+static struct mci_platform_data __initdata mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -ENODEV,
+		.wp_pin		= -ENODEV,
+	},
+};
+#endif
+
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 static void __init atstk1003_setup_extdac(void)
 static void __init atstk1003_setup_extdac(void)
 {
 {
@@ -154,7 +164,7 @@ static int __init atstk1003_init(void)
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #endif
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
-	at32_add_device_mci(0, NULL);
+	at32_add_device_mci(0, &mci0_data);
 #endif
 #endif
 	at32_add_device_usba(0, NULL);
 	at32_add_device_usba(0, NULL);
 #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
 #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM

+ 11 - 1
arch/avr32/boards/atstk1000/atstk1004.c

@@ -71,6 +71,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
 } };
 } };
 #endif
 #endif
 
 
+#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
+static struct mci_platform_data __initdata mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -ENODEV,
+		.wp_pin		= -ENODEV,
+	},
+};
+#endif
+
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 static void __init atstk1004_setup_extdac(void)
 static void __init atstk1004_setup_extdac(void)
 {
 {
@@ -137,7 +147,7 @@ static int __init atstk1004_init(void)
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 	at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
 #endif
 #endif
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
 #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
-	at32_add_device_mci(0, NULL);
+	at32_add_device_mci(0, &mci0_data);
 #endif
 #endif
 	at32_add_device_lcdc(0, &atstk1000_lcdc_data,
 	at32_add_device_lcdc(0, &atstk1000_lcdc_data,
 			     fbmem_start, fbmem_size, 0);
 			     fbmem_start, fbmem_size, 0);

+ 31 - 1
arch/avr32/include/asm/atmel-mci.h

@@ -1,9 +1,39 @@
 #ifndef __ASM_AVR32_ATMEL_MCI_H
 #ifndef __ASM_AVR32_ATMEL_MCI_H
 #define __ASM_AVR32_ATMEL_MCI_H
 #define __ASM_AVR32_ATMEL_MCI_H
 
 
-struct mci_platform_data {
+#define ATMEL_MCI_MAX_NR_SLOTS	2
+
+struct dma_slave;
+
+/**
+ * struct mci_slot_pdata - board-specific per-slot configuration
+ * @bus_width: Number of data lines wired up the slot
+ * @detect_pin: GPIO pin wired to the card detect switch
+ * @wp_pin: GPIO pin wired to the write protect sensor
+ *
+ * If a given slot is not present on the board, @bus_width should be
+ * set to 0. The other fields are ignored in this case.
+ *
+ * Any pins that aren't available should be set to a negative value.
+ *
+ * Note that support for multiple slots is experimental -- some cards
+ * might get upset if we don't get the clock management exactly right.
+ * But in most cases, it should work just fine.
+ */
+struct mci_slot_pdata {
+	unsigned int		bus_width;
 	int			detect_pin;
 	int			detect_pin;
 	int			wp_pin;
 	int			wp_pin;
 };
 };
 
 
+/**
+ * struct mci_platform_data - board-specific MMC/SDcard configuration
+ * @dma_slave: DMA slave interface to use in data transfers, or NULL.
+ * @slot: Per-slot configuration data.
+ */
+struct mci_platform_data {
+	struct dma_slave	*dma_slave;
+	struct mci_slot_pdata	slot[ATMEL_MCI_MAX_NR_SLOTS];
+};
+
 #endif /* __ASM_AVR32_ATMEL_MCI_H */
 #endif /* __ASM_AVR32_ATMEL_MCI_H */

+ 70 - 18
arch/avr32/mach-at32ap/at32ap700x.c

@@ -1272,10 +1272,14 @@ static struct clk atmel_mci0_pclk = {
 struct platform_device *__init
 struct platform_device *__init
 at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 {
 {
-	struct mci_platform_data	_data;
 	struct platform_device		*pdev;
 	struct platform_device		*pdev;
+	struct dw_dma_slave		*dws;
 
 
-	if (id != 0)
+	if (id != 0 || !data)
+		return NULL;
+
+	/* Must have at least one usable slot */
+	if (!data->slot[0].bus_width && !data->slot[1].bus_width)
 		return NULL;
 		return NULL;
 
 
 	pdev = platform_device_alloc("atmel_mci", id);
 	pdev = platform_device_alloc("atmel_mci", id);
@@ -1286,28 +1290,76 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
 				ARRAY_SIZE(atmel_mci0_resource)))
 				ARRAY_SIZE(atmel_mci0_resource)))
 		goto fail;
 		goto fail;
 
 
-	if (!data) {
-		data = &_data;
-		memset(data, -1, sizeof(struct mci_platform_data));
-		data->detect_pin = GPIO_PIN_NONE;
-		data->wp_pin = GPIO_PIN_NONE;
-	}
+	if (data->dma_slave)
+		dws = kmemdup(to_dw_dma_slave(data->dma_slave),
+				sizeof(struct dw_dma_slave), GFP_KERNEL);
+	else
+		dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL);
+
+	dws->slave.dev = &pdev->dev;
+	dws->slave.dma_dev = &dw_dmac0_device.dev;
+	dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT;
+	dws->cfg_hi = (DWC_CFGH_SRC_PER(0)
+				| DWC_CFGH_DST_PER(1));
+	dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL
+				| DWC_CFGL_HS_SRC_POL);
+
+	data->dma_slave = &dws->slave;
 
 
 	if (platform_device_add_data(pdev, data,
 	if (platform_device_add_data(pdev, data,
 				sizeof(struct mci_platform_data)))
 				sizeof(struct mci_platform_data)))
 		goto fail;
 		goto fail;
 
 
-	select_peripheral(PA(10), PERIPH_A, 0);	/* CLK	 */
-	select_peripheral(PA(11), PERIPH_A, 0);	/* CMD	 */
-	select_peripheral(PA(12), PERIPH_A, 0);	/* DATA0 */
-	select_peripheral(PA(13), PERIPH_A, 0);	/* DATA1 */
-	select_peripheral(PA(14), PERIPH_A, 0);	/* DATA2 */
-	select_peripheral(PA(15), PERIPH_A, 0);	/* DATA3 */
+	/* CLK line is common to both slots */
+	select_peripheral(PA(10), PERIPH_A, 0);
 
 
-	if (gpio_is_valid(data->detect_pin))
-		at32_select_gpio(data->detect_pin, 0);
-	if (gpio_is_valid(data->wp_pin))
-		at32_select_gpio(data->wp_pin, 0);
+	switch (data->slot[0].bus_width) {
+	case 4:
+		select_peripheral(PA(13), PERIPH_A, 0);	/* DATA1 */
+		select_peripheral(PA(14), PERIPH_A, 0);	/* DATA2 */
+		select_peripheral(PA(15), PERIPH_A, 0);	/* DATA3 */
+		/* fall through */
+	case 1:
+		select_peripheral(PA(11), PERIPH_A, 0);	/* CMD	 */
+		select_peripheral(PA(12), PERIPH_A, 0);	/* DATA0 */
+
+		if (gpio_is_valid(data->slot[0].detect_pin))
+			at32_select_gpio(data->slot[0].detect_pin, 0);
+		if (gpio_is_valid(data->slot[0].wp_pin))
+			at32_select_gpio(data->slot[0].wp_pin, 0);
+		break;
+	case 0:
+		/* Slot is unused */
+		break;
+	default:
+		goto fail;
+	}
+
+	switch (data->slot[1].bus_width) {
+	case 4:
+		select_peripheral(PB(8),  PERIPH_B, 0);	/* DATA1 */
+		select_peripheral(PB(9),  PERIPH_B, 0);	/* DATA2 */
+		select_peripheral(PB(10), PERIPH_B, 0);	/* DATA3 */
+		/* fall through */
+	case 1:
+		select_peripheral(PB(6),  PERIPH_B, 0); /* CMD	 */
+		select_peripheral(PB(7),  PERIPH_B, 0); /* DATA0 */
+
+		if (gpio_is_valid(data->slot[1].detect_pin))
+			at32_select_gpio(data->slot[1].detect_pin, 0);
+		if (gpio_is_valid(data->slot[1].wp_pin))
+			at32_select_gpio(data->slot[1].wp_pin, 0);
+		break;
+	case 0:
+		/* Slot is unused */
+		break;
+	default:
+		if (!data->slot[0].bus_width)
+			goto fail;
+
+		data->slot[1].bus_width = 0;
+		break;
+	}
 
 
 	atmel_mci0_pclk.dev = &pdev->dev;
 	atmel_mci0_pclk.dev = &pdev->dev;
 
 

+ 5 - 4
drivers/mmc/Kconfig

@@ -3,13 +3,14 @@
 #
 #
 
 
 menuconfig MMC
 menuconfig MMC
-	tristate "MMC/SD card support"
+	tristate "MMC/SD/SDIO card support"
 	depends on HAS_IOMEM
 	depends on HAS_IOMEM
 	help
 	help
-	  MMC is the "multi-media card" bus protocol.
+	  This selects MultiMediaCard, Secure Digital and Secure
+	  Digital I/O support.
 
 
-	  If you want MMC support, you should say Y here and also
-	  to the specific driver for your MMC interface.
+	  If you want MMC/SD/SDIO support, you should say Y here and
+	  also to your specific host controller driver.
 
 
 config MMC_DEBUG
 config MMC_DEBUG
 	bool "MMC debugging"
 	bool "MMC debugging"

+ 1 - 2
drivers/mmc/card/Kconfig

@@ -2,7 +2,7 @@
 # MMC/SD card drivers
 # MMC/SD card drivers
 #
 #
 
 
-comment "MMC/SD Card Drivers"
+comment "MMC/SD/SDIO Card Drivers"
 
 
 config MMC_BLOCK
 config MMC_BLOCK
 	tristate "MMC block device driver"
 	tristate "MMC block device driver"
@@ -34,7 +34,6 @@ config MMC_BLOCK_BOUNCE
 
 
 config SDIO_UART
 config SDIO_UART
 	tristate "SDIO UART/GPS class support"
 	tristate "SDIO UART/GPS class support"
-	depends on MMC
 	help
 	help
 	  SDIO function driver for SDIO cards that implements the UART
 	  SDIO function driver for SDIO cards that implements the UART
 	  class, as well as the GPS class which appears like a UART.
 	  class, as well as the GPS class which appears like a UART.

+ 6 - 40
drivers/mmc/card/block.c

@@ -58,7 +58,6 @@ struct mmc_blk_data {
 	struct mmc_queue queue;
 	struct mmc_queue queue;
 
 
 	unsigned int	usage;
 	unsigned int	usage;
-	unsigned int	block_bits;
 	unsigned int	read_only;
 	unsigned int	read_only;
 };
 };
 
 
@@ -216,8 +215,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request brq;
 	struct mmc_blk_request brq;
-	int ret = 1, data_size, i;
-	struct scatterlist *sg;
+	int ret = 1;
 
 
 	mmc_claim_host(card->host);
 	mmc_claim_host(card->host);
 
 
@@ -233,13 +231,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 		if (!mmc_card_blockaddr(card))
 		if (!mmc_card_blockaddr(card))
 			brq.cmd.arg <<= 9;
 			brq.cmd.arg <<= 9;
 		brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
 		brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-		brq.data.blksz = 1 << md->block_bits;
+		brq.data.blksz = 512;
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
 		brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
-		if (brq.data.blocks > card->host->max_blk_count)
-			brq.data.blocks = card->host->max_blk_count;
+		brq.data.blocks = req->nr_sectors;
 
 
 		if (brq.data.blocks > 1) {
 		if (brq.data.blocks > 1) {
 			/* SPI multiblock writes terminate using a special
 			/* SPI multiblock writes terminate using a special
@@ -271,24 +267,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 
 		mmc_queue_bounce_pre(mq);
 		mmc_queue_bounce_pre(mq);
 
 
-		/*
-		 * Adjust the sg list so it is the same size as the
-		 * request.
-		 */
-		if (brq.data.blocks !=
-		    (req->nr_sectors >> (md->block_bits - 9))) {
-			data_size = brq.data.blocks * brq.data.blksz;
-			for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
-				data_size -= sg->length;
-				if (data_size <= 0) {
-					sg->length += data_size;
-					i++;
-					break;
-				}
-			}
-			brq.data.sg_len = i;
-		}
-
 		mmc_wait_for_req(card->host, &brq.mrq);
 		mmc_wait_for_req(card->host, &brq.mrq);
 
 
 		mmc_queue_bounce_post(mq);
 		mmc_queue_bounce_post(mq);
@@ -373,16 +351,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	if (rq_data_dir(req) != READ) {
 	if (rq_data_dir(req) != READ) {
 		if (mmc_card_sd(card)) {
 		if (mmc_card_sd(card)) {
 			u32 blocks;
 			u32 blocks;
-			unsigned int bytes;
 
 
 			blocks = mmc_sd_num_wr_blocks(card);
 			blocks = mmc_sd_num_wr_blocks(card);
 			if (blocks != (u32)-1) {
 			if (blocks != (u32)-1) {
-				if (card->csd.write_partial)
-					bytes = blocks << md->block_bits;
-				else
-					bytes = blocks << 9;
 				spin_lock_irq(&md->lock);
 				spin_lock_irq(&md->lock);
-				ret = __blk_end_request(req, 0, bytes);
+				ret = __blk_end_request(req, 0, blocks << 9);
 				spin_unlock_irq(&md->lock);
 				spin_unlock_irq(&md->lock);
 			}
 			}
 		} else {
 		} else {
@@ -432,13 +405,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 	 */
 	 */
 	md->read_only = mmc_blk_readonly(card);
 	md->read_only = mmc_blk_readonly(card);
 
 
-	/*
-	 * Both SD and MMC specifications state (although a bit
-	 * unclearly in the MMC case) that a block size of 512
-	 * bytes must always be supported by the card.
-	 */
-	md->block_bits = 9;
-
 	md->disk = alloc_disk(1 << MMC_SHIFT);
 	md->disk = alloc_disk(1 << MMC_SHIFT);
 	if (md->disk == NULL) {
 	if (md->disk == NULL) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
@@ -476,7 +442,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 
 
 	sprintf(md->disk->disk_name, "mmcblk%d", devidx);
 	sprintf(md->disk->disk_name, "mmcblk%d", devidx);
 
 
-	blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+	blk_queue_hardsect_size(md->queue.queue, 512);
 
 
 	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
 	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
 		/*
 		/*
@@ -514,7 +480,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
 
 
 	mmc_claim_host(card->host);
 	mmc_claim_host(card->host);
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.opcode = MMC_SET_BLOCKLEN;
-	cmd.arg = 1 << md->block_bits;
+	cmd.arg = 512;
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 5);
 	err = mmc_wait_for_cmd(card->host, &cmd, 5);
 	mmc_release_host(card->host);
 	mmc_release_host(card->host);

+ 16 - 7
drivers/mmc/card/queue.c

@@ -31,7 +31,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
 	/*
 	/*
 	 * We only like normal block requests.
 	 * We only like normal block requests.
 	 */
 	 */
-	if (!blk_fs_request(req) && !blk_pc_request(req)) {
+	if (!blk_fs_request(req)) {
 		blk_dump_rq_flags(req, "MMC bad request");
 		blk_dump_rq_flags(req, "MMC bad request");
 		return BLKPREP_KILL;
 		return BLKPREP_KILL;
 	}
 	}
@@ -131,6 +131,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
 	mq->req = NULL;
 	mq->req = NULL;
 
 
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
+	blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL);
 
 
 #ifdef CONFIG_MMC_BLOCK_BOUNCE
 #ifdef CONFIG_MMC_BLOCK_BOUNCE
 	if (host->max_hw_segs == 1) {
 	if (host->max_hw_segs == 1) {
@@ -142,12 +143,19 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
 			bouncesz = host->max_req_size;
 			bouncesz = host->max_req_size;
 		if (bouncesz > host->max_seg_size)
 		if (bouncesz > host->max_seg_size)
 			bouncesz = host->max_seg_size;
 			bouncesz = host->max_seg_size;
+		if (bouncesz > (host->max_blk_count * 512))
+			bouncesz = host->max_blk_count * 512;
+
+		if (bouncesz > 512) {
+			mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+			if (!mq->bounce_buf) {
+				printk(KERN_WARNING "%s: unable to "
+					"allocate bounce buffer\n",
+					mmc_card_name(card));
+			}
+		}
 
 
-		mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
-		if (!mq->bounce_buf) {
-			printk(KERN_WARNING "%s: unable to allocate "
-				"bounce buffer\n", mmc_card_name(card));
-		} else {
+		if (mq->bounce_buf) {
 			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
 			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
 			blk_queue_max_sectors(mq->queue, bouncesz / 512);
 			blk_queue_max_sectors(mq->queue, bouncesz / 512);
 			blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
 			blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
@@ -175,7 +183,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
 
 
 	if (!mq->bounce_buf) {
 	if (!mq->bounce_buf) {
 		blk_queue_bounce_limit(mq->queue, limit);
 		blk_queue_bounce_limit(mq->queue, limit);
-		blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+		blk_queue_max_sectors(mq->queue,
+			min(host->max_blk_count, host->max_req_size / 512));
 		blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
 		blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
 		blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
 		blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
 		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
 		blk_queue_max_segment_size(mq->queue, host->max_seg_size);

+ 6 - 2
drivers/mmc/core/mmc_ops.c

@@ -248,8 +248,12 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
 
 
 	sg_init_one(&sg, data_buf, len);
 	sg_init_one(&sg, data_buf, len);
 
 
-	if (card)
-		mmc_set_data_timeout(&data, card);
+	/*
+	 * The spec states that CSR and CID accesses have a timeout
+	 * of 64 clock cycles.
+	 */
+	data.timeout_ns = 0;
+	data.timeout_clks = 64;
 
 
 	mmc_wait_for_req(host, &mrq);
 	mmc_wait_for_req(host, &mrq);
 
 

+ 49 - 3
drivers/mmc/core/sdio.c

@@ -164,6 +164,36 @@ static int sdio_enable_wide(struct mmc_card *card)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+static int sdio_enable_hs(struct mmc_card *card)
+{
+	int ret;
+	u8 speed;
+
+	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+		return 0;
+
+	if (!card->cccr.high_speed)
+		return 0;
+
+	ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
+	if (ret)
+		return ret;
+
+	speed |= SDIO_SPEED_EHS;
+
+	ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
+	if (ret)
+		return ret;
+
+	mmc_card_set_highspeed(card);
+	mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+
+	return 0;
+}
+
 /*
 /*
  * Host is being removed. Free up the current card.
  * Host is being removed. Free up the current card.
  */
  */
@@ -333,10 +363,26 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
 		goto remove;
 		goto remove;
 
 
 	/*
 	/*
-	 * No support for high-speed yet, so just set
-	 * the card's maximum speed.
+	 * Switch to high-speed (if supported).
 	 */
 	 */
-	mmc_set_clock(host, card->cis.max_dtr);
+	err = sdio_enable_hs(card);
+	if (err)
+		goto remove;
+
+	/*
+	 * Change to the card's maximum speed.
+	 */
+	if (mmc_card_highspeed(card)) {
+		/*
+		 * The SDIO specification doesn't mention how
+		 * the CIS transfer speed register relates to
+		 * high-speed, but it seems that 50 MHz is
+		 * mandatory.
+		 */
+		mmc_set_clock(host, 50000000);
+	} else {
+		mmc_set_clock(host, card->cis.max_dtr);
+	}
 
 
 	/*
 	/*
 	 * Switch to wider bus (if supported).
 	 * Switch to wider bus (if supported).

+ 11 - 5
drivers/mmc/core/sdio_irq.c

@@ -5,6 +5,8 @@
  * Created:     June 18, 2007
  * Created:     June 18, 2007
  * Copyright:   MontaVista Software Inc.
  * Copyright:   MontaVista Software Inc.
  *
  *
+ * Copyright 2008 Pierre Ossman
+ *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or (at
  * the Free Software Foundation; either version 2 of the License, or (at
@@ -107,11 +109,14 @@ static int sdio_irq_thread(void *_host)
 
 
 		/*
 		/*
 		 * Give other threads a chance to run in the presence of
 		 * Give other threads a chance to run in the presence of
-		 * errors.  FIXME: determine if due to card removal and
-		 * possibly exit this thread if so.
+		 * errors.
 		 */
 		 */
-		if (ret < 0)
-			ssleep(1);
+		if (ret < 0) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!kthread_should_stop())
+				schedule_timeout(HZ);
+			set_current_state(TASK_RUNNING);
+		}
 
 
 		/*
 		/*
 		 * Adaptive polling frequency based on the assumption
 		 * Adaptive polling frequency based on the assumption
@@ -154,7 +159,8 @@ static int sdio_card_irq_get(struct mmc_card *card)
 	if (!host->sdio_irqs++) {
 	if (!host->sdio_irqs++) {
 		atomic_set(&host->sdio_irq_thread_abort, 0);
 		atomic_set(&host->sdio_irq_thread_abort, 0);
 		host->sdio_irq_thread =
 		host->sdio_irq_thread =
-			kthread_run(sdio_irq_thread, host, "ksdiorqd");
+			kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
+				mmc_hostname(host));
 		if (IS_ERR(host->sdio_irq_thread)) {
 		if (IS_ERR(host->sdio_irq_thread)) {
 			int err = PTR_ERR(host->sdio_irq_thread);
 			int err = PTR_ERR(host->sdio_irq_thread);
 			host->sdio_irqs--;
 			host->sdio_irqs--;

+ 21 - 9
drivers/mmc/host/Kconfig

@@ -2,7 +2,7 @@
 # MMC/SD host controller drivers
 # MMC/SD host controller drivers
 #
 #
 
 
-comment "MMC/SD Host Controller Drivers"
+comment "MMC/SD/SDIO Host Controller Drivers"
 
 
 config MMC_ARMMMCI
 config MMC_ARMMMCI
 	tristate "ARM AMBA Multimedia Card Interface support"
 	tristate "ARM AMBA Multimedia Card Interface support"
@@ -114,6 +114,17 @@ config MMC_ATMELMCI
 
 
 	  If unsure, say N.
 	  If unsure, say N.
 
 
+config MMC_ATMELMCI_DMA
+	bool "Atmel MCI DMA support (EXPERIMENTAL)"
+	depends on MMC_ATMELMCI && DMA_ENGINE && EXPERIMENTAL
+	help
+	  Say Y here to have the Atmel MCI driver use a DMA engine to
+	  do data transfers and thus increase the throughput and
+	  reduce the CPU utilization. Note that this is highly
+	  experimental and may cause the driver to lock up.
+
+	  If unsure, say N.
+
 config MMC_IMX
 config MMC_IMX
 	tristate "Motorola i.MX Multimedia Card Interface support"
 	tristate "Motorola i.MX Multimedia Card Interface support"
 	depends on ARCH_IMX
 	depends on ARCH_IMX
@@ -141,21 +152,22 @@ config MMC_TIFM_SD
 	  module will be called tifm_sd.
 	  module will be called tifm_sd.
 
 
 config MMC_SPI
 config MMC_SPI
-	tristate "MMC/SD over SPI"
-	depends on MMC && SPI_MASTER && !HIGHMEM && HAS_DMA
+	tristate "MMC/SD/SDIO over SPI"
+	depends on SPI_MASTER && !HIGHMEM && HAS_DMA
 	select CRC7
 	select CRC7
 	select CRC_ITU_T
 	select CRC_ITU_T
 	help
 	help
-	  Some systems accss MMC/SD cards using a SPI controller instead of
-	  using a "native" MMC/SD controller.  This has a disadvantage of
-	  being relatively high overhead, but a compensating advantage of
-	  working on many systems without dedicated MMC/SD controllers.
+	  Some systems accss MMC/SD/SDIO cards using a SPI controller
+	  instead of using a "native" MMC/SD/SDIO controller.  This has a
+	  disadvantage of being relatively high overhead, but a compensating
+	  advantage of working on many systems without dedicated MMC/SD/SDIO
+	  controllers.
 
 
 	  If unsure, or if your system has no SPI master driver, say N.
 	  If unsure, or if your system has no SPI master driver, say N.
 
 
 config MMC_S3C
 config MMC_S3C
 	tristate "Samsung S3C SD/MMC Card Interface support"
 	tristate "Samsung S3C SD/MMC Card Interface support"
-	depends on ARCH_S3C2410 && MMC
+	depends on ARCH_S3C2410
 	help
 	help
 	  This selects a driver for the MCI interface found in
 	  This selects a driver for the MCI interface found in
           Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
           Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
@@ -166,7 +178,7 @@ config MMC_S3C
 
 
 config MMC_SDRICOH_CS
 config MMC_SDRICOH_CS
 	tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
 	tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && MMC && PCI && PCMCIA
+	depends on EXPERIMENTAL && PCI && PCMCIA
 	help
 	help
 	  Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA
 	  Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA
 	  card whenever you insert a MMC or SD card into the card slot.
 	  card whenever you insert a MMC or SD card into the card slot.

+ 4 - 2
drivers/mmc/host/atmel-mci-regs.h

@@ -25,8 +25,10 @@
 #define MCI_SDCR		0x000c	/* SD Card / SDIO */
 #define MCI_SDCR		0x000c	/* SD Card / SDIO */
 # define MCI_SDCSEL_SLOT_A	(  0 <<  0)	/* Select SD slot A */
 # define MCI_SDCSEL_SLOT_A	(  0 <<  0)	/* Select SD slot A */
 # define MCI_SDCSEL_SLOT_B	(  1 <<  0)	/* Select SD slot A */
 # define MCI_SDCSEL_SLOT_B	(  1 <<  0)	/* Select SD slot A */
-# define MCI_SDCBUS_1BIT	(  0 <<  7)	/* 1-bit data bus */
-# define MCI_SDCBUS_4BIT	(  1 <<  7)	/* 4-bit data bus */
+# define MCI_SDCSEL_MASK	(  3 <<  0)
+# define MCI_SDCBUS_1BIT	(  0 <<  6)	/* 1-bit data bus */
+# define MCI_SDCBUS_4BIT	(  2 <<  6)	/* 4-bit data bus */
+# define MCI_SDCBUS_MASK	(  3 <<  6)
 #define MCI_ARGR		0x0010	/* Command Argument */
 #define MCI_ARGR		0x0010	/* Command Argument */
 #define MCI_CMDR		0x0014	/* Command */
 #define MCI_CMDR		0x0014	/* Command */
 # define MCI_CMDR_CMDNB(x)	((x) <<  0)	/* Command Opcode */
 # define MCI_CMDR_CMDNB(x)	((x) <<  0)	/* Command Opcode */

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 718 - 254
drivers/mmc/host/atmel-mci.c


+ 21 - 11
drivers/mmc/host/mmc_spi.c

@@ -95,8 +95,6 @@
  * reads which takes nowhere near that long.  Older cards may be able to use
  * reads which takes nowhere near that long.  Older cards may be able to use
  * shorter timeouts ... but why bother?
  * shorter timeouts ... but why bother?
  */
  */
-#define readblock_timeout	ktime_set(0, 100 * 1000 * 1000)
-#define writeblock_timeout	ktime_set(0, 250 * 1000 * 1000)
 #define r1b_timeout		ktime_set(3, 0)
 #define r1b_timeout		ktime_set(3, 0)
 
 
 
 
@@ -220,9 +218,9 @@ mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout)
 	return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
 	return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
 }
 }
 
 
-static int mmc_spi_readtoken(struct mmc_spi_host *host)
+static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout)
 {
 {
-	return mmc_spi_skip(host, readblock_timeout, 1, 0xff);
+	return mmc_spi_skip(host, timeout, 1, 0xff);
 }
 }
 
 
 
 
@@ -605,7 +603,8 @@ mmc_spi_setup_data_message(
  * Return negative errno, else success.
  * Return negative errno, else success.
  */
  */
 static int
 static int
-mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
+	ktime_t timeout)
 {
 {
 	struct spi_device	*spi = host->spi;
 	struct spi_device	*spi = host->spi;
 	int			status, i;
 	int			status, i;
@@ -673,7 +672,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
 		if (scratch->status[i] != 0)
 		if (scratch->status[i] != 0)
 			return 0;
 			return 0;
 	}
 	}
-	return mmc_spi_wait_unbusy(host, writeblock_timeout);
+	return mmc_spi_wait_unbusy(host, timeout);
 }
 }
 
 
 /*
 /*
@@ -693,7 +692,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
  * STOP_TRANSMISSION command.
  * STOP_TRANSMISSION command.
  */
  */
 static int
 static int
-mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
+mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
+	ktime_t timeout)
 {
 {
 	struct spi_device	*spi = host->spi;
 	struct spi_device	*spi = host->spi;
 	int			status;
 	int			status;
@@ -707,7 +707,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
 		return status;
 		return status;
 	status = scratch->status[0];
 	status = scratch->status[0];
 	if (status == 0xff || status == 0)
 	if (status == 0xff || status == 0)
-		status = mmc_spi_readtoken(host);
+		status = mmc_spi_readtoken(host, timeout);
 
 
 	if (status == SPI_TOKEN_SINGLE) {
 	if (status == SPI_TOKEN_SINGLE) {
 		if (host->dma_dev) {
 		if (host->dma_dev) {
@@ -778,6 +778,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
 	struct scatterlist	*sg;
 	struct scatterlist	*sg;
 	unsigned		n_sg;
 	unsigned		n_sg;
 	int			multiple = (data->blocks > 1);
 	int			multiple = (data->blocks > 1);
+	u32			clock_rate;
+	ktime_t			timeout;
 
 
 	if (data->flags & MMC_DATA_READ)
 	if (data->flags & MMC_DATA_READ)
 		direction = DMA_FROM_DEVICE;
 		direction = DMA_FROM_DEVICE;
@@ -786,6 +788,14 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
 	mmc_spi_setup_data_message(host, multiple, direction);
 	mmc_spi_setup_data_message(host, multiple, direction);
 	t = &host->t;
 	t = &host->t;
 
 
+	if (t->speed_hz)
+		clock_rate = t->speed_hz;
+	else
+		clock_rate = spi->max_speed_hz;
+
+	timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns +
+			data->timeout_clks * 1000000 / clock_rate);
+
 	/* Handle scatterlist segments one at a time, with synch for
 	/* Handle scatterlist segments one at a time, with synch for
 	 * each 512-byte block
 	 * each 512-byte block
 	 */
 	 */
@@ -832,9 +842,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
 				t->len);
 				t->len);
 
 
 			if (direction == DMA_TO_DEVICE)
 			if (direction == DMA_TO_DEVICE)
-				status = mmc_spi_writeblock(host, t);
+				status = mmc_spi_writeblock(host, t, timeout);
 			else
 			else
-				status = mmc_spi_readblock(host, t);
+				status = mmc_spi_readblock(host, t, timeout);
 			if (status < 0)
 			if (status < 0)
 				break;
 				break;
 
 
@@ -917,7 +927,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
 			if (scratch->status[tmp] != 0)
 			if (scratch->status[tmp] != 0)
 				return;
 				return;
 		}
 		}
-		tmp = mmc_spi_wait_unbusy(host, writeblock_timeout);
+		tmp = mmc_spi_wait_unbusy(host, timeout);
 		if (tmp < 0 && !data->error)
 		if (tmp < 0 && !data->error)
 			data->error = tmp;
 			data->error = tmp;
 	}
 	}

+ 2 - 1
drivers/mmc/host/sdhci-pci.c

@@ -144,7 +144,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
 			  SDHCI_QUIRK_32BIT_DMA_SIZE |
 			  SDHCI_QUIRK_32BIT_DMA_SIZE |
 			  SDHCI_QUIRK_32BIT_ADMA_SIZE |
 			  SDHCI_QUIRK_32BIT_ADMA_SIZE |
 			  SDHCI_QUIRK_RESET_AFTER_REQUEST |
 			  SDHCI_QUIRK_RESET_AFTER_REQUEST |
-			  SDHCI_QUIRK_BROKEN_SMALL_PIO;
+			  SDHCI_QUIRK_BROKEN_SMALL_PIO |
+			  SDHCI_QUIRK_FORCE_HIGHSPEED;
 	}
 	}
 
 
 	/*
 	/*

+ 37 - 9
drivers/mmc/host/sdhci.c

@@ -177,7 +177,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 	size_t blksize, len, chunk;
 	size_t blksize, len, chunk;
-	u32 scratch;
+	u32 uninitialized_var(scratch);
 	u8 *buf;
 	u8 *buf;
 
 
 	DBG("PIO reading\n");
 	DBG("PIO reading\n");
@@ -1154,7 +1154,7 @@ static void sdhci_tasklet_card(unsigned long param)
 
 
 	spin_unlock_irqrestore(&host->lock, flags);
 	spin_unlock_irqrestore(&host->lock, flags);
 
 
-	mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
 }
 }
 
 
 static void sdhci_tasklet_finish(unsigned long param)
 static void sdhci_tasklet_finish(unsigned long param)
@@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
 			SDHCI_INT_INDEX))
 			SDHCI_INT_INDEX))
 		host->cmd->error = -EILSEQ;
 		host->cmd->error = -EILSEQ;
 
 
-	if (host->cmd->error)
+	if (host->cmd->error) {
 		tasklet_schedule(&host->finish_tasklet);
 		tasklet_schedule(&host->finish_tasklet);
-	else if (intmask & SDHCI_INT_RESPONSE)
+		return;
+	}
+
+	/*
+	 * The host can send and interrupt when the busy state has
+	 * ended, allowing us to wait without wasting CPU cycles.
+	 * Unfortunately this is overloaded on the "data complete"
+	 * interrupt, so we need to take some care when handling
+	 * it.
+	 *
+	 * Note: The 1.0 specification is a bit ambiguous about this
+	 *       feature so there might be some problems with older
+	 *       controllers.
+	 */
+	if (host->cmd->flags & MMC_RSP_BUSY) {
+		if (host->cmd->data)
+			DBG("Cannot wait for busy signal when also "
+				"doing a data transfer");
+		else
+			return;
+	}
+
+	if (intmask & SDHCI_INT_RESPONSE)
 		sdhci_finish_command(host);
 		sdhci_finish_command(host);
 }
 }
 
 
@@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 
 
 	if (!host->data) {
 	if (!host->data) {
 		/*
 		/*
-		 * A data end interrupt is sent together with the response
-		 * for the stop command.
+		 * The "data complete" interrupt is also used to
+		 * indicate that a busy state has ended. See comment
+		 * above in sdhci_cmd_irq().
 		 */
 		 */
-		if (intmask & SDHCI_INT_DATA_END)
-			return;
+		if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
+			if (intmask & SDHCI_INT_DATA_END) {
+				sdhci_finish_command(host);
+				return;
+			}
+		}
 
 
 		printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
 		printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
 			"though no data operation was in progress.\n",
 			"though no data operation was in progress.\n",
@@ -1604,7 +1631,8 @@ int sdhci_add_host(struct sdhci_host *host)
 	mmc->f_max = host->max_clk;
 	mmc->f_max = host->max_clk;
 	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
 	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
 
 
-	if (caps & SDHCI_CAN_DO_HISPD)
+	if ((caps & SDHCI_CAN_DO_HISPD) ||
+		(host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED))
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
 
 
 	mmc->ocr_avail = 0;
 	mmc->ocr_avail = 0;

+ 2 - 0
drivers/mmc/host/sdhci.h

@@ -208,6 +208,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL			(1<<12)
 #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL			(1<<12)
 /* Controller has an issue with buffer bits for small transfers */
 /* Controller has an issue with buffer bits for small transfers */
 #define SDHCI_QUIRK_BROKEN_SMALL_PIO			(1<<13)
 #define SDHCI_QUIRK_BROKEN_SMALL_PIO			(1<<13)
+/* Controller supports high speed but doesn't have the caps bit set */
+#define SDHCI_QUIRK_FORCE_HIGHSPEED			(1<<14)
 
 
 	int			irq;		/* Device IRQ */
 	int			irq;		/* Device IRQ */
 	void __iomem *		ioaddr;		/* Mapped address */
 	void __iomem *		ioaddr;		/* Mapped address */

+ 1 - 1
include/linux/mmc/host.h

@@ -65,7 +65,7 @@ struct mmc_host_ops {
 	 *   -ENOSYS when not supported (equal to NULL callback)
 	 *   -ENOSYS when not supported (equal to NULL callback)
 	 *   or a negative errno value when something bad happened
 	 *   or a negative errno value when something bad happened
 	 *
 	 *
-	 * Return values for the get_ro callback should be:
+	 * Return values for the get_cd callback should be:
 	 *   0 for a absent card
 	 *   0 for a absent card
 	 *   1 for a present card
 	 *   1 for a present card
 	 *   -ENOSYS when not supported (equal to NULL callback)
 	 *   -ENOSYS when not supported (equal to NULL callback)

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно