aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael-Luke Jones <mlj28@cam.ac.uk>2007-04-28 03:31:40 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-05-05 05:06:49 -0400
commit28bd3a0dcce11bea6f99a351cc64053dff00196e (patch)
treea6c467f56fc626c234d6c8e90283384ded566b22 /arch
parent53b2e01be55f3c140e2704cf8d5f99ddba0ff823 (diff)
[ARM] 4318/2: DSM-G600 Board Support
This patch adds support for the D-Link DSM-G600 Rev A. This is an ARM XScale IXP4xx system relatively similar to the NSLU2 and NAS-100D already supported by mainline. An important difference is Gigabit Ethernet support using the Via Velocity chipset. This patch is the combined work of Michael Westerhof and Alessandro Zummo, with contributions from Michael-Luke Jones. This version addresses review comments from rmk and Deepak Saxena. Signed-off-by: Michael-Luke Jones <mlj28@cam.ac.uk> Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Michael Westerhof <mwester@dls.net> Signed-off-by: Deepak Saxena <dsaxena@plexity.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig9
-rw-r--r--arch/arm/mach-ixp4xx/Makefile2
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-pci.c74
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-power.c125
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c175
5 files changed, 385 insertions, 0 deletions
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index dd0fb7239a80..9715ef506c24 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -95,6 +95,15 @@ config MACH_NAS100D
95 NAS 100d device. For more information on this platform, 95 NAS 100d device. For more information on this platform,
96 see http://www.nslu2-linux.org/wiki/NAS100d/HomePage 96 see http://www.nslu2-linux.org/wiki/NAS100d/HomePage
97 97
98config MACH_DSMG600
99 bool
100 prompt "D-Link DSM-G600 RevA"
101 select PCI
102 help
103 Say 'Y' here if you want your kernel to support D-Link's
104 DSM-G600 RevA device. For more information on this platform,
105 see http://www.nslu2-linux.org/wiki/DSMG600/HomePage
106
98# 107#
99# Avila and IXDP share the same source for now. Will change in future 108# Avila and IXDP share the same source for now. Will change in future
100# 109#
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 746e297284ed..3b87c47e06cf 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -12,6 +12,7 @@ obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o
12obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o 12obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o
13obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o 13obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o
14obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o 14obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o
15obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o
15 16
16obj-y += common.o 17obj-y += common.o
17 18
@@ -22,5 +23,6 @@ obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
22obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o 23obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
23obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o 24obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o
24obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o 25obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o
26obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o
25 27
26obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o 28obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c
new file mode 100644
index 000000000000..9db7e1f42011
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/dsmg600-pci.c
@@ -0,0 +1,74 @@
1/*
2 * DSM-G600 board-level PCI initialization
3 *
4 * Copyright (C) 2006 Tower Technologies
5 * Author: Alessandro Zummo <a.zummo@towertech.it>
6 *
7 * based on ixdp425-pci.c:
8 * Copyright (C) 2002 Intel Corporation.
9 * Copyright (C) 2003-2004 MontaVista Software, Inc.
10 *
11 * Maintainer: http://www.nslu2-linux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 */
18
19#include <linux/pci.h>
20#include <linux/init.h>
21#include <linux/irq.h>
22
23#include <asm/mach/pci.h>
24#include <asm/mach-types.h>
25
26void __init dsmg600_pci_preinit(void)
27{
28 set_irq_type(IRQ_DSMG600_PCI_INTA, IRQT_LOW);
29 set_irq_type(IRQ_DSMG600_PCI_INTB, IRQT_LOW);
30 set_irq_type(IRQ_DSMG600_PCI_INTC, IRQT_LOW);
31 set_irq_type(IRQ_DSMG600_PCI_INTD, IRQT_LOW);
32 set_irq_type(IRQ_DSMG600_PCI_INTE, IRQT_LOW);
33 set_irq_type(IRQ_DSMG600_PCI_INTF, IRQT_LOW);
34
35 ixp4xx_pci_preinit();
36}
37
38static int __init dsmg600_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
39{
40 static int pci_irq_table[DSMG600_PCI_MAX_DEV][DSMG600_PCI_IRQ_LINES] =
41 {
42 { IRQ_DSMG600_PCI_INTE, -1, -1 },
43 { IRQ_DSMG600_PCI_INTA, -1, -1 },
44 { IRQ_DSMG600_PCI_INTB, IRQ_DSMG600_PCI_INTC, IRQ_DSMG600_PCI_INTD },
45 { IRQ_DSMG600_PCI_INTF, -1, -1 },
46 };
47
48 int irq = -1;
49
50 if (slot >= 1 && slot <= DSMG600_PCI_MAX_DEV &&
51 pin >= 1 && pin <= DSMG600_PCI_IRQ_LINES)
52 irq = pci_irq_table[slot-1][pin-1];
53
54 return irq;
55}
56
57struct hw_pci __initdata dsmg600_pci = {
58 .nr_controllers = 1,
59 .preinit = dsmg600_pci_preinit,
60 .swizzle = pci_std_swizzle,
61 .setup = ixp4xx_setup,
62 .scan = ixp4xx_scan_bus,
63 .map_irq = dsmg600_map_irq,
64};
65
66int __init dsmg600_pci_init(void)
67{
68 if (machine_is_dsmg600())
69 pci_common_init(&dsmg600_pci);
70
71 return 0;
72}
73
74subsys_initcall(dsmg600_pci_init);
diff --git a/arch/arm/mach-ixp4xx/dsmg600-power.c b/arch/arm/mach-ixp4xx/dsmg600-power.c
new file mode 100644
index 000000000000..34717872d076
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/dsmg600-power.c
@@ -0,0 +1,125 @@
1/*
2 * arch/arm/mach-ixp4xx/dsmg600-power.c
3 *
4 * DSM-G600 Power/Reset driver
5 * Author: Michael Westerhof <mwester@dls.net>
6 *
7 * Based on nslu2-power.c
8 * Copyright (C) 2005 Tower Technologies
9 * Author: Alessandro Zummo <a.zummo@towertech.it>
10 *
11 * which was based on nslu2-io.c
12 * Copyright (C) 2004 Karen Spearel
13 *
14 * Maintainers: http://www.nslu2-linux.org/
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2 as
18 * published by the Free Software Foundation.
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/reboot.h>
24#include <linux/interrupt.h>
25#include <linux/irq.h>
26#include <linux/jiffies.h>
27#include <linux/timer.h>
28
29#include <asm/mach-types.h>
30
31extern void ctrl_alt_del(void);
32
33/* This is used to make sure the power-button pusher is serious. The button
34 * must be held until the value of this counter reaches zero.
35 */
36static volatile int power_button_countdown;
37
38/* Must hold the button down for at least this many counts to be processed */
39#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
40
41static void dsmg600_power_handler(unsigned long data);
42static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
43
44static void dsmg600_power_handler(unsigned long data)
45{
46 /* This routine is called twice per second to check the
47 * state of the power button.
48 */
49
50 if (*IXP4XX_GPIO_GPINR & DSMG600_PB_BM) {
51
52 /* IO Pin is 1 (button pushed) */
53 if (power_button_countdown == 0) {
54 /* Signal init to do the ctrlaltdel action, this will bypass
55 * init if it hasn't started and do a kernel_restart.
56 */
57 ctrl_alt_del();
58
59 /* Change the state of the power LED to "blink" */
60 gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
61 }
62 power_button_countdown--;
63
64 } else {
65 power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
66 }
67
68 mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
69}
70
71static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
72{
73 /* This is the paper-clip reset, it shuts the machine down directly. */
74 machine_power_off();
75
76 return IRQ_HANDLED;
77}
78
79static int __init dsmg600_power_init(void)
80{
81 if (!(machine_is_dsmg600()))
82 return 0;
83
84 if (request_irq(DSMG600_RB_IRQ, &dsmg600_reset_handler,
85 IRQF_DISABLED | IRQF_TRIGGER_LOW, "DSM-G600 reset button",
86 NULL) < 0) {
87
88 printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
89 DSMG600_RB_IRQ);
90
91 return -EIO;
92 }
93
94 /* The power button on the D-Link DSM-G600 is on GPIO 15, but
95 * it cannot handle interrupts on that GPIO line. So we'll
96 * have to poll it with a kernel timer.
97 */
98
99 /* Make sure that the power button GPIO is set up as an input */
100 gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
101
102 /* Set the initial value for the power button IRQ handler */
103 power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
104
105 mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
106
107 return 0;
108}
109
110static void __exit dsmg600_power_exit(void)
111{
112 if (!(machine_is_dsmg600()))
113 return;
114
115 del_timer_sync(&dsmg600_power_timer);
116
117 free_irq(DSMG600_RB_IRQ, NULL);
118}
119
120module_init(dsmg600_power_init);
121module_exit(dsmg600_power_exit);
122
123MODULE_AUTHOR("Michael Westerhof <mwester@dls.net>");
124MODULE_DESCRIPTION("DSM-G600 Power/Reset driver");
125MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
new file mode 100644
index 000000000000..1caff65e22cc
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -0,0 +1,175 @@
1/*
2 * DSM-G600 board-setup
3 *
4 * Copyright (C) 2006 Tower Technologies
5 * Author: Alessandro Zummo <a.zummo@towertech.it>
6 *
7 * based ixdp425-setup.c:
8 * Copyright (C) 2003-2004 MontaVista Software, Inc.
9 *
10 * Author: Alessandro Zummo <a.zummo@towertech.it>
11 * Maintainers: http://www.nslu2-linux.org/
12 */
13
14#include <linux/kernel.h>
15#include <linux/serial.h>
16#include <linux/serial_8250.h>
17
18#include <asm/mach-types.h>
19#include <asm/mach/arch.h>
20#include <asm/mach/flash.h>
21
22static struct flash_platform_data dsmg600_flash_data = {
23 .map_name = "cfi_probe",
24 .width = 2,
25};
26
27static struct resource dsmg600_flash_resource = {
28 .flags = IORESOURCE_MEM,
29};
30
31static struct platform_device dsmg600_flash = {
32 .name = "IXP4XX-Flash",
33 .id = 0,
34 .dev.platform_data = &dsmg600_flash_data,
35 .num_resources = 1,
36 .resource = &dsmg600_flash_resource,
37};
38
39static struct ixp4xx_i2c_pins dsmg600_i2c_gpio_pins = {
40 .sda_pin = DSMG600_SDA_PIN,
41 .scl_pin = DSMG600_SCL_PIN,
42};
43
44static struct platform_device dsmg600_i2c_controller = {
45 .name = "IXP4XX-I2C",
46 .id = 0,
47 .dev.platform_data = &dsmg600_i2c_gpio_pins,
48};
49
50#ifdef CONFIG_LEDS_CLASS
51static struct resource dsmg600_led_resources[] = {
52 {
53 .name = "power",
54 .start = DSMG600_LED_PWR_GPIO,
55 .end = DSMG600_LED_PWR_GPIO,
56 .flags = IXP4XX_GPIO_HIGH,
57 },
58 {
59 .name = "wlan",
60 .start = DSMG600_LED_WLAN_GPIO,
61 .end = DSMG600_LED_WLAN_GPIO,
62 .flags = IXP4XX_GPIO_LOW,
63 },
64};
65
66static struct platform_device dsmg600_leds = {
67 .name = "IXP4XX-GPIO-LED",
68 .id = -1,
69 .num_resources = ARRAY_SIZE(dsmg600_led_resources),
70 .resource = dsmg600_led_resources,
71};
72#endif
73
74static struct resource dsmg600_uart_resources[] = {
75 {
76 .start = IXP4XX_UART1_BASE_PHYS,
77 .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
78 .flags = IORESOURCE_MEM,
79 },
80 {
81 .start = IXP4XX_UART2_BASE_PHYS,
82 .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
83 .flags = IORESOURCE_MEM,
84 }
85};
86
87static struct plat_serial8250_port dsmg600_uart_data[] = {
88 {
89 .mapbase = IXP4XX_UART1_BASE_PHYS,
90 .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
91 .irq = IRQ_IXP4XX_UART1,
92 .flags = UPF_BOOT_AUTOCONF,
93 .iotype = UPIO_MEM,
94 .regshift = 2,
95 .uartclk = IXP4XX_UART_XTAL,
96 },
97 {
98 .mapbase = IXP4XX_UART2_BASE_PHYS,
99 .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
100 .irq = IRQ_IXP4XX_UART2,
101 .flags = UPF_BOOT_AUTOCONF,
102 .iotype = UPIO_MEM,
103 .regshift = 2,
104 .uartclk = IXP4XX_UART_XTAL,
105 },
106 { }
107};
108
109static struct platform_device dsmg600_uart = {
110 .name = "serial8250",
111 .id = PLAT8250_DEV_PLATFORM,
112 .dev.platform_data = dsmg600_uart_data,
113 .num_resources = ARRAY_SIZE(dsmg600_uart_resources),
114 .resource = dsmg600_uart_resources,
115};
116
117static struct platform_device *dsmg600_devices[] __initdata = {
118 &dsmg600_i2c_controller,
119 &dsmg600_flash,
120};
121
122static void dsmg600_power_off(void)
123{
124 /* enable the pwr cntl gpio */
125 gpio_line_config(DSMG600_PO_GPIO, IXP4XX_GPIO_OUT);
126
127 /* poweroff */
128 gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
129}
130
131static void __init dsmg600_init(void)
132{
133 ixp4xx_sys_init();
134
135 /* Make sure that GPIO14 and GPIO15 are not used as clocks */
136 *IXP4XX_GPIO_GPCLKR = 0;
137
138 dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
139 dsmg600_flash_resource.end =
140 IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
141
142 pm_power_off = dsmg600_power_off;
143
144 /* The UART is required on the DSM-G600 (Redboot cannot use the
145 * NIC) -- do it here so that it does *not* get removed if
146 * platform_add_devices fails!
147 */
148 (void)platform_device_register(&dsmg600_uart);
149
150 platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
151
152#ifdef CONFIG_LEDS_CLASS
153 /* We don't care whether or not this works. */
154 (void)platform_device_register(&dsmg600_leds);
155#endif
156}
157
158static void __init dsmg600_fixup(struct machine_desc *desc,
159 struct tag *tags, char **cmdline, struct meminfo *mi)
160{
161 /* The xtal on this machine is non-standard. */
162 ixp4xx_timer_freq = DSMG600_FREQ;
163}
164
165MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
166 /* Maintainer: www.nslu2-linux.org */
167 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
168 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
169 .boot_params = 0x00000100,
170 .fixup = dsmg600_fixup,
171 .map_io = ixp4xx_map_io,
172 .init_irq = ixp4xx_init_irq,
173 .timer = &ixp4xx_timer,
174 .init_machine = dsmg600_init,
175MACHINE_END