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