From 1685a03e98b7e9b83e0aa692c1cc470b3aa37597 Mon Sep 17 00:00:00 2001 From: Jan Nikitenko Date: Thu, 24 Jul 2008 01:27:07 +0200 Subject: mmc_spi: put signals to low power off fix The original intention was to write a zero byte to mmc to force spi signals to low when doing power off. Somehow the spi_w8r8 call got there so a read followed the write of single zero byte. This patch changes that to simple write of zero byte without the following read. This way the power off is more reliable and completely sufficient. Signed-off-by: Jan Nikitenko Signed-off-by: David Brownell Signed-off-by: Pierre Ossman --- drivers/mmc/host/mmc_spi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 41cc63360e4..7503b81374e 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1076,6 +1076,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) */ if (canpower && ios->power_mode == MMC_POWER_OFF) { int mres; + u8 nullbyte = 0; host->spi->mode &= ~(SPI_CPOL|SPI_CPHA); mres = spi_setup(host->spi); @@ -1083,7 +1084,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) dev_dbg(&host->spi->dev, "switch to SPI mode 0 failed\n"); - if (spi_w8r8(host->spi, 0x00) < 0) + if (spi_write(host->spi, &nullbyte, 1) < 0) dev_dbg(&host->spi->dev, "put spi signals to low failed\n"); -- cgit v1.2.3 From 322069c9df1fd4da269b2a57d78f753684962523 Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 9 Jul 2008 16:03:13 +0300 Subject: imxmmc: remove DEBUG definition Removed DEBUG #define #undef, because module is automaticaly compiled with -DDEBUG when CONFIG_MMC_DEBUG is defined. Currently it just generates compiler warning about redefinition. Signed-off-by: Paulius Zaleckas Acked-by: Pavel Pisa Signed-off-by: Pierre Ossman --- drivers/mmc/host/imxmmc.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 5e880c0f134..77493339303 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -26,12 +26,6 @@ * */ -#ifdef CONFIG_MMC_DEBUG -#define DEBUG -#else -#undef DEBUG -#endif - #include #include #include -- cgit v1.2.3 From 5fc63dfba8a016caf832572aeaa90abef82f0ba0 Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 9 Jul 2008 16:03:17 +0300 Subject: imxmmc: fix platform resources Fixup platform resources handling. Signed-off-by: Paulius Zaleckas Acked-by: Pavel Pisa Signed-off-by: Pierre Ossman --- drivers/mmc/host/imxmmc.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 77493339303..9cda12fba9a 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -901,26 +901,6 @@ static const struct mmc_host_ops imxmci_ops = { .get_ro = imxmci_get_ro, }; -static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr) -{ - int i; - - for (i = 0; i < dev->num_resources; i++) - if (dev->resource[i].flags == mask && nr-- == 0) - return &dev->resource[i]; - return NULL; -} - -static int platform_device_irq(struct platform_device *dev, int nr) -{ - int i; - - for (i = 0; i < dev->num_resources; i++) - if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0) - return dev->resource[i].start; - return NO_IRQ; -} - static void imxmci_check_status(unsigned long data) { struct imxmci_host *host = (struct imxmci_host *)data; @@ -956,13 +936,12 @@ static int imxmci_probe(struct platform_device *pdev) printk(KERN_INFO "i.MX mmc driver\n"); - r = platform_device_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_device_irq(pdev, 0); - if (!r || irq == NO_IRQ) + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!r || irq < 0) return -ENXIO; - r = request_mem_region(r->start, 0x100, "IMXMCI"); - if (!r) + if (!request_mem_region(r->start, 0x100, pdev->name)) return -EBUSY; mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev); @@ -1067,7 +1046,7 @@ out: } if (mmc) mmc_free_host(mmc); - release_resource(r); + release_mem_region(r->start, 0x100); return ret; } @@ -1096,7 +1075,7 @@ static int imxmci_remove(struct platform_device *pdev) clk_disable(host->clk); clk_put(host->clk); - release_resource(host->res); + release_mem_region(host->res->start, 0x100); mmc_free_host(mmc); } -- cgit v1.2.3 From c5d5e9c40fc6cabedd5fdc7441e6e9d37f5c9bba Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 9 Jul 2008 16:03:20 +0300 Subject: imxmmc: fix crash when no platform data is provided Don't crash if no platform data is provided. In this case assume that card is present. Signed-off-by: Paulius Zaleckas Acked-by: Pavel Pisa Signed-off-by: Pierre Ossman --- drivers/mmc/host/imxmmc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 9cda12fba9a..f61406da65d 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -905,7 +905,8 @@ static void imxmci_check_status(unsigned long data) { struct imxmci_host *host = (struct imxmci_host *)data; - if( host->pdata->card_present(mmc_dev(host->mmc)) != host->present ) { + if (host->pdata && host->pdata->card_present && + host->pdata->card_present(mmc_dev(host->mmc)) != host->present) { host->present ^= 1; dev_info(mmc_dev(host->mmc), "card %s\n", host->present ? "inserted" : "removed"); @@ -968,6 +969,8 @@ static int imxmci_probe(struct platform_device *pdev) host->mmc = mmc; host->dma_allocated = 0; host->pdata = pdev->dev.platform_data; + if (!host->pdata) + dev_warn(&pdev->dev, "No platform data provided!\n"); spin_lock_init(&host->lock); host->res = r; @@ -1020,7 +1023,11 @@ static int imxmci_probe(struct platform_device *pdev) if (ret) goto out; - host->present = host->pdata->card_present(mmc_dev(mmc)); + if (host->pdata && host->pdata->card_present) + host->present = host->pdata->card_present(mmc_dev(mmc)); + else /* if there is no way to detect assume that card is present */ + host->present = 1; + init_timer(&host->timer); host->timer.data = (unsigned long)host; host->timer.function = imxmci_check_status; -- cgit v1.2.3 From deec9ae31e6079551ce9260d29a4cf83e5b19a83 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Thu, 24 Jul 2008 14:18:59 +0200 Subject: atmel-mci: debugfs support Create additional files under the host's debugfs directory containing additional host-specific debug information. Signed-off-by: Haavard Skinnemoen Signed-off-by: Pierre Ossman --- drivers/mmc/host/atmel-mci-regs.h | 2 + drivers/mmc/host/atmel-mci.c | 189 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) (limited to 'drivers/mmc/host') diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index a9a5657706c..26bd80e6503 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h @@ -82,6 +82,8 @@ # define MCI_OVRE ( 1 << 30) /* RX Overrun Error */ # define MCI_UNRE ( 1 << 31) /* TX Underrun Error */ +#define MCI_REGS_SIZE 0x100 + /* Register access macros */ #define mci_readl(port,reg) \ __raw_readl((port)->regs + MCI_##reg) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index cce873c5a14..b68381f7bfd 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -16,6 +17,8 @@ #include #include #include +#include +#include #include @@ -88,6 +91,188 @@ struct atmel_mci { #define atmci_clear_pending(host, event) \ clear_bit(event, &host->pending_events) +/* + * The debugfs stuff below is mostly optimized away when + * CONFIG_DEBUG_FS is not set. + */ +static int atmci_req_show(struct seq_file *s, void *v) +{ + struct atmel_mci *host = s->private; + struct mmc_request *mrq = host->mrq; + struct mmc_command *cmd; + struct mmc_command *stop; + struct mmc_data *data; + + /* Make sure we get a consistent snapshot */ + spin_lock_irq(&host->mmc->lock); + + if (mrq) { + cmd = mrq->cmd; + data = mrq->data; + stop = mrq->stop; + + if (cmd) + seq_printf(s, + "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", + cmd->opcode, cmd->arg, cmd->flags, + cmd->resp[0], cmd->resp[1], cmd->resp[2], + cmd->resp[2], cmd->error); + if (data) + seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", + data->bytes_xfered, data->blocks, + data->blksz, data->flags, data->error); + if (stop) + seq_printf(s, + "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", + stop->opcode, stop->arg, stop->flags, + stop->resp[0], stop->resp[1], stop->resp[2], + stop->resp[2], stop->error); + } + + spin_unlock_irq(&host->mmc->lock); + + return 0; +} + +static int atmci_req_open(struct inode *inode, struct file *file) +{ + return single_open(file, atmci_req_show, inode->i_private); +} + +static const struct file_operations atmci_req_fops = { + .owner = THIS_MODULE, + .open = atmci_req_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void atmci_show_status_reg(struct seq_file *s, + const char *regname, u32 value) +{ + static const char *sr_bit[] = { + [0] = "CMDRDY", + [1] = "RXRDY", + [2] = "TXRDY", + [3] = "BLKE", + [4] = "DTIP", + [5] = "NOTBUSY", + [8] = "SDIOIRQA", + [9] = "SDIOIRQB", + [16] = "RINDE", + [17] = "RDIRE", + [18] = "RCRCE", + [19] = "RENDE", + [20] = "RTOE", + [21] = "DCRCE", + [22] = "DTOE", + [30] = "OVRE", + [31] = "UNRE", + }; + unsigned int i; + + seq_printf(s, "%s:\t0x%08x", regname, value); + for (i = 0; i < ARRAY_SIZE(sr_bit); i++) { + if (value & (1 << i)) { + if (sr_bit[i]) + seq_printf(s, " %s", sr_bit[i]); + else + seq_puts(s, " UNKNOWN"); + } + } + seq_putc(s, '\n'); +} + +static int atmci_regs_show(struct seq_file *s, void *v) +{ + struct atmel_mci *host = s->private; + u32 *buf; + + buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* Grab a more or less consistent snapshot */ + spin_lock_irq(&host->mmc->lock); + memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); + spin_unlock_irq(&host->mmc->lock); + + seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", + buf[MCI_MR / 4], + buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "", + buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "", + buf[MCI_MR / 4] & 0xff); + seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]); + seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]); + seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]); + seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n", + buf[MCI_BLKR / 4], + buf[MCI_BLKR / 4] & 0xffff, + (buf[MCI_BLKR / 4] >> 16) & 0xffff); + + /* Don't read RSPR and RDR; it will consume the data there */ + + atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); + atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); + + return 0; +} + +static int atmci_regs_open(struct inode *inode, struct file *file) +{ + return single_open(file, atmci_regs_show, inode->i_private); +} + +static const struct file_operations atmci_regs_fops = { + .owner = THIS_MODULE, + .open = atmci_regs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void atmci_init_debugfs(struct atmel_mci *host) +{ + struct mmc_host *mmc; + struct dentry *root; + struct dentry *node; + struct resource *res; + + mmc = host->mmc; + root = mmc->debugfs_root; + if (!root) + return; + + node = debugfs_create_file("regs", S_IRUSR, root, host, + &atmci_regs_fops); + if (IS_ERR(node)) + return; + if (!node) + goto err; + + res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); + node->d_inode->i_size = res->end - res->start + 1; + + node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops); + if (!node) + goto err; + + node = debugfs_create_x32("pending_events", S_IRUSR, root, + (u32 *)&host->pending_events); + if (!node) + goto err; + + node = debugfs_create_x32("completed_events", S_IRUSR, root, + (u32 *)&host->completed_events); + if (!node) + goto err; + + return; + +err: + dev_err(&host->pdev->dev, + "failed to initialize debugfs for controller\n"); +} static void atmci_enable(struct atmel_mci *host) { @@ -905,6 +1090,8 @@ static int __init atmci_probe(struct platform_device *pdev) "Atmel MCI controller at 0x%08lx irq %d\n", host->mapbase, irq); + atmci_init_debugfs(host); + return 0; err_request_irq: @@ -923,6 +1110,8 @@ static int __exit atmci_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); if (host) { + /* Debugfs stuff is cleaned up by mmc core */ + if (host->detect_pin >= 0) { int pin = host->detect_pin; -- cgit v1.2.3