aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp4xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ixp4xx')
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig22
-rw-r--r--arch/arm/mach-ixp4xx/Makefile2
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c4
-rw-r--r--arch/arm/mach-ixp4xx/common.c122
-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
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c2
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c18
9 files changed, 518 insertions, 26 deletions
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 8a339cdfe222..9715ef506c24 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -62,6 +62,12 @@ config MACH_IXDP465
62 IXDP465 Development Platform (Also known as BMP). 62 IXDP465 Development Platform (Also known as BMP).
63 For more information on this platform, see <file:Documentation/arm/IXP4xx>. 63 For more information on this platform, see <file:Documentation/arm/IXP4xx>.
64 64
65config MACH_KIXRP435
66 bool "KIXRP435"
67 help
68 Say 'Y' here if you want your kernel to support Intel's
69 KIXRP435 Reference Platform.
70 For more information on this platform, see <file:Documentation/arm/IXP4xx>.
65 71
66# 72#
67# IXCDP1100 is the exact same HW as IXDP425, but with a different machine 73# IXCDP1100 is the exact same HW as IXDP425, but with a different machine
@@ -89,12 +95,21 @@ config MACH_NAS100D
89 NAS 100d device. For more information on this platform, 95 NAS 100d device. For more information on this platform,
90 see http://www.nslu2-linux.org/wiki/NAS100d/HomePage 96 see http://www.nslu2-linux.org/wiki/NAS100d/HomePage
91 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
92# 107#
93# 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
94# 109#
95config ARCH_IXDP4XX 110config ARCH_IXDP4XX
96 bool 111 bool
97 depends on ARCH_IXDP425 || MACH_IXDP465 112 depends on ARCH_IXDP425 || MACH_IXDP465 || MACH_KIXRP435
98 default y 113 default y
99 114
100# 115#
@@ -105,6 +120,11 @@ config CPU_IXP46X
105 depends on MACH_IXDP465 120 depends on MACH_IXDP465
106 default y 121 default y
107 122
123config CPU_IXP43X
124 bool
125 depends on MACH_KIXRP435
126 default y
127
108config MACH_GTWX5715 128config MACH_GTWX5715
109 bool "Gemtek WX5715 (Linksys WRV54G)" 129 bool "Gemtek WX5715 (Linksys WRV54G)"
110 depends on ARCH_IXP4XX 130 depends on ARCH_IXP4XX
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/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 9562177b5fe1..bf04121d1a31 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -374,7 +374,7 @@ void __init ixp4xx_pci_preinit(void)
374 * Determine which PCI read method to use. 374 * Determine which PCI read method to use.
375 * Rev 0 IXP425 requires workaround. 375 * Rev 0 IXP425 requires workaround.
376 */ 376 */
377 if (!(processor_id & 0xf) && !cpu_is_ixp46x()) { 377 if (!(processor_id & 0xf) && cpu_is_ixp42x()) {
378 printk("PCI: IXP42x A0 silicon detected - " 378 printk("PCI: IXP42x A0 silicon detected - "
379 "PCI Non-Prefetch Workaround Enabled\n"); 379 "PCI Non-Prefetch Workaround Enabled\n");
380 ixp4xx_pci_read = ixp4xx_pci_read_errata; 380 ixp4xx_pci_read = ixp4xx_pci_read_errata;
@@ -480,7 +480,7 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
480 res[0].flags = IORESOURCE_IO; 480 res[0].flags = IORESOURCE_IO;
481 481
482 res[1].name = "PCI Memory Space"; 482 res[1].name = "PCI Memory Space";
483 res[1].start = 0x48000000; 483 res[1].start = PCIBIOS_MIN_MEM;
484#ifndef CONFIG_IXP4XX_INDIRECT_PCI 484#ifndef CONFIG_IXP4XX_INDIRECT_PCI
485 res[1].end = 0x4bffffff; 485 res[1].end = 0x4bffffff;
486#else 486#else
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 45068c3d8dcc..f5cae1e46b7e 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -27,6 +27,7 @@
27#include <linux/time.h> 27#include <linux/time.h>
28#include <linux/timex.h> 28#include <linux/timex.h>
29#include <linux/clocksource.h> 29#include <linux/clocksource.h>
30#include <linux/clockchips.h>
30 31
31#include <asm/arch/udc.h> 32#include <asm/arch/udc.h>
32#include <asm/hardware.h> 33#include <asm/hardware.h>
@@ -41,6 +42,8 @@
41#include <asm/mach/time.h> 42#include <asm/mach/time.h>
42 43
43static int __init ixp4xx_clocksource_init(void); 44static int __init ixp4xx_clocksource_init(void);
45static int __init ixp4xx_clockevent_init(void);
46static struct clock_event_device clockevent_ixp4xx;
44 47
45/************************************************************************* 48/*************************************************************************
46 * IXP4xx chipset I/O mapping 49 * IXP4xx chipset I/O mapping
@@ -102,6 +105,29 @@ static signed char irq2gpio[32] = {
102 7, 8, 9, 10, 11, 12, -1, -1, 105 7, 8, 9, 10, 11, 12, -1, -1,
103}; 106};
104 107
108int gpio_to_irq(int gpio)
109{
110 int irq;
111
112 for (irq = 0; irq < 32; irq++) {
113 if (irq2gpio[irq] == gpio)
114 return irq;
115 }
116 return -EINVAL;
117}
118EXPORT_SYMBOL(gpio_to_irq);
119
120int irq_to_gpio(int irq)
121{
122 int gpio = (irq < 32) ? irq2gpio[irq] : -EINVAL;
123
124 if (gpio == -1)
125 return -EINVAL;
126
127 return gpio;
128}
129EXPORT_SYMBOL(irq_to_gpio);
130
105static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) 131static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
106{ 132{
107 int line = irq2gpio[irq]; 133 int line = irq2gpio[irq];
@@ -169,7 +195,7 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
169 195
170static void ixp4xx_irq_mask(unsigned int irq) 196static void ixp4xx_irq_mask(unsigned int irq)
171{ 197{
172 if (cpu_is_ixp46x() && irq >= 32) 198 if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && irq >= 32)
173 *IXP4XX_ICMR2 &= ~(1 << (irq - 32)); 199 *IXP4XX_ICMR2 &= ~(1 << (irq - 32));
174 else 200 else
175 *IXP4XX_ICMR &= ~(1 << irq); 201 *IXP4XX_ICMR &= ~(1 << irq);
@@ -192,7 +218,7 @@ static void ixp4xx_irq_unmask(unsigned int irq)
192 if (!(ixp4xx_irq_edge & (1 << irq))) 218 if (!(ixp4xx_irq_edge & (1 << irq)))
193 ixp4xx_irq_ack(irq); 219 ixp4xx_irq_ack(irq);
194 220
195 if (cpu_is_ixp46x() && irq >= 32) 221 if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && irq >= 32)
196 *IXP4XX_ICMR2 |= (1 << (irq - 32)); 222 *IXP4XX_ICMR2 |= (1 << (irq - 32));
197 else 223 else
198 *IXP4XX_ICMR |= (1 << irq); 224 *IXP4XX_ICMR |= (1 << irq);
@@ -216,7 +242,7 @@ void __init ixp4xx_init_irq(void)
216 /* Disable all interrupt */ 242 /* Disable all interrupt */
217 *IXP4XX_ICMR = 0x0; 243 *IXP4XX_ICMR = 0x0;
218 244
219 if (cpu_is_ixp46x()) { 245 if (cpu_is_ixp46x() || cpu_is_ixp43x()) {
220 /* Route upper 32 sources to IRQ instead of FIQ */ 246 /* Route upper 32 sources to IRQ instead of FIQ */
221 *IXP4XX_ICLR2 = 0x00; 247 *IXP4XX_ICLR2 = 0x00;
222 248
@@ -239,52 +265,40 @@ void __init ixp4xx_init_irq(void)
239 * counter as a source of real clock ticks to account for missed jiffies. 265 * counter as a source of real clock ticks to account for missed jiffies.
240 *************************************************************************/ 266 *************************************************************************/
241 267
242static unsigned volatile last_jiffy_time;
243
244#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
245
246static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) 268static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
247{ 269{
248 write_seqlock(&xtime_lock); 270 struct clock_event_device *evt = &clockevent_ixp4xx;
249 271
250 /* Clear Pending Interrupt by writing '1' to it */ 272 /* Clear Pending Interrupt by writing '1' to it */
251 *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; 273 *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
252 274
253 /* 275 evt->event_handler(evt);
254 * Catch up with the real idea of time
255 */
256 while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
257 timer_tick();
258 last_jiffy_time += LATCH;
259 }
260
261 write_sequnlock(&xtime_lock);
262 276
263 return IRQ_HANDLED; 277 return IRQ_HANDLED;
264} 278}
265 279
266static struct irqaction ixp4xx_timer_irq = { 280static struct irqaction ixp4xx_timer_irq = {
267 .name = "IXP4xx Timer Tick", 281 .name = "timer1",
268 .flags = IRQF_DISABLED | IRQF_TIMER, 282 .flags = IRQF_DISABLED | IRQF_TIMER,
269 .handler = ixp4xx_timer_interrupt, 283 .handler = ixp4xx_timer_interrupt,
270}; 284};
271 285
272static void __init ixp4xx_timer_init(void) 286static void __init ixp4xx_timer_init(void)
273{ 287{
288 /* Reset/disable counter */
289 *IXP4XX_OSRT1 = 0;
290
274 /* Clear Pending Interrupt by writing '1' to it */ 291 /* Clear Pending Interrupt by writing '1' to it */
275 *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; 292 *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
276 293
277 /* Setup the Timer counter value */
278 *IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
279
280 /* Reset time-stamp counter */ 294 /* Reset time-stamp counter */
281 *IXP4XX_OSTS = 0; 295 *IXP4XX_OSTS = 0;
282 last_jiffy_time = 0;
283 296
284 /* Connect the interrupt handler and enable the interrupt */ 297 /* Connect the interrupt handler and enable the interrupt */
285 setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); 298 setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
286 299
287 ixp4xx_clocksource_init(); 300 ixp4xx_clocksource_init();
301 ixp4xx_clockevent_init();
288} 302}
289 303
290struct sys_timer ixp4xx_timer = { 304struct sys_timer ixp4xx_timer = {
@@ -384,6 +398,9 @@ void __init ixp4xx_sys_init(void)
384 ixp4xx_exp_bus_size >> 20); 398 ixp4xx_exp_bus_size >> 20);
385} 399}
386 400
401/*
402 * clocksource
403 */
387cycle_t ixp4xx_get_cycles(void) 404cycle_t ixp4xx_get_cycles(void)
388{ 405{
389 return *IXP4XX_OSTS; 406 return *IXP4XX_OSTS;
@@ -408,3 +425,64 @@ static int __init ixp4xx_clocksource_init(void)
408 425
409 return 0; 426 return 0;
410} 427}
428
429/*
430 * clockevents
431 */
432static int ixp4xx_set_next_event(unsigned long evt,
433 struct clock_event_device *unused)
434{
435 unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
436
437 *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
438
439 return 0;
440}
441
442static void ixp4xx_set_mode(enum clock_event_mode mode,
443 struct clock_event_device *evt)
444{
445 unsigned long opts, osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
446
447 switch (mode) {
448 case CLOCK_EVT_MODE_PERIODIC:
449 osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK;
450 opts = IXP4XX_OST_ENABLE;
451 break;
452 case CLOCK_EVT_MODE_ONESHOT:
453 /* period set by 'set next_event' */
454 osrt = 0;
455 opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
456 break;
457 case CLOCK_EVT_MODE_SHUTDOWN:
458 case CLOCK_EVT_MODE_UNUSED:
459 default:
460 osrt = opts = 0;
461 break;
462 }
463
464 *IXP4XX_OSRT1 = osrt | opts;
465}
466
467static struct clock_event_device clockevent_ixp4xx = {
468 .name = "ixp4xx timer1",
469 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
470 .rating = 200,
471 .shift = 24,
472 .set_mode = ixp4xx_set_mode,
473 .set_next_event = ixp4xx_set_next_event,
474};
475
476static int __init ixp4xx_clockevent_init(void)
477{
478 clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC,
479 clockevent_ixp4xx.shift);
480 clockevent_ixp4xx.max_delta_ns =
481 clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
482 clockevent_ixp4xx.min_delta_ns =
483 clockevent_delta2ns(0xf, &clockevent_ixp4xx);
484 clockevent_ixp4xx.cpumask = cpumask_of_cpu(0);
485
486 clockevents_register_device(&clockevent_ixp4xx);
487 return 0;
488}
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
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index 99c1dc8033c8..408796004812 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -66,7 +66,7 @@ struct hw_pci ixdp425_pci __initdata = {
66int __init ixdp425_pci_init(void) 66int __init ixdp425_pci_init(void)
67{ 67{
68 if (machine_is_ixdp425() || machine_is_ixcdp1100() || 68 if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
69 machine_is_ixdp465()) 69 machine_is_ixdp465() || machine_is_kixrp435())
70 pci_common_init(&ixdp425_pci); 70 pci_common_init(&ixdp425_pci);
71 return 0; 71 return 0;
72} 72}
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 04b1d56396a0..ec4f07950ec6 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -115,6 +115,11 @@ static void __init ixdp425_init(void)
115 ixdp425_flash_resource.end = 115 ixdp425_flash_resource.end =
116 IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; 116 IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
117 117
118 if (cpu_is_ixp43x()) {
119 ixdp425_uart.num_resources = 1;
120 ixdp425_uart_data[1].flags = 0;
121 }
122
118 platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); 123 platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
119} 124}
120 125
@@ -156,3 +161,16 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
156 .init_machine = ixdp425_init, 161 .init_machine = ixdp425_init,
157MACHINE_END 162MACHINE_END
158#endif 163#endif
164
165#ifdef CONFIG_MACH_KIXRP435
166MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
167 /* Maintainer: MontaVista Software, Inc. */
168 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
169 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
170 .map_io = ixp4xx_map_io,
171 .init_irq = ixp4xx_init_irq,
172 .timer = &ixp4xx_timer,
173 .boot_params = 0x0100,
174 .init_machine = ixdp425_init,
175MACHINE_END
176#endif