X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmmc%2Fpxamci.c;fp=drivers%2Fmmc%2Fpxamci.c;h=285d7d0680977a6fbba99139a71a77fe7645d168;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=ef350908478c75217ff2474dca8824cdb9cd99e9;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index ef3509084..285d7d068 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -16,6 +16,7 @@ * 1 and 3 byte data transfers not supported * max block length up to 1023 */ +#include #include #include #include @@ -36,6 +37,12 @@ #include "pxamci.h" +#ifdef CONFIG_MMC_DEBUG +#define DBG(x...) printk(KERN_DEBUG x) +#else +#define DBG(x...) do { } while (0) +#endif + #define DRIVER_NAME "pxa2xx-mci" #define NR_SG 1 @@ -64,6 +71,11 @@ struct pxamci_host { unsigned int dma_dir; }; +static inline unsigned int ns_to_clocks(unsigned int ns) +{ + return (ns * (CLOCKRATE / 1000000) + 999) / 1000; +} + static void pxamci_stop_clock(struct pxamci_host *host) { if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { @@ -107,7 +119,6 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) { unsigned int nob = data->blocks; - unsigned long long clks; unsigned int timeout; u32 dcmd; int i; @@ -118,11 +129,9 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) nob = 0xffff; writel(nob, host->base + MMC_NOB); - writel(data->blksz, host->base + MMC_BLKLEN); + writel(1 << data->blksz_bits, host->base + MMC_BLKLEN); - clks = (unsigned long long)data->timeout_ns * CLOCKRATE; - do_div(clks, 1000000000UL); - timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); + timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks; writel((timeout + 255) / 256, host->base + MMC_RDTO); if (data->flags & MMC_DATA_READ) { @@ -197,6 +206,7 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) { + DBG("PXAMCI: request done\n"); host->mrq = NULL; host->cmd = NULL; host->data = NULL; @@ -242,7 +252,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) if ((cmd->resp[0] & 0x80000000) == 0) cmd->error = MMC_ERR_BADCRC; } else { - pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode); + DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode); } #else cmd->error = MMC_ERR_BADCRC; @@ -282,14 +292,14 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) * data blocks as being in error. */ if (data->error == MMC_ERR_NONE) - data->bytes_xfered = data->blocks * data->blksz; + data->bytes_xfered = data->blocks << data->blksz_bits; else data->bytes_xfered = 0; pxamci_disable_irq(host, DATA_TRAN_DONE); host->data = NULL; - if (host->mrq->stop) { + if (host->mrq->stop && data->error == MMC_ERR_NONE) { pxamci_stop_clock(host); pxamci_start_cmd(host, host->mrq->stop, 0); } else { @@ -307,10 +317,12 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs) ireg = readl(host->base + MMC_I_REG); + DBG("PXAMCI: irq %08x\n", ireg); + if (ireg) { unsigned stat = readl(host->base + MMC_STAT); - pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat); + DBG("PXAMCI: stat %08x\n", stat); if (ireg & END_CMD_RES) handled |= pxamci_cmd_done(host, stat); @@ -364,6 +376,10 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct pxamci_host *host = mmc_priv(mmc); + DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n", + ios->clock, ios->power_mode, ios->vdd / 100, + ios->vdd % 100); + if (ios->clock) { unsigned int clk = CLOCKRATE / ios->clock; if (CLOCKRATE / clk > ios->clock) @@ -389,8 +405,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->cmdat |= CMDAT_INIT; } - pr_debug("PXAMCI: clkrt = %x cmdat = %x\n", - host->clkrt, host->cmdat); + DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n", + host->clkrt, host->cmdat); } static struct mmc_host_ops pxamci_ops = { @@ -422,7 +438,7 @@ static int pxamci_probe(struct platform_device *pdev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!r || irq < 0) + if (!r || irq == NO_IRQ) return -ENXIO; r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);