1 /*
2  * arch/arm/mach-orion5x/d2net-setup.c
3  *
4  * LaCie d2Network and Big Disk 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/pci.h>
17 #include <linux/irq.h>
18 #include <linux/mtd/physmap.h>
19 #include <linux/mv643xx_eth.h>
20 #include <linux/leds.h>
21 #include <linux/gpio_keys.h>
22 #include <linux/input.h>
23 #include <linux/i2c.h>
24 #include <linux/ata_platform.h>
25 #include <linux/gpio.h>
26 #include <asm/mach-types.h>
27 #include <asm/mach/arch.h>
28 #include <asm/mach/pci.h>
29 #include <mach/orion5x.h>
30 #include "common.h"
31 #include "mpp.h"
32 
33 /*****************************************************************************
34  * LaCie d2 Network Info
35  ****************************************************************************/
36 
37 /*
38  * 512KB NOR flash Device bus boot chip select
39  */
40 
41 #define D2NET_NOR_BOOT_BASE		0xfff80000
42 #define D2NET_NOR_BOOT_SIZE		SZ_512K
43 
44 /*****************************************************************************
45  * 512KB NOR Flash on Boot Device
46  ****************************************************************************/
47 
48 /*
49  * TODO: Check write support on flash MX29LV400CBTC-70G
50  */
51 
52 static struct mtd_partition d2net_partitions[] = {
53 	{
54 		.name		= "Full512kb",
55 		.size		= MTDPART_SIZ_FULL,
56 		.offset		= 0,
57 		.mask_flags	= MTD_WRITEABLE,
58 	},
59 };
60 
61 static struct physmap_flash_data d2net_nor_flash_data = {
62 	.width		= 1,
63 	.parts		= d2net_partitions,
64 	.nr_parts	= ARRAY_SIZE(d2net_partitions),
65 };
66 
67 static struct resource d2net_nor_flash_resource = {
68 	.flags			= IORESOURCE_MEM,
69 	.start			= D2NET_NOR_BOOT_BASE,
70 	.end			= D2NET_NOR_BOOT_BASE
71 					+ D2NET_NOR_BOOT_SIZE - 1,
72 };
73 
74 static struct platform_device d2net_nor_flash = {
75 	.name			= "physmap-flash",
76 	.id			= 0,
77 	.dev		= {
78 		.platform_data	= &d2net_nor_flash_data,
79 	},
80 	.num_resources		= 1,
81 	.resource		= &d2net_nor_flash_resource,
82 };
83 
84 /*****************************************************************************
85  * Ethernet
86  ****************************************************************************/
87 
88 static struct mv643xx_eth_platform_data d2net_eth_data = {
89 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
90 };
91 
92 /*****************************************************************************
93  * I2C devices
94  ****************************************************************************/
95 
96 /*
97  * i2c addr | chip         | description
98  * 0x32     | Ricoh 5C372b | RTC
99  * 0x3e     | GMT G762     | PWM fan controller
100  * 0x50     | HT24LC08     | eeprom (1kB)
101  *
102  * TODO: Add G762 support to the g760a driver.
103  */
104 static struct i2c_board_info __initdata d2net_i2c_devices[] = {
105 	{
106 		I2C_BOARD_INFO("rs5c372b", 0x32),
107 	}, {
108 		I2C_BOARD_INFO("24c08", 0x50),
109 	},
110 };
111 
112 /*****************************************************************************
113  * SATA
114  ****************************************************************************/
115 
116 static struct mv_sata_platform_data d2net_sata_data = {
117 	.n_ports	= 2,
118 };
119 
120 #define D2NET_GPIO_SATA0_POWER	3
121 #define D2NET_GPIO_SATA1_POWER	12
122 
d2net_sata_power_init(void)123 static void __init d2net_sata_power_init(void)
124 {
125 	int err;
126 
127 	err = gpio_request(D2NET_GPIO_SATA0_POWER, "SATA0 power");
128 	if (err == 0) {
129 		err = gpio_direction_output(D2NET_GPIO_SATA0_POWER, 1);
130 		if (err)
131 			gpio_free(D2NET_GPIO_SATA0_POWER);
132 	}
133 	if (err)
134 		pr_err("d2net: failed to configure SATA0 power GPIO\n");
135 
136 	err = gpio_request(D2NET_GPIO_SATA1_POWER, "SATA1 power");
137 	if (err == 0) {
138 		err = gpio_direction_output(D2NET_GPIO_SATA1_POWER, 1);
139 		if (err)
140 			gpio_free(D2NET_GPIO_SATA1_POWER);
141 	}
142 	if (err)
143 		pr_err("d2net: failed to configure SATA1 power GPIO\n");
144 }
145 
146 /*****************************************************************************
147  * GPIO LED's
148  ****************************************************************************/
149 
150 /*
151  * The blue front LED is wired to the CPLD and can blink in relation with the
152  * SATA activity.
153  *
154  * The following array detail the different LED registers and the combination
155  * of their possible values:
156  *
157  * led_off   | blink_ctrl | SATA active | LED state
158  *           |            |             |
159  *    1      |     x      |      x      |  off
160  *    0      |     0      |      0      |  off
161  *    0      |     1      |      0      |  blink (rate 300ms)
162  *    0      |     x      |      1      |  on
163  *
164  * Notes: The blue and the red front LED's can't be on at the same time.
165  *        Red LED have priority.
166  */
167 
168 #define D2NET_GPIO_RED_LED		6
169 #define D2NET_GPIO_BLUE_LED_BLINK_CTRL	16
170 #define D2NET_GPIO_BLUE_LED_OFF		23
171 
172 static struct gpio_led d2net_leds[] = {
173 	{
174 		.name = "d2net:blue:sata",
175 		.default_trigger = "default-on",
176 		.gpio = D2NET_GPIO_BLUE_LED_OFF,
177 		.active_low = 1,
178 	},
179 	{
180 		.name = "d2net:red:fail",
181 		.gpio = D2NET_GPIO_RED_LED,
182 	},
183 };
184 
185 static struct gpio_led_platform_data d2net_led_data = {
186 	.num_leds = ARRAY_SIZE(d2net_leds),
187 	.leds = d2net_leds,
188 };
189 
190 static struct platform_device d2net_gpio_leds = {
191 	.name           = "leds-gpio",
192 	.id             = -1,
193 	.dev            = {
194 		.platform_data  = &d2net_led_data,
195 	},
196 };
197 
d2net_gpio_leds_init(void)198 static void __init d2net_gpio_leds_init(void)
199 {
200 	int err;
201 
202 	/* Configure GPIO over MPP max number. */
203 	orion_gpio_set_valid(D2NET_GPIO_BLUE_LED_OFF, 1);
204 
205 	/* Configure register blink_ctrl to allow SATA activity LED blinking. */
206 	err = gpio_request(D2NET_GPIO_BLUE_LED_BLINK_CTRL, "blue LED blink");
207 	if (err == 0) {
208 		err = gpio_direction_output(D2NET_GPIO_BLUE_LED_BLINK_CTRL, 1);
209 		if (err)
210 			gpio_free(D2NET_GPIO_BLUE_LED_BLINK_CTRL);
211 	}
212 	if (err)
213 		pr_err("d2net: failed to configure blue LED blink GPIO\n");
214 
215 	platform_device_register(&d2net_gpio_leds);
216 }
217 
218 /****************************************************************************
219  * GPIO keys
220  ****************************************************************************/
221 
222 #define D2NET_GPIO_PUSH_BUTTON		18
223 #define D2NET_GPIO_POWER_SWITCH_ON	8
224 #define D2NET_GPIO_POWER_SWITCH_OFF	9
225 
226 #define D2NET_SWITCH_POWER_ON		0x1
227 #define D2NET_SWITCH_POWER_OFF		0x2
228 
229 static struct gpio_keys_button d2net_buttons[] = {
230 	{
231 		.type		= EV_SW,
232 		.code		= D2NET_SWITCH_POWER_OFF,
233 		.gpio		= D2NET_GPIO_POWER_SWITCH_OFF,
234 		.desc		= "Power rocker switch (auto|off)",
235 		.active_low	= 0,
236 	},
237 	{
238 		.type		= EV_SW,
239 		.code		= D2NET_SWITCH_POWER_ON,
240 		.gpio		= D2NET_GPIO_POWER_SWITCH_ON,
241 		.desc		= "Power rocker switch (on|auto)",
242 		.active_low	= 0,
243 	},
244 	{
245 		.type		= EV_KEY,
246 		.code		= KEY_POWER,
247 		.gpio		= D2NET_GPIO_PUSH_BUTTON,
248 		.desc		= "Front Push Button",
249 		.active_low	= 0,
250 	},
251 };
252 
253 static struct gpio_keys_platform_data d2net_button_data = {
254 	.buttons	= d2net_buttons,
255 	.nbuttons	= ARRAY_SIZE(d2net_buttons),
256 };
257 
258 static struct platform_device d2net_gpio_buttons = {
259 	.name		= "gpio-keys",
260 	.id		= -1,
261 	.dev		= {
262 		.platform_data	= &d2net_button_data,
263 	},
264 };
265 
266 /*****************************************************************************
267  * General Setup
268  ****************************************************************************/
269 
270 static unsigned int d2net_mpp_modes[] __initdata = {
271 	MPP0_GPIO,	/* Board ID (bit 0) */
272 	MPP1_GPIO,	/* Board ID (bit 1) */
273 	MPP2_GPIO,	/* Board ID (bit 2) */
274 	MPP3_GPIO,	/* SATA 0 power */
275 	MPP4_UNUSED,
276 	MPP5_GPIO,	/* Fan fail detection */
277 	MPP6_GPIO,	/* Red front LED */
278 	MPP7_UNUSED,
279 	MPP8_GPIO,	/* Rear power switch (on|auto) */
280 	MPP9_GPIO,	/* Rear power switch (auto|off) */
281 	MPP10_UNUSED,
282 	MPP11_UNUSED,
283 	MPP12_GPIO,	/* SATA 1 power */
284 	MPP13_UNUSED,
285 	MPP14_SATA_LED,	/* SATA 0 active */
286 	MPP15_SATA_LED,	/* SATA 1 active */
287 	MPP16_GPIO,	/* Blue front LED blink control */
288 	MPP17_UNUSED,
289 	MPP18_GPIO,	/* Front button (0 = Released, 1 = Pushed ) */
290 	MPP19_UNUSED,
291 	0,
292 	/* 22: USB port 1 fuse (0 = Fail, 1 = Ok) */
293 	/* 23: Blue front LED off */
294 	/* 24: Inhibit board power off (0 = Disabled, 1 = Enabled) */
295 };
296 
297 #define D2NET_GPIO_INHIBIT_POWER_OFF    24
298 
d2net_init(void)299 static void __init d2net_init(void)
300 {
301 	/*
302 	 * Setup basic Orion functions. Need to be called early.
303 	 */
304 	orion5x_init();
305 
306 	orion5x_mpp_conf(d2net_mpp_modes);
307 
308 	/*
309 	 * Configure peripherals.
310 	 */
311 	orion5x_ehci0_init();
312 	orion5x_eth_init(&d2net_eth_data);
313 	orion5x_i2c_init();
314 	orion5x_uart0_init();
315 
316 	d2net_sata_power_init();
317 	orion5x_sata_init(&d2net_sata_data);
318 
319 	orion5x_setup_dev_boot_win(D2NET_NOR_BOOT_BASE,
320 				D2NET_NOR_BOOT_SIZE);
321 	platform_device_register(&d2net_nor_flash);
322 
323 	platform_device_register(&d2net_gpio_buttons);
324 
325 	d2net_gpio_leds_init();
326 
327 	pr_notice("d2net: Flash write are not yet supported.\n");
328 
329 	i2c_register_board_info(0, d2net_i2c_devices,
330 				ARRAY_SIZE(d2net_i2c_devices));
331 
332 	orion_gpio_set_valid(D2NET_GPIO_INHIBIT_POWER_OFF, 1);
333 }
334 
335 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
336 
337 #ifdef CONFIG_MACH_D2NET
338 MACHINE_START(D2NET, "LaCie d2 Network")
339 	.atag_offset	= 0x100,
340 	.init_machine	= d2net_init,
341 	.map_io		= orion5x_map_io,
342 	.init_early	= orion5x_init_early,
343 	.init_irq	= orion5x_init_irq,
344 	.timer		= &orion5x_timer,
345 	.fixup		= tag_fixup_mem32,
346 	.restart	= orion5x_restart,
347 MACHINE_END
348 #endif
349 
350 #ifdef CONFIG_MACH_BIGDISK
351 MACHINE_START(BIGDISK, "LaCie Big Disk Network")
352 	.atag_offset	= 0x100,
353 	.init_machine	= d2net_init,
354 	.map_io		= orion5x_map_io,
355 	.init_early	= orion5x_init_early,
356 	.init_irq	= orion5x_init_irq,
357 	.timer		= &orion5x_timer,
358 	.fixup		= tag_fixup_mem32,
359 	.restart	= orion5x_restart,
360 MACHINE_END
361 #endif
362 
363