Merge branch 'fixes' into for-linus
Conflicts: arch/arm/mach-versatile/core.c
This commit is contained in:
@@ -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"
|
||||
|
@@ -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"
|
||||
@@ -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.
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/host.h>
|
||||
@@ -57,7 +58,6 @@ struct mmc_blk_data {
|
||||
struct mmc_queue queue;
|
||||
|
||||
unsigned int usage;
|
||||
unsigned int block_bits;
|
||||
unsigned int read_only;
|
||||
};
|
||||
|
||||
@@ -83,7 +83,7 @@ static void mmc_blk_put(struct mmc_blk_data *md)
|
||||
mutex_lock(&open_lock);
|
||||
md->usage--;
|
||||
if (md->usage == 0) {
|
||||
int devidx = md->disk->first_minor >> MMC_SHIFT;
|
||||
int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
|
||||
__clear_bit(devidx, dev_use);
|
||||
|
||||
put_disk(md->disk);
|
||||
@@ -215,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);
|
||||
|
||||
@@ -232,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
|
||||
@@ -270,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);
|
||||
@@ -372,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 {
|
||||
@@ -431,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;
|
||||
@@ -475,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)) {
|
||||
/*
|
||||
@@ -513,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);
|
||||
@@ -532,6 +499,8 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
struct mmc_blk_data *md;
|
||||
int err;
|
||||
|
||||
char cap_str[10];
|
||||
|
||||
/*
|
||||
* Check that the card supports the command class(es) we need.
|
||||
*/
|
||||
@@ -546,10 +515,11 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
|
||||
string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
|
||||
cap_str, sizeof(cap_str));
|
||||
printk(KERN_INFO "%s: %s %s %s %s\n",
|
||||
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
|
||||
(unsigned long long)(get_capacity(md->disk) >> 1),
|
||||
md->read_only ? "(ro)" : "");
|
||||
cap_str, md->read_only ? "(ro)" : "");
|
||||
|
||||
mmc_set_drvdata(card, md);
|
||||
add_disk(md->disk);
|
||||
|
@@ -31,7 +31,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
|
||||
/*
|
||||
* 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");
|
||||
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;
|
||||
|
||||
blk_queue_prep_rq(mq->queue, mmc_prep_request);
|
||||
blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL);
|
||||
|
||||
#ifdef CONFIG_MMC_BLOCK_BOUNCE
|
||||
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;
|
||||
if (bouncesz > host->max_seg_size)
|
||||
bouncesz = host->max_seg_size;
|
||||
if (bouncesz > (host->max_blk_count * 512))
|
||||
bouncesz = host->max_blk_count * 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));
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
if (mq->bounce_buf) {
|
||||
blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
|
||||
blk_queue_max_sectors(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) {
|
||||
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_hw_segments(mq->queue, host->max_hw_segs);
|
||||
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
|
||||
|
@@ -248,8 +248,12 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
|
||||
|
||||
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);
|
||||
|
||||
|
@@ -164,6 +164,36 @@ static int sdio_enable_wide(struct mmc_card *card)
|
||||
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.
|
||||
*/
|
||||
@@ -333,10 +363,26 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
|
||||
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).
|
||||
|
@@ -5,6 +5,8 @@
|
||||
* Created: June 18, 2007
|
||||
* Copyright: MontaVista Software Inc.
|
||||
*
|
||||
* Copyright 2008 Pierre Ossman
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
@@ -154,7 +159,8 @@ static int sdio_card_irq_get(struct mmc_card *card)
|
||||
if (!host->sdio_irqs++) {
|
||||
atomic_set(&host->sdio_irq_thread_abort, 0);
|
||||
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)) {
|
||||
int err = PTR_ERR(host->sdio_irq_thread);
|
||||
host->sdio_irqs--;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
# MMC/SD host controller drivers
|
||||
#
|
||||
|
||||
comment "MMC/SD Host Controller Drivers"
|
||||
comment "MMC/SD/SDIO Host Controller Drivers"
|
||||
|
||||
config MMC_ARMMMCI
|
||||
tristate "ARM AMBA Multimedia Card Interface support"
|
||||
@@ -114,6 +114,17 @@ config MMC_ATMELMCI
|
||||
|
||||
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
|
||||
tristate "Motorola i.MX Multimedia Card Interface support"
|
||||
depends on ARCH_IMX
|
||||
@@ -141,21 +152,22 @@ config MMC_TIFM_SD
|
||||
module will be called tifm_sd.
|
||||
|
||||
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 CRC_ITU_T
|
||||
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.
|
||||
|
||||
config MMC_S3C
|
||||
tristate "Samsung S3C SD/MMC Card Interface support"
|
||||
depends on ARCH_S3C2410 && MMC
|
||||
depends on ARCH_S3C2410
|
||||
help
|
||||
This selects a driver for the MCI interface found in
|
||||
Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
|
||||
@@ -166,7 +178,7 @@ config MMC_S3C
|
||||
|
||||
config MMC_SDRICOH_CS
|
||||
tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && MMC && PCI && PCMCIA
|
||||
depends on EXPERIMENTAL && PCI && PCMCIA
|
||||
help
|
||||
Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA
|
||||
card whenever you insert a MMC or SD card into the card slot.
|
||||
|
@@ -25,8 +25,10 @@
|
||||
#define MCI_SDCR 0x000c /* SD Card / SDIO */
|
||||
# define MCI_SDCSEL_SLOT_A ( 0 << 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_CMDR 0x0014 /* Command */
|
||||
# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -95,8 +95,6 @@
|
||||
* reads which takes nowhere near that long. Older cards may be able to use
|
||||
* 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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
int status, i;
|
||||
@@ -673,7 +672,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t)
|
||||
if (scratch->status[i] != 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.
|
||||
*/
|
||||
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;
|
||||
int status;
|
||||
@@ -707,7 +707,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t)
|
||||
return status;
|
||||
status = scratch->status[0];
|
||||
if (status == 0xff || status == 0)
|
||||
status = mmc_spi_readtoken(host);
|
||||
status = mmc_spi_readtoken(host, timeout);
|
||||
|
||||
if (status == SPI_TOKEN_SINGLE) {
|
||||
if (host->dma_dev) {
|
||||
@@ -778,6 +778,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
struct scatterlist *sg;
|
||||
unsigned n_sg;
|
||||
int multiple = (data->blocks > 1);
|
||||
u32 clock_rate;
|
||||
ktime_t timeout;
|
||||
|
||||
if (data->flags & MMC_DATA_READ)
|
||||
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);
|
||||
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
|
||||
* each 512-byte block
|
||||
*/
|
||||
@@ -832,9 +842,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
t->len);
|
||||
|
||||
if (direction == DMA_TO_DEVICE)
|
||||
status = mmc_spi_writeblock(host, t);
|
||||
status = mmc_spi_writeblock(host, t, timeout);
|
||||
else
|
||||
status = mmc_spi_readblock(host, t);
|
||||
status = mmc_spi_readblock(host, t, timeout);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
@@ -917,7 +927,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
if (scratch->status[tmp] != 0)
|
||||
return;
|
||||
}
|
||||
tmp = mmc_spi_wait_unbusy(host, writeblock_timeout);
|
||||
tmp = mmc_spi_wait_unbusy(host, timeout);
|
||||
if (tmp < 0 && !data->error)
|
||||
data->error = tmp;
|
||||
}
|
||||
|
@@ -144,7 +144,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
|
||||
SDHCI_QUIRK_32BIT_DMA_SIZE |
|
||||
SDHCI_QUIRK_32BIT_ADMA_SIZE |
|
||||
SDHCI_QUIRK_RESET_AFTER_REQUEST |
|
||||
SDHCI_QUIRK_BROKEN_SMALL_PIO;
|
||||
SDHCI_QUIRK_BROKEN_SMALL_PIO |
|
||||
SDHCI_QUIRK_FORCE_HIGHSPEED;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -326,7 +327,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
|
||||
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_MARVELL,
|
||||
.device = PCI_DEVICE_ID_MARVELL_CAFE_SD,
|
||||
.device = PCI_DEVICE_ID_MARVELL_88ALP01_SD,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = (kernel_ulong_t)&sdhci_cafe,
|
||||
|
@@ -177,7 +177,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
|
||||
{
|
||||
unsigned long flags;
|
||||
size_t blksize, len, chunk;
|
||||
u32 scratch;
|
||||
u32 uninitialized_var(scratch);
|
||||
u8 *buf;
|
||||
|
||||
DBG("PIO reading\n");
|
||||
@@ -1154,7 +1154,7 @@ static void sdhci_tasklet_card(unsigned long param)
|
||||
|
||||
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)
|
||||
@@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
|
||||
SDHCI_INT_INDEX))
|
||||
host->cmd->error = -EILSEQ;
|
||||
|
||||
if (host->cmd->error)
|
||||
if (host->cmd->error) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
|
||||
|
||||
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 "
|
||||
"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->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->ocr_avail = 0;
|
||||
|
@@ -208,6 +208,8 @@ struct sdhci_host {
|
||||
#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
|
||||
/* Controller has an issue with buffer bits for small transfers */
|
||||
#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 */
|
||||
void __iomem * ioaddr; /* Mapped address */
|
||||
|
Reference in New Issue
Block a user