Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 227160
b: refs/heads/master
c: aa0787a
h: refs/heads/master
v: v3
  • Loading branch information
Guennadi Liakhovetski authored and Paul Mundt committed Nov 25, 2010
1 parent 08001b2 commit eb4f025
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 72 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2d3e4e7652f1db2de0fe8798a1a9be460ac9057b
refs/heads/master: aa0787a90c70587db6934547bb7687efc30062c7
117 changes: 46 additions & 71 deletions trunk/drivers/mmc/host/sh_mmcif.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*
*/

#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
Expand All @@ -24,7 +26,6 @@
#include <linux/mmc/sdio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/mmc/sh_mmcif.h>

#define DRIVER_NAME "sh_mmcif"
Expand Down Expand Up @@ -158,11 +159,10 @@ struct sh_mmcif_host {
struct clk *hclk;
unsigned int clk;
int bus_width;
u16 wait_int;
u16 sd_error;
bool sd_error;
long timeout;
void __iomem *addr;
wait_queue_head_t intr_wait;
struct completion intr_wait;
};


Expand Down Expand Up @@ -216,8 +216,7 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
u32 state1, state2;
int ret, timeout = 10000000;

host->sd_error = 0;
host->wait_int = 0;
host->sd_error = false;

state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
Expand Down Expand Up @@ -264,31 +263,25 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host,
long time;
u32 blocksize, i, *p = sg_virt(data->sg);

host->wait_int = 0;

/* buf read enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);
if (time <= 0 || host->sd_error)
return sh_mmcif_error_manage(host);

host->wait_int = 0;
blocksize = (BLOCK_SIZE_MASK &
sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
for (i = 0; i < blocksize / 4; i++)
*p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);

/* buffer read end */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);
if (time <= 0 || host->sd_error)
return sh_mmcif_error_manage(host);

host->wait_int = 0;
return 0;
}

Expand All @@ -303,19 +296,15 @@ static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
MMCIF_CE_BLOCK_SET);
for (j = 0; j < data->sg_len; j++) {
p = sg_virt(data->sg);
host->wait_int = 0;
for (sec = 0; sec < data->sg->length / blocksize; sec++) {
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
/* buf read enable */
time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);

if (host->wait_int != 1 &&
(time == 0 || host->sd_error != 0))
if (time <= 0 || host->sd_error)
return sh_mmcif_error_manage(host);

host->wait_int = 0;
for (i = 0; i < blocksize / 4; i++)
*p++ = sh_mmcif_readl(host->addr,
MMCIF_CE_DATA);
Expand All @@ -333,17 +322,14 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
long time;
u32 blocksize, i, *p = sg_virt(data->sg);

host->wait_int = 0;
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);

/* buf write enable */
time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);
if (time <= 0 || host->sd_error)
return sh_mmcif_error_manage(host);

host->wait_int = 0;
blocksize = (BLOCK_SIZE_MASK &
sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
for (i = 0; i < blocksize / 4; i++)
Expand All @@ -352,13 +338,11 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
/* buffer write end */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);

time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);
if (time <= 0 || host->sd_error)
return sh_mmcif_error_manage(host);

host->wait_int = 0;
return 0;
}

Expand All @@ -374,19 +358,15 @@ static int sh_mmcif_multi_write(struct sh_mmcif_host *host,

for (j = 0; j < data->sg_len; j++) {
p = sg_virt(data->sg);
host->wait_int = 0;
for (sec = 0; sec < data->sg->length / blocksize; sec++) {
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
/* buf write enable*/
time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);

if (host->wait_int != 1 &&
(time == 0 || host->sd_error != 0))
if (time <= 0 || host->sd_error)
return sh_mmcif_error_manage(host);

host->wait_int = 0;
for (i = 0; i < blocksize / 4; i++)
sh_mmcif_writel(host->addr,
MMCIF_CE_DATA, *p++);
Expand Down Expand Up @@ -556,13 +536,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
/* set arg */
sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
host->wait_int = 0;
/* set cmd */
sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);

time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 || host->sd_error == 1, host->timeout);
if (host->wait_int != 1 && time == 0) {
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);
if (time <= 0) {
cmd->error = sh_mmcif_error_manage(host);
return;
}
Expand All @@ -579,19 +558,14 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
cmd->error = sh_mmcif_error_manage(host);
break;
}
host->sd_error = 0;
host->wait_int = 0;
host->sd_error = false;
return;
}
if (!(cmd->flags & MMC_RSP_PRESENT)) {
cmd->error = ret;
host->wait_int = 0;
return;
}
if (host->wait_int == 1) {
sh_mmcif_get_response(host, cmd);
host->wait_int = 0;
}
sh_mmcif_get_response(host, cmd);
if (host->data) {
ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
if (ret < 0)
Expand All @@ -618,15 +592,13 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
return;
}

time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 ||
host->sd_error == 1, host->timeout);
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) {
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
host->timeout);
if (time <= 0 || host->sd_error) {
cmd->error = sh_mmcif_error_manage(host);
return;
}
sh_mmcif_get_cmd12response(host, cmd);
host->wait_int = 0;
cmd->error = 0;
}

Expand Down Expand Up @@ -712,7 +684,7 @@ static void sh_mmcif_detect(struct mmc_host *mmc)
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
{
struct sh_mmcif_host *host = dev_id;
u32 state = 0;
u32 state;
int err = 0;

state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
Expand Down Expand Up @@ -757,11 +729,13 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
err = 1;
}
if (err) {
host->sd_error = 1;
host->sd_error = true;
pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state);
}
host->wait_int = 1;
wake_up(&host->intr_wait);
if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
complete(&host->intr_wait);
else
dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);

return IRQ_HANDLED;
}
Expand Down Expand Up @@ -819,7 +793,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
host->clk = clk_get_rate(host->hclk);
host->pd = pdev;

init_waitqueue_head(&host->intr_wait);
init_completion(&host->intr_wait);

mmc->ops = &sh_mmcif_ops;
mmc->f_max = host->clk;
Expand Down Expand Up @@ -880,20 +854,21 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
int irq[2];

sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);

irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq(pdev, 1);
mmc_remove_host(host->mmc);

if (host->addr)
iounmap(host->addr);

platform_set_drvdata(pdev, NULL);
mmc_remove_host(host->mmc);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);

irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq(pdev, 1);

free_irq(irq[0], host);
free_irq(irq[1], host);

platform_set_drvdata(pdev, NULL);

clk_disable(host->hclk);
mmc_free_host(host->mmc);

Expand Down Expand Up @@ -924,5 +899,5 @@ module_exit(sh_mmcif_exit);

MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS(DRIVER_NAME);
MODULE_ALIAS("platform:" DRIVER_NAME);
MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>");

0 comments on commit eb4f025

Please sign in to comment.