diff options
Diffstat (limited to 'target/linux/ixp4xx/patches-2.6.25/031-ixp4xx_fsg_led_driver.patch')
-rw-r--r-- | target/linux/ixp4xx/patches-2.6.25/031-ixp4xx_fsg_led_driver.patch | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/target/linux/ixp4xx/patches-2.6.25/031-ixp4xx_fsg_led_driver.patch b/target/linux/ixp4xx/patches-2.6.25/031-ixp4xx_fsg_led_driver.patch new file mode 100644 index 0000000..5e82d1f --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.25/031-ixp4xx_fsg_led_driver.patch @@ -0,0 +1,319 @@ +From a66e34fefb3f8142d7f16808563eb610225f6e77 Mon Sep 17 00:00:00 2001 +From: Rod Whitby <rod@whitby.id.au> +Date: Tue, 29 Jan 2008 23:17:42 +1030 +Subject: [PATCH] leds: Add new driver for the LEDs on the Freecom FSG-3 + +The LEDs on the Freecom FSG-3 are connected to an external +memory-mapped latch on the ixp4xx expansion bus, and therefore cannot +be supported by any of the existing LEDs drivers. + +Signed-off-by: Rod Whitby <rod@whitby.id.au> +-- +PATCH FOLLOWS +KernelVersion: v2.6.25-rc6-117-g457fb60 +--- + drivers/leds/Kconfig | 6 + + drivers/leds/Makefile | 1 + + drivers/leds/leds-fsg.c | 261 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 268 insertions(+), 0 deletions(-) + create mode 100644 drivers/leds/leds-fsg.c + +diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig +index 859814f..aefbe04 100644 +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -46,6 +46,12 @@ config LEDS_SPITZ + This option enables support for the LEDs on Sharp Zaurus + SL-Cxx00 series (C1000, C3000, C3100). + ++config LEDS_FSG ++ tristate "LED Support for the Freecom FSG-3" ++ depends on LEDS_CLASS && MACH_FSG ++ help ++ This option enables support for the LEDs on the Freecom FSG-3. ++ + config LEDS_TOSA + tristate "LED Support for the Sharp SL-6000 series" + depends on LEDS_CLASS && PXA_SHARPSL +diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile +index 84ced3b..b17bd91 100644 +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -21,6 +21,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o + obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o + obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o + obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o ++obj-$(CONFIG_LEDS_FSG) += leds-fsg.o + + # LED Triggers + obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o +diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c +new file mode 100644 +index 0000000..a7421b8 +--- /dev/null ++++ b/drivers/leds/leds-fsg.c +@@ -0,0 +1,261 @@ ++/* ++ * LED Driver for the Freecom FSG-3 ++ * ++ * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au> ++ * ++ * Author: Rod Whitby <rod@whitby.id.au> ++ * ++ * Based on leds-spitz.c ++ * Copyright 2005-2006 Openedhand Ltd. ++ * Author: Richard Purdie <rpurdie@openedhand.com> ++ * ++ * 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/kernel.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/leds.h> ++#include <asm/arch/hardware.h> ++#include <asm/io.h> ++ ++static short __iomem *latch_address; ++static unsigned short latch_value; ++ ++ ++static void fsg_led_wlan_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ if (value) { ++ latch_value &= ~(1 << FSG_LED_WLAN_BIT); ++ *latch_address = latch_value; ++ } else { ++ latch_value |= (1 << FSG_LED_WLAN_BIT); ++ *latch_address = latch_value; ++ } ++} ++ ++static void fsg_led_wan_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ if (value) { ++ latch_value &= ~(1 << FSG_LED_WAN_BIT); ++ *latch_address = latch_value; ++ } else { ++ latch_value |= (1 << FSG_LED_WAN_BIT); ++ *latch_address = latch_value; ++ } ++} ++ ++static void fsg_led_sata_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ if (value) { ++ latch_value &= ~(1 << FSG_LED_SATA_BIT); ++ *latch_address = latch_value; ++ } else { ++ latch_value |= (1 << FSG_LED_SATA_BIT); ++ *latch_address = latch_value; ++ } ++} ++ ++static void fsg_led_usb_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ if (value) { ++ latch_value &= ~(1 << FSG_LED_USB_BIT); ++ *latch_address = latch_value; ++ } else { ++ latch_value |= (1 << FSG_LED_USB_BIT); ++ *latch_address = latch_value; ++ } ++} ++ ++static void fsg_led_sync_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ if (value) { ++ latch_value &= ~(1 << FSG_LED_SYNC_BIT); ++ *latch_address = latch_value; ++ } else { ++ latch_value |= (1 << FSG_LED_SYNC_BIT); ++ *latch_address = latch_value; ++ } ++} ++ ++static void fsg_led_ring_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ if (value) { ++ latch_value &= ~(1 << FSG_LED_RING_BIT); ++ *latch_address = latch_value; ++ } else { ++ latch_value |= (1 << FSG_LED_RING_BIT); ++ *latch_address = latch_value; ++ } ++} ++ ++ ++ ++static struct led_classdev fsg_wlan_led = { ++ .name = "fsg:blue:wlan", ++ .brightness_set = fsg_led_wlan_set, ++}; ++ ++static struct led_classdev fsg_wan_led = { ++ .name = "fsg:blue:wan", ++ .brightness_set = fsg_led_wan_set, ++}; ++ ++static struct led_classdev fsg_sata_led = { ++ .name = "fsg:blue:sata", ++ .brightness_set = fsg_led_sata_set, ++}; ++ ++static struct led_classdev fsg_usb_led = { ++ .name = "fsg:blue:usb", ++ .brightness_set = fsg_led_usb_set, ++}; ++ ++static struct led_classdev fsg_sync_led = { ++ .name = "fsg:blue:sync", ++ .brightness_set = fsg_led_sync_set, ++}; ++ ++static struct led_classdev fsg_ring_led = { ++ .name = "fsg:blue:ring", ++ .brightness_set = fsg_led_ring_set, ++}; ++ ++ ++ ++#ifdef CONFIG_PM ++static int fsg_led_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ led_classdev_suspend(&fsg_wlan_led); ++ led_classdev_suspend(&fsg_wan_led); ++ led_classdev_suspend(&fsg_sata_led); ++ led_classdev_suspend(&fsg_usb_led); ++ led_classdev_suspend(&fsg_sync_led); ++ led_classdev_suspend(&fsg_ring_led); ++ return 0; ++} ++ ++static int fsg_led_resume(struct platform_device *dev) ++{ ++ led_classdev_resume(&fsg_wlan_led); ++ led_classdev_resume(&fsg_wan_led); ++ led_classdev_resume(&fsg_sata_led); ++ led_classdev_resume(&fsg_usb_led); ++ led_classdev_resume(&fsg_sync_led); ++ led_classdev_resume(&fsg_ring_led); ++ return 0; ++} ++#endif ++ ++ ++static int fsg_led_probe(struct platform_device *pdev) ++{ ++ int ret; ++ ++ ret = led_classdev_register(&pdev->dev, &fsg_wlan_led); ++ if (ret < 0) ++ goto failwlan; ++ ++ ret = led_classdev_register(&pdev->dev, &fsg_wan_led); ++ if (ret < 0) ++ goto failwan; ++ ++ ret = led_classdev_register(&pdev->dev, &fsg_sata_led); ++ if (ret < 0) ++ goto failsata; ++ ++ ret = led_classdev_register(&pdev->dev, &fsg_usb_led); ++ if (ret < 0) ++ goto failusb; ++ ++ ret = led_classdev_register(&pdev->dev, &fsg_sync_led); ++ if (ret < 0) ++ goto failsync; ++ ++ ret = led_classdev_register(&pdev->dev, &fsg_ring_led); ++ if (ret < 0) ++ goto failring; ++ ++ /* Map the LED chip select address space */ ++ latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512); ++ if (!latch_address) { ++ ret = -ENOMEM; ++ goto failremap; ++ } ++ ++ latch_value = 0xffff; ++ *latch_address = latch_value; ++ ++ return ret; ++ ++ failremap: ++ led_classdev_unregister(&fsg_ring_led); ++ failring: ++ led_classdev_unregister(&fsg_sync_led); ++ failsync: ++ led_classdev_unregister(&fsg_usb_led); ++ failusb: ++ led_classdev_unregister(&fsg_sata_led); ++ failsata: ++ led_classdev_unregister(&fsg_wan_led); ++ failwan: ++ led_classdev_unregister(&fsg_wlan_led); ++ failwlan: ++ ++ return ret; ++} ++ ++static int fsg_led_remove(struct platform_device *pdev) ++{ ++ iounmap(latch_address); ++ ++ led_classdev_unregister(&fsg_wlan_led); ++ led_classdev_unregister(&fsg_wan_led); ++ led_classdev_unregister(&fsg_sata_led); ++ led_classdev_unregister(&fsg_usb_led); ++ led_classdev_unregister(&fsg_sync_led); ++ led_classdev_unregister(&fsg_ring_led); ++ ++ return 0; ++} ++ ++ ++static struct platform_driver fsg_led_driver = { ++ .probe = fsg_led_probe, ++ .remove = fsg_led_remove, ++#ifdef CONFIG_PM ++ .suspend = fsg_led_suspend, ++ .resume = fsg_led_resume, ++#endif ++ .driver = { ++ .name = "fsg-led", ++ }, ++}; ++ ++ ++static int __init fsg_led_init(void) ++{ ++ return platform_driver_register(&fsg_led_driver); ++} ++ ++static void __exit fsg_led_exit(void) ++{ ++ platform_driver_unregister(&fsg_led_driver); ++} ++ ++ ++module_init(fsg_led_init); ++module_exit(fsg_led_exit); ++ ++MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>"); ++MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); ++MODULE_LICENSE("GPL"); +-- +1.5.2.5 + |