mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: atmel-mci: debugfs support mmc: Add per-card debugfs support mmc: Export internal host state through debugfs imxmmc: fix crash when no platform data is provided imxmmc: fix platform resources imxmmc: remove DEBUG definition mmc_spi: put signals to low power off fix
This commit is contained in:
commit
bdee6ac7d1
@ -12,3 +12,4 @@ mmc_core-y := core.o bus.o host.o \
|
||||
sdio.o sdio_ops.o sdio_bus.o \
|
||||
sdio_cis.o sdio_io.o sdio_irq.o
|
||||
|
||||
mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
|
@ -252,6 +252,10 @@ int mmc_add_card(struct mmc_card *card)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
mmc_add_card_debugfs(card);
|
||||
#endif
|
||||
|
||||
mmc_card_set_present(card);
|
||||
|
||||
return 0;
|
||||
@ -263,6 +267,10 @@ int mmc_add_card(struct mmc_card *card)
|
||||
*/
|
||||
void mmc_remove_card(struct mmc_card *card)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
mmc_remove_card_debugfs(card);
|
||||
#endif
|
||||
|
||||
if (mmc_card_present(card)) {
|
||||
if (mmc_host_is_spi(card->host)) {
|
||||
printk(KERN_INFO "%s: SPI card removed\n",
|
||||
|
@ -52,5 +52,12 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
|
||||
|
||||
extern int use_spi_crc;
|
||||
|
||||
/* Debugfs information for hosts and cards */
|
||||
void mmc_add_host_debugfs(struct mmc_host *host);
|
||||
void mmc_remove_host_debugfs(struct mmc_host *host);
|
||||
|
||||
void mmc_add_card_debugfs(struct mmc_card *card);
|
||||
void mmc_remove_card_debugfs(struct mmc_card *card);
|
||||
|
||||
#endif
|
||||
|
||||
|
225
drivers/mmc/core/debugfs.c
Normal file
225
drivers/mmc/core/debugfs.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Debugfs support for hosts and cards
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/stat.h>
|
||||
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "mmc_ops.h"
|
||||
|
||||
/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
|
||||
static int mmc_ios_show(struct seq_file *s, void *data)
|
||||
{
|
||||
static const char *vdd_str[] = {
|
||||
[8] = "2.0",
|
||||
[9] = "2.1",
|
||||
[10] = "2.2",
|
||||
[11] = "2.3",
|
||||
[12] = "2.4",
|
||||
[13] = "2.5",
|
||||
[14] = "2.6",
|
||||
[15] = "2.7",
|
||||
[16] = "2.8",
|
||||
[17] = "2.9",
|
||||
[18] = "3.0",
|
||||
[19] = "3.1",
|
||||
[20] = "3.2",
|
||||
[21] = "3.3",
|
||||
[22] = "3.4",
|
||||
[23] = "3.5",
|
||||
[24] = "3.6",
|
||||
};
|
||||
struct mmc_host *host = s->private;
|
||||
struct mmc_ios *ios = &host->ios;
|
||||
const char *str;
|
||||
|
||||
seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
|
||||
seq_printf(s, "vdd:\t\t%u ", ios->vdd);
|
||||
if ((1 << ios->vdd) & MMC_VDD_165_195)
|
||||
seq_printf(s, "(1.65 - 1.95 V)\n");
|
||||
else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1)
|
||||
&& vdd_str[ios->vdd] && vdd_str[ios->vdd + 1])
|
||||
seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd],
|
||||
vdd_str[ios->vdd + 1]);
|
||||
else
|
||||
seq_printf(s, "(invalid)\n");
|
||||
|
||||
switch (ios->bus_mode) {
|
||||
case MMC_BUSMODE_OPENDRAIN:
|
||||
str = "open drain";
|
||||
break;
|
||||
case MMC_BUSMODE_PUSHPULL:
|
||||
str = "push-pull";
|
||||
break;
|
||||
default:
|
||||
str = "invalid";
|
||||
break;
|
||||
}
|
||||
seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str);
|
||||
|
||||
switch (ios->chip_select) {
|
||||
case MMC_CS_DONTCARE:
|
||||
str = "don't care";
|
||||
break;
|
||||
case MMC_CS_HIGH:
|
||||
str = "active high";
|
||||
break;
|
||||
case MMC_CS_LOW:
|
||||
str = "active low";
|
||||
break;
|
||||
default:
|
||||
str = "invalid";
|
||||
break;
|
||||
}
|
||||
seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str);
|
||||
|
||||
switch (ios->power_mode) {
|
||||
case MMC_POWER_OFF:
|
||||
str = "off";
|
||||
break;
|
||||
case MMC_POWER_UP:
|
||||
str = "up";
|
||||
break;
|
||||
case MMC_POWER_ON:
|
||||
str = "on";
|
||||
break;
|
||||
default:
|
||||
str = "invalid";
|
||||
break;
|
||||
}
|
||||
seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str);
|
||||
seq_printf(s, "bus width:\t%u (%u bits)\n",
|
||||
ios->bus_width, 1 << ios->bus_width);
|
||||
|
||||
switch (ios->timing) {
|
||||
case MMC_TIMING_LEGACY:
|
||||
str = "legacy";
|
||||
break;
|
||||
case MMC_TIMING_MMC_HS:
|
||||
str = "mmc high-speed";
|
||||
break;
|
||||
case MMC_TIMING_SD_HS:
|
||||
str = "sd high-speed";
|
||||
break;
|
||||
default:
|
||||
str = "invalid";
|
||||
break;
|
||||
}
|
||||
seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_ios_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mmc_ios_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations mmc_ios_fops = {
|
||||
.open = mmc_ios_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void mmc_add_host_debugfs(struct mmc_host *host)
|
||||
{
|
||||
struct dentry *root;
|
||||
|
||||
root = debugfs_create_dir(mmc_hostname(host), NULL);
|
||||
if (IS_ERR(root))
|
||||
/* Don't complain -- debugfs just isn't enabled */
|
||||
return;
|
||||
if (!root)
|
||||
/* Complain -- debugfs is enabled, but it failed to
|
||||
* create the directory. */
|
||||
goto err_root;
|
||||
|
||||
host->debugfs_root = root;
|
||||
|
||||
if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
|
||||
goto err_ios;
|
||||
|
||||
return;
|
||||
|
||||
err_ios:
|
||||
debugfs_remove_recursive(root);
|
||||
host->debugfs_root = NULL;
|
||||
err_root:
|
||||
dev_err(&host->class_dev, "failed to initialize debugfs\n");
|
||||
}
|
||||
|
||||
void mmc_remove_host_debugfs(struct mmc_host *host)
|
||||
{
|
||||
debugfs_remove_recursive(host->debugfs_root);
|
||||
}
|
||||
|
||||
static int mmc_dbg_card_status_get(void *data, u64 *val)
|
||||
{
|
||||
struct mmc_card *card = data;
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
mmc_claim_host(card->host);
|
||||
|
||||
ret = mmc_send_status(data, &status);
|
||||
if (!ret)
|
||||
*val = status;
|
||||
|
||||
mmc_release_host(card->host);
|
||||
|
||||
return ret;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
|
||||
NULL, "%08llx\n");
|
||||
|
||||
void mmc_add_card_debugfs(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
struct dentry *root;
|
||||
|
||||
if (!host->debugfs_root)
|
||||
return;
|
||||
|
||||
root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
|
||||
if (IS_ERR(root))
|
||||
/* Don't complain -- debugfs just isn't enabled */
|
||||
return;
|
||||
if (!root)
|
||||
/* Complain -- debugfs is enabled, but it failed to
|
||||
* create the directory. */
|
||||
goto err;
|
||||
|
||||
card->debugfs_root = root;
|
||||
|
||||
if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
|
||||
goto err;
|
||||
|
||||
if (mmc_card_mmc(card) || mmc_card_sd(card))
|
||||
if (!debugfs_create_file("status", S_IRUSR, root, card,
|
||||
&mmc_dbg_card_status_fops))
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
debugfs_remove_recursive(root);
|
||||
card->debugfs_root = NULL;
|
||||
dev_err(&card->dev, "failed to initialize debugfs\n");
|
||||
}
|
||||
|
||||
void mmc_remove_card_debugfs(struct mmc_card *card)
|
||||
{
|
||||
debugfs_remove_recursive(card->debugfs_root);
|
||||
}
|
@ -127,6 +127,10 @@ int mmc_add_host(struct mmc_host *host)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
mmc_add_host_debugfs(host);
|
||||
#endif
|
||||
|
||||
mmc_start_host(host);
|
||||
|
||||
return 0;
|
||||
@ -146,6 +150,10 @@ void mmc_remove_host(struct mmc_host *host)
|
||||
{
|
||||
mmc_stop_host(host);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
mmc_remove_host_debugfs(host);
|
||||
#endif
|
||||
|
||||
device_del(&host->class_dev);
|
||||
|
||||
led_trigger_unregister_simple(host->led);
|
||||
|
@ -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)
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -16,6 +17,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/stat.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
@ -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;
|
||||
|
||||
|
@ -26,12 +26,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
@ -907,31 +901,12 @@ 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;
|
||||
|
||||
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");
|
||||
@ -962,13 +937,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);
|
||||
@ -995,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;
|
||||
@ -1047,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;
|
||||
@ -1073,7 +1053,7 @@ out:
|
||||
}
|
||||
if (mmc)
|
||||
mmc_free_host(mmc);
|
||||
release_resource(r);
|
||||
release_mem_region(r->start, 0x100);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1102,7 +1082,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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
||||
|
@ -111,6 +111,8 @@ struct mmc_card {
|
||||
unsigned num_info; /* number of info strings */
|
||||
const char **info; /* info strings */
|
||||
struct sdio_func_tuple *tuples; /* unknown common tuples */
|
||||
|
||||
struct dentry *debugfs_root;
|
||||
};
|
||||
|
||||
#define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC)
|
||||
|
@ -157,6 +157,8 @@ struct mmc_host {
|
||||
struct led_trigger *led; /* activity led */
|
||||
#endif
|
||||
|
||||
struct dentry *debugfs_root;
|
||||
|
||||
unsigned long private[0] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user