cns3xxx: sync kernel config
[openwrt/svn-archive/archive.git] / target / linux / generic / patches-2.6.39 / 105-alix_platform_leds.patch
1 From: Ed Wildgoose <git@wildgooses.com>
2 Date: Wed, 3 Aug 2011 00:52:36 +0000 (+1000)
3 Subject: This new driver replaces the old PCEngines Alix 2/3 LED driver with a new
4 X-Git-Tag: next-20110812~1^2~75
5 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=2cd7b3e8f8078c214c93a2c60cb845500c92df4a;hp=dc849eae35bbf651ab3ee459f5683e1ff780413d
6
7 This new driver replaces the old PCEngines Alix 2/3 LED driver with a new
8 driver that controls the LEDs through the leds-gpio driver. The old
9 driver accessed GPIOs directly, which created a conflict and prevented
10 also loading the cs5535-gpio driver to read other GPIOs on the Alix board.
11 With this new driver, we hook into leds-gpio which in turn uses GPIO to
12 control the LEDs and therefore it's possible to control both the LEDs and
13 access onboard GPIOs
14
15 Driver is moved to platform/geode and any other geode initialisation
16 modules should move here also.
17
18 This driver is inspired by leds-net5501.c by Alessandro Zummo.
19
20 Ideally, leds-net5501.c should also be moved to platform/geode.
21 Additionally the driver relies on parts of the patch: 7f131cf3ed ("leds:
22 leds-alix2c - take port address from MSR) by Daniel Mack to perform
23 detection of the Alix board.
24
25 Signed-off-by: Ed Wildgoose <kernel@wildgooses.com>
26 Cc: Alessandro Zummo <a.zummo@towertech.it>
27 Cc: Daniel Mack <daniel@caiaq.de>
28 Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
29 Cc: Ingo Molnar <mingo@elte.hu>
30 Cc: Thomas Gleixner <tglx@linutronix.de>
31 Cc: "H. Peter Anvin" <hpa@zytor.com>
32 Cc: Richard Purdie <rpurdie@rpsys.net>
33 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
34 ---
35
36 --- a/arch/x86/Kconfig
37 +++ b/arch/x86/Kconfig
38 @@ -2087,6 +2087,20 @@ config OLPC_XO1
39 ---help---
40 Add support for non-essential features of the OLPC XO-1 laptop.
41
42 +config ALIX
43 + bool "PCEngines ALIX System Support (LED setup)"
44 + select GPIOLIB
45 + ---help---
46 + This option enables system support for the PCEngines ALIX.
47 + At present this just sets up LEDs for GPIO control on
48 + ALIX2/3/6 boards. However, other system specific setup should
49 + get added here.
50 +
51 + Note: You must still enable the drivers for GPIO and LED support
52 + (GPIO_CS5535 & LEDS_GPIO) to actually use the LEDs
53 +
54 + Note: You have to set alix.force=1 for boards with Award BIOS.
55 +
56 endif # X86_32
57
58 config AMD_NB
59 --- a/arch/x86/platform/Makefile
60 +++ b/arch/x86/platform/Makefile
61 @@ -1,6 +1,7 @@
62 # Platform specific code goes here
63 obj-y += ce4100/
64 obj-y += efi/
65 +obj-y += geode/
66 obj-y += iris/
67 obj-y += mrst/
68 obj-y += olpc/
69 --- /dev/null
70 +++ b/arch/x86/platform/geode/Makefile
71 @@ -0,0 +1 @@
72 +obj-$(CONFIG_ALIX) += alix.o
73 --- /dev/null
74 +++ b/arch/x86/platform/geode/alix.c
75 @@ -0,0 +1,141 @@
76 +/*
77 + * System Specific setup for PCEngines ALIX.
78 + * At the moment this means setup of GPIO control of LEDs
79 + * on Alix.2/3/6 boards.
80 + *
81 + *
82 + * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
83 + * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
84 + *
85 + * TODO: There are large similarities with leds-net5501.c
86 + * by Alessandro Zummo <a.zummo@towertech.it>
87 + * In the future leds-net5501.c should be migrated over to platform
88 + *
89 + * This program is free software; you can redistribute it and/or modify
90 + * it under the terms of the GNU General Public License version 2
91 + * as published by the Free Software Foundation.
92 + */
93 +
94 +#include <linux/kernel.h>
95 +#include <linux/init.h>
96 +#include <linux/io.h>
97 +#include <linux/string.h>
98 +#include <linux/leds.h>
99 +#include <linux/platform_device.h>
100 +#include <linux/gpio.h>
101 +
102 +#include <asm/geode.h>
103 +
104 +static int force = 0;
105 +module_param(force, bool, 0444);
106 +/* FIXME: Award bios is not automatically detected as Alix platform */
107 +MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform");
108 +
109 +static struct gpio_led alix_leds[] = {
110 + {
111 + .name = "alix:1",
112 + .gpio = 6,
113 + .default_trigger = "default-on",
114 + .active_low = 1,
115 + },
116 + {
117 + .name = "alix:2",
118 + .gpio = 25,
119 + .default_trigger = "default-off",
120 + .active_low = 1,
121 + },
122 + {
123 + .name = "alix:3",
124 + .gpio = 27,
125 + .default_trigger = "default-off",
126 + .active_low = 1,
127 + },
128 +};
129 +
130 +static struct gpio_led_platform_data alix_leds_data = {
131 + .num_leds = ARRAY_SIZE(alix_leds),
132 + .leds = alix_leds,
133 +};
134 +
135 +static struct platform_device alix_leds_dev = {
136 + .name = "leds-gpio",
137 + .id = -1,
138 + .dev.platform_data = &alix_leds_data,
139 +};
140 +
141 +static void __init register_alix(void)
142 +{
143 + /* Setup LED control through leds-gpio driver */
144 + platform_device_register(&alix_leds_dev);
145 +}
146 +
147 +static int __init alix_present(unsigned long bios_phys,
148 + const char *alix_sig,
149 + size_t alix_sig_len)
150 +{
151 + const size_t bios_len = 0x00010000;
152 + const char *bios_virt;
153 + const char *scan_end;
154 + const char *p;
155 + char name[64];
156 +
157 + if (force) {
158 + printk(KERN_NOTICE "%s: forced to skip BIOS test, "
159 + "assume system is ALIX.2/ALIX.3\n",
160 + KBUILD_MODNAME);
161 + return 1;
162 + }
163 +
164 + bios_virt = phys_to_virt(bios_phys);
165 + scan_end = bios_virt + bios_len - (alix_sig_len + 2);
166 + for (p = bios_virt; p < scan_end; p++) {
167 + const char *tail;
168 + char *a;
169 +
170 + if (memcmp(p, alix_sig, alix_sig_len) != 0)
171 + continue;
172 +
173 + memcpy(name, p, sizeof(name));
174 +
175 + /* remove the first \0 character from string */
176 + a = strchr(name, '\0');
177 + if (a)
178 + *a = ' ';
179 +
180 + /* cut the string at a newline */
181 + a = strchr(name, '\r');
182 + if (a)
183 + *a = '\0';
184 +
185 + tail = p + alix_sig_len;
186 + if ((tail[0] == '2' || tail[0] == '3')) {
187 + printk(KERN_INFO
188 + "%s: system is recognized as \"%s\"\n",
189 + KBUILD_MODNAME, name);
190 + return 1;
191 + }
192 + }
193 +
194 + return 0;
195 +}
196 +
197 +static int __init alix_init(void)
198 +{
199 + const char tinybios_sig[] = "PC Engines ALIX.";
200 + const char coreboot_sig[] = "PC Engines\0ALIX.";
201 +
202 + if (!is_geode())
203 + return 0;
204 +
205 + if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
206 + alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
207 + register_alix();
208 +
209 + return 0;
210 +}
211 +
212 +module_init(alix_init);
213 +
214 +MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>");
215 +MODULE_DESCRIPTION("PCEngines ALIX System Setup");
216 +MODULE_LICENSE("GPL");
217 --- a/drivers/leds/Kconfig
218 +++ b/drivers/leds/Kconfig
219 @@ -107,14 +107,6 @@ config LEDS_WRAP
220 help
221 This option enables support for the PCEngines WRAP programmable LEDs.
222
223 -config LEDS_ALIX2
224 - tristate "LED Support for ALIX.2 and ALIX.3 series"
225 - depends on LEDS_CLASS
226 - depends on X86 && !GPIO_CS5535 && !CS5535_GPIO
227 - help
228 - This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
229 - You have to set leds-alix2.force=1 for boards with Award BIOS.
230 -
231 config LEDS_H1940
232 tristate "LED Support for iPAQ H1940 device"
233 depends on LEDS_CLASS
234 --- a/drivers/leds/Makefile
235 +++ b/drivers/leds/Makefile
236 @@ -16,7 +16,6 @@ obj-$(CONFIG_LEDS_AMS_DELTA) += leds-am
237 obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
238 obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o
239 obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
240 -obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o
241 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
242 obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
243 obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
244 --- a/drivers/leds/leds-alix2.c
245 +++ /dev/null
246 @@ -1,239 +0,0 @@
247 -/*
248 - * LEDs driver for PCEngines ALIX.2 and ALIX.3
249 - *
250 - * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
251 - */
252 -
253 -#include <linux/err.h>
254 -#include <linux/io.h>
255 -#include <linux/kernel.h>
256 -#include <linux/leds.h>
257 -#include <linux/module.h>
258 -#include <linux/platform_device.h>
259 -#include <linux/string.h>
260 -#include <linux/pci.h>
261 -
262 -static int force = 0;
263 -module_param(force, bool, 0444);
264 -MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
265 -
266 -#define MSR_LBAR_GPIO 0x5140000C
267 -#define CS5535_GPIO_SIZE 256
268 -
269 -static u32 gpio_base;
270 -
271 -static struct pci_device_id divil_pci[] = {
272 - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
273 - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
274 - { } /* NULL entry */
275 -};
276 -MODULE_DEVICE_TABLE(pci, divil_pci);
277 -
278 -struct alix_led {
279 - struct led_classdev cdev;
280 - unsigned short port;
281 - unsigned int on_value;
282 - unsigned int off_value;
283 -};
284 -
285 -static void alix_led_set(struct led_classdev *led_cdev,
286 - enum led_brightness brightness)
287 -{
288 - struct alix_led *led_dev =
289 - container_of(led_cdev, struct alix_led, cdev);
290 -
291 - if (brightness)
292 - outl(led_dev->on_value, gpio_base + led_dev->port);
293 - else
294 - outl(led_dev->off_value, gpio_base + led_dev->port);
295 -}
296 -
297 -static struct alix_led alix_leds[] = {
298 - {
299 - .cdev = {
300 - .name = "alix:1",
301 - .brightness_set = alix_led_set,
302 - },
303 - .port = 0x00,
304 - .on_value = 1 << 22,
305 - .off_value = 1 << 6,
306 - },
307 - {
308 - .cdev = {
309 - .name = "alix:2",
310 - .brightness_set = alix_led_set,
311 - },
312 - .port = 0x80,
313 - .on_value = 1 << 25,
314 - .off_value = 1 << 9,
315 - },
316 - {
317 - .cdev = {
318 - .name = "alix:3",
319 - .brightness_set = alix_led_set,
320 - },
321 - .port = 0x80,
322 - .on_value = 1 << 27,
323 - .off_value = 1 << 11,
324 - },
325 -};
326 -
327 -static int __init alix_led_probe(struct platform_device *pdev)
328 -{
329 - int i;
330 - int ret;
331 -
332 - for (i = 0; i < ARRAY_SIZE(alix_leds); i++) {
333 - alix_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
334 - ret = led_classdev_register(&pdev->dev, &alix_leds[i].cdev);
335 - if (ret < 0)
336 - goto fail;
337 - }
338 - return 0;
339 -
340 -fail:
341 - while (--i >= 0)
342 - led_classdev_unregister(&alix_leds[i].cdev);
343 - return ret;
344 -}
345 -
346 -static int alix_led_remove(struct platform_device *pdev)
347 -{
348 - int i;
349 -
350 - for (i = 0; i < ARRAY_SIZE(alix_leds); i++)
351 - led_classdev_unregister(&alix_leds[i].cdev);
352 - return 0;
353 -}
354 -
355 -static struct platform_driver alix_led_driver = {
356 - .remove = alix_led_remove,
357 - .driver = {
358 - .name = KBUILD_MODNAME,
359 - .owner = THIS_MODULE,
360 - },
361 -};
362 -
363 -static int __init alix_present(unsigned long bios_phys,
364 - const char *alix_sig,
365 - size_t alix_sig_len)
366 -{
367 - const size_t bios_len = 0x00010000;
368 - const char *bios_virt;
369 - const char *scan_end;
370 - const char *p;
371 - char name[64];
372 -
373 - if (force) {
374 - printk(KERN_NOTICE "%s: forced to skip BIOS test, "
375 - "assume system has ALIX.2 style LEDs\n",
376 - KBUILD_MODNAME);
377 - return 1;
378 - }
379 -
380 - bios_virt = phys_to_virt(bios_phys);
381 - scan_end = bios_virt + bios_len - (alix_sig_len + 2);
382 - for (p = bios_virt; p < scan_end; p++) {
383 - const char *tail;
384 - char *a;
385 -
386 - if (memcmp(p, alix_sig, alix_sig_len) != 0)
387 - continue;
388 -
389 - memcpy(name, p, sizeof(name));
390 -
391 - /* remove the first \0 character from string */
392 - a = strchr(name, '\0');
393 - if (a)
394 - *a = ' ';
395 -
396 - /* cut the string at a newline */
397 - a = strchr(name, '\r');
398 - if (a)
399 - *a = '\0';
400 -
401 - tail = p + alix_sig_len;
402 - if ((tail[0] == '2' || tail[0] == '3')) {
403 - printk(KERN_INFO
404 - "%s: system is recognized as \"%s\"\n",
405 - KBUILD_MODNAME, name);
406 - return 1;
407 - }
408 - }
409 -
410 - return 0;
411 -}
412 -
413 -static struct platform_device *pdev;
414 -
415 -static int __init alix_pci_led_init(void)
416 -{
417 - u32 low, hi;
418 -
419 - if (pci_dev_present(divil_pci) == 0) {
420 - printk(KERN_WARNING KBUILD_MODNAME": DIVIL not found\n");
421 - return -ENODEV;
422 - }
423 -
424 - /* Grab the GPIO I/O range */
425 - rdmsr(MSR_LBAR_GPIO, low, hi);
426 -
427 - /* Check the mask and whether GPIO is enabled (sanity check) */
428 - if (hi != 0x0000f001) {
429 - printk(KERN_WARNING KBUILD_MODNAME": GPIO not enabled\n");
430 - return -ENODEV;
431 - }
432 -
433 - /* Mask off the IO base address */
434 - gpio_base = low & 0x0000ff00;
435 -
436 - if (!request_region(gpio_base, CS5535_GPIO_SIZE, KBUILD_MODNAME)) {
437 - printk(KERN_ERR KBUILD_MODNAME": can't allocate I/O for GPIO\n");
438 - return -ENODEV;
439 - }
440 -
441 - /* Set GPIO function to output */
442 - outl(1 << 6, gpio_base + 0x04);
443 - outl(1 << 9, gpio_base + 0x84);
444 - outl(1 << 11, gpio_base + 0x84);
445 -
446 - return 0;
447 -}
448 -
449 -static int __init alix_led_init(void)
450 -{
451 - int ret = -ENODEV;
452 - const char tinybios_sig[] = "PC Engines ALIX.";
453 - const char coreboot_sig[] = "PC Engines\0ALIX.";
454 -
455 - if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
456 - alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
457 - ret = alix_pci_led_init();
458 -
459 - if (ret < 0)
460 - return ret;
461 -
462 - pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
463 - if (!IS_ERR(pdev)) {
464 - ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
465 - if (ret)
466 - platform_device_unregister(pdev);
467 - } else
468 - ret = PTR_ERR(pdev);
469 -
470 - return ret;
471 -}
472 -
473 -static void __exit alix_led_exit(void)
474 -{
475 - platform_device_unregister(pdev);
476 - platform_driver_unregister(&alix_led_driver);
477 - release_region(gpio_base, CS5535_GPIO_SIZE);
478 -}
479 -
480 -module_init(alix_led_init);
481 -module_exit(alix_led_exit);
482 -
483 -MODULE_AUTHOR("Constantin Baranov <const@mimas.ru>");
484 -MODULE_DESCRIPTION("PCEngines ALIX.2 and ALIX.3 LED driver");
485 -MODULE_LICENSE("GPL");