Commit 135cedad authored by Linus Torvalds's avatar Linus Torvalds

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: (26 commits)
  mmc: sdio_ops.c should #include "sdio_ops.h"
  mmc: proper prototypes for mmc_attach_*()
  mmc: make __mmc_release_bus() static
  sdhci: improve no card, no reset quirk
  MMC: OMAP: Do not busy wait for end of command for ever
  MMC: OMAP: Start new commands from work queue instead of irq
  MMC: OMAP: Lazy clock shutdown
  MMC: OMAP: Move failing command abortion to workqueue
  MMC: OMAP: Use tasklet instead of workqueue for cover switch notification
  MMC: OMAP: Check the get_cover_state function pointer if not set
  MMC: OMAP: Using setup_timer instead of init_timer
  MMC: OMAP: Abort stuck commands
  MMC: OMAP: General cleanup for MMC multislot support
  MMC: OMAP: Power functions modified to MMC multislot support
  MMC: OMAP: Fix timeout calculation for MMC multislot support
  MMC: OMAP: New release dma and abort xfer functions
  MMC: OMAP: Add back cover switch support
  MMC: OMAP: Introduce new multislot structure and change driver to use it
  MMC: OMAP: Remove cover switch handling to allow adding multislot support
  MMC: OMAP: Fix the BYTEBLOCK capability removal
  ...
