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