Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: add led driver for Bachmann's ot200

Add 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. It incorporates feedback from Lars-Peter Clausen

[akpm@linux-foundation.org: add dependency on HAS_IOMEM]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Sebastian Andrzej Siewior and committed by
Linus Torvalds
e9a4593c 656a0706

+179
+7
drivers/leds/Kconfig
··· 403 403 This option enables support for on-chip LED drivers on 404 404 MAXIM MAX8997 PMIC. 405 405 406 + config LEDS_OT200 407 + tristate "LED support for the Bachmann OT200" 408 + depends on LEDS_CLASS && HAS_IOMEM 409 + help 410 + This option enables support for the LEDs on the Bachmann OT200. 411 + Say Y to enable LEDs on the Bachmann OT200. 412 + 406 413 config LEDS_TRIGGERS 407 414 bool "LED Trigger support" 408 415 depends on LEDS_CLASS
+1
drivers/leds/Makefile
··· 28 28 obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o 29 29 obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 30 30 obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 31 + obj-$(CONFIG_LEDS_OT200) += leds-ot200.o 31 32 obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 32 33 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o 33 34 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
+171
drivers/leds/leds-ot200.c
··· 1 + /* 2 + * Bachmann ot200 leds driver. 3 + * 4 + * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> 5 + * Christian Gmeiner <christian.gmeiner@gmail.com> 6 + * 7 + * License: GPL as published by the FSF. 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/init.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/slab.h> 14 + #include <linux/leds.h> 15 + #include <linux/io.h> 16 + #include <linux/module.h> 17 + 18 + 19 + struct ot200_led { 20 + struct led_classdev cdev; 21 + const char *name; 22 + unsigned long port; 23 + u8 mask; 24 + }; 25 + 26 + /* 27 + * The device has three leds on the back panel (led_err, led_init and led_run) 28 + * and can handle up to seven leds on the front panel. 29 + */ 30 + 31 + static struct ot200_led leds[] = { 32 + { 33 + .name = "led_run", 34 + .port = 0x5a, 35 + .mask = BIT(0), 36 + }, 37 + { 38 + .name = "led_init", 39 + .port = 0x5a, 40 + .mask = BIT(1), 41 + }, 42 + { 43 + .name = "led_err", 44 + .port = 0x5a, 45 + .mask = BIT(2), 46 + }, 47 + { 48 + .name = "led_1", 49 + .port = 0x49, 50 + .mask = BIT(7), 51 + }, 52 + { 53 + .name = "led_2", 54 + .port = 0x49, 55 + .mask = BIT(6), 56 + }, 57 + { 58 + .name = "led_3", 59 + .port = 0x49, 60 + .mask = BIT(5), 61 + }, 62 + { 63 + .name = "led_4", 64 + .port = 0x49, 65 + .mask = BIT(4), 66 + }, 67 + { 68 + .name = "led_5", 69 + .port = 0x49, 70 + .mask = BIT(3), 71 + }, 72 + { 73 + .name = "led_6", 74 + .port = 0x49, 75 + .mask = BIT(2), 76 + }, 77 + { 78 + .name = "led_7", 79 + .port = 0x49, 80 + .mask = BIT(1), 81 + } 82 + }; 83 + 84 + static DEFINE_SPINLOCK(value_lock); 85 + 86 + /* 87 + * we need to store the current led states, as it is not 88 + * possible to read the current led state via inb(). 89 + */ 90 + static u8 leds_back; 91 + static u8 leds_front; 92 + 93 + static void ot200_led_brightness_set(struct led_classdev *led_cdev, 94 + enum led_brightness value) 95 + { 96 + struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev); 97 + u8 *val; 98 + unsigned long flags; 99 + 100 + spin_lock_irqsave(&value_lock, flags); 101 + 102 + if (led->port == 0x49) 103 + val = &leds_front; 104 + else if (led->port == 0x5a) 105 + val = &leds_back; 106 + else 107 + BUG(); 108 + 109 + if (value == LED_OFF) 110 + *val &= ~led->mask; 111 + else 112 + *val |= led->mask; 113 + 114 + outb(*val, led->port); 115 + spin_unlock_irqrestore(&value_lock, flags); 116 + } 117 + 118 + static int __devinit ot200_led_probe(struct platform_device *pdev) 119 + { 120 + int i; 121 + int ret; 122 + 123 + for (i = 0; i < ARRAY_SIZE(leds); i++) { 124 + 125 + leds[i].cdev.name = leds[i].name; 126 + leds[i].cdev.brightness_set = ot200_led_brightness_set; 127 + 128 + ret = led_classdev_register(&pdev->dev, &leds[i].cdev); 129 + if (ret < 0) 130 + goto err; 131 + } 132 + 133 + leds_front = 0; /* turn off all front leds */ 134 + leds_back = BIT(1); /* turn on init led */ 135 + outb(leds_front, 0x49); 136 + outb(leds_back, 0x5a); 137 + 138 + return 0; 139 + 140 + err: 141 + for (i = i - 1; i >= 0; i--) 142 + led_classdev_unregister(&leds[i].cdev); 143 + 144 + return ret; 145 + } 146 + 147 + static int __devexit ot200_led_remove(struct platform_device *pdev) 148 + { 149 + int i; 150 + 151 + for (i = 0; i < ARRAY_SIZE(leds); i++) 152 + led_classdev_unregister(&leds[i].cdev); 153 + 154 + return 0; 155 + } 156 + 157 + static struct platform_driver ot200_led_driver = { 158 + .probe = ot200_led_probe, 159 + .remove = __devexit_p(ot200_led_remove), 160 + .driver = { 161 + .name = "leds-ot200", 162 + .owner = THIS_MODULE, 163 + }, 164 + }; 165 + 166 + module_platform_driver(ot200_led_driver); 167 + 168 + MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>"); 169 + MODULE_DESCRIPTION("ot200 LED driver"); 170 + MODULE_LICENSE("GPL"); 171 + MODULE_ALIAS("platform:leds-ot200");