parents 8a322726 e70aa3fa
...@@ -35,10 +35,6 @@ ...@@ -35,10 +35,6 @@
#include "sd_ops.h" #include "sd_ops.h"
#include "sdio_ops.h" #include "sdio_ops.h"
extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
extern int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
static struct workqueue_struct *workqueue; static struct workqueue_struct *workqueue;
/* /*
...@@ -516,7 +512,7 @@ static void mmc_power_off(struct mmc_host *host) ...@@ -516,7 +512,7 @@ static void mmc_power_off(struct mmc_host *host)
/* /*
* Cleanup when the last reference to the bus operator is dropped. * Cleanup when the last reference to the bus operator is dropped.
*/ */
void __mmc_release_bus(struct mmc_host *host) static void __mmc_release_bus(struct mmc_host *host)
{ {
BUG_ON(!host); BUG_ON(!host);
BUG_ON(host->bus_refs); BUG_ON(host->bus_refs);
......
...@@ -46,6 +46,10 @@ void mmc_rescan(struct work_struct *work); ...@@ -46,6 +46,10 @@ void mmc_rescan(struct work_struct *work);
void mmc_start_host(struct mmc_host *host); void mmc_start_host(struct mmc_host *host);
void mmc_stop_host(struct mmc_host *host); void mmc_stop_host(struct mmc_host *host);
int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
int mmc_attach_sd(struct mmc_host *host, u32 ocr);
int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
extern int use_spi_crc; extern int use_spi_crc;
#endif #endif
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* linux/drivers/mmc/core/host.c * linux/drivers/mmc/core/host.c
* *
* Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright (C) 2007 Pierre Ossman * Copyright (C) 2007-2008 Pierre Ossman
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -57,12 +57,25 @@ static DEFINE_SPINLOCK(mmc_host_lock); ...@@ -57,12 +57,25 @@ static DEFINE_SPINLOCK(mmc_host_lock);
*/ */
struct mmc_host *mmc_alloc_host(int extra, struct device *dev) struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{ {
int err;
struct mmc_host *host; struct mmc_host *host;
if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
return NULL;
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host) if (!host)
return NULL; return NULL;
spin_lock(&mmc_host_lock);
err = idr_get_new(&mmc_host_idr, host, &host->index);
spin_unlock(&mmc_host_lock);
if (err)
goto free;
snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
"mmc%d", host->index);
host->parent = dev; host->parent = dev;
host->class_dev.parent = dev; host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class; host->class_dev.class = &mmc_host_class;
...@@ -85,6 +98,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -85,6 +98,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
host->max_blk_count = PAGE_CACHE_SIZE / 512; host->max_blk_count = PAGE_CACHE_SIZE / 512;
return host; return host;
free:
kfree(host);
return NULL;
} }
EXPORT_SYMBOL(mmc_alloc_host); EXPORT_SYMBOL(mmc_alloc_host);
...@@ -104,18 +121,6 @@ int mmc_add_host(struct mmc_host *host) ...@@ -104,18 +121,6 @@ int mmc_add_host(struct mmc_host *host)
WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
!host->ops->enable_sdio_irq); !host->ops->enable_sdio_irq);
if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
return -ENOMEM;
spin_lock(&mmc_host_lock);
err = idr_get_new(&mmc_host_idr, host, &host->index);
spin_unlock(&mmc_host_lock);
if (err)
return err;
snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
"mmc%d", host->index);
led_trigger_register_simple(host->class_dev.bus_id, &host->led); led_trigger_register_simple(host->class_dev.bus_id, &host->led);
err = device_add(&host->class_dev); err = device_add(&host->class_dev);
...@@ -144,10 +149,6 @@ void mmc_remove_host(struct mmc_host *host) ...@@ -144,10 +149,6 @@ void mmc_remove_host(struct mmc_host *host)
device_del(&host->class_dev); device_del(&host->class_dev);
led_trigger_unregister_simple(host->led); led_trigger_unregister_simple(host->led);
spin_lock(&mmc_host_lock);
idr_remove(&mmc_host_idr, host->index);
spin_unlock(&mmc_host_lock);
} }
EXPORT_SYMBOL(mmc_remove_host); EXPORT_SYMBOL(mmc_remove_host);
...@@ -160,6 +161,10 @@ EXPORT_SYMBOL(mmc_remove_host); ...@@ -160,6 +161,10 @@ EXPORT_SYMBOL(mmc_remove_host);
*/ */
void mmc_free_host(struct mmc_host *host) void mmc_free_host(struct mmc_host *host)
{ {
spin_lock(&mmc_host_lock);
idr_remove(&mmc_host_idr, host->index);
spin_unlock(&mmc_host_lock);
put_device(&host->class_dev); put_device(&host->class_dev);
} }
......
...@@ -128,12 +128,12 @@ static int sdio_irq_thread(void *_host) ...@@ -128,12 +128,12 @@ static int sdio_irq_thread(void *_host)
} }
} }
set_task_state(current, TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (host->caps & MMC_CAP_SDIO_IRQ) if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 1); host->ops->enable_sdio_irq(host, 1);
if (!kthread_should_stop()) if (!kthread_should_stop())
schedule_timeout(period); schedule_timeout(period);
set_task_state(current, TASK_RUNNING); set_current_state(TASK_RUNNING);
} while (!kthread_should_stop()); } while (!kthread_should_stop());
if (host->caps & MMC_CAP_SDIO_IRQ) if (host->caps & MMC_CAP_SDIO_IRQ)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/mmc/sdio.h> #include <linux/mmc/sdio.h>
#include "core.h" #include "core.h"
#include "sdio_ops.h"
int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
{ {
......
This diff is collapsed.
/* /*
* linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
* *
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/leds.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include "sdhci.h" #include "sdhci.h"
...@@ -30,10 +32,6 @@ ...@@ -30,10 +32,6 @@
static unsigned int debug_quirks = 0; static unsigned int debug_quirks = 0;
/* For multi controllers in one platform case */
static u16 chip_index = 0;
static spinlock_t index_lock;
/* /*
* Different quirks to handle when the hardware deviates from a strict * Different quirks to handle when the hardware deviates from a strict
* interpretation of the SDHCI specification. * interpretation of the SDHCI specification.
...@@ -43,7 +41,7 @@ static spinlock_t index_lock; ...@@ -43,7 +41,7 @@ static spinlock_t index_lock;
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
/* Controller has bad caps bits, but really supports DMA */ /* Controller has bad caps bits, but really supports DMA */
#define SDHCI_QUIRK_FORCE_DMA (1<<1) #define SDHCI_QUIRK_FORCE_DMA (1<<1)
/* Controller doesn't like some resets when there is no card inserted. */ /* Controller doesn't like to be reset when there is no card inserted. */
#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
/* Controller doesn't like clearing the power reg before a change */ /* Controller doesn't like clearing the power reg before a change */
#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
...@@ -71,12 +69,20 @@ static const struct pci_device_id pci_ids[] __devinitdata = { ...@@ -71,12 +69,20 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
{ {
.vendor = PCI_VENDOR_ID_RICOH, .vendor = PCI_VENDOR_ID_RICOH,
.device = PCI_DEVICE_ID_RICOH_R5C822, .device = PCI_DEVICE_ID_RICOH_R5C822,
.subvendor = PCI_ANY_ID, .subvendor = PCI_VENDOR_ID_SAMSUNG,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = SDHCI_QUIRK_FORCE_DMA | .driver_data = SDHCI_QUIRK_FORCE_DMA |
SDHCI_QUIRK_NO_CARD_NO_RESET, SDHCI_QUIRK_NO_CARD_NO_RESET,
}, },
{
.vendor = PCI_VENDOR_ID_RICOH,
.device = PCI_DEVICE_ID_RICOH_R5C822,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = SDHCI_QUIRK_FORCE_DMA,
},
{ {
.vendor = PCI_VENDOR_ID_TI, .vendor = PCI_VENDOR_ID_TI,
.device = PCI_DEVICE_ID_TI_XX21_XX11_SD, .device = PCI_DEVICE_ID_TI_XX21_XX11_SD,
...@@ -256,6 +262,24 @@ static void sdhci_deactivate_led(struct sdhci_host *host) ...@@ -256,6 +262,24 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
} }
#ifdef CONFIG_LEDS_CLASS
static void sdhci_led_control(struct led_classdev *led,
enum led_brightness brightness)
{
struct sdhci_host *host = container_of(led, struct sdhci_host, led);
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
if (brightness == LED_OFF)
sdhci_deactivate_led(host);
else
sdhci_activate_led(host);
spin_unlock_irqrestore(&host->lock, flags);
}
#endif
/*****************************************************************************\ /*****************************************************************************\
* * * *
* Core functions * * Core functions *
...@@ -773,7 +797,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) ...@@ -773,7 +797,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
WARN_ON(host->mrq != NULL); WARN_ON(host->mrq != NULL);
#ifndef CONFIG_LEDS_CLASS
sdhci_activate_led(host); sdhci_activate_led(host);
#endif
host->mrq = mrq; host->mrq = mrq;
...@@ -965,7 +991,9 @@ static void sdhci_tasklet_finish(unsigned long param) ...@@ -965,7 +991,9 @@ static void sdhci_tasklet_finish(unsigned long param)
host->cmd = NULL; host->cmd = NULL;
host->data = NULL; host->data = NULL;
#ifndef CONFIG_LEDS_CLASS
sdhci_deactivate_led(host); sdhci_deactivate_led(host);
#endif
mmiowb(); mmiowb();
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
...@@ -1105,7 +1133,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) ...@@ -1105,7 +1133,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
goto out; goto out;
} }
DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask); DBG("*** %s got interrupt: 0x%08x\n",
mmc_hostname(host->mmc), intmask);
if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
...@@ -1235,7 +1264,7 @@ static int sdhci_resume (struct pci_dev *pdev) ...@@ -1235,7 +1264,7 @@ static int sdhci_resume (struct pci_dev *pdev)
if (chip->hosts[i]->flags & SDHCI_USE_DMA) if (chip->hosts[i]->flags & SDHCI_USE_DMA)
pci_set_master(pdev); pci_set_master(pdev);
ret = request_irq(chip->hosts[i]->irq, sdhci_irq, ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
IRQF_SHARED, chip->hosts[i]->slot_descr, IRQF_SHARED, mmc_hostname(chip->hosts[i]->mmc),
chip->hosts[i]); chip->hosts[i]);
if (ret) if (ret)
return ret; return ret;
...@@ -1324,9 +1353,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1324,9 +1353,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq); DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot); ret = pci_request_region(pdev, host->bar, mmc_hostname(mmc));
ret = pci_request_region(pdev, host->bar, host->slot_descr);
if (ret) if (ret)
goto free; goto free;
...@@ -1343,7 +1370,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1343,7 +1370,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
if (version > 1) { if (version > 1) {
printk(KERN_ERR "%s: Unknown controller version (%d). " printk(KERN_ERR "%s: Unknown controller version (%d). "
"You may experience problems.\n", host->slot_descr, "You may experience problems.\n", mmc_hostname(mmc),
version); version);
} }
...@@ -1366,13 +1393,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1366,13 +1393,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
(host->flags & SDHCI_USE_DMA)) { (host->flags & SDHCI_USE_DMA)) {
printk(KERN_WARNING "%s: Will use DMA " printk(KERN_WARNING "%s: Will use DMA "
"mode even though HW doesn't fully " "mode even though HW doesn't fully "
"claim to support it.\n", host->slot_descr); "claim to support it.\n", mmc_hostname(mmc));
} }
if (host->flags & SDHCI_USE_DMA) { if (host->flags & SDHCI_USE_DMA) {
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "%s: No suitable DMA available. " printk(KERN_WARNING "%s: No suitable DMA available. "
"Falling back to PIO.\n", host->slot_descr); "Falling back to PIO.\n", mmc_hostname(mmc));
host->flags &= ~SDHCI_USE_DMA; host->flags &= ~SDHCI_USE_DMA;
} }
} }
...@@ -1386,7 +1413,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1386,7 +1413,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
if (host->max_clk == 0) { if (host->max_clk == 0) {
printk(KERN_ERR "%s: Hardware doesn't specify base clock " printk(KERN_ERR "%s: Hardware doesn't specify base clock "
"frequency.\n", host->slot_descr); "frequency.\n", mmc_hostname(mmc));
ret = -ENODEV; ret = -ENODEV;
goto unmap; goto unmap;
} }
...@@ -1396,7 +1423,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1396,7 +1423,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
if (host->timeout_clk == 0) { if (host->timeout_clk == 0) {
printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
"frequency.\n", host->slot_descr); "frequency.\n", mmc_hostname(mmc));
ret = -ENODEV; ret = -ENODEV;
goto unmap; goto unmap;
} }
...@@ -1424,7 +1451,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1424,7 +1451,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
if (mmc->ocr_avail == 0) { if (mmc->ocr_avail == 0) {
printk(KERN_ERR "%s: Hardware doesn't report any " printk(KERN_ERR "%s: Hardware doesn't report any "
"support voltages.\n", host->slot_descr); "support voltages.\n", mmc_hostname(mmc));
ret = -ENODEV; ret = -ENODEV;
goto unmap; goto unmap;
} }
...@@ -1458,8 +1485,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1458,8 +1485,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
*/ */
mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
if (mmc->max_blk_size >= 3) { if (mmc->max_blk_size >= 3) {
printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n", printk(KERN_WARNING "%s: Invalid maximum block size, "
host->slot_descr); "assuming 512 bytes\n", mmc_hostname(mmc));
mmc->max_blk_size = 512; mmc->max_blk_size = 512;
} else } else
mmc->max_blk_size = 512 << mmc->max_blk_size; mmc->max_blk_size = 512 << mmc->max_blk_size;
...@@ -1480,7 +1507,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1480,7 +1507,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
host->slot_descr, host); mmc_hostname(mmc), host);
if (ret) if (ret)
goto untasklet; goto untasklet;
...@@ -1490,16 +1517,32 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) ...@@ -1490,16 +1517,32 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
sdhci_dumpregs(host); sdhci_dumpregs(host);
#endif #endif
#ifdef CONFIG_LEDS_CLASS
host->led.name = mmc_hostname(mmc);
host->led.brightness = LED_OFF;
host->led.default_trigger = mmc_hostname(mmc);
host->led.brightness_set = sdhci_led_control;
ret = led_classdev_register(&pdev->dev, &host->led);
if (ret)
goto reset;
#endif
mmiowb(); mmiowb();
mmc_add_host(mmc); mmc_add_host(mmc);
printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc), printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n",
host->addr, host->irq, mmc_hostname(mmc), host->addr, host->irq,
(host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
return 0; return 0;
#ifdef CONFIG_LEDS_CLASS
reset:
sdhci_reset(host, SDHCI_RESET_ALL);
free_irq(host->irq, host);
#endif
untasklet: untasklet:
tasklet_kill(&host->card_tasklet); tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->finish_tasklet); tasklet_kill(&host->finish_tasklet);
...@@ -1527,6 +1570,10 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot) ...@@ -1527,6 +1570,10 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
mmc_remove_host(mmc); mmc_remove_host(mmc);
#ifdef CONFIG_LEDS_CLASS
led_classdev_unregister(&host->led);
#endif
sdhci_reset(host, SDHCI_RESET_ALL); sdhci_reset(host, SDHCI_RESET_ALL);
free_irq(host->irq, host); free_irq(host->irq, host);
...@@ -1589,11 +1636,6 @@ static int __devinit sdhci_probe(struct pci_dev *pdev, ...@@ -1589,11 +1636,6 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
chip->num_slots = slots; chip->num_slots = slots;
pci_set_drvdata(pdev, chip); pci_set_drvdata(pdev, chip);
/* Add for multi controller case */
spin_lock(&index_lock);
chip->index = chip_index++;
spin_unlock(&index_lock);
for (i = 0;i < slots;i++) { for (i = 0;i < slots;i++) {
ret = sdhci_probe_slot(pdev, i); ret = sdhci_probe_slot(pdev, i);
if (ret) { if (ret) {
...@@ -1654,8 +1696,6 @@ static int __init sdhci_drv_init(void) ...@@ -1654,8 +1696,6 @@ static int __init sdhci_drv_init(void)
": Secure Digital Host Controller Interface driver\n"); ": Secure Digital Host Controller Interface driver\n");
printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
spin_lock_init(&index_lock);
return pci_register_driver(&sdhci_driver); return pci_register_driver(&sdhci_driver);
} }
......
/* /*
* linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
* *
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -168,6 +168,10 @@ struct sdhci_host { ...@@ -168,6 +168,10 @@ struct sdhci_host {
struct sdhci_chip *chip; struct sdhci_chip *chip;
struct mmc_host *mmc; /* MMC structure */ struct mmc_host *mmc; /* MMC structure */
#ifdef CONFIG_LEDS_CLASS
struct led_classdev led; /* LED control */
#endif
spinlock_t lock; /* Mutex */ spinlock_t lock; /* Mutex */
int flags; /* Host attributes */ int flags; /* Host attributes */
...@@ -190,8 +194,6 @@ struct sdhci_host { ...@@ -190,8 +194,6 @@ struct sdhci_host {
int offset; /* Offset into current sg */ int offset; /* Offset into current sg */
int remain; /* Bytes left in current */ int remain; /* Bytes left in current */
char slot_descr[20]; /* Name for reservations */
int irq; /* Device IRQ */ int irq; /* Device IRQ */
int bar; /* PCI BAR index */ int bar; /* PCI BAR index */
unsigned long addr; /* Bus address */ unsigned long addr; /* Bus address */
...@@ -208,7 +210,6 @@ struct sdhci_chip { ...@@ -208,7 +210,6 @@ struct sdhci_chip {
unsigned long quirks; unsigned long quirks;
int index; /* Index for chip0, chip1 ...*/
int num_slots; /* Slots on controller */ int num_slots; /* Slots on controller */
struct sdhci_host *hosts[0]; /* Pointers to hosts */ struct sdhci_host *hosts[0]; /* Pointers to hosts */
}; };
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#define OMAP_MMC_MAX_SLOTS 2 #define OMAP_MMC_MAX_SLOTS 2
struct omap_mmc_platform_data { struct omap_mmc_platform_data {
struct omap_mmc_conf conf;
unsigned enabled:1; unsigned enabled:1;
/* number of slots on board */ /* number of slots on board */
unsigned nr_slots:2; unsigned nr_slots:2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment