]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mmc/host/sdhci.c
sched: print module list in the "scheduling while atomic" warning
[linux-2.6-omap-h63xx.git] / drivers / mmc / host / sdhci.c
index 71e020d6718db2329f2154a2b90bb86fbd7ef06f..07c2048b230ba0ec37d8ca3d140921162ae96253 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 
+#include <linux/leds.h>
+
 #include <linux/mmc/host.h>
 
 #include "sdhci.h"
@@ -39,7 +41,7 @@ static unsigned int debug_quirks = 0;
 #define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
 /* Controller has bad caps bits, but really supports DMA */
 #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)
 /* Controller doesn't like clearing the power reg before a change */
 #define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
@@ -67,12 +69,20 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
        {
                .vendor         = PCI_VENDOR_ID_RICOH,
                .device         = PCI_DEVICE_ID_RICOH_R5C822,
-               .subvendor      = PCI_ANY_ID,
+               .subvendor      = PCI_VENDOR_ID_SAMSUNG,
                .subdevice      = PCI_ANY_ID,
                .driver_data    = SDHCI_QUIRK_FORCE_DMA |
                                  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,
                .device         = PCI_DEVICE_ID_TI_XX21_XX11_SD,
@@ -252,6 +262,24 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
        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                                                            *
@@ -769,7 +797,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        WARN_ON(host->mrq != NULL);
 
+#ifndef CONFIG_LEDS_CLASS
        sdhci_activate_led(host);
+#endif
 
        host->mrq = mrq;
 
@@ -961,7 +991,9 @@ static void sdhci_tasklet_finish(unsigned long param)
        host->cmd = NULL;
        host->data = NULL;
 
+#ifndef CONFIG_LEDS_CLASS
        sdhci_deactivate_led(host);
+#endif
 
        mmiowb();
        spin_unlock_irqrestore(&host->lock, flags);
@@ -1485,6 +1517,17 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        sdhci_dumpregs(host);
 #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();
 
        mmc_add_host(mmc);
@@ -1495,6 +1538,11 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        return 0;
 
+#ifdef CONFIG_LEDS_CLASS
+reset:
+       sdhci_reset(host, SDHCI_RESET_ALL);
+       free_irq(host->irq, host);
+#endif
 untasklet:
        tasklet_kill(&host->card_tasklet);
        tasklet_kill(&host->finish_tasklet);
@@ -1522,6 +1570,10 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
 
        mmc_remove_host(mmc);
 
+#ifdef CONFIG_LEDS_CLASS
+       led_classdev_unregister(&host->led);
+#endif
+
        sdhci_reset(host, SDHCI_RESET_ALL);
 
        free_irq(host->irq, host);