Commit | Line | Data |
---|---|---|
da4e3302 PP |
1 | /* |
2 | * System Specific setup for Soekris net5501 | |
3 | * At the moment this means setup of GPIO control of LEDs and buttons | |
4 | * on net5501 boards. | |
5 | * | |
6 | * | |
7 | * Copyright (C) 2008-2009 Tower Technologies | |
8 | * Written by Alessandro Zummo <a.zummo@towertech.it> | |
9 | * | |
10 | * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> | |
11 | * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> | |
12 | * and Philip Prindeville <philipp@redfish-solutions.com> | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify | |
15 | * it under the terms of the GNU General Public License version 2 | |
16 | * as published by the Free Software Foundation. | |
17 | */ | |
18 | ||
19 | #include <linux/kernel.h> | |
20 | #include <linux/init.h> | |
21 | #include <linux/io.h> | |
22 | #include <linux/string.h> | |
da4e3302 PP |
23 | #include <linux/leds.h> |
24 | #include <linux/platform_device.h> | |
25 | #include <linux/gpio.h> | |
26 | #include <linux/input.h> | |
27 | #include <linux/gpio_keys.h> | |
28 | ||
29 | #include <asm/geode.h> | |
30 | ||
31 | #define BIOS_REGION_BASE 0xffff0000 | |
32 | #define BIOS_REGION_SIZE 0x00010000 | |
33 | ||
34 | static struct gpio_keys_button net5501_gpio_buttons[] = { | |
35 | { | |
36 | .code = KEY_RESTART, | |
37 | .gpio = 24, | |
38 | .active_low = 1, | |
39 | .desc = "Reset button", | |
40 | .type = EV_KEY, | |
41 | .wakeup = 0, | |
42 | .debounce_interval = 100, | |
43 | .can_disable = 0, | |
44 | } | |
45 | }; | |
46 | static struct gpio_keys_platform_data net5501_buttons_data = { | |
47 | .buttons = net5501_gpio_buttons, | |
48 | .nbuttons = ARRAY_SIZE(net5501_gpio_buttons), | |
49 | .poll_interval = 20, | |
50 | }; | |
51 | ||
52 | static struct platform_device net5501_buttons_dev = { | |
53 | .name = "gpio-keys-polled", | |
54 | .id = 1, | |
55 | .dev = { | |
56 | .platform_data = &net5501_buttons_data, | |
57 | } | |
58 | }; | |
59 | ||
60 | static struct gpio_led net5501_leds[] = { | |
61 | { | |
62 | .name = "net5501:1", | |
63 | .gpio = 6, | |
64 | .default_trigger = "default-on", | |
d1d0589a | 65 | .active_low = 0, |
da4e3302 PP |
66 | }, |
67 | }; | |
68 | ||
69 | static struct gpio_led_platform_data net5501_leds_data = { | |
70 | .num_leds = ARRAY_SIZE(net5501_leds), | |
71 | .leds = net5501_leds, | |
72 | }; | |
73 | ||
74 | static struct platform_device net5501_leds_dev = { | |
75 | .name = "leds-gpio", | |
76 | .id = -1, | |
77 | .dev.platform_data = &net5501_leds_data, | |
78 | }; | |
79 | ||
a6d30e0f | 80 | static struct platform_device *net5501_devs[] __initdata = { |
da4e3302 PP |
81 | &net5501_buttons_dev, |
82 | &net5501_leds_dev, | |
83 | }; | |
84 | ||
85 | static void __init register_net5501(void) | |
86 | { | |
87 | /* Setup LED control through leds-gpio driver */ | |
88 | platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs)); | |
89 | } | |
90 | ||
91 | struct net5501_board { | |
92 | u16 offset; | |
93 | u16 len; | |
94 | char *sig; | |
95 | }; | |
96 | ||
97 | static struct net5501_board __initdata boards[] = { | |
98 | { 0xb7b, 7, "net5501" }, /* net5501 v1.33/1.33c */ | |
99 | { 0xb1f, 7, "net5501" }, /* net5501 v1.32i */ | |
100 | }; | |
101 | ||
102 | static bool __init net5501_present(void) | |
103 | { | |
104 | int i; | |
105 | unsigned char *rombase, *bios; | |
106 | bool found = false; | |
107 | ||
108 | rombase = ioremap(BIOS_REGION_BASE, BIOS_REGION_SIZE - 1); | |
109 | if (!rombase) { | |
110 | printk(KERN_ERR "%s: failed to get rombase\n", KBUILD_MODNAME); | |
111 | return found; | |
112 | } | |
113 | ||
114 | bios = rombase + 0x20; /* null terminated */ | |
115 | ||
116 | if (memcmp(bios, "comBIOS", 7)) | |
117 | goto unmap; | |
118 | ||
119 | for (i = 0; i < ARRAY_SIZE(boards); i++) { | |
120 | unsigned char *model = rombase + boards[i].offset; | |
121 | ||
122 | if (!memcmp(model, boards[i].sig, boards[i].len)) { | |
123 | printk(KERN_INFO "%s: system is recognized as \"%s\"\n", | |
124 | KBUILD_MODNAME, model); | |
125 | ||
126 | found = true; | |
127 | break; | |
128 | } | |
129 | } | |
130 | ||
131 | unmap: | |
132 | iounmap(rombase); | |
133 | return found; | |
134 | } | |
135 | ||
136 | static int __init net5501_init(void) | |
137 | { | |
138 | if (!is_geode()) | |
139 | return 0; | |
140 | ||
141 | if (!net5501_present()) | |
142 | return 0; | |
143 | ||
144 | register_net5501(); | |
145 | ||
146 | return 0; | |
147 | } | |
605a46ee | 148 | device_initcall(net5501_init); |