Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  ...
  • Loading branch information
Linus Torvalds committed Oct 12, 2008
2 parents 94a9f8a + 6ee6c6a commit 46b5e34
Show file tree
Hide file tree
Showing 21 changed files with 1,293 additions and 506 deletions.
7 changes: 5 additions & 2 deletions arch/avr32/boards/atngw100/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
};

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),
},
};

/*
Expand Down
18 changes: 11 additions & 7 deletions arch/avr32/boards/atstk1000/atstk1002.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,20 @@ void __init setup_board(void)

#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 */
#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
#define MCI_PDATA NULL
.detect_pin = -ENODEV,
.wp_pin = -ENODEV,
#endif /* SW6 for sd{cd,wp} routing */
},
};

#endif /* SW2 for MMC signal routing */

Expand Down Expand Up @@ -326,7 +330,7 @@ static int __init atstk1002_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, MCI_PDATA);
at32_add_device_mci(0, &mci0_pdata);
#endif
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
Expand Down
12 changes: 11 additions & 1 deletion arch/avr32/boards/atstk1000/atstk1003.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
} };
#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
static void __init atstk1003_setup_extdac(void)
{
Expand Down Expand Up @@ -154,7 +164,7 @@ static int __init atstk1003_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, NULL);
at32_add_device_mci(0, &mci0_data);
#endif
at32_add_device_usba(0, NULL);
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
Expand Down
12 changes: 11 additions & 1 deletion arch/avr32/boards/atstk1000/atstk1004.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
} };
#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
static void __init atstk1004_setup_extdac(void)
{
Expand Down Expand Up @@ -137,7 +147,7 @@ static int __init atstk1004_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, NULL);
at32_add_device_mci(0, &mci0_data);
#endif
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size, 0);
Expand Down
32 changes: 31 additions & 1 deletion arch/avr32/include/asm/atmel-mci.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
#ifndef __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 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 */
88 changes: 70 additions & 18 deletions arch/avr32/mach-at32ap/at32ap700x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,10 +1272,14 @@ static struct clk atmel_mci0_pclk = {
struct platform_device *__init
at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{
struct mci_platform_data _data;
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;

pdev = platform_device_alloc("atmel_mci", id);
Expand All @@ -1286,28 +1290,76 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
ARRAY_SIZE(atmel_mci0_resource)))
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,
sizeof(struct mci_platform_data)))
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;

Expand Down
9 changes: 5 additions & 4 deletions drivers/mmc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
#

menuconfig MMC
tristate "MMC/SD card support"
tristate "MMC/SD/SDIO card support"
depends on HAS_IOMEM
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
bool "MMC debugging"
Expand Down
3 changes: 1 addition & 2 deletions drivers/mmc/card/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# MMC/SD card drivers
#

comment "MMC/SD Card Drivers"
comment "MMC/SD/SDIO Card Drivers"

config MMC_BLOCK
tristate "MMC block device driver"
Expand Down Expand Up @@ -34,7 +34,6 @@ config MMC_BLOCK_BOUNCE

config SDIO_UART
tristate "SDIO UART/GPS class support"
depends on MMC
help
SDIO function driver for SDIO cards that implements the UART
class, as well as the GPS class which appears like a UART.
Expand Down
46 changes: 6 additions & 40 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ struct mmc_blk_data {
struct mmc_queue queue;

unsigned int usage;
unsigned int block_bits;
unsigned int read_only;
};

Expand Down Expand Up @@ -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_card *card = md->queue.card;
struct mmc_blk_request brq;
int ret = 1, data_size, i;
struct scatterlist *sg;
int ret = 1;

mmc_claim_host(card->host);

Expand All @@ -233,13 +231,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
if (!mmc_card_blockaddr(card))
brq.cmd.arg <<= 9;
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.arg = 0;
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) {
/* SPI multiblock writes terminate using a special
Expand Down Expand Up @@ -271,24 +267,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)

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_queue_bounce_post(mq);
Expand Down Expand Up @@ -373,16 +351,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
if (rq_data_dir(req) != READ) {
if (mmc_card_sd(card)) {
u32 blocks;
unsigned int bytes;

blocks = mmc_sd_num_wr_blocks(card);
if (blocks != (u32)-1) {
if (card->csd.write_partial)
bytes = blocks << md->block_bits;
else
bytes = blocks << 9;
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);
}
} else {
Expand Down Expand Up @@ -432,13 +405,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *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);
if (md->disk == NULL) {
ret = -ENOMEM;
Expand Down Expand Up @@ -476,7 +442,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)

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)) {
/*
Expand Down Expand Up @@ -514,7 +480,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)

mmc_claim_host(card->host);
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;
err = mmc_wait_for_cmd(card->host, &cmd, 5);
mmc_release_host(card->host);
Expand Down
Loading

0 comments on commit 46b5e34

Please sign in to comment.