sdhci: allow led to be controlled freely
authorPierre Ossman <drzeus@drzeus.cx>
Mon, 17 Mar 2008 09:29:38 +0000 (10:29 +0100)
committerPierre Ossman <drzeus@drzeus.cx>
Fri, 18 Apr 2008 18:05:27 +0000 (20:05 +0200)
Hook up the controller LED to the LED subsystem, allowing more flexible
control than simply indicating an ongoing request.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index 71e020d..6250eb5 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"
@@ -252,6 +254,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 +789,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 +983,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 +1509,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 +1530,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 +1562,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);
index 3288e20..7fb02e1 100644 (file)
@@ -168,6 +168,10 @@ struct sdhci_host {
        struct sdhci_chip       *chip;
        struct mmc_host         *mmc;           /* MMC structure */
 
+#ifdef CONFIG_LEDS_CLASS
+       struct led_classdev     led;            /* LED control */
+#endif
+
        spinlock_t              lock;           /* Mutex */
 
        int                     flags;          /* Host attributes */