diff options
author | Philip Prindeville <philipp@redfish-solutions.com> | 2012-03-05 18:05:14 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-03-06 03:23:56 -0500 |
commit | 373913b568cbfbefcee3263b98bd5a1a8b491f1b (patch) | |
tree | 96f2d7925a7c66d145d9db0f452d318d07a93eac /arch/x86/platform | |
parent | 8bee7cea6c93b5514b672d1c347dad9960823f12 (diff) |
x86/geode/alix2: Supplement driver to include GPIO button support
GPIO 24 is used in reference designs as a soft-reset button, and
the alix2 is no exception. Add it as a gpio-button.
Use symbolic values to describe BIOS addresses.
Record the model number.
Signed-off-by: Philip A. Prindeville <philipp@redfish-solutions.com>
Acked-by: Ed Wildgoose <kernel@wildgooses.com>
Acked-by: Andres Salomon <dilinger@queued.net>
Cc: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Link: http://lkml.kernel.org/n/tip-sjp6k1rjksitx1pej0c0qxd1@git.kernel.org
[ tidied up the code a bit ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/platform')
-rw-r--r-- | arch/x86/platform/geode/alix.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c index dc5f1d32ace..90e23e7679a 100644 --- a/arch/x86/platform/geode/alix.c +++ b/arch/x86/platform/geode/alix.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> | 7 | * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> |
8 | * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> | 8 | * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> |
9 | * and Philip Prindeville <philipp@redfish-solutions.com> | ||
9 | * | 10 | * |
10 | * TODO: There are large similarities with leds-net5501.c | 11 | * TODO: There are large similarities with leds-net5501.c |
11 | * by Alessandro Zummo <a.zummo@towertech.it> | 12 | * by Alessandro Zummo <a.zummo@towertech.it> |
@@ -24,14 +25,47 @@ | |||
24 | #include <linux/leds.h> | 25 | #include <linux/leds.h> |
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/input.h> | ||
29 | #include <linux/gpio_keys.h> | ||
30 | #include <linux/dmi.h> | ||
27 | 31 | ||
28 | #include <asm/geode.h> | 32 | #include <asm/geode.h> |
29 | 33 | ||
34 | #define BIOS_SIGNATURE_TINYBIOS 0xf0000 | ||
35 | #define BIOS_SIGNATURE_COREBOOT 0x500 | ||
36 | #define BIOS_REGION_SIZE 0x10000 | ||
37 | |||
30 | static bool force = 0; | 38 | static bool force = 0; |
31 | module_param(force, bool, 0444); | 39 | module_param(force, bool, 0444); |
32 | /* FIXME: Award bios is not automatically detected as Alix platform */ | 40 | /* FIXME: Award bios is not automatically detected as Alix platform */ |
33 | MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); | 41 | MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); |
34 | 42 | ||
43 | static struct gpio_keys_button alix_gpio_buttons[] = { | ||
44 | { | ||
45 | .code = KEY_RESTART, | ||
46 | .gpio = 24, | ||
47 | .active_low = 1, | ||
48 | .desc = "Reset button", | ||
49 | .type = EV_KEY, | ||
50 | .wakeup = 0, | ||
51 | .debounce_interval = 100, | ||
52 | .can_disable = 0, | ||
53 | } | ||
54 | }; | ||
55 | static struct gpio_keys_platform_data alix_buttons_data = { | ||
56 | .buttons = alix_gpio_buttons, | ||
57 | .nbuttons = ARRAY_SIZE(alix_gpio_buttons), | ||
58 | .poll_interval = 20, | ||
59 | }; | ||
60 | |||
61 | static struct platform_device alix_buttons_dev = { | ||
62 | .name = "gpio-keys-polled", | ||
63 | .id = 1, | ||
64 | .dev = { | ||
65 | .platform_data = &alix_buttons_data, | ||
66 | } | ||
67 | }; | ||
68 | |||
35 | static struct gpio_led alix_leds[] = { | 69 | static struct gpio_led alix_leds[] = { |
36 | { | 70 | { |
37 | .name = "alix:1", | 71 | .name = "alix:1", |
@@ -64,17 +98,22 @@ static struct platform_device alix_leds_dev = { | |||
64 | .dev.platform_data = &alix_leds_data, | 98 | .dev.platform_data = &alix_leds_data, |
65 | }; | 99 | }; |
66 | 100 | ||
101 | static struct __initdata platform_device *alix_devs[] = { | ||
102 | &alix_buttons_dev, | ||
103 | &alix_leds_dev, | ||
104 | }; | ||
105 | |||
67 | static void __init register_alix(void) | 106 | static void __init register_alix(void) |
68 | { | 107 | { |
69 | /* Setup LED control through leds-gpio driver */ | 108 | /* Setup LED control through leds-gpio driver */ |
70 | platform_device_register(&alix_leds_dev); | 109 | platform_add_devices(alix_devs, ARRAY_SIZE(alix_devs)); |
71 | } | 110 | } |
72 | 111 | ||
73 | static int __init alix_present(unsigned long bios_phys, | 112 | static bool __init alix_present(unsigned long bios_phys, |
74 | const char *alix_sig, | 113 | const char *alix_sig, |
75 | size_t alix_sig_len) | 114 | size_t alix_sig_len) |
76 | { | 115 | { |
77 | const size_t bios_len = 0x00010000; | 116 | const size_t bios_len = BIOS_REGION_SIZE; |
78 | const char *bios_virt; | 117 | const char *bios_virt; |
79 | const char *scan_end; | 118 | const char *scan_end; |
80 | const char *p; | 119 | const char *p; |
@@ -84,7 +123,7 @@ static int __init alix_present(unsigned long bios_phys, | |||
84 | printk(KERN_NOTICE "%s: forced to skip BIOS test, " | 123 | printk(KERN_NOTICE "%s: forced to skip BIOS test, " |
85 | "assume system is ALIX.2/ALIX.3\n", | 124 | "assume system is ALIX.2/ALIX.3\n", |
86 | KBUILD_MODNAME); | 125 | KBUILD_MODNAME); |
87 | return 1; | 126 | return true; |
88 | } | 127 | } |
89 | 128 | ||
90 | bios_virt = phys_to_virt(bios_phys); | 129 | bios_virt = phys_to_virt(bios_phys); |
@@ -109,15 +148,33 @@ static int __init alix_present(unsigned long bios_phys, | |||
109 | *a = '\0'; | 148 | *a = '\0'; |
110 | 149 | ||
111 | tail = p + alix_sig_len; | 150 | tail = p + alix_sig_len; |
112 | if ((tail[0] == '2' || tail[0] == '3')) { | 151 | if ((tail[0] == '2' || tail[0] == '3' || tail[0] == '6')) { |
113 | printk(KERN_INFO | 152 | printk(KERN_INFO |
114 | "%s: system is recognized as \"%s\"\n", | 153 | "%s: system is recognized as \"%s\"\n", |
115 | KBUILD_MODNAME, name); | 154 | KBUILD_MODNAME, name); |
116 | return 1; | 155 | return true; |
117 | } | 156 | } |
118 | } | 157 | } |
119 | 158 | ||
120 | return 0; | 159 | return false; |
160 | } | ||
161 | |||
162 | static bool __init alix_present_dmi(void) | ||
163 | { | ||
164 | const char *vendor, *product; | ||
165 | |||
166 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); | ||
167 | if (!vendor || strcmp(vendor, "PC Engines")) | ||
168 | return false; | ||
169 | |||
170 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
171 | if (!product || (strcmp(product, "ALIX.2D") && strcmp(product, "ALIX.6"))) | ||
172 | return false; | ||
173 | |||
174 | printk(KERN_INFO "%s: system is recognized as \"%s %s\"\n", | ||
175 | KBUILD_MODNAME, vendor, product); | ||
176 | |||
177 | return true; | ||
121 | } | 178 | } |
122 | 179 | ||
123 | static int __init alix_init(void) | 180 | static int __init alix_init(void) |
@@ -128,8 +185,9 @@ static int __init alix_init(void) | |||
128 | if (!is_geode()) | 185 | if (!is_geode()) |
129 | return 0; | 186 | return 0; |
130 | 187 | ||
131 | if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) || | 188 | if (alix_present(BIOS_SIGNATURE_TINYBIOS, tinybios_sig, sizeof(tinybios_sig) - 1) || |
132 | alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1)) | 189 | alix_present(BIOS_SIGNATURE_COREBOOT, coreboot_sig, sizeof(coreboot_sig) - 1) || |
190 | alix_present_dmi()) | ||
133 | register_alix(); | 191 | register_alix(); |
134 | 192 | ||
135 | return 0; | 193 | return 0; |