add led driver for Bachmann's ot200
From: | Christian Gmeiner <christian.gmeiner@gmail.com> | |
To: | linux-kernel@vger.kernel.org, akpm@linux-foundation.org, lars@metafoo.de | |
Subject: | [PATCH v2] add led driver for Bachmann's ot200 | |
Date: | Mon, 09 Jan 2012 11:24:44 +0100 | |
Message-ID: | <4F0AC06C.3000502@gmail.com> | |
Cc: | bigeasy@linutronix.de, rpurdie@rpsys.net | |
Archive‑link: | Article |
From a7fecf3426ef98fdd19e9d2610665b9d1ce358a0 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior <bigeasy@linutronix.de <mailto:bigeasy@linutronix.de>> Date: Mon, 9 Jan 2012 10:09:50 +0100 Subject: [PATCH v2] add led driver for Bachmann's ot200 This patch adds support for leds on Bachmann's ot200 visualisation device. The device has three leds on the back panel (led_err, led_init and led_run) and can handle up to seven leds on the front panel. The driver was written by Linutronix on behalf of Bachmann electronic GmbH. Changes in v2: - *incorporated* feedback from Andrew Morton and Lars-Peter Clausen Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de <mailto:bigeasy@linutronix.de>> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com <mailto:christian.gmeiner@gmail.com>> --- drivers/leds/Kconfig | 7 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-ot200.c | 177 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 0 deletions(-) create mode 100644 drivers/leds/leds-ot200.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index ff203a4..71cb89b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -387,6 +387,13 @@ config LEDS_RENESAS_TPU pin function. The latter to support brightness control. Brightness control is supported but hardware blinking is not. +config LEDS_OT200 + tristate "LED support for the Bachmann OT200" + depends on LEDS_CLASS + help + This option enables support for the LEDs on the Bachmann OT200. + Say Y to enable LEDs on the Bachmann OT200. + config LEDS_TRIGGERS bool "LED Trigger support" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index e4f6bf5..0814d42 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o +obj-$(CONFIG_LEDS_OT200) += leds-ot200.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c new file mode 100644 index 0000000..4d000ac --- /dev/null +++ b/drivers/leds/leds-ot200.c @@ -0,0 +1,177 @@ +/* + * Bachmann ot200 leds driver. + * + * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> + * Christian Gmeiner <christian.gmeiner@gmail.com> + * + * License: GPL as published by the FSF. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/leds.h> +#include <linux/io.h> +#include <linux/module.h> + + +struct ot200_led { + struct led_classdev cdev; + const char *name; + unsigned long port; + u8 mask; +}; + +/* + * The device has three leds on the back panel (led_err, led_init and led_run) + * and can handle up to seven leds on the front panel. + */ + +static struct ot200_led leds[] = { + { + .name = "led_run", + .port = 0x5a, + .mask = BIT(0), + }, + { + .name = "led_init", + .port = 0x5a, + .mask = BIT(1), + }, + { + .name = "led_err", + .port = 0x5a, + .mask = BIT(2), + }, + { + .name = "led_1", + .port = 0x49, + .mask = BIT(7), + }, + { + .name = "led_2", + .port = 0x49, + .mask = BIT(6), + }, + { + .name = "led_3", + .port = 0x49, + .mask = BIT(5), + }, + { + .name = "led_4", + .port = 0x49, + .mask = BIT(4), + }, + { + .name = "led_5", + .port = 0x49, + .mask = BIT(3), + }, + { + .name = "led_6", + .port = 0x49, + .mask = BIT(2), + }, + { + .name = "led_7", + .port = 0x49, + .mask = BIT(1), + } +}; + +static DEFINE_SPINLOCK(value_lock); + +/* + * we need to store the current led states, as it is not + * possible to read the current led state via inb(). + */ +static u8 leds_back; +static u8 leds_front; + +static void ot200_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev); + u8 *val; + unsigned long flags; + + spin_lock_irqsave(&value_lock, flags); + + if (led->port == 0x49) + val = &leds_front; + else if (led->port == 0x5a) + val = &leds_back; + else + BUG(); + + if (value == LED_OFF) + *val &= ~led->mask; + else + *val |= led->mask; + + outb(*val, led->port); + spin_unlock_irqrestore(&value_lock, flags); +} + +static int __devinit ot200_led_probe(struct platform_device *pdev) +{ + int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(leds); i++) { + + leds[i].cdev.name = leds[i].name; + leds[i].cdev.default_trigger = NULL; + leds[i].cdev.blink_set = NULL; + leds[i].cdev.brightness_set = ot200_led_brightness_set; + + ret = led_classdev_register(&pdev->dev, &leds[i].cdev); + if (ret < 0) + goto err; + + dev_set_drvdata(leds[i].cdev.dev, &leds[i]); + } + + platform_set_drvdata(pdev, leds); + + outb(0x0, 0x49); /* turn off all front leds */ + outb(0x2, 0x5a); /* turn on init led */ + leds_front = 0; + leds_back = BIT(1); + + return 0; + +err: + for (i = i - 1; i >= 0; i--) + led_classdev_unregister(&leds[i].cdev); + + return ret; +} + +static int __devexit ot200_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(leds); i++) + led_classdev_unregister(&leds[i].cdev); + + return 0; +} + +static struct platform_driver ot200_led_driver = { + .probe = ot200_led_probe, + .remove = __devexit_p(ot200_led_remove), + .driver = { + .name = "leds-ot200", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(ot200_led_driver); + +MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>"); +MODULE_DESCRIPTION("ot200 LED driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-ot200"); -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/