[PATCH] SMU LED driver
Michael Hanselmann
linux-kernel at hansmi.ch
Mon Jan 15 11:26:17 EST 2007
On Mon, Jan 15, 2007 at 08:48:59AM +1100, Benjamin Herrenschmidt wrote:
> No, you have to deal with it in the unload. You can for example wait for
> the SMU request to complete after setting wanted to -1, that sort of
> thing.
Done in the patch below.
> Also, use spin_lock_irqsave/restore or you'll deadlock if the SMU
> completion interrupt happens to interrupt your request function.
Okay, didn't notice the done function is called in interrupt context.
Signed-off-by: Michael Hanselmann <linux-kernel at hansmi.ch>
---
diff -Nrup --exclude-from linux-exclude-from linux-2.6.19.1.orig/drivers/macintosh/Kconfig linux-2.6.19.1/drivers/macintosh/Kconfig
--- linux-2.6.19.1.orig/drivers/macintosh/Kconfig 2007-01-14 12:58:25.000000000 +0100
+++ linux-2.6.19.1/drivers/macintosh/Kconfig 2007-01-15 00:57:16.000000000 +0100
@@ -107,6 +107,15 @@ config PMAC_SMU
on the "SMU" system control chip which replaces the old PMU.
If you don't know, say Y.
+config PMAC_SMU_LED
+ tristate "Support for the PowerMac front LED"
+ depends on PMAC_SMU
+ select NEW_LEDS
+ select LEDS_CLASS
+ help
+ Support the front LED on PowerMacs as a generic LED that can be
+ triggered by any of the supported triggers.
+
config PMAC_APM_EMU
tristate "APM emulation"
depends on PPC_PMAC && PPC32 && PM && ADB_PMU
diff -Nrup --exclude-from linux-exclude-from linux-2.6.19.1.orig/drivers/macintosh/Makefile linux-2.6.19.1/drivers/macintosh/Makefile
--- linux-2.6.19.1.orig/drivers/macintosh/Makefile 2007-01-14 12:58:25.000000000 +0100
+++ linux-2.6.19.1/drivers/macintosh/Makefile 2007-01-15 00:57:16.000000000 +0100
@@ -17,6 +17,7 @@ obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-
obj-$(CONFIG_ADB_CUDA) += via-cuda.o
obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o
obj-$(CONFIG_PMAC_SMU) += smu.o
+obj-$(CONFIG_PMAC_SMU_LED) += smu-led.o
obj-$(CONFIG_ADB) += adb.o
obj-$(CONFIG_ADB_MACII) += via-macii.o
diff -Nrup --exclude-from linux-exclude-from linux-2.6.19.1.orig/drivers/macintosh/smu-led.c linux-2.6.19.1/drivers/macintosh/smu-led.c
--- linux-2.6.19.1.orig/drivers/macintosh/smu-led.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.19.1/drivers/macintosh/smu-led.c 2007-01-15 01:19:11.000000000 +0100
@@ -0,0 +1,147 @@
+/*
+ * smu LED class device
+ *
+ * Copyright 2006, 2007 Michael Hanselmann <linux-kernel at hansmi.ch>
+ *
+ * This code is based upon via-pmu-led, written by Johannes Berg, and a sample
+ * program written by Benjamin Herrenschmidt.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <linux/spinlock.h>
+#include <asm/smu.h>
+
+static DEFINE_SPINLOCK(lock);
+static struct smu_simple_cmd cmd;
+static unsigned char cmd_value;
+static int wanted = -1;
+
+static void __smu_led_set(struct led_classdev*, unsigned char);
+
+static void smu_led_done(struct smu_cmd *cmd, void *misc)
+{
+ struct led_classdev *led_cdev = misc;
+ unsigned long flags;
+
+ if (cmd->status) {
+ printk(KERN_ERR "smu-led: SMU command failed\n");
+ }
+
+ spin_lock_irqsave(&lock, flags);
+
+ if (wanted != -1) {
+ if (cmd_value == wanted)
+ wanted = -1;
+ else
+ __smu_led_set(led_cdev, wanted);
+ }
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/* Call with lock held */
+static void __smu_led_set(struct led_classdev *led_cdev,
+ unsigned char value)
+{
+ int rc;
+
+ cmd_value = value;
+ rc = smu_queue_simple(&cmd, SMU_CMD_MISC_ee_COMMAND, 3,
+ smu_led_done, led_cdev,
+ SMU_CMD_MISC_ee_LEDS_CTRL, 0x00, value);
+ if (rc) {
+ printk(KERN_ERR "smu-led: "
+ "Command queueing failed, error %d\n", rc);
+ }
+}
+
+static void smu_led_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ unsigned long flags;
+ unsigned char value;
+
+ /* Setting the LED to its default half bright status isn't possible
+ * yet. Reason is that we don't know for sure how to do it.
+ */
+
+ switch (brightness) {
+ case LED_OFF:
+ value = 0x00;
+ break;
+
+ case LED_FULL:
+ value = 0x01;
+ break;
+
+ default:
+ /* Unknown brightness, do nothing */
+ return;
+ }
+
+ spin_lock_irqsave(&lock, flags);
+
+ if (wanted == -1) {
+ wanted = value;
+ __smu_led_set(led_cdev, value);
+ } else
+ wanted = value;
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+static struct led_classdev smu_led = {
+ .name = "smu-front-led",
+ .brightness_set = smu_led_set,
+};
+
+static int __init smu_led_init(void)
+{
+ if (!smu_present())
+ return -ENODEV;
+
+ return led_classdev_register(NULL, &smu_led);
+}
+
+static void __exit smu_led_exit(void)
+{
+ unsigned long flags;
+
+ led_classdev_unregister(&smu_led);
+
+ spin_lock_irqsave(&lock, flags);
+ while (wanted != -1) {
+ spin_unlock_irqrestore(&lock, flags);
+
+ /* Wait for pending request */
+ smu_spinwait_cmd(&cmd.cmd);
+
+ spin_lock_irqsave(&lock, flags);
+ }
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+module_init(smu_led_init);
+module_exit(smu_led_exit);
+
+MODULE_AUTHOR("Michael Hanselmann <linux-kernel at hansmi.ch>");
+MODULE_DESCRIPTION("Front LED support for SMU based PowerMacs");
+MODULE_LICENSE("GPL");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20070115/986f7dc8/attachment.pgp>
More information about the Linuxppc-dev
mailing list