File Index
Files and directories
Sign in
FILE

dns323-setup.c

File preview with syntax highlighting.

linux-6.19.14/arch/arm/mach-orion5x/dns323-setup.c C
  1/*
  2 * arch/arm/mach-orion5x/dns323-setup.c
  3 *
  4 * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
  5 *
  6 * Support for HW Rev C1:
  7 *
  8 * Copyright (C) 2010 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU Lesser General Public License as
 12 * published by the Free Software Foundation; either version 2 of the
 13 * License, or (at your option) any later version.
 14 *
 15 */
 16#include <linux/gpio.h>
 17#include <linux/gpio/machine.h>
 18#include <linux/kernel.h>
 19#include <linux/init.h>
 20#include <linux/delay.h>
 21#include <linux/platform_device.h>
 22#include <linux/pci.h>
 23#include <linux/irq.h>
 24#include <linux/mtd/physmap.h>
 25#include <linux/mv643xx_eth.h>
 26#include <linux/leds.h>
 27#include <linux/gpio_keys.h>
 28#include <linux/input.h>
 29#include <linux/i2c.h>
 30#include <linux/ata_platform.h>
 31#include <linux/phy.h>
 32#include <linux/marvell_phy.h>
 33#include <asm/mach-types.h>
 34#include <asm/mach/arch.h>
 35#include <asm/mach/pci.h>
 36#include <asm/system_info.h>
 37#include <plat/orion-gpio.h>
 38#include "orion5x.h"
 39#include "common.h"
 40#include "mpp.h"
 41
 42/* Rev A1 and B1 */
 43#define DNS323_GPIO_LED_RIGHT_AMBER	1
 44#define DNS323_GPIO_LED_LEFT_AMBER	2
 45#define DNS323_GPIO_SYSTEM_UP		3
 46#define DNS323_GPIO_LED_POWER1		4
 47#define DNS323_GPIO_LED_POWER2		5
 48#define DNS323_GPIO_OVERTEMP		6
 49#define DNS323_GPIO_RTC			7
 50#define DNS323_GPIO_POWER_OFF		8
 51#define DNS323_GPIO_KEY_POWER		9
 52#define DNS323_GPIO_KEY_RESET		10
 53
 54/* Rev C1 */
 55#define DNS323C_GPIO_KEY_POWER		1
 56#define DNS323C_GPIO_POWER_OFF		2
 57#define DNS323C_GPIO_LED_RIGHT_AMBER	8
 58#define DNS323C_GPIO_LED_LEFT_AMBER	9
 59#define DNS323C_GPIO_LED_POWER		17
 60#define DNS323C_GPIO_FAN_BIT1		18
 61#define DNS323C_GPIO_FAN_BIT0		19
 62
 63/* Exposed to userspace, do not change */
 64enum {
 65	DNS323_REV_A1,	/* 0 */
 66	DNS323_REV_B1,	/* 1 */
 67	DNS323_REV_C1,	/* 2 */
 68};
 69
 70
 71/****************************************************************************
 72 * PCI setup
 73 */
 74
 75static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 76{
 77	int irq;
 78
 79	/*
 80	 * Check for devices with hard-wired IRQs.
 81	 */
 82	irq = orion5x_pci_map_irq(dev, slot, pin);
 83	if (irq != -1)
 84		return irq;
 85
 86	return -1;
 87}
 88
 89static struct hw_pci dns323_pci __initdata = {
 90	.nr_controllers = 2,
 91	.setup		= orion5x_pci_sys_setup,
 92	.scan		= orion5x_pci_sys_scan_bus,
 93	.map_irq	= dns323_pci_map_irq,
 94};
 95
 96static int __init dns323_pci_init(void)
 97{
 98	/* Rev B1 and C1 doesn't really use its PCI bus, and initialising PCI
 99	 * gets in the way of initialising the SATA controller.
100	 */
101	if (machine_is_dns323() && system_rev == DNS323_REV_A1)
102		pci_common_init(&dns323_pci);
103
104	return 0;
105}
106
107subsys_initcall(dns323_pci_init);
108
109/****************************************************************************
110 * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
111 *
112 * Layout as used by D-Link:
113 *  0x00000000-0x00010000 : "MTD1"
114 *  0x00010000-0x00020000 : "MTD2"
115 *  0x00020000-0x001a0000 : "Linux Kernel"
116 *  0x001a0000-0x007d0000 : "File System"
117 *  0x007d0000-0x00800000 : "u-boot"
118 */
119
120#define DNS323_NOR_BOOT_BASE 0xf4000000
121#define DNS323_NOR_BOOT_SIZE SZ_8M
122
123static struct mtd_partition dns323_partitions[] = {
124	{
125		.name	= "MTD1",
126		.size	= 0x00010000,
127		.offset	= 0,
128	}, {
129		.name	= "MTD2",
130		.size	= 0x00010000,
131		.offset = 0x00010000,
132	}, {
133		.name	= "Linux Kernel",
134		.size	= 0x00180000,
135		.offset	= 0x00020000,
136	}, {
137		.name	= "File System",
138		.size	= 0x00630000,
139		.offset	= 0x001A0000,
140	}, {
141		.name	= "u-boot",
142		.size	= 0x00030000,
143		.offset	= 0x007d0000,
144	},
145};
146
147static struct physmap_flash_data dns323_nor_flash_data = {
148	.width		= 1,
149	.parts		= dns323_partitions,
150	.nr_parts	= ARRAY_SIZE(dns323_partitions)
151};
152
153static struct resource dns323_nor_flash_resource = {
154	.flags		= IORESOURCE_MEM,
155	.start		= DNS323_NOR_BOOT_BASE,
156	.end		= DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
157};
158
159static struct platform_device dns323_nor_flash = {
160	.name		= "physmap-flash",
161	.id		= 0,
162	.dev		= {
163		.platform_data	= &dns323_nor_flash_data,
164	},
165	.resource	= &dns323_nor_flash_resource,
166	.num_resources	= 1,
167};
168
169/****************************************************************************
170 * Ethernet
171 */
172
173static struct mv643xx_eth_platform_data dns323_eth_data = {
174	.phy_addr = MV643XX_ETH_PHY_ADDR(8),
175};
176
177/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these
178 * functions be kept somewhere?
179 */
180static int __init dns323_parse_hex_nibble(char n)
181{
182	if (n >= '0' && n <= '9')
183		return n - '0';
184
185	if (n >= 'A' && n <= 'F')
186		return n - 'A' + 10;
187
188	if (n >= 'a' && n <= 'f')
189		return n - 'a' + 10;
190
191	return -1;
192}
193
194static int __init dns323_parse_hex_byte(const char *b)
195{
196	int hi;
197	int lo;
198
199	hi = dns323_parse_hex_nibble(b[0]);
200	lo = dns323_parse_hex_nibble(b[1]);
201
202	if (hi < 0 || lo < 0)
203		return -1;
204
205	return (hi << 4) | lo;
206}
207
208static int __init dns323_read_mac_addr(void)
209{
210	u_int8_t addr[6];
211	int i;
212	char *mac_page;
213
214	/* MAC address is stored as a regular ol' string in /dev/mtdblock4
215	 * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80).
216	 */
217	mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024);
218	if (!mac_page)
219		return -ENOMEM;
220
221	/* Sanity check the string we're looking at */
222	for (i = 0; i < 5; i++) {
223		if (*(mac_page + (i * 3) + 2) != ':') {
224			goto error_fail;
225		}
226	}
227
228	for (i = 0; i < 6; i++)	{
229		int byte;
230
231		byte = dns323_parse_hex_byte(mac_page + (i * 3));
232		if (byte < 0) {
233			goto error_fail;
234		}
235
236		addr[i] = byte;
237	}
238
239	iounmap(mac_page);
240	printk("DNS-323: Found ethernet MAC address: %pM\n", addr);
241
242	memcpy(dns323_eth_data.mac_addr, addr, 6);
243
244	return 0;
245
246error_fail:
247	iounmap(mac_page);
248	return -EINVAL;
249}
250
251/****************************************************************************
252 * GPIO LEDs (simple - doesn't use hardware blinking support)
253 */
254
255static struct gpio_led dns323ab_leds[] = {
256	{
257		.name = "power:blue",
258		.default_trigger = "default-on",
259	}, {
260		.name = "right:amber",
261	}, {
262		.name = "left:amber",
263	},
264};
265
266static struct gpiod_lookup_table dns323a1_leds_gpio_table = {
267	.dev_id = "leds-gpio",
268	.table = {
269		GPIO_LOOKUP_IDX("orion_gpio0", DNS323_GPIO_LED_POWER2, NULL,
270				0, GPIO_ACTIVE_LOW),
271		GPIO_LOOKUP_IDX("orion_gpio0", DNS323_GPIO_LED_RIGHT_AMBER, NULL,
272				1, GPIO_ACTIVE_LOW),
273		GPIO_LOOKUP_IDX("orion_gpio0", DNS323_GPIO_LED_LEFT_AMBER, NULL,
274				2, GPIO_ACTIVE_LOW),
275		{ },
276	},
277};
278
279/* B1 is the same but power LED is active high */
280static struct gpiod_lookup_table dns323b1_leds_gpio_table = {
281	.dev_id = "leds-gpio",
282	.table = {
283		GPIO_LOOKUP_IDX("orion_gpio0", DNS323_GPIO_LED_POWER2, NULL,
284				0, GPIO_ACTIVE_HIGH),
285		GPIO_LOOKUP_IDX("orion_gpio0", DNS323_GPIO_LED_RIGHT_AMBER, NULL,
286				1, GPIO_ACTIVE_LOW),
287		GPIO_LOOKUP_IDX("orion_gpio0", DNS323_GPIO_LED_LEFT_AMBER, NULL,
288				2, GPIO_ACTIVE_LOW),
289		{ },
290	},
291};
292
293static struct gpio_led dns323c_leds[] = {
294	{
295		.name = "power:blue",
296		.default_trigger = "timer",
297	}, {
298		.name = "right:amber",
299	}, {
300		.name = "left:amber",
301	},
302};
303
304static struct gpiod_lookup_table dns323c_leds_gpio_table = {
305	.dev_id = "leds-gpio",
306	.table = {
307		GPIO_LOOKUP_IDX("orion_gpio0", DNS323C_GPIO_LED_POWER, NULL,
308				0, GPIO_ACTIVE_LOW),
309		GPIO_LOOKUP_IDX("orion_gpio0", DNS323C_GPIO_LED_RIGHT_AMBER, NULL,
310				1, GPIO_ACTIVE_LOW),
311		GPIO_LOOKUP_IDX("orion_gpio0", DNS323C_GPIO_LED_LEFT_AMBER, NULL,
312				2, GPIO_ACTIVE_LOW),
313		{ },
314	},
315};
316
317static struct gpio_led_platform_data dns323ab_led_data = {
318	.num_leds	= ARRAY_SIZE(dns323ab_leds),
319	.leds		= dns323ab_leds,
320	.gpio_blink_set = orion_gpio_led_blink_set,
321};
322
323static struct gpio_led_platform_data dns323c_led_data = {
324	.num_leds	= ARRAY_SIZE(dns323c_leds),
325	.leds		= dns323c_leds,
326	.gpio_blink_set = orion_gpio_led_blink_set,
327};
328
329static struct platform_device dns323_gpio_leds = {
330	.name		= "leds-gpio",
331	.id		= -1,
332	.dev		= {
333		.platform_data	= &dns323ab_led_data,
334	},
335};
336
337/****************************************************************************
338 * GPIO Attached Keys
339 */
340
341static struct gpio_keys_button dns323ab_buttons[] = {
342	{
343		.code		= KEY_RESTART,
344		.gpio		= DNS323_GPIO_KEY_RESET,
345		.desc		= "Reset Button",
346		.active_low	= 1,
347	}, {
348		.code		= KEY_POWER,
349		.gpio		= DNS323_GPIO_KEY_POWER,
350		.desc		= "Power Button",
351		.active_low	= 1,
352	},
353};
354
355static struct gpio_keys_platform_data dns323ab_button_data = {
356	.buttons	= dns323ab_buttons,
357	.nbuttons	= ARRAY_SIZE(dns323ab_buttons),
358};
359
360static struct gpio_keys_button dns323c_buttons[] = {
361	{
362		.code		= KEY_POWER,
363		.gpio		= DNS323C_GPIO_KEY_POWER,
364		.desc		= "Power Button",
365		.active_low	= 1,
366	},
367};
368
369static struct gpio_keys_platform_data dns323c_button_data = {
370	.buttons	= dns323c_buttons,
371	.nbuttons	= ARRAY_SIZE(dns323c_buttons),
372};
373
374static struct platform_device dns323_button_device = {
375	.name		= "gpio-keys",
376	.id		= -1,
377	.num_resources	= 0,
378	.dev		= {
379		.platform_data	= &dns323ab_button_data,
380	},
381};
382
383/*****************************************************************************
384 * SATA
385 */
386static struct mv_sata_platform_data dns323_sata_data = {
387       .n_ports        = 2,
388};
389
390/****************************************************************************
391 * General Setup
392 */
393static unsigned int dns323a_mpp_modes[] __initdata = {
394	MPP0_PCIE_RST_OUTn,
395	MPP1_GPIO,		/* right amber LED (sata ch0) */
396	MPP2_GPIO,		/* left amber LED (sata ch1) */
397	MPP3_UNUSED,
398	MPP4_GPIO,		/* power button LED */
399	MPP5_GPIO,		/* power button LED */
400	MPP6_GPIO,		/* GMT G751-2f overtemp */
401	MPP7_GPIO,		/* M41T80 nIRQ/OUT/SQW */
402	MPP8_GPIO,		/* triggers power off */
403	MPP9_GPIO,		/* power button switch */
404	MPP10_GPIO,		/* reset button switch */
405	MPP11_UNUSED,
406	MPP12_UNUSED,
407	MPP13_UNUSED,
408	MPP14_UNUSED,
409	MPP15_UNUSED,
410	MPP16_UNUSED,
411	MPP17_UNUSED,
412	MPP18_UNUSED,
413	MPP19_UNUSED,
414	0,
415};
416
417static unsigned int dns323b_mpp_modes[] __initdata = {
418	MPP0_UNUSED,
419	MPP1_GPIO,		/* right amber LED (sata ch0) */
420	MPP2_GPIO,		/* left amber LED (sata ch1) */
421	MPP3_GPIO,		/* system up flag */
422	MPP4_GPIO,		/* power button LED */
423	MPP5_GPIO,		/* power button LED */
424	MPP6_GPIO,		/* GMT G751-2f overtemp */
425	MPP7_GPIO,		/* M41T80 nIRQ/OUT/SQW */
426	MPP8_GPIO,		/* triggers power off */
427	MPP9_GPIO,		/* power button switch */
428	MPP10_GPIO,		/* reset button switch */
429	MPP11_UNUSED,
430	MPP12_SATA_LED,
431	MPP13_SATA_LED,
432	MPP14_SATA_LED,
433	MPP15_SATA_LED,
434	MPP16_UNUSED,
435	MPP17_UNUSED,
436	MPP18_UNUSED,
437	MPP19_UNUSED,
438	0,
439};
440
441static unsigned int dns323c_mpp_modes[] __initdata = {
442	MPP0_GPIO,		/* ? input */
443	MPP1_GPIO,		/* input power switch (0 = pressed) */
444	MPP2_GPIO,		/* output power off */
445	MPP3_UNUSED,		/* ? output */
446	MPP4_UNUSED,		/* ? output */
447	MPP5_UNUSED,		/* ? output */
448	MPP6_UNUSED,		/* ? output */
449	MPP7_UNUSED,		/* ? output */
450	MPP8_GPIO,		/* i/o right amber LED */
451	MPP9_GPIO,		/* i/o left amber LED */
452	MPP10_GPIO,		/* input */
453	MPP11_UNUSED,
454	MPP12_SATA_LED,
455	MPP13_SATA_LED,
456	MPP14_SATA_LED,
457	MPP15_SATA_LED,
458	MPP16_UNUSED,
459	MPP17_GPIO,		/* power button LED */
460	MPP18_GPIO,		/* fan speed bit 0 */
461	MPP19_GPIO,		/* fan speed bit 1 */
462	0,
463};
464
465/* Rev C1 Fan speed notes:
466 *
467 * The fan is controlled by 2 GPIOs on this board. The settings
468 * of the bits is as follow:
469 *
470 *  GPIO 18    GPIO 19    Fan
471 *
472 *    0          0        stopped
473 *    0          1        low speed
474 *    1          0        high speed
475 *    1          1        don't do that (*)
476 *
477 * (*) I think the two bits control two feed-in resistors into a fixed
478 *     PWN circuit, setting both bits will basically go a 'bit' faster
479 *     than high speed, but d-link doesn't do it and you may get out of
480 *     HW spec so don't do it.
481 */
482
483/*
484 * On the DNS-323 A1 and B1 the following devices are attached via I2C:
485 *
486 *  i2c addr | chip        | description
487 *  0x3e     | GMT G760Af  | fan speed PWM controller
488 *  0x48     | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
489 *  0x68     | ST M41T80   | RTC w/ alarm
490 */
491static struct i2c_board_info __initdata dns323ab_i2c_devices[] = {
492	{
493		I2C_BOARD_INFO("g760a", 0x3e),
494	}, {
495		I2C_BOARD_INFO("lm75", 0x48),
496	}, {
497		I2C_BOARD_INFO("m41t80", 0x68),
498	},
499};
500
501/*
502 * On the DNS-323 C1 the following devices are attached via I2C:
503 *
504 *  i2c addr | chip        | description
505 *  0x48     | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
506 *  0x68     | ST M41T80   | RTC w/ alarm
507 */
508static struct i2c_board_info __initdata dns323c_i2c_devices[] = {
509	{
510		I2C_BOARD_INFO("lm75", 0x48),
511	}, {
512		I2C_BOARD_INFO("m41t80", 0x68),
513	},
514};
515
516/* DNS-323 rev. A specific power off method */
517static void dns323a_power_off(void)
518{
519	pr_info("DNS-323: Triggering power-off...\n");
520	gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
521}
522
523/* DNS-323 rev B specific power off method */
524static void dns323b_power_off(void)
525{
526	pr_info("DNS-323: Triggering power-off...\n");
527	/* Pin has to be changed to 1 and back to 0 to do actual power off. */
528	gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
529	mdelay(100);
530	gpio_set_value(DNS323_GPIO_POWER_OFF, 0);
531}
532
533/* DNS-323 rev. C specific power off method */
534static void dns323c_power_off(void)
535{
536	pr_info("DNS-323: Triggering power-off...\n");
537	gpio_set_value(DNS323C_GPIO_POWER_OFF, 1);
538}
539
540static int dns323c_phy_fixup(struct phy_device *phy)
541{
542	phy->dev_flags |= MARVELL_PHY_M1118_DNS323_LEDS;
543
544	return 0;
545}
546
547static int __init dns323_identify_rev(void)
548{
549	u32 dev, rev, i, reg;
550
551	pr_debug("DNS-323: Identifying board ... \n");
552
553	/* Rev A1 has a 5181 */
554	orion5x_pcie_id(&dev, &rev);
555	if (dev == MV88F5181_DEV_ID) {
556		pr_debug("DNS-323: 5181 found, board is A1\n");
557		return DNS323_REV_A1;
558	}
559	pr_debug("DNS-323: 5182 found, board is B1 or C1, checking PHY...\n");
560
561	/* Rev B1 and C1 both have 5182, let's poke at the eth PHY. This is
562	 * a bit gross but we want to do that without links into the eth
563	 * driver so let's poke at it directly. We default to rev B1 in
564	 * case the accesses fail
565	 */
566
567#define ETH_SMI_REG		(ORION5X_ETH_VIRT_BASE + 0x2000 + 0x004)
568#define  SMI_BUSY		0x10000000
569#define  SMI_READ_VALID		0x08000000
570#define  SMI_OPCODE_READ	0x04000000
571#define  SMI_OPCODE_WRITE	0x00000000
572
573	for (i = 0; i < 1000; i++) {
574		reg = readl(ETH_SMI_REG);
575		if (!(reg & SMI_BUSY))
576			break;
577	}
578	if (i >= 1000) {
579		pr_warn("DNS-323: Timeout accessing PHY, assuming rev B1\n");
580		return DNS323_REV_B1;
581	}
582	writel((3 << 21)	/* phy ID reg */ |
583	       (8 << 16)	/* phy addr */ |
584	       SMI_OPCODE_READ, ETH_SMI_REG);
585	for (i = 0; i < 1000; i++) {
586		reg = readl(ETH_SMI_REG);
587		if (reg & SMI_READ_VALID)
588			break;
589	}
590	if (i >= 1000) {
591		pr_warn("DNS-323: Timeout reading PHY, assuming rev B1\n");
592		return DNS323_REV_B1;
593	}
594	pr_debug("DNS-323: Ethernet PHY ID 0x%x\n", reg & 0xffff);
595
596	/* Note: the Marvell tools mask the ID with 0x3f0 before comparison
597	 * but I don't see that making a difference here, at least with
598	 * any known Marvell PHY ID
599	 */
600	switch(reg & 0xfff0) {
601	case 0x0cc0: /* MV88E1111 */
602		return DNS323_REV_B1;
603	case 0x0e10: /* MV88E1118 */
604		return DNS323_REV_C1;
605	default:
606		pr_warn("DNS-323: Unknown PHY ID 0x%04x, assuming rev B1\n",
607			reg & 0xffff);
608	}
609	return DNS323_REV_B1;
610}
611
612static void __init dns323_init(void)
613{
614	/* Setup basic Orion functions. Need to be called early. */
615	orion5x_init();
616
617	/* Identify revision */
618	system_rev = dns323_identify_rev();
619	pr_info("DNS-323: Identified HW revision %c1\n", 'A' + system_rev);
620
621	/* Just to be tricky, the 5182 has a completely different
622	 * set of MPP modes to the 5181.
623	 */
624	switch(system_rev) {
625	case DNS323_REV_A1:
626		orion5x_mpp_conf(dns323a_mpp_modes);
627		writel(0, MPP_DEV_CTRL);		/* DEV_D[31:16] */
628		break;
629	case DNS323_REV_B1:
630		orion5x_mpp_conf(dns323b_mpp_modes);
631		break;
632	case DNS323_REV_C1:
633		orion5x_mpp_conf(dns323c_mpp_modes);
634		break;
635	}
636
637	/* setup flash mapping
638	 * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
639	 */
640	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
641				    ORION_MBUS_DEVBUS_BOOT_ATTR,
642				    DNS323_NOR_BOOT_BASE,
643				    DNS323_NOR_BOOT_SIZE);
644	platform_device_register(&dns323_nor_flash);
645
646	/* Sort out LEDs, Buttons and i2c devices */
647	switch(system_rev) {
648	case DNS323_REV_A1:
649		/* The 5181 power LED is active low and requires
650		 * DNS323_GPIO_LED_POWER1 to also be low.
651		 */
652		gpiod_add_lookup_table(&dns323a1_leds_gpio_table);
653		gpio_request(DNS323_GPIO_LED_POWER1, "Power Led Enable");
654		gpio_direction_output(DNS323_GPIO_LED_POWER1, 0);
655		i2c_register_board_info(0, dns323ab_i2c_devices,
656					ARRAY_SIZE(dns323ab_i2c_devices));
657
658		break;
659	case DNS323_REV_B1:
660		gpiod_add_lookup_table(&dns323b1_leds_gpio_table);
661		i2c_register_board_info(0, dns323ab_i2c_devices,
662				ARRAY_SIZE(dns323ab_i2c_devices));
663		break;
664	case DNS323_REV_C1:
665		/* Hookup LEDs & Buttons */
666		gpiod_add_lookup_table(&dns323c_leds_gpio_table);
667		dns323_gpio_leds.dev.platform_data = &dns323c_led_data;
668		dns323_button_device.dev.platform_data = &dns323c_button_data;
669
670		/* Hookup i2c devices and fan driver */
671		i2c_register_board_info(0, dns323c_i2c_devices,
672				ARRAY_SIZE(dns323c_i2c_devices));
673		platform_device_register_simple("dns323c-fan", 0, NULL, 0);
674
675		/* Register fixup for the PHY LEDs */
676		if (!IS_BUILTIN(CONFIG_PHYLIB))
677			break;
678		phy_register_fixup_for_uid(MARVELL_PHY_ID_88E1118,
679					   MARVELL_PHY_ID_MASK,
680					   dns323c_phy_fixup);
681	}
682
683	platform_device_register(&dns323_gpio_leds);
684	platform_device_register(&dns323_button_device);
685
686	/*
687	 * Configure peripherals.
688	 */
689	if (dns323_read_mac_addr() < 0)
690		printk("DNS-323: Failed to read MAC address\n");
691	orion5x_ehci0_init();
692	orion5x_eth_init(&dns323_eth_data);
693	orion5x_i2c_init();
694	orion5x_uart0_init();
695
696	/* Remaining GPIOs */
697	switch(system_rev) {
698	case DNS323_REV_A1:
699		/* Poweroff GPIO */
700		if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
701		    gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
702			pr_err("DNS-323: failed to setup power-off GPIO\n");
703		register_platform_power_off(dns323a_power_off);
704		break;
705	case DNS323_REV_B1:
706		/* 5182 built-in SATA init */
707		orion5x_sata_init(&dns323_sata_data);
708
709		/* The DNS323 rev B1 has flag to indicate the system is up.
710		 * Without this flag set, power LED will flash and cannot be
711		 * controlled via leds-gpio.
712		 */
713		if (gpio_request(DNS323_GPIO_SYSTEM_UP, "SYS_READY") == 0)
714			gpio_direction_output(DNS323_GPIO_SYSTEM_UP, 1);
715
716		/* Poweroff GPIO */
717		if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
718		    gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
719			pr_err("DNS-323: failed to setup power-off GPIO\n");
720		register_platform_power_off(dns323b_power_off);
721		break;
722	case DNS323_REV_C1:
723		/* 5182 built-in SATA init */
724		orion5x_sata_init(&dns323_sata_data);
725
726		/* Poweroff GPIO */
727		if (gpio_request(DNS323C_GPIO_POWER_OFF, "POWEROFF") != 0 ||
728		    gpio_direction_output(DNS323C_GPIO_POWER_OFF, 0) != 0)
729			pr_err("DNS-323: failed to setup power-off GPIO\n");
730		register_platform_power_off(dns323c_power_off);
731
732		/* Now, -this- should theoretically be done by the sata_mv driver
733		 * once I figure out what's going on there. Maybe the behaviour
734		 * of the LEDs should be somewhat passed via the platform_data.
735		 * for now, just whack the register and make the LEDs happy
736		 *
737		 * Note: AFAIK, rev B1 needs the same treatment but I'll let
738		 * somebody else test it.
739		 */
740		writel(0x5, ORION5X_SATA_VIRT_BASE + 0x2c);
741		break;
742	}
743}
744
745/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
746MACHINE_START(DNS323, "D-Link DNS-323")
747	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
748	.atag_offset	= 0x100,
749	.nr_irqs	= ORION5X_NR_IRQS,
750	.init_machine	= dns323_init,
751	.map_io		= orion5x_map_io,
752	.init_early	= orion5x_init_early,
753	.init_irq	= orion5x_init_irq,
754	.init_time	= orion5x_timer_init,
755	.fixup		= tag_fixup_mem32,
756	.restart	= orion5x_restart,
757MACHINE_END
~/ Read-only file preview.