]>
Commit | Line | Data |
---|---|---|
54782674 SG |
1 | /* |
2 | * arch/arm/mach-orion5x/net2big-setup.c | |
3 | * | |
4 | * LaCie 2Big Network NAS setup | |
5 | * | |
6 | * Copyright (C) 2009 Simon Guinot <sguinot@lacie.com> | |
7 | * | |
8 | * This file is licensed under the terms of the GNU General Public | |
9 | * License version 2. This program is licensed "as is" without any | |
10 | * warranty of any kind, whether express or implied. | |
11 | */ | |
12 | ||
13 | #include <linux/kernel.h> | |
14 | #include <linux/init.h> | |
15 | #include <linux/platform_device.h> | |
16 | #include <linux/mtd/physmap.h> | |
17 | #include <linux/mv643xx_eth.h> | |
18 | #include <linux/leds.h> | |
19 | #include <linux/gpio_keys.h> | |
20 | #include <linux/input.h> | |
21 | #include <linux/i2c.h> | |
22 | #include <linux/ata_platform.h> | |
23 | #include <linux/gpio.h> | |
24 | #include <linux/delay.h> | |
25 | #include <asm/mach-types.h> | |
26 | #include <asm/mach/arch.h> | |
27 | #include <mach/orion5x.h> | |
28 | #include "common.h" | |
29 | #include "mpp.h" | |
30 | ||
31 | /***************************************************************************** | |
32 | * LaCie 2Big Network Info | |
33 | ****************************************************************************/ | |
34 | ||
35 | /* | |
36 | * 512KB NOR flash Device bus boot chip select | |
37 | */ | |
38 | ||
39 | #define NET2BIG_NOR_BOOT_BASE 0xfff80000 | |
40 | #define NET2BIG_NOR_BOOT_SIZE SZ_512K | |
41 | ||
42 | /***************************************************************************** | |
43 | * 512KB NOR Flash on Boot Device | |
44 | ****************************************************************************/ | |
45 | ||
46 | /* | |
47 | * TODO: Check write support on flash MX29LV400CBTC-70G | |
48 | */ | |
49 | ||
50 | static struct mtd_partition net2big_partitions[] = { | |
51 | { | |
52 | .name = "Full512kb", | |
53 | .size = MTDPART_SIZ_FULL, | |
54 | .offset = 0x00000000, | |
55 | .mask_flags = MTD_WRITEABLE, | |
56 | }, | |
57 | }; | |
58 | ||
59 | static struct physmap_flash_data net2big_nor_flash_data = { | |
60 | .width = 1, | |
61 | .parts = net2big_partitions, | |
62 | .nr_parts = ARRAY_SIZE(net2big_partitions), | |
63 | }; | |
64 | ||
65 | static struct resource net2big_nor_flash_resource = { | |
66 | .flags = IORESOURCE_MEM, | |
67 | .start = NET2BIG_NOR_BOOT_BASE, | |
68 | .end = NET2BIG_NOR_BOOT_BASE | |
69 | + NET2BIG_NOR_BOOT_SIZE - 1, | |
70 | }; | |
71 | ||
72 | static struct platform_device net2big_nor_flash = { | |
73 | .name = "physmap-flash", | |
74 | .id = 0, | |
75 | .dev = { | |
76 | .platform_data = &net2big_nor_flash_data, | |
77 | }, | |
78 | .num_resources = 1, | |
79 | .resource = &net2big_nor_flash_resource, | |
80 | }; | |
81 | ||
82 | /***************************************************************************** | |
83 | * Ethernet | |
84 | ****************************************************************************/ | |
85 | ||
86 | static struct mv643xx_eth_platform_data net2big_eth_data = { | |
87 | .phy_addr = MV643XX_ETH_PHY_ADDR(8), | |
88 | }; | |
89 | ||
90 | /***************************************************************************** | |
91 | * I2C devices | |
92 | ****************************************************************************/ | |
93 | ||
94 | /* | |
95 | * i2c addr | chip | description | |
96 | * 0x32 | Ricoh 5C372b | RTC | |
97 | * 0x50 | HT24LC08 | eeprom (1kB) | |
98 | */ | |
99 | static struct i2c_board_info __initdata net2big_i2c_devices[] = { | |
100 | { | |
101 | I2C_BOARD_INFO("rs5c372b", 0x32), | |
102 | }, { | |
103 | I2C_BOARD_INFO("24c08", 0x50), | |
104 | }, | |
105 | }; | |
106 | ||
107 | /***************************************************************************** | |
108 | * SATA | |
109 | ****************************************************************************/ | |
110 | ||
111 | static struct mv_sata_platform_data net2big_sata_data = { | |
112 | .n_ports = 2, | |
113 | }; | |
114 | ||
115 | #define NET2BIG_GPIO_SATA_POWER_REQ 19 | |
116 | #define NET2BIG_GPIO_SATA0_POWER 23 | |
117 | #define NET2BIG_GPIO_SATA1_POWER 25 | |
118 | ||
119 | static void __init net2big_sata_power_init(void) | |
120 | { | |
121 | int err; | |
122 | ||
123 | /* Configure GPIOs over MPP max number. */ | |
124 | orion_gpio_set_valid(NET2BIG_GPIO_SATA0_POWER, 1); | |
125 | orion_gpio_set_valid(NET2BIG_GPIO_SATA1_POWER, 1); | |
126 | ||
127 | err = gpio_request(NET2BIG_GPIO_SATA0_POWER, "SATA0 power status"); | |
128 | if (err == 0) { | |
129 | err = gpio_direction_input(NET2BIG_GPIO_SATA0_POWER); | |
130 | if (err) | |
131 | gpio_free(NET2BIG_GPIO_SATA0_POWER); | |
132 | } | |
133 | if (err) { | |
134 | pr_err("net2big: failed to setup SATA0 power GPIO\n"); | |
135 | return; | |
136 | } | |
137 | ||
138 | err = gpio_request(NET2BIG_GPIO_SATA1_POWER, "SATA1 power status"); | |
139 | if (err == 0) { | |
140 | err = gpio_direction_input(NET2BIG_GPIO_SATA1_POWER); | |
141 | if (err) | |
142 | gpio_free(NET2BIG_GPIO_SATA1_POWER); | |
143 | } | |
144 | if (err) { | |
145 | pr_err("net2big: failed to setup SATA1 power GPIO\n"); | |
146 | goto err_free_1; | |
147 | } | |
148 | ||
149 | err = gpio_request(NET2BIG_GPIO_SATA_POWER_REQ, "SATA power request"); | |
150 | if (err == 0) { | |
151 | err = gpio_direction_output(NET2BIG_GPIO_SATA_POWER_REQ, 0); | |
152 | if (err) | |
153 | gpio_free(NET2BIG_GPIO_SATA_POWER_REQ); | |
154 | } | |
155 | if (err) { | |
156 | pr_err("net2big: failed to setup SATA power request GPIO\n"); | |
157 | goto err_free_2; | |
158 | } | |
159 | ||
160 | if (gpio_get_value(NET2BIG_GPIO_SATA0_POWER) && | |
161 | gpio_get_value(NET2BIG_GPIO_SATA1_POWER)) { | |
162 | return; | |
163 | } | |
164 | ||
165 | /* | |
166 | * SATA power up on both disk is done by pulling high the CPLD power | |
167 | * request line. The 300ms delay is related to the CPLD clock and is | |
168 | * needed to be sure that the CPLD has take into account the low line | |
169 | * status. | |
170 | */ | |
171 | msleep(300); | |
172 | gpio_set_value(NET2BIG_GPIO_SATA_POWER_REQ, 1); | |
173 | pr_info("net2big: power up SATA hard disks\n"); | |
174 | ||
175 | return; | |
176 | ||
177 | err_free_2: | |
178 | gpio_free(NET2BIG_GPIO_SATA1_POWER); | |
179 | err_free_1: | |
180 | gpio_free(NET2BIG_GPIO_SATA0_POWER); | |
181 | ||
182 | return; | |
183 | } | |
184 | ||
185 | /***************************************************************************** | |
186 | * GPIO LEDs | |
187 | ****************************************************************************/ | |
188 | ||
189 | /* | |
190 | * The power front LEDs (blue and red) and SATA red LEDs are controlled via a | |
191 | * single GPIO line and are compatible with the leds-gpio driver. | |
192 | * | |
25985edc | 193 | * The SATA blue LEDs have some hardware blink capabilities which are detailed |
54782674 SG |
194 | * in the following array: |
195 | * | |
196 | * SATAx blue LED | SATAx activity | LED state | |
197 | * | | | |
198 | * 0 | 0 | blink (rate 300ms) | |
199 | * 1 | 0 | off | |
200 | * ? | 1 | on | |
201 | * | |
202 | * Notes: The blue and the red front LED's can't be on at the same time. | |
203 | * Blue LED have priority. | |
204 | */ | |
205 | ||
206 | #define NET2BIG_GPIO_PWR_RED_LED 6 | |
207 | #define NET2BIG_GPIO_PWR_BLUE_LED 16 | |
208 | #define NET2BIG_GPIO_PWR_LED_BLINK_STOP 7 | |
209 | ||
210 | #define NET2BIG_GPIO_SATA0_RED_LED 11 | |
211 | #define NET2BIG_GPIO_SATA1_RED_LED 10 | |
212 | ||
213 | #define NET2BIG_GPIO_SATA0_BLUE_LED 17 | |
214 | #define NET2BIG_GPIO_SATA1_BLUE_LED 13 | |
215 | ||
216 | static struct gpio_led net2big_leds[] = { | |
217 | { | |
218 | .name = "net2big:red:power", | |
219 | .gpio = NET2BIG_GPIO_PWR_RED_LED, | |
220 | }, | |
221 | { | |
222 | .name = "net2big:blue:power", | |
223 | .gpio = NET2BIG_GPIO_PWR_BLUE_LED, | |
224 | }, | |
225 | { | |
226 | .name = "net2big:red:sata0", | |
227 | .gpio = NET2BIG_GPIO_SATA0_RED_LED, | |
228 | }, | |
229 | { | |
230 | .name = "net2big:red:sata1", | |
231 | .gpio = NET2BIG_GPIO_SATA1_RED_LED, | |
232 | }, | |
233 | }; | |
234 | ||
235 | static struct gpio_led_platform_data net2big_led_data = { | |
236 | .num_leds = ARRAY_SIZE(net2big_leds), | |
237 | .leds = net2big_leds, | |
238 | }; | |
239 | ||
240 | static struct platform_device net2big_gpio_leds = { | |
241 | .name = "leds-gpio", | |
242 | .id = -1, | |
243 | .dev = { | |
244 | .platform_data = &net2big_led_data, | |
245 | }, | |
246 | }; | |
247 | ||
248 | static void __init net2big_gpio_leds_init(void) | |
249 | { | |
250 | int err; | |
251 | ||
252 | /* Stop initial CPLD slow red/blue blinking on power LED. */ | |
253 | err = gpio_request(NET2BIG_GPIO_PWR_LED_BLINK_STOP, | |
254 | "Power LED blink stop"); | |
255 | if (err == 0) { | |
256 | err = gpio_direction_output(NET2BIG_GPIO_PWR_LED_BLINK_STOP, 1); | |
257 | if (err) | |
258 | gpio_free(NET2BIG_GPIO_PWR_LED_BLINK_STOP); | |
259 | } | |
260 | if (err) | |
261 | pr_err("net2big: failed to setup power LED blink GPIO\n"); | |
262 | ||
263 | /* | |
264 | * Configure SATA0 and SATA1 blue LEDs to blink in relation with the | |
265 | * hard disk activity. | |
266 | */ | |
267 | err = gpio_request(NET2BIG_GPIO_SATA0_BLUE_LED, | |
268 | "SATA0 blue LED control"); | |
269 | if (err == 0) { | |
270 | err = gpio_direction_output(NET2BIG_GPIO_SATA0_BLUE_LED, 1); | |
271 | if (err) | |
272 | gpio_free(NET2BIG_GPIO_SATA0_BLUE_LED); | |
273 | } | |
274 | if (err) | |
275 | pr_err("net2big: failed to setup SATA0 blue LED GPIO\n"); | |
276 | ||
277 | err = gpio_request(NET2BIG_GPIO_SATA1_BLUE_LED, | |
278 | "SATA1 blue LED control"); | |
279 | if (err == 0) { | |
280 | err = gpio_direction_output(NET2BIG_GPIO_SATA1_BLUE_LED, 1); | |
281 | if (err) | |
282 | gpio_free(NET2BIG_GPIO_SATA1_BLUE_LED); | |
283 | } | |
284 | if (err) | |
285 | pr_err("net2big: failed to setup SATA1 blue LED GPIO\n"); | |
286 | ||
287 | platform_device_register(&net2big_gpio_leds); | |
288 | } | |
289 | ||
290 | /**************************************************************************** | |
291 | * GPIO keys | |
292 | ****************************************************************************/ | |
293 | ||
294 | #define NET2BIG_GPIO_PUSH_BUTTON 18 | |
295 | #define NET2BIG_GPIO_POWER_SWITCH_ON 8 | |
296 | #define NET2BIG_GPIO_POWER_SWITCH_OFF 9 | |
297 | ||
298 | #define NET2BIG_SWITCH_POWER_ON 0x1 | |
299 | #define NET2BIG_SWITCH_POWER_OFF 0x2 | |
300 | ||
301 | static struct gpio_keys_button net2big_buttons[] = { | |
302 | { | |
303 | .type = EV_SW, | |
304 | .code = NET2BIG_SWITCH_POWER_OFF, | |
305 | .gpio = NET2BIG_GPIO_POWER_SWITCH_OFF, | |
306 | .desc = "Power rocker switch (auto|off)", | |
307 | .active_low = 0, | |
308 | }, | |
309 | { | |
310 | .type = EV_SW, | |
311 | .code = NET2BIG_SWITCH_POWER_ON, | |
312 | .gpio = NET2BIG_GPIO_POWER_SWITCH_ON, | |
313 | .desc = "Power rocker switch (on|auto)", | |
314 | .active_low = 0, | |
315 | }, | |
316 | { | |
317 | .type = EV_KEY, | |
318 | .code = KEY_POWER, | |
319 | .gpio = NET2BIG_GPIO_PUSH_BUTTON, | |
320 | .desc = "Front Push Button", | |
321 | .active_low = 0, | |
322 | }, | |
323 | }; | |
324 | ||
325 | static struct gpio_keys_platform_data net2big_button_data = { | |
326 | .buttons = net2big_buttons, | |
327 | .nbuttons = ARRAY_SIZE(net2big_buttons), | |
328 | }; | |
329 | ||
330 | static struct platform_device net2big_gpio_buttons = { | |
331 | .name = "gpio-keys", | |
332 | .id = -1, | |
333 | .dev = { | |
334 | .platform_data = &net2big_button_data, | |
335 | }, | |
336 | }; | |
337 | ||
338 | /***************************************************************************** | |
339 | * General Setup | |
340 | ****************************************************************************/ | |
341 | ||
554cdaef AL |
342 | static unsigned int net2big_mpp_modes[] __initdata = { |
343 | MPP0_GPIO, /* Raid mode (bit 0) */ | |
344 | MPP1_GPIO, /* USB port 2 fuse (0 = Fail, 1 = Ok) */ | |
345 | MPP2_GPIO, /* Raid mode (bit 1) */ | |
346 | MPP3_GPIO, /* Board ID (bit 0) */ | |
347 | MPP4_GPIO, /* Fan activity (0 = Off, 1 = On) */ | |
348 | MPP5_GPIO, /* Fan fail detection */ | |
349 | MPP6_GPIO, /* Red front LED (0 = Off, 1 = On) */ | |
350 | MPP7_GPIO, /* Disable initial blinking on front LED */ | |
351 | MPP8_GPIO, /* Rear power switch (on|auto) */ | |
352 | MPP9_GPIO, /* Rear power switch (auto|off) */ | |
353 | MPP10_GPIO, /* SATA 1 red LED (0 = Off, 1 = On) */ | |
354 | MPP11_GPIO, /* SATA 0 red LED (0 = Off, 1 = On) */ | |
355 | MPP12_GPIO, /* Board ID (bit 1) */ | |
356 | MPP13_GPIO, /* SATA 1 blue LED blink control */ | |
357 | MPP14_SATA_LED, | |
358 | MPP15_SATA_LED, | |
359 | MPP16_GPIO, /* Blue front LED control */ | |
360 | MPP17_GPIO, /* SATA 0 blue LED blink control */ | |
361 | MPP18_GPIO, /* Front button (0 = Released, 1 = Pushed ) */ | |
362 | MPP19_GPIO, /* SATA{0,1} power On/Off request */ | |
363 | 0, | |
54782674 SG |
364 | /* 22: USB port 1 fuse (0 = Fail, 1 = Ok) */ |
365 | /* 23: SATA 0 power status */ | |
366 | /* 24: Board power off */ | |
367 | /* 25: SATA 1 power status */ | |
368 | }; | |
369 | ||
370 | #define NET2BIG_GPIO_POWER_OFF 24 | |
371 | ||
372 | static void net2big_power_off(void) | |
373 | { | |
374 | gpio_set_value(NET2BIG_GPIO_POWER_OFF, 1); | |
375 | } | |
376 | ||
377 | static void __init net2big_init(void) | |
378 | { | |
379 | /* | |
380 | * Setup basic Orion functions. Need to be called early. | |
381 | */ | |
382 | orion5x_init(); | |
383 | ||
384 | orion5x_mpp_conf(net2big_mpp_modes); | |
385 | ||
386 | /* | |
387 | * Configure peripherals. | |
388 | */ | |
389 | orion5x_ehci0_init(); | |
390 | orion5x_ehci1_init(); | |
391 | orion5x_eth_init(&net2big_eth_data); | |
392 | orion5x_i2c_init(); | |
393 | orion5x_uart0_init(); | |
394 | orion5x_xor_init(); | |
395 | ||
396 | net2big_sata_power_init(); | |
397 | orion5x_sata_init(&net2big_sata_data); | |
398 | ||
399 | orion5x_setup_dev_boot_win(NET2BIG_NOR_BOOT_BASE, | |
400 | NET2BIG_NOR_BOOT_SIZE); | |
401 | platform_device_register(&net2big_nor_flash); | |
402 | ||
403 | platform_device_register(&net2big_gpio_buttons); | |
404 | net2big_gpio_leds_init(); | |
405 | ||
406 | i2c_register_board_info(0, net2big_i2c_devices, | |
407 | ARRAY_SIZE(net2big_i2c_devices)); | |
408 | ||
409 | orion_gpio_set_valid(NET2BIG_GPIO_POWER_OFF, 1); | |
410 | ||
411 | if (gpio_request(NET2BIG_GPIO_POWER_OFF, "power-off") == 0 && | |
412 | gpio_direction_output(NET2BIG_GPIO_POWER_OFF, 0) == 0) | |
413 | pm_power_off = net2big_power_off; | |
414 | else | |
415 | pr_err("net2big: failed to configure power-off GPIO\n"); | |
416 | ||
417 | pr_notice("net2big: Flash writing is not yet supported.\n"); | |
418 | } | |
419 | ||
420 | /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */ | |
421 | MACHINE_START(NET2BIG, "LaCie 2Big Network") | |
54782674 SG |
422 | .boot_params = 0x00000100, |
423 | .init_machine = net2big_init, | |
424 | .map_io = orion5x_map_io, | |
4ee1f6b5 | 425 | .init_early = orion5x_init_early, |
54782674 SG |
426 | .init_irq = orion5x_init_irq, |
427 | .timer = &orion5x_timer, | |
428 | .fixup = tag_fixup_mem32, | |
429 | MACHINE_END | |
430 |