aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-footbridge
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-footbridge')
-rw-r--r--arch/arm/mach-footbridge/Kconfig80
-rw-r--r--arch/arm/mach-footbridge/Makefile30
-rw-r--r--arch/arm/mach-footbridge/Makefile.boot4
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c95
-rw-r--r--arch/arm/mach-footbridge/cats-pci.c55
-rw-r--r--arch/arm/mach-footbridge/co285.c38
-rw-r--r--arch/arm/mach-footbridge/common.c205
-rw-r--r--arch/arm/mach-footbridge/common.h9
-rw-r--r--arch/arm/mach-footbridge/dc21285-timer.c68
-rw-r--r--arch/arm/mach-footbridge/dc21285.c384
-rw-r--r--arch/arm/mach-footbridge/dma.c54
-rw-r--r--arch/arm/mach-footbridge/ebsa285-leds.c140
-rw-r--r--arch/arm/mach-footbridge/ebsa285-pci.c48
-rw-r--r--arch/arm/mach-footbridge/ebsa285.c24
-rw-r--r--arch/arm/mach-footbridge/isa-irq.c168
-rw-r--r--arch/arm/mach-footbridge/isa-timer.c94
-rw-r--r--arch/arm/mach-footbridge/isa.c48
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c660
-rw-r--r--arch/arm/mach-footbridge/netwinder-leds.c141
-rw-r--r--arch/arm/mach-footbridge/netwinder-pci.c62
-rw-r--r--arch/arm/mach-footbridge/personal-pci.c56
-rw-r--r--arch/arm/mach-footbridge/personal.c23
-rw-r--r--arch/arm/mach-footbridge/time.c180
23 files changed, 2666 insertions, 0 deletions
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
new file mode 100644
index 000000000000..1090c680b6dd
--- /dev/null
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -0,0 +1,80 @@
1if ARCH_FOOTBRIDGE
2
3menu "Footbridge Implementations"
4
5config ARCH_CATS
6 bool "CATS"
7 select FOOTBRIDGE_HOST
8 help
9 Say Y here if you intend to run this kernel on the CATS.
10
11 Saying N will reduce the size of the Footbridge kernel.
12
13config ARCH_PERSONAL_SERVER
14 bool "Compaq Personal Server"
15 select FOOTBRIDGE_HOST
16 ---help---
17 Say Y here if you intend to run this kernel on the Compaq
18 Personal Server.
19
20 Saying N will reduce the size of the Footbridge kernel.
21
22 The Compaq Personal Server is not available for purchase.
23 There are no product plans beyond the current research
24 prototypes at this time. Information is available at:
25
26 <http://www.crl.hpl.hp.com/projects/personalserver/>
27
28 If you have any questions or comments about the Compaq Personal
29 Server, send e-mail to <skiff@crl.dec.com>.
30
31config ARCH_EBSA285_ADDIN
32 bool "EBSA285 (addin mode)"
33 select ARCH_EBSA285
34 select FOOTBRIDGE_ADDIN
35 help
36 Say Y here if you intend to run this kernel on the EBSA285 card
37 in addin mode.
38
39 Saying N will reduce the size of the Footbridge kernel.
40
41config ARCH_EBSA285_HOST
42 bool "EBSA285 (host mode)"
43 select ARCH_EBSA285
44 select FOOTBRIDGE_HOST
45 help
46 Say Y here if you intend to run this kernel on the EBSA285 card
47 in host ("central function") mode.
48
49 Saying N will reduce the size of the Footbridge kernel.
50
51config ARCH_NETWINDER
52 bool "NetWinder"
53 select FOOTBRIDGE_HOST
54 help
55 Say Y here if you intend to run this kernel on the Rebel.COM
56 NetWinder. Information about this machine can be found at:
57
58 <http://www.netwinder.org/>
59
60 Saying N will reduce the size of the Footbridge kernel.
61
62endmenu
63
64# Footbridge support
65config FOOTBRIDGE
66 bool
67
68# Footbridge in host mode
69config FOOTBRIDGE_HOST
70 bool
71
72# Footbridge in addin mode
73config FOOTBRIDGE_ADDIN
74 bool
75
76# EBSA285 board in either host or addin mode
77config ARCH_EBSA285
78 bool
79
80endif
diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile
new file mode 100644
index 000000000000..0694ad6b6476
--- /dev/null
+++ b/arch/arm/mach-footbridge/Makefile
@@ -0,0 +1,30 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Object file lists.
6
7obj-y := common.o dc21285.o dma.o isa-irq.o time.o
8obj-m :=
9obj-n :=
10obj- :=
11
12pci-$(CONFIG_ARCH_CATS) += cats-pci.o
13pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o
14pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
15pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
16
17leds-$(CONFIG_ARCH_CO285) += ebsa285-leds.o
18leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
19leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
20
21obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o
22obj-$(CONFIG_ARCH_CO285) += co285.o dc21285-timer.o
23obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o
24obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o
25obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o
26
27obj-$(CONFIG_PCI) +=$(pci-y)
28obj-$(CONFIG_LEDS) +=$(leds-y)
29
30obj-$(CONFIG_ISA) += isa.o
diff --git a/arch/arm/mach-footbridge/Makefile.boot b/arch/arm/mach-footbridge/Makefile.boot
new file mode 100644
index 000000000000..c7e75acfe6c9
--- /dev/null
+++ b/arch/arm/mach-footbridge/Makefile.boot
@@ -0,0 +1,4 @@
1 zreladdr-y := 0x00008000
2params_phys-y := 0x00000100
3initrd_phys-y := 0x00800000
4
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
new file mode 100644
index 000000000000..d1ced86c379c
--- /dev/null
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -0,0 +1,95 @@
1/*
2 * linux/arch/arm/mach-footbridge/cats-hw.c
3 *
4 * CATS machine fixup
5 *
6 * Copyright (C) 1998, 1999 Russell King, Phil Blundell
7 */
8#include <linux/ioport.h>
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/tty.h>
12
13#include <asm/hardware/dec21285.h>
14#include <asm/io.h>
15#include <asm/mach-types.h>
16#include <asm/setup.h>
17
18#include <asm/mach/arch.h>
19
20#include "common.h"
21
22#define CFG_PORT 0x370
23#define INDEX_PORT (CFG_PORT)
24#define DATA_PORT (CFG_PORT + 1)
25
26static int __init cats_hw_init(void)
27{
28 if (machine_is_cats()) {
29 /* Set Aladdin to CONFIGURE mode */
30 outb(0x51, CFG_PORT);
31 outb(0x23, CFG_PORT);
32
33 /* Select logical device 3 */
34 outb(0x07, INDEX_PORT);
35 outb(0x03, DATA_PORT);
36
37 /* Set parallel port to DMA channel 3, ECP+EPP1.9,
38 enable EPP timeout */
39 outb(0x74, INDEX_PORT);
40 outb(0x03, DATA_PORT);
41
42 outb(0xf0, INDEX_PORT);
43 outb(0x0f, DATA_PORT);
44
45 outb(0xf1, INDEX_PORT);
46 outb(0x07, DATA_PORT);
47
48 /* Select logical device 4 */
49 outb(0x07, INDEX_PORT);
50 outb(0x04, DATA_PORT);
51
52 /* UART1 high speed mode */
53 outb(0xf0, INDEX_PORT);
54 outb(0x02, DATA_PORT);
55
56 /* Select logical device 5 */
57 outb(0x07, INDEX_PORT);
58 outb(0x05, DATA_PORT);
59
60 /* UART2 high speed mode */
61 outb(0xf0, INDEX_PORT);
62 outb(0x02, DATA_PORT);
63
64 /* Set Aladdin to RUN mode */
65 outb(0xbb, CFG_PORT);
66 }
67
68 return 0;
69}
70
71__initcall(cats_hw_init);
72
73/*
74 * CATS uses soft-reboot by default, since
75 * hard reboots fail on early boards.
76 */
77static void __init
78fixup_cats(struct machine_desc *desc, struct tag *tags,
79 char **cmdline, struct meminfo *mi)
80{
81 ORIG_VIDEO_LINES = 25;
82 ORIG_VIDEO_POINTS = 16;
83 ORIG_Y = 24;
84}
85
86MACHINE_START(CATS, "Chalice-CATS")
87 MAINTAINER("Philip Blundell")
88 BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
89 BOOT_PARAMS(0x00000100)
90 SOFT_REBOOT
91 FIXUP(fixup_cats)
92 MAPIO(footbridge_map_io)
93 INITIRQ(footbridge_init_irq)
94 .timer = &isa_timer,
95MACHINE_END
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
new file mode 100644
index 000000000000..4f984fde7375
--- /dev/null
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -0,0 +1,55 @@
1/*
2 * linux/arch/arm/mach-footbridge/cats-pci.c
3 *
4 * PCI bios-type initialisation for PCI machines
5 *
6 * Bits taken from various places.
7 */
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11
12#include <asm/irq.h>
13#include <asm/mach/pci.h>
14#include <asm/mach-types.h>
15
16/* cats host-specific stuff */
17static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
18
19static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
20{
21 if (dev->irq >= 128)
22 return dev->irq & 0x1f;
23
24 if (dev->irq >= 1 && dev->irq <= 4)
25 return irqmap_cats[dev->irq - 1];
26
27 if (dev->irq != 0)
28 printk("PCI: device %02x:%02x has unknown irq line %x\n",
29 dev->bus->number, dev->devfn, dev->irq);
30
31 return -1;
32}
33
34/*
35 * why not the standard PCI swizzle? does this prevent 4-port tulip
36 * cards being used (ie, pci-pci bridge based cards)?
37 */
38static struct hw_pci cats_pci __initdata = {
39 .swizzle = NULL,
40 .map_irq = cats_map_irq,
41 .nr_controllers = 1,
42 .setup = dc21285_setup,
43 .scan = dc21285_scan_bus,
44 .preinit = dc21285_preinit,
45 .postinit = dc21285_postinit,
46};
47
48static int cats_pci_init(void)
49{
50 if (machine_is_cats())
51 pci_common_init(&cats_pci);
52 return 0;
53}
54
55subsys_initcall(cats_pci_init);
diff --git a/arch/arm/mach-footbridge/co285.c b/arch/arm/mach-footbridge/co285.c
new file mode 100644
index 000000000000..e1541914fdcd
--- /dev/null
+++ b/arch/arm/mach-footbridge/co285.c
@@ -0,0 +1,38 @@
1/*
2 * linux/arch/arm/mach-footbridge/co285.c
3 *
4 * CO285 machine fixup
5 */
6#include <linux/init.h>
7
8#include <asm/hardware/dec21285.h>
9#include <asm/mach-types.h>
10
11#include <asm/mach/arch.h>
12
13#include "common.h"
14
15static void __init
16fixup_coebsa285(struct machine_desc *desc, struct tag *tags,
17 char **cmdline, struct meminfo *mi)
18{
19 extern unsigned long boot_memory_end;
20 extern char boot_command_line[];
21
22 mi->nr_banks = 1;
23 mi->bank[0].start = PHYS_OFFSET;
24 mi->bank[0].size = boot_memory_end;
25 mi->bank[0].node = 0;
26
27 *cmdline = boot_command_line;
28}
29
30MACHINE_START(CO285, "co-EBSA285")
31 MAINTAINER("Mark van Doesburg")
32 BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000)
33 FIXUP(fixup_coebsa285)
34 MAPIO(footbridge_map_io)
35 INITIRQ(footbridge_init_irq)
36 .timer = &footbridge_timer,
37MACHINE_END
38
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
new file mode 100644
index 000000000000..eb8238c1ef06
--- /dev/null
+++ b/arch/arm/mach-footbridge/common.c
@@ -0,0 +1,205 @@
1/*
2 * linux/arch/arm/mach-footbridge/common.c
3 *
4 * Copyright (C) 1998-2000 Russell King, Dave Gilbert.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/config.h>
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/ioport.h>
15#include <linux/list.h>
16#include <linux/init.h>
17
18#include <asm/pgtable.h>
19#include <asm/page.h>
20#include <asm/irq.h>
21#include <asm/io.h>
22#include <asm/mach-types.h>
23#include <asm/setup.h>
24#include <asm/hardware/dec21285.h>
25
26#include <asm/mach/irq.h>
27#include <asm/mach/map.h>
28
29#include "common.h"
30
31extern void __init isa_init_irq(unsigned int irq);
32
33unsigned int mem_fclk_21285 = 50000000;
34
35EXPORT_SYMBOL(mem_fclk_21285);
36
37static int __init parse_tag_memclk(const struct tag *tag)
38{
39 mem_fclk_21285 = tag->u.memclk.fmemclk;
40 return 0;
41}
42
43__tagtable(ATAG_MEMCLK, parse_tag_memclk);
44
45/*
46 * Footbridge IRQ translation table
47 * Converts from our IRQ numbers into FootBridge masks
48 */
49static const int fb_irq_mask[] = {
50 IRQ_MASK_UART_RX, /* 0 */
51 IRQ_MASK_UART_TX, /* 1 */
52 IRQ_MASK_TIMER1, /* 2 */
53 IRQ_MASK_TIMER2, /* 3 */
54 IRQ_MASK_TIMER3, /* 4 */
55 IRQ_MASK_IN0, /* 5 */
56 IRQ_MASK_IN1, /* 6 */
57 IRQ_MASK_IN2, /* 7 */
58 IRQ_MASK_IN3, /* 8 */
59 IRQ_MASK_DOORBELLHOST, /* 9 */
60 IRQ_MASK_DMA1, /* 10 */
61 IRQ_MASK_DMA2, /* 11 */
62 IRQ_MASK_PCI, /* 12 */
63 IRQ_MASK_SDRAMPARITY, /* 13 */
64 IRQ_MASK_I2OINPOST, /* 14 */
65 IRQ_MASK_PCI_ABORT, /* 15 */
66 IRQ_MASK_PCI_SERR, /* 16 */
67 IRQ_MASK_DISCARD_TIMER, /* 17 */
68 IRQ_MASK_PCI_DPERR, /* 18 */
69 IRQ_MASK_PCI_PERR, /* 19 */
70};
71
72static void fb_mask_irq(unsigned int irq)
73{
74 *CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(irq)];
75}
76
77static void fb_unmask_irq(unsigned int irq)
78{
79 *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
80}
81
82static struct irqchip fb_chip = {
83 .ack = fb_mask_irq,
84 .mask = fb_mask_irq,
85 .unmask = fb_unmask_irq,
86};
87
88static void __init __fb_init_irq(void)
89{
90 unsigned int irq;
91
92 /*
93 * setup DC21285 IRQs
94 */
95 *CSR_IRQ_DISABLE = -1;
96 *CSR_FIQ_DISABLE = -1;
97
98 for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
99 set_irq_chip(irq, &fb_chip);
100 set_irq_handler(irq, do_level_IRQ);
101 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
102 }
103}
104
105void __init footbridge_init_irq(void)
106{
107 __fb_init_irq();
108
109 if (!footbridge_cfn_mode())
110 return;
111
112 if (machine_is_ebsa285())
113 /* The following is dependent on which slot
114 * you plug the Southbridge card into. We
115 * currently assume that you plug it into
116 * the right-hand most slot.
117 */
118 isa_init_irq(IRQ_PCI);
119
120 if (machine_is_cats())
121 isa_init_irq(IRQ_IN2);
122
123 if (machine_is_netwinder())
124 isa_init_irq(IRQ_IN3);
125}
126
127/*
128 * Common mapping for all systems. Note that the outbound write flush is
129 * commented out since there is a "No Fix" problem with it. Not mapping
130 * it means that we have extra bullet protection on our feet.
131 */
132static struct map_desc fb_common_io_desc[] __initdata = {
133 { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, MT_DEVICE },
134 { XBUS_BASE, 0x40000000, XBUS_SIZE, MT_DEVICE }
135};
136
137/*
138 * The mapping when the footbridge is in host mode. We don't map any of
139 * this when we are in add-in mode.
140 */
141static struct map_desc ebsa285_host_io_desc[] __initdata = {
142#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
143 { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, MT_DEVICE },
144 { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, MT_DEVICE },
145 { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, MT_DEVICE },
146 { PCIIACK_BASE, DC21285_PCI_IACK, PCIIACK_SIZE, MT_DEVICE },
147 { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, MT_DEVICE }
148#endif
149};
150
151/*
152 * The CO-ebsa285 mapping.
153 */
154static struct map_desc co285_io_desc[] __initdata = {
155#ifdef CONFIG_ARCH_CO285
156 { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, MT_DEVICE },
157 { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, MT_DEVICE }
158#endif
159};
160
161void __init footbridge_map_io(void)
162{
163 /*
164 * Set up the common mapping first; we need this to
165 * determine whether we're in host mode or not.
166 */
167 iotable_init(fb_common_io_desc, ARRAY_SIZE(fb_common_io_desc));
168
169 /*
170 * Now, work out what we've got to map in addition on this
171 * platform.
172 */
173 if (machine_is_co285())
174 iotable_init(co285_io_desc, ARRAY_SIZE(co285_io_desc));
175 if (footbridge_cfn_mode())
176 iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
177}
178
179#ifdef CONFIG_FOOTBRIDGE_ADDIN
180
181/*
182 * These two functions convert virtual addresses to PCI addresses and PCI
183 * addresses to virtual addresses. Note that it is only legal to use these
184 * on memory obtained via get_zeroed_page or kmalloc.
185 */
186unsigned long __virt_to_bus(unsigned long res)
187{
188 WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
189
190 return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
191}
192EXPORT_SYMBOL(__virt_to_bus);
193
194unsigned long __bus_to_virt(unsigned long res)
195{
196 res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
197 res += PAGE_OFFSET;
198
199 WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
200
201 return res;
202}
203EXPORT_SYMBOL(__bus_to_virt);
204
205#endif
diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h
new file mode 100644
index 000000000000..580e31bbc711
--- /dev/null
+++ b/arch/arm/mach-footbridge/common.h
@@ -0,0 +1,9 @@
1
2extern struct sys_timer footbridge_timer;
3extern struct sys_timer isa_timer;
4
5extern void isa_rtc_init(void);
6
7extern void footbridge_map_io(void);
8extern void footbridge_init_irq(void);
9
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
new file mode 100644
index 000000000000..580e1d4bce08
--- /dev/null
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -0,0 +1,68 @@
1/*
2 * linux/arch/arm/mach-footbridge/dc21285-timer.c
3 *
4 * Copyright (C) 1998 Russell King.
5 * Copyright (C) 1998 Phil Blundell
6 */
7#include <linux/init.h>
8#include <linux/interrupt.h>
9
10#include <asm/irq.h>
11
12#include <asm/hardware/dec21285.h>
13#include <asm/mach/time.h>
14
15#include "common.h"
16
17/*
18 * Footbridge timer 1 support.
19 */
20static unsigned long timer1_latch;
21
22static unsigned long timer1_gettimeoffset (void)
23{
24 unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
25
26 return ((tick_nsec / 1000) * value) / timer1_latch;
27}
28
29static irqreturn_t
30timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
31{
32 write_seqlock(&xtime_lock);
33
34 *CSR_TIMER1_CLR = 0;
35
36 timer_tick(regs);
37
38 write_sequnlock(&xtime_lock);
39
40 return IRQ_HANDLED;
41}
42
43static struct irqaction footbridge_timer_irq = {
44 .name = "Timer1 timer tick",
45 .handler = timer1_interrupt,
46 .flags = SA_INTERRUPT,
47};
48
49/*
50 * Set up timer interrupt.
51 */
52static void __init footbridge_timer_init(void)
53{
54 isa_rtc_init();
55
56 timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
57
58 *CSR_TIMER1_CLR = 0;
59 *CSR_TIMER1_LOAD = timer1_latch;
60 *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
61
62 setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
63}
64
65struct sys_timer footbridge_timer = {
66 .init = footbridge_timer_init,
67 .offset = timer1_gettimeoffset,
68};
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
new file mode 100644
index 000000000000..e79884eea1f7
--- /dev/null
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -0,0 +1,384 @@
1/*
2 * linux/arch/arm/kernel/dec21285.c: PCI functions for DC21285
3 *
4 * Copyright (C) 1998-2001 Russell King
5 * Copyright (C) 1998-2000 Phil Blundell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/kernel.h>
12#include <linux/pci.h>
13#include <linux/ptrace.h>
14#include <linux/interrupt.h>
15#include <linux/mm.h>
16#include <linux/slab.h>
17#include <linux/init.h>
18#include <linux/ioport.h>
19
20#include <asm/io.h>
21#include <asm/irq.h>
22#include <asm/system.h>
23#include <asm/mach/pci.h>
24#include <asm/hardware/dec21285.h>
25
26#define MAX_SLOTS 21
27
28#define PCICMD_ABORT ((PCI_STATUS_REC_MASTER_ABORT| \
29 PCI_STATUS_REC_TARGET_ABORT)<<16)
30
31#define PCICMD_ERROR_BITS ((PCI_STATUS_DETECTED_PARITY | \
32 PCI_STATUS_REC_MASTER_ABORT | \
33 PCI_STATUS_REC_TARGET_ABORT | \
34 PCI_STATUS_PARITY) << 16)
35
36extern int setup_arm_irq(int, struct irqaction *);
37extern void pcibios_report_status(u_int status_mask, int warn);
38extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
39
40static unsigned long
41dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
42{
43 unsigned long addr = 0;
44
45 if (bus->number == 0) {
46 if (PCI_SLOT(devfn) == 0)
47 /*
48 * For devfn 0, point at the 21285
49 */
50 addr = ARMCSR_BASE;
51 else {
52 devfn -= 1 << 3;
53
54 if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
55 addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
56 }
57 } else
58 addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8);
59
60 return addr;
61}
62
63static int
64dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
65 int size, u32 *value)
66{
67 unsigned long addr = dc21285_base_address(bus, devfn);
68 u32 v = 0xffffffff;
69
70 if (addr)
71 switch (size) {
72 case 1:
73 asm("ldr%?b %0, [%1, %2]"
74 : "=r" (v) : "r" (addr), "r" (where));
75 break;
76 case 2:
77 asm("ldr%?h %0, [%1, %2]"
78 : "=r" (v) : "r" (addr), "r" (where));
79 break;
80 case 4:
81 asm("ldr%? %0, [%1, %2]"
82 : "=r" (v) : "r" (addr), "r" (where));
83 break;
84 }
85
86 *value = v;
87
88 v = *CSR_PCICMD;
89 if (v & PCICMD_ABORT) {
90 *CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
91 return -1;
92 }
93
94 return PCIBIOS_SUCCESSFUL;
95}
96
97static int
98dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
99 int size, u32 value)
100{
101 unsigned long addr = dc21285_base_address(bus, devfn);
102 u32 v;
103
104 if (addr)
105 switch (size) {
106 case 1:
107 asm("str%?b %0, [%1, %2]"
108 : : "r" (value), "r" (addr), "r" (where));
109 break;
110 case 2:
111 asm("str%?h %0, [%1, %2]"
112 : : "r" (value), "r" (addr), "r" (where));
113 break;
114 case 4:
115 asm("str%? %0, [%1, %2]"
116 : : "r" (value), "r" (addr), "r" (where));
117 break;
118 }
119
120 v = *CSR_PCICMD;
121 if (v & PCICMD_ABORT) {
122 *CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
123 return -1;
124 }
125
126 return PCIBIOS_SUCCESSFUL;
127}
128
129static struct pci_ops dc21285_ops = {
130 .read = dc21285_read_config,
131 .write = dc21285_write_config,
132};
133
134static struct timer_list serr_timer;
135static struct timer_list perr_timer;
136
137static void dc21285_enable_error(unsigned long __data)
138{
139 switch (__data) {
140 case IRQ_PCI_SERR:
141 del_timer(&serr_timer);
142 break;
143
144 case IRQ_PCI_PERR:
145 del_timer(&perr_timer);
146 break;
147 }
148
149 enable_irq(__data);
150}
151
152/*
153 * Warn on PCI errors.
154 */
155static irqreturn_t dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs)
156{
157 unsigned int cmd;
158 unsigned int status;
159
160 cmd = *CSR_PCICMD;
161 status = cmd >> 16;
162 cmd = cmd & 0xffff;
163
164 if (status & PCI_STATUS_REC_MASTER_ABORT) {
165 printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n",
166 instruction_pointer(regs));
167 cmd |= PCI_STATUS_REC_MASTER_ABORT << 16;
168 }
169
170 if (status & PCI_STATUS_REC_TARGET_ABORT) {
171 printk(KERN_DEBUG "PCI: target abort: ");
172 pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT |
173 PCI_STATUS_SIG_TARGET_ABORT |
174 PCI_STATUS_REC_TARGET_ABORT, 1);
175 printk("\n");
176
177 cmd |= PCI_STATUS_REC_TARGET_ABORT << 16;
178 }
179
180 *CSR_PCICMD = cmd;
181
182 return IRQ_HANDLED;
183}
184
185static irqreturn_t dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
186{
187 struct timer_list *timer = dev_id;
188 unsigned int cntl;
189
190 printk(KERN_DEBUG "PCI: system error received: ");
191 pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
192 printk("\n");
193
194 cntl = *CSR_SA110_CNTL & 0xffffdf07;
195 *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
196
197 /*
198 * back off this interrupt
199 */
200 disable_irq(irq);
201 timer->expires = jiffies + HZ;
202 add_timer(timer);
203
204 return IRQ_HANDLED;
205}
206
207static irqreturn_t dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs)
208{
209 printk(KERN_DEBUG "PCI: discard timer expired\n");
210 *CSR_SA110_CNTL &= 0xffffde07;
211
212 return IRQ_HANDLED;
213}
214
215static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs)
216{
217 unsigned int cmd;
218
219 printk(KERN_DEBUG "PCI: data parity error detected: ");
220 pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
221 printk("\n");
222
223 cmd = *CSR_PCICMD & 0xffff;
224 *CSR_PCICMD = cmd | 1 << 24;
225
226 return IRQ_HANDLED;
227}
228
229static irqreturn_t dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
230{
231 struct timer_list *timer = dev_id;
232 unsigned int cmd;
233
234 printk(KERN_DEBUG "PCI: parity error detected: ");
235 pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
236 printk("\n");
237
238 cmd = *CSR_PCICMD & 0xffff;
239 *CSR_PCICMD = cmd | 1 << 31;
240
241 /*
242 * back off this interrupt
243 */
244 disable_irq(irq);
245 timer->expires = jiffies + HZ;
246 add_timer(timer);
247
248 return IRQ_HANDLED;
249}
250
251int __init dc21285_setup(int nr, struct pci_sys_data *sys)
252{
253 struct resource *res;
254
255 if (nr || !footbridge_cfn_mode())
256 return 0;
257
258 res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
259 if (!res) {
260 printk("out of memory for root bus resources");
261 return 0;
262 }
263
264 memset(res, 0, sizeof(struct resource) * 2);
265
266 res[0].flags = IORESOURCE_MEM;
267 res[0].name = "Footbridge non-prefetch";
268 res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
269 res[1].name = "Footbridge prefetch";
270
271 allocate_resource(&iomem_resource, &res[1], 0x20000000,
272 0xa0000000, 0xffffffff, 0x20000000, NULL, NULL);
273 allocate_resource(&iomem_resource, &res[0], 0x40000000,
274 0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
275
276 sys->resource[0] = &ioport_resource;
277 sys->resource[1] = &res[0];
278 sys->resource[2] = &res[1];
279 sys->mem_offset = DC21285_PCI_MEM;
280
281 return 1;
282}
283
284struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
285{
286 return pci_scan_bus(0, &dc21285_ops, sys);
287}
288
289void __init dc21285_preinit(void)
290{
291 unsigned int mem_size, mem_mask;
292 int cfn_mode;
293
294 mem_size = (unsigned int)high_memory - PAGE_OFFSET;
295 for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
296 if (mem_mask >= mem_size)
297 break;
298
299 /*
300 * These registers need to be set up whether we're the
301 * central function or not.
302 */
303 *CSR_SDRAMBASEMASK = (mem_mask - 1) & 0x0ffc0000;
304 *CSR_SDRAMBASEOFFSET = 0;
305 *CSR_ROMBASEMASK = 0x80000000;
306 *CSR_CSRBASEMASK = 0;
307 *CSR_CSRBASEOFFSET = 0;
308 *CSR_PCIADDR_EXTN = 0;
309
310 cfn_mode = __footbridge_cfn_mode();
311
312 printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX, in "
313 "%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ?
314 "central function" : "addin");
315
316 if (footbridge_cfn_mode()) {
317 /*
318 * Clear any existing errors - we aren't
319 * interested in historical data...
320 */
321 *CSR_SA110_CNTL = (*CSR_SA110_CNTL & 0xffffde07) |
322 SA110_CNTL_RXSERR;
323 *CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS;
324 }
325
326 init_timer(&serr_timer);
327 init_timer(&perr_timer);
328
329 serr_timer.data = IRQ_PCI_SERR;
330 serr_timer.function = dc21285_enable_error;
331 perr_timer.data = IRQ_PCI_PERR;
332 perr_timer.function = dc21285_enable_error;
333
334 /*
335 * We don't care if these fail.
336 */
337 request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT,
338 "PCI system error", &serr_timer);
339 request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT,
340 "PCI parity error", &perr_timer);
341 request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT,
342 "PCI abort", NULL);
343 request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT,
344 "Discard timer", NULL);
345 request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT,
346 "PCI data parity", NULL);
347
348 if (cfn_mode) {
349 static struct resource csrio;
350
351 csrio.flags = IORESOURCE_IO;
352 csrio.name = "Footbridge";
353
354 allocate_resource(&ioport_resource, &csrio, 128,
355 0xff00, 0xffff, 128, NULL, NULL);
356
357 /*
358 * Map our SDRAM at a known address in PCI space, just in case
359 * the firmware had other ideas. Using a nonzero base is
360 * necessary, since some VGA cards forcefully use PCI addresses
361 * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
362 */
363 *CSR_PCICSRBASE = 0xf4000000;
364 *CSR_PCICSRIOBASE = csrio.start;
365 *CSR_PCISDRAMBASE = __virt_to_bus(PAGE_OFFSET);
366 *CSR_PCIROMBASE = 0;
367 *CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
368 PCI_COMMAND_INVALIDATE | PCICMD_ERROR_BITS;
369 } else if (footbridge_cfn_mode() != 0) {
370 /*
371 * If we are not compiled to accept "add-in" mode, then
372 * we are using a constant virt_to_bus translation which
373 * can not hope to cater for the way the host BIOS has
374 * set up the machine.
375 */
376 panic("PCI: this kernel is compiled for central "
377 "function mode only");
378 }
379}
380
381void __init dc21285_postinit(void)
382{
383 register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
384}
diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
new file mode 100644
index 000000000000..a6b1396b0951
--- /dev/null
+++ b/arch/arm/mach-footbridge/dma.c
@@ -0,0 +1,54 @@
1/*
2 * linux/arch/arm/kernel/dma-ebsa285.c
3 *
4 * Copyright (C) 1998 Phil Blundell
5 *
6 * DMA functions specific to EBSA-285/CATS architectures
7 *
8 * Changelog:
9 * 09-Nov-1998 RMK Split out ISA DMA functions to dma-isa.c
10 * 17-Mar-1999 RMK Allow any EBSA285-like architecture to have
11 * ISA DMA controllers.
12 */
13#include <linux/config.h>
14#include <linux/init.h>
15
16#include <asm/dma.h>
17#include <asm/io.h>
18
19#include <asm/mach/dma.h>
20#include <asm/hardware/dec21285.h>
21
22#if 0
23static int fb_dma_request(dmach_t channel, dma_t *dma)
24{
25 return -EINVAL;
26}
27
28static void fb_dma_enable(dmach_t channel, dma_t *dma)
29{
30}
31
32static void fb_dma_disable(dmach_t channel, dma_t *dma)
33{
34}
35
36static struct dma_ops fb_dma_ops = {
37 .type = "fb",
38 .request = fb_dma_request,
39 .enable = fb_dma_enable,
40 .disable = fb_dma_disable,
41};
42#endif
43
44void __init arch_dma_init(dma_t *dma)
45{
46#if 0
47 dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
48 dma[_DC21285_DMA(1)].d_ops = &fb_dma_ops;
49#endif
50#ifdef CONFIG_ISA_DMA
51 if (footbridge_cfn_mode())
52 isa_init_dma(dma + _ISA_DMA(0));
53#endif
54}
diff --git a/arch/arm/mach-footbridge/ebsa285-leds.c b/arch/arm/mach-footbridge/ebsa285-leds.c
new file mode 100644
index 000000000000..2c7c3630401b
--- /dev/null
+++ b/arch/arm/mach-footbridge/ebsa285-leds.c
@@ -0,0 +1,140 @@
1/*
2 * linux/arch/arm/mach-footbridge/ebsa285-leds.c
3 *
4 * Copyright (C) 1998-1999 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 * EBSA-285 control routines.
10 *
11 * The EBSA-285 uses the leds as follows:
12 * - Green - toggles state every 50 timer interrupts
13 * - Amber - On if system is not idle
14 * - Red - currently unused
15 *
16 * Changelog:
17 * 02-05-1999 RMK Various cleanups
18 */
19#include <linux/config.h>
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/spinlock.h>
24
25#include <asm/hardware.h>
26#include <asm/leds.h>
27#include <asm/mach-types.h>
28#include <asm/system.h>
29
30#define LED_STATE_ENABLED 1
31#define LED_STATE_CLAIMED 2
32static char led_state;
33static char hw_led_state;
34
35static DEFINE_SPINLOCK(leds_lock);
36
37static void ebsa285_leds_event(led_event_t evt)
38{
39 unsigned long flags;
40
41 spin_lock_irqsave(&leds_lock, flags);
42
43 switch (evt) {
44 case led_start:
45 hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN;
46#ifndef CONFIG_LEDS_CPU
47 hw_led_state |= XBUS_LED_AMBER;
48#endif
49 led_state |= LED_STATE_ENABLED;
50 break;
51
52 case led_stop:
53 led_state &= ~LED_STATE_ENABLED;
54 break;
55
56 case led_claim:
57 led_state |= LED_STATE_CLAIMED;
58 hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
59 break;
60
61 case led_release:
62 led_state &= ~LED_STATE_CLAIMED;
63 hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
64 break;
65
66#ifdef CONFIG_LEDS_TIMER
67 case led_timer:
68 if (!(led_state & LED_STATE_CLAIMED))
69 hw_led_state ^= XBUS_LED_GREEN;
70 break;
71#endif
72
73#ifdef CONFIG_LEDS_CPU
74 case led_idle_start:
75 if (!(led_state & LED_STATE_CLAIMED))
76 hw_led_state |= XBUS_LED_AMBER;
77 break;
78
79 case led_idle_end:
80 if (!(led_state & LED_STATE_CLAIMED))
81 hw_led_state &= ~XBUS_LED_AMBER;
82 break;
83#endif
84
85 case led_halted:
86 if (!(led_state & LED_STATE_CLAIMED))
87 hw_led_state &= ~XBUS_LED_RED;
88 break;
89
90 case led_green_on:
91 if (led_state & LED_STATE_CLAIMED)
92 hw_led_state &= ~XBUS_LED_GREEN;
93 break;
94
95 case led_green_off:
96 if (led_state & LED_STATE_CLAIMED)
97 hw_led_state |= XBUS_LED_GREEN;
98 break;
99
100 case led_amber_on:
101 if (led_state & LED_STATE_CLAIMED)
102 hw_led_state &= ~XBUS_LED_AMBER;
103 break;
104
105 case led_amber_off:
106 if (led_state & LED_STATE_CLAIMED)
107 hw_led_state |= XBUS_LED_AMBER;
108 break;
109
110 case led_red_on:
111 if (led_state & LED_STATE_CLAIMED)
112 hw_led_state &= ~XBUS_LED_RED;
113 break;
114
115 case led_red_off:
116 if (led_state & LED_STATE_CLAIMED)
117 hw_led_state |= XBUS_LED_RED;
118 break;
119
120 default:
121 break;
122 }
123
124 if (led_state & LED_STATE_ENABLED)
125 *XBUS_LEDS = hw_led_state;
126
127 spin_unlock_irqrestore(&leds_lock, flags);
128}
129
130static int __init leds_init(void)
131{
132 if (machine_is_ebsa285() || machine_is_co285())
133 leds_event = ebsa285_leds_event;
134
135 leds_event(led_start);
136
137 return 0;
138}
139
140__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c
new file mode 100644
index 000000000000..720c0bac1702
--- /dev/null
+++ b/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -0,0 +1,48 @@
1/*
2 * linux/arch/arm/mach-footbridge/ebsa285-pci.c
3 *
4 * PCI bios-type initialisation for PCI machines
5 *
6 * Bits taken from various places.
7 */
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11
12#include <asm/irq.h>
13#include <asm/mach/pci.h>
14#include <asm/mach-types.h>
15
16static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
17
18static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
19{
20 if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
21 dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
22 switch (PCI_FUNC(dev->devfn)) {
23 case 1: return 14;
24 case 2: return 15;
25 case 3: return 12;
26 }
27
28 return irqmap_ebsa285[(slot + pin) & 3];
29}
30
31static struct hw_pci ebsa285_pci __initdata = {
32 .swizzle = pci_std_swizzle,
33 .map_irq = ebsa285_map_irq,
34 .nr_controllers = 1,
35 .setup = dc21285_setup,
36 .scan = dc21285_scan_bus,
37 .preinit = dc21285_preinit,
38 .postinit = dc21285_postinit,
39};
40
41static int __init ebsa285_init_pci(void)
42{
43 if (machine_is_ebsa285())
44 pci_common_init(&ebsa285_pci);
45 return 0;
46}
47
48subsys_initcall(ebsa285_init_pci);
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
new file mode 100644
index 000000000000..d0931f5a63c8
--- /dev/null
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -0,0 +1,24 @@
1/*
2 * linux/arch/arm/mach-footbridge/ebsa285.c
3 *
4 * EBSA285 machine fixup
5 */
6#include <linux/init.h>
7
8#include <asm/hardware/dec21285.h>
9#include <asm/mach-types.h>
10
11#include <asm/mach/arch.h>
12
13#include "common.h"
14
15MACHINE_START(EBSA285, "EBSA285")
16 MAINTAINER("Russell King")
17 BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
18 BOOT_PARAMS(0x00000100)
19 VIDEO(0x000a0000, 0x000bffff)
20 MAPIO(footbridge_map_io)
21 INITIRQ(footbridge_init_irq)
22 .timer = &footbridge_timer,
23MACHINE_END
24
diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
new file mode 100644
index 000000000000..b21016070ea3
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa-irq.c
@@ -0,0 +1,168 @@
1/*
2 * linux/arch/arm/mach-footbridge/irq.c
3 *
4 * Copyright (C) 1996-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Changelog:
11 * 22-Aug-1998 RMK Restructured IRQ routines
12 * 03-Sep-1998 PJB Merged CATS support
13 * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
14 * 26-Jan-1999 PJB Don't use IACK on CATS
15 * 16-Mar-1999 RMK Added autodetect of ISA PICs
16 */
17#include <linux/ioport.h>
18#include <linux/interrupt.h>
19#include <linux/list.h>
20#include <linux/init.h>
21
22#include <asm/mach/irq.h>
23
24#include <asm/hardware.h>
25#include <asm/hardware/dec21285.h>
26#include <asm/irq.h>
27#include <asm/io.h>
28#include <asm/mach-types.h>
29
30static void isa_mask_pic_lo_irq(unsigned int irq)
31{
32 unsigned int mask = 1 << (irq & 7);
33
34 outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
35}
36
37static void isa_ack_pic_lo_irq(unsigned int irq)
38{
39 unsigned int mask = 1 << (irq & 7);
40
41 outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
42 outb(0x20, PIC_LO);
43}
44
45static void isa_unmask_pic_lo_irq(unsigned int irq)
46{
47 unsigned int mask = 1 << (irq & 7);
48
49 outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
50}
51
52static struct irqchip isa_lo_chip = {
53 .ack = isa_ack_pic_lo_irq,
54 .mask = isa_mask_pic_lo_irq,
55 .unmask = isa_unmask_pic_lo_irq,
56};
57
58static void isa_mask_pic_hi_irq(unsigned int irq)
59{
60 unsigned int mask = 1 << (irq & 7);
61
62 outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
63}
64
65static void isa_ack_pic_hi_irq(unsigned int irq)
66{
67 unsigned int mask = 1 << (irq & 7);
68
69 outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
70 outb(0x62, PIC_LO);
71 outb(0x20, PIC_HI);
72}
73
74static void isa_unmask_pic_hi_irq(unsigned int irq)
75{
76 unsigned int mask = 1 << (irq & 7);
77
78 outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
79}
80
81static struct irqchip isa_hi_chip = {
82 .ack = isa_ack_pic_hi_irq,
83 .mask = isa_mask_pic_hi_irq,
84 .unmask = isa_unmask_pic_hi_irq,
85};
86
87static void
88isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
89{
90 unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
91
92 if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
93 do_bad_IRQ(isa_irq, desc, regs);
94 return;
95 }
96
97 desc = irq_desc + isa_irq;
98 desc->handle(isa_irq, desc, regs);
99}
100
101static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
102static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
103static struct resource pic2_resource = { "pic2", 0xa0, 0xbf };
104
105void __init isa_init_irq(unsigned int host_irq)
106{
107 unsigned int irq;
108
109 /*
110 * Setup, and then probe for an ISA PIC
111 * If the PIC is not there, then we
112 * ignore the PIC.
113 */
114 outb(0x11, PIC_LO);
115 outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */
116 outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */
117 outb(0x01, PIC_MASK_LO); /* x86 */
118 outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */
119
120 outb(0x11, PIC_HI);
121 outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */
122 outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */
123 outb(0x01, PIC_MASK_HI); /* x86 */
124 outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */
125
126 outb(0x0b, PIC_LO);
127 outb(0x0b, PIC_HI);
128
129 if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
130 outb(0xff, PIC_MASK_LO);/* mask all IRQs */
131 outb(0xff, PIC_MASK_HI);/* mask all IRQs */
132 } else {
133 printk(KERN_INFO "IRQ: ISA PIC not found\n");
134 host_irq = (unsigned int)-1;
135 }
136
137 if (host_irq != (unsigned int)-1) {
138 for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
139 set_irq_chip(irq, &isa_lo_chip);
140 set_irq_handler(irq, do_level_IRQ);
141 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
142 }
143
144 for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
145 set_irq_chip(irq, &isa_hi_chip);
146 set_irq_handler(irq, do_level_IRQ);
147 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
148 }
149
150 request_resource(&ioport_resource, &pic1_resource);
151 request_resource(&ioport_resource, &pic2_resource);
152 setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
153
154 set_irq_chained_handler(host_irq, isa_irq_handler);
155
156 /*
157 * On the NetWinder, don't automatically
158 * enable ISA IRQ11 when it is requested.
159 * There appears to be a missing pull-up
160 * resistor on this line.
161 */
162 if (machine_is_netwinder())
163 set_irq_flags(_ISA_IRQ(11), IRQF_VALID |
164 IRQF_PROBE | IRQF_NOAUTOEN);
165 }
166}
167
168
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
new file mode 100644
index 000000000000..a4fefa0bb5a1
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -0,0 +1,94 @@
1/*
2 * linux/arch/arm/mach-footbridge/isa-timer.c
3 *
4 * Copyright (C) 1998 Russell King.
5 * Copyright (C) 1998 Phil Blundell
6 */
7#include <linux/init.h>
8#include <linux/interrupt.h>
9
10#include <asm/io.h>
11#include <asm/irq.h>
12
13#include <asm/mach/time.h>
14
15#include "common.h"
16
17/*
18 * ISA timer tick support
19 */
20#define mSEC_10_from_14 ((14318180 + 100) / 200)
21
22static unsigned long isa_gettimeoffset(void)
23{
24 int count;
25
26 static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
27 static unsigned long jiffies_p = 0;
28
29 /*
30 * cache volatile jiffies temporarily; we have IRQs turned off.
31 */
32 unsigned long jiffies_t;
33
34 /* timer count may underflow right here */
35 outb_p(0x00, 0x43); /* latch the count ASAP */
36
37 count = inb_p(0x40); /* read the latched count */
38
39 /*
40 * We do this guaranteed double memory access instead of a _p
41 * postfix in the previous port access. Wheee, hackady hack
42 */
43 jiffies_t = jiffies;
44
45 count |= inb_p(0x40) << 8;
46
47 /* Detect timer underflows. If we haven't had a timer tick since
48 the last time we were called, and time is apparently going
49 backwards, the counter must have wrapped during this routine. */
50 if ((jiffies_t == jiffies_p) && (count > count_p))
51 count -= (mSEC_10_from_14/6);
52 else
53 jiffies_p = jiffies_t;
54
55 count_p = count;
56
57 count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
58 count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
59
60 return count;
61}
62
63static irqreturn_t
64isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
65{
66 write_seqlock(&xtime_lock);
67 timer_tick(regs);
68 write_sequnlock(&xtime_lock);
69 return IRQ_HANDLED;
70}
71
72static struct irqaction isa_timer_irq = {
73 .name = "ISA timer tick",
74 .handler = isa_timer_interrupt,
75 .flags = SA_INTERRUPT,
76};
77
78static void __init isa_timer_init(void)
79{
80 isa_rtc_init();
81
82 /* enable PIT timer */
83 /* set for periodic (4) and LSB/MSB write (0x30) */
84 outb(0x34, 0x43);
85 outb((mSEC_10_from_14/6) & 0xFF, 0x40);
86 outb((mSEC_10_from_14/6) >> 8, 0x40);
87
88 setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
89}
90
91struct sys_timer isa_timer = {
92 .init = isa_timer_init,
93 .offset = isa_gettimeoffset,
94};
diff --git a/arch/arm/mach-footbridge/isa.c b/arch/arm/mach-footbridge/isa.c
new file mode 100644
index 000000000000..aa3a1fef563e
--- /dev/null
+++ b/arch/arm/mach-footbridge/isa.c
@@ -0,0 +1,48 @@
1/*
2 * linux/arch/arm/mach-footbridge/isa.c
3 *
4 * Copyright (C) 2004 Russell King.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/init.h>
11#include <linux/serial_8250.h>
12
13#include <asm/irq.h>
14
15static struct plat_serial8250_port serial_platform_data[] = {
16 {
17 .iobase = 0x3f8,
18 .irq = IRQ_ISA_UART,
19 .uartclk = 1843200,
20 .regshift = 0,
21 .iotype = UPIO_PORT,
22 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
23 },
24 {
25 .iobase = 0x2f8,
26 .irq = IRQ_ISA_UART2,
27 .uartclk = 1843200,
28 .regshift = 0,
29 .iotype = UPIO_PORT,
30 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
31 },
32 { },
33};
34
35static struct platform_device serial_device = {
36 .name = "serial8250",
37 .id = 0,
38 .dev = {
39 .platform_data = serial_platform_data,
40 },
41};
42
43static int __init footbridge_isa_init(void)
44{
45 return platform_device_register(&serial_device);
46}
47
48arch_initcall(footbridge_isa_init);
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
new file mode 100644
index 000000000000..1e1dfd79f4fe
--- /dev/null
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -0,0 +1,660 @@
1/*
2 * linux/arch/arm/mach-footbridge/netwinder-hw.c
3 *
4 * Netwinder machine fixup
5 *
6 * Copyright (C) 1998, 1999 Russell King, Phil Blundell
7 */
8#include <linux/config.h>
9#include <linux/module.h>
10#include <linux/ioport.h>
11#include <linux/kernel.h>
12#include <linux/delay.h>
13#include <linux/init.h>
14
15#include <asm/hardware/dec21285.h>
16#include <asm/io.h>
17#include <asm/leds.h>
18#include <asm/mach-types.h>
19#include <asm/setup.h>
20
21#include <asm/mach/arch.h>
22
23#include "common.h"
24
25#define IRDA_IO_BASE 0x180
26#define GP1_IO_BASE 0x338
27#define GP2_IO_BASE 0x33a
28
29
30#ifdef CONFIG_LEDS
31#define DEFAULT_LEDS 0
32#else
33#define DEFAULT_LEDS GPIO_GREEN_LED
34#endif
35
36/*
37 * Winbond WB83977F accessibility stuff
38 */
39static inline void wb977_open(void)
40{
41 outb(0x87, 0x370);
42 outb(0x87, 0x370);
43}
44
45static inline void wb977_close(void)
46{
47 outb(0xaa, 0x370);
48}
49
50static inline void wb977_wb(int reg, int val)
51{
52 outb(reg, 0x370);
53 outb(val, 0x371);
54}
55
56static inline void wb977_ww(int reg, int val)
57{
58 outb(reg, 0x370);
59 outb(val >> 8, 0x371);
60 outb(reg + 1, 0x370);
61 outb(val & 255, 0x371);
62}
63
64#define wb977_device_select(dev) wb977_wb(0x07, dev)
65#define wb977_device_disable() wb977_wb(0x30, 0x00)
66#define wb977_device_enable() wb977_wb(0x30, 0x01)
67
68/*
69 * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
70 */
71DEFINE_SPINLOCK(gpio_lock);
72
73static unsigned int current_gpio_op;
74static unsigned int current_gpio_io;
75static unsigned int current_cpld;
76
77void gpio_modify_op(int mask, int set)
78{
79 unsigned int new_gpio, changed;
80
81 new_gpio = (current_gpio_op & ~mask) | set;
82 changed = new_gpio ^ current_gpio_op;
83 current_gpio_op = new_gpio;
84
85 if (changed & 0xff)
86 outb(new_gpio, GP1_IO_BASE);
87 if (changed & 0xff00)
88 outb(new_gpio >> 8, GP2_IO_BASE);
89}
90
91static inline void __gpio_modify_io(int mask, int in)
92{
93 unsigned int new_gpio, changed;
94 int port;
95
96 new_gpio = (current_gpio_io & ~mask) | in;
97 changed = new_gpio ^ current_gpio_io;
98 current_gpio_io = new_gpio;
99
100 changed >>= 1;
101 new_gpio >>= 1;
102
103 wb977_device_select(7);
104
105 for (port = 0xe1; changed && port < 0xe8; changed >>= 1) {
106 wb977_wb(port, new_gpio & 1);
107
108 port += 1;
109 new_gpio >>= 1;
110 }
111
112 wb977_device_select(8);
113
114 for (port = 0xe8; changed && port < 0xec; changed >>= 1) {
115 wb977_wb(port, new_gpio & 1);
116
117 port += 1;
118 new_gpio >>= 1;
119 }
120}
121
122void gpio_modify_io(int mask, int in)
123{
124 /* Open up the SuperIO chip */
125 wb977_open();
126
127 __gpio_modify_io(mask, in);
128
129 /* Close up the EFER gate */
130 wb977_close();
131}
132
133int gpio_read(void)
134{
135 return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
136}
137
138/*
139 * Initialise the Winbond W83977F global registers
140 */
141static inline void wb977_init_global(void)
142{
143 /*
144 * Enable R/W config registers
145 */
146 wb977_wb(0x26, 0x40);
147
148 /*
149 * Power down FDC (not used)
150 */
151 wb977_wb(0x22, 0xfe);
152
153 /*
154 * GP12, GP11, CIRRX, IRRXH, GP10
155 */
156 wb977_wb(0x2a, 0xc1);
157
158 /*
159 * GP23, GP22, GP21, GP20, GP13
160 */
161 wb977_wb(0x2b, 0x6b);
162
163 /*
164 * GP17, GP16, GP15, GP14
165 */
166 wb977_wb(0x2c, 0x55);
167}
168
169/*
170 * Initialise the Winbond W83977F printer port
171 */
172static inline void wb977_init_printer(void)
173{
174 wb977_device_select(1);
175
176 /*
177 * mode 1 == EPP
178 */
179 wb977_wb(0xf0, 0x01);
180}
181
182/*
183 * Initialise the Winbond W83977F keyboard controller
184 */
185static inline void wb977_init_keyboard(void)
186{
187 wb977_device_select(5);
188
189 /*
190 * Keyboard controller address
191 */
192 wb977_ww(0x60, 0x0060);
193 wb977_ww(0x62, 0x0064);
194
195 /*
196 * Keyboard IRQ 1, active high, edge trigger
197 */
198 wb977_wb(0x70, 1);
199 wb977_wb(0x71, 0x02);
200
201 /*
202 * Mouse IRQ 5, active high, edge trigger
203 */
204 wb977_wb(0x72, 5);
205 wb977_wb(0x73, 0x02);
206
207 /*
208 * KBC 8MHz
209 */
210 wb977_wb(0xf0, 0x40);
211
212 /*
213 * Enable device
214 */
215 wb977_device_enable();
216}
217
218/*
219 * Initialise the Winbond W83977F Infra-Red device
220 */
221static inline void wb977_init_irda(void)
222{
223 wb977_device_select(6);
224
225 /*
226 * IR base address
227 */
228 wb977_ww(0x60, IRDA_IO_BASE);
229
230 /*
231 * IRDA IRQ 6, active high, edge trigger
232 */
233 wb977_wb(0x70, 6);
234 wb977_wb(0x71, 0x02);
235
236 /*
237 * RX DMA - ISA DMA 0
238 */
239 wb977_wb(0x74, 0x00);
240
241 /*
242 * TX DMA - Disable Tx DMA
243 */
244 wb977_wb(0x75, 0x04);
245
246 /*
247 * Append CRC, Enable bank selection
248 */
249 wb977_wb(0xf0, 0x03);
250
251 /*
252 * Enable device
253 */
254 wb977_device_enable();
255}
256
257/*
258 * Initialise Winbond W83977F general purpose IO
259 */
260static inline void wb977_init_gpio(void)
261{
262 unsigned long flags;
263
264 /*
265 * Set up initial I/O definitions
266 */
267 current_gpio_io = -1;
268 __gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER);
269
270 wb977_device_select(7);
271
272 /*
273 * Group1 base address
274 */
275 wb977_ww(0x60, GP1_IO_BASE);
276 wb977_ww(0x62, 0);
277 wb977_ww(0x64, 0);
278
279 /*
280 * GP10 (Orage button) IRQ 10, active high, edge trigger
281 */
282 wb977_wb(0x70, 10);
283 wb977_wb(0x71, 0x02);
284
285 /*
286 * GP10: Debounce filter enabled, IRQ, input
287 */
288 wb977_wb(0xe0, 0x19);
289
290 /*
291 * Enable Group1
292 */
293 wb977_device_enable();
294
295 wb977_device_select(8);
296
297 /*
298 * Group2 base address
299 */
300 wb977_ww(0x60, GP2_IO_BASE);
301
302 /*
303 * Clear watchdog timer regs
304 * - timer disable
305 */
306 wb977_wb(0xf2, 0x00);
307
308 /*
309 * - disable LED, no mouse nor keyboard IRQ
310 */
311 wb977_wb(0xf3, 0x00);
312
313 /*
314 * - timer counting, disable power LED, disable timeouot
315 */
316 wb977_wb(0xf4, 0x00);
317
318 /*
319 * Enable group2
320 */
321 wb977_device_enable();
322
323 /*
324 * Set Group1/Group2 outputs
325 */
326 spin_lock_irqsave(&gpio_lock, flags);
327 gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
328 spin_unlock_irqrestore(&gpio_lock, flags);
329}
330
331/*
332 * Initialise the Winbond W83977F chip.
333 */
334static void __init wb977_init(void)
335{
336 request_region(0x370, 2, "W83977AF configuration");
337
338 /*
339 * Open up the SuperIO chip
340 */
341 wb977_open();
342
343 /*
344 * Initialise the global registers
345 */
346 wb977_init_global();
347
348 /*
349 * Initialise the various devices in
350 * the multi-IO chip.
351 */
352 wb977_init_printer();
353 wb977_init_keyboard();
354 wb977_init_irda();
355 wb977_init_gpio();
356
357 /*
358 * Close up the EFER gate
359 */
360 wb977_close();
361}
362
363void cpld_modify(int mask, int set)
364{
365 int msk;
366
367 current_cpld = (current_cpld & ~mask) | set;
368
369 gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
370 gpio_modify_op(GPIO_IOLOAD, 0);
371
372 for (msk = 8; msk; msk >>= 1) {
373 int bit = current_cpld & msk;
374
375 gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
376 gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
377 }
378
379 gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
380 gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
381 gpio_modify_op(GPIO_IOLOAD, 0);
382}
383
384static void __init cpld_init(void)
385{
386 unsigned long flags;
387
388 spin_lock_irqsave(&gpio_lock, flags);
389 cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
390 spin_unlock_irqrestore(&gpio_lock, flags);
391}
392
393static unsigned char rwa_unlock[] __initdata =
394{ 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b,
395 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74,
396 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
397
398#ifndef DEBUG
399#define dprintk(x...)
400#else
401#define dprintk(x...) printk(x)
402#endif
403
404#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
405
406static inline void rwa010_unlock(void)
407{
408 int i;
409
410 WRITE_RWA(2, 2);
411 mdelay(10);
412
413 for (i = 0; i < sizeof(rwa_unlock); i++) {
414 outb(rwa_unlock[i], 0x279);
415 udelay(10);
416 }
417}
418
419static inline void rwa010_read_ident(void)
420{
421 unsigned char si[9];
422 int i, j;
423
424 WRITE_RWA(3, 0);
425 WRITE_RWA(0, 128);
426
427 outb(1, 0x279);
428
429 mdelay(1);
430
431 dprintk("Identifier: ");
432 for (i = 0; i < 9; i++) {
433 si[i] = 0;
434 for (j = 0; j < 8; j++) {
435 int bit;
436 udelay(250);
437 inb(0x203);
438 udelay(250);
439 bit = inb(0x203);
440 dprintk("%02X ", bit);
441 bit = (bit == 0xaa) ? 1 : 0;
442 si[i] |= bit << j;
443 }
444 dprintk("(%02X) ", si[i]);
445 }
446 dprintk("\n");
447}
448
449static inline void rwa010_global_init(void)
450{
451 WRITE_RWA(6, 2); // Assign a card no = 2
452
453 dprintk("Card no = %d\n", inb(0x203));
454
455 /* disable the modem section of the chip */
456 WRITE_RWA(7, 3);
457 WRITE_RWA(0x30, 0);
458
459 /* disable the cdrom section of the chip */
460 WRITE_RWA(7, 4);
461 WRITE_RWA(0x30, 0);
462
463 /* disable the MPU-401 section of the chip */
464 WRITE_RWA(7, 2);
465 WRITE_RWA(0x30, 0);
466}
467
468static inline void rwa010_game_port_init(void)
469{
470 int i;
471
472 WRITE_RWA(7, 5);
473
474 dprintk("Slider base: ");
475 WRITE_RWA(0x61, 1);
476 i = inb(0x203);
477
478 WRITE_RWA(0x60, 2);
479 dprintk("%02X%02X (201)\n", inb(0x203), i);
480
481 WRITE_RWA(0x30, 1);
482}
483
484static inline void rwa010_waveartist_init(int base, int irq, int dma)
485{
486 int i;
487
488 WRITE_RWA(7, 0);
489
490 dprintk("WaveArtist base: ");
491 WRITE_RWA(0x61, base & 255);
492 i = inb(0x203);
493
494 WRITE_RWA(0x60, base >> 8);
495 dprintk("%02X%02X (%X),", inb(0x203), i, base);
496
497 WRITE_RWA(0x70, irq);
498 dprintk(" irq: %d (%d),", inb(0x203), irq);
499
500 WRITE_RWA(0x74, dma);
501 dprintk(" dma: %d (%d)\n", inb(0x203), dma);
502
503 WRITE_RWA(0x30, 1);
504}
505
506static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, int dma)
507{
508 int i;
509
510 WRITE_RWA(7, 1);
511
512 dprintk("SoundBlaster base: ");
513 WRITE_RWA(0x61, sb_base & 255);
514 i = inb(0x203);
515
516 WRITE_RWA(0x60, sb_base >> 8);
517 dprintk("%02X%02X (%X),", inb(0x203), i, sb_base);
518
519 dprintk(" irq: ");
520 WRITE_RWA(0x70, irq);
521 dprintk("%d (%d),", inb(0x203), irq);
522
523 dprintk(" 8-bit DMA: ");
524 WRITE_RWA(0x74, dma);
525 dprintk("%d (%d)\n", inb(0x203), dma);
526
527 dprintk("AdLib base: ");
528 WRITE_RWA(0x63, al_base & 255);
529 i = inb(0x203);
530
531 WRITE_RWA(0x62, al_base >> 8);
532 dprintk("%02X%02X (%X)\n", inb(0x203), i, al_base);
533
534 WRITE_RWA(0x30, 1);
535}
536
537static void rwa010_soundblaster_reset(void)
538{
539 int i;
540
541 outb(1, 0x226);
542 udelay(3);
543 outb(0, 0x226);
544
545 for (i = 0; i < 5; i++) {
546 if (inb(0x22e) & 0x80)
547 break;
548 mdelay(1);
549 }
550 if (i == 5)
551 printk("SoundBlaster: DSP reset failed\n");
552
553 dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a));
554
555 for (i = 0; i < 5; i++) {
556 if ((inb(0x22c) & 0x80) == 0)
557 break;
558 mdelay(1);
559 }
560
561 if (i == 5)
562 printk("SoundBlaster: DSP not ready\n");
563 else {
564 outb(0xe1, 0x22c);
565
566 dprintk("SoundBlaster DSP id: ");
567 i = inb(0x22a);
568 udelay(1);
569 i |= inb(0x22a) << 8;
570 dprintk("%04X\n", i);
571
572 for (i = 0; i < 5; i++) {
573 if ((inb(0x22c) & 0x80) == 0)
574 break;
575 mdelay(1);
576 }
577
578 if (i == 5)
579 printk("SoundBlaster: could not turn speaker off\n");
580
581 outb(0xd3, 0x22c);
582 }
583
584 /* turn on OPL3 */
585 outb(5, 0x38a);
586 outb(1, 0x38b);
587}
588
589static void __init rwa010_init(void)
590{
591 rwa010_unlock();
592 rwa010_read_ident();
593 rwa010_global_init();
594 rwa010_game_port_init();
595 rwa010_waveartist_init(0x250, 3, 7);
596 rwa010_soundblaster_init(0x220, 0x388, 3, 1);
597 rwa010_soundblaster_reset();
598}
599
600EXPORT_SYMBOL(gpio_lock);
601EXPORT_SYMBOL(gpio_modify_op);
602EXPORT_SYMBOL(gpio_modify_io);
603EXPORT_SYMBOL(cpld_modify);
604
605/*
606 * Initialise any other hardware after we've got the PCI bus
607 * initialised. We may need the PCI bus to talk to this other
608 * hardware.
609 */
610static int __init nw_hw_init(void)
611{
612 if (machine_is_netwinder()) {
613 unsigned long flags;
614
615 wb977_init();
616 cpld_init();
617 rwa010_init();
618
619 spin_lock_irqsave(&gpio_lock, flags);
620 gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
621 spin_unlock_irqrestore(&gpio_lock, flags);
622 }
623 return 0;
624}
625
626__initcall(nw_hw_init);
627
628/*
629 * Older NeTTroms either do not provide a parameters
630 * page, or they don't supply correct information in
631 * the parameter page.
632 */
633static void __init
634fixup_netwinder(struct machine_desc *desc, struct tag *tags,
635 char **cmdline, struct meminfo *mi)
636{
637#ifdef CONFIG_ISAPNP
638 extern int isapnp_disable;
639
640 /*
641 * We must not use the kernels ISAPnP code
642 * on the NetWinder - it will reset the settings
643 * for the WaveArtist chip and render it inoperable.
644 */
645 isapnp_disable = 1;
646#endif
647}
648
649MACHINE_START(NETWINDER, "Rebel-NetWinder")
650 MAINTAINER("Russell King/Rebel.com")
651 BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
652 BOOT_PARAMS(0x00000100)
653 VIDEO(0x000a0000, 0x000bffff)
654 DISABLE_PARPORT(0)
655 DISABLE_PARPORT(2)
656 FIXUP(fixup_netwinder)
657 MAPIO(footbridge_map_io)
658 INITIRQ(footbridge_init_irq)
659 .timer = &isa_timer,
660MACHINE_END
diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c
new file mode 100644
index 000000000000..7451fc07b85a
--- /dev/null
+++ b/arch/arm/mach-footbridge/netwinder-leds.c
@@ -0,0 +1,141 @@
1/*
2 * linux/arch/arm/mach-footbridge/netwinder-leds.c
3 *
4 * Copyright (C) 1998-1999 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * NetWinder LED control routines.
11 *
12 * The Netwinder uses the leds as follows:
13 * - Green - toggles state every 50 timer interrupts
14 * - Red - On if the system is not idle
15 *
16 * Changelog:
17 * 02-05-1999 RMK Various cleanups
18 */
19#include <linux/config.h>
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/spinlock.h>
24
25#include <asm/hardware.h>
26#include <asm/leds.h>
27#include <asm/mach-types.h>
28#include <asm/system.h>
29
30#define LED_STATE_ENABLED 1
31#define LED_STATE_CLAIMED 2
32static char led_state;
33static char hw_led_state;
34
35static DEFINE_SPINLOCK(leds_lock);
36extern spinlock_t gpio_lock;
37
38static void netwinder_leds_event(led_event_t evt)
39{
40 unsigned long flags;
41
42 spin_lock_irqsave(&leds_lock, flags);
43
44 switch (evt) {
45 case led_start:
46 led_state |= LED_STATE_ENABLED;
47 hw_led_state = GPIO_GREEN_LED;
48 break;
49
50 case led_stop:
51 led_state &= ~LED_STATE_ENABLED;
52 break;
53
54 case led_claim:
55 led_state |= LED_STATE_CLAIMED;
56 hw_led_state = 0;
57 break;
58
59 case led_release:
60 led_state &= ~LED_STATE_CLAIMED;
61 hw_led_state = 0;
62 break;
63
64#ifdef CONFIG_LEDS_TIMER
65 case led_timer:
66 if (!(led_state & LED_STATE_CLAIMED))
67 hw_led_state ^= GPIO_GREEN_LED;
68 break;
69#endif
70
71#ifdef CONFIG_LEDS_CPU
72 case led_idle_start:
73 if (!(led_state & LED_STATE_CLAIMED))
74 hw_led_state &= ~GPIO_RED_LED;
75 break;
76
77 case led_idle_end:
78 if (!(led_state & LED_STATE_CLAIMED))
79 hw_led_state |= GPIO_RED_LED;
80 break;
81#endif
82
83 case led_halted:
84 if (!(led_state & LED_STATE_CLAIMED))
85 hw_led_state |= GPIO_RED_LED;
86 break;
87
88 case led_green_on:
89 if (led_state & LED_STATE_CLAIMED)
90 hw_led_state |= GPIO_GREEN_LED;
91 break;
92
93 case led_green_off:
94 if (led_state & LED_STATE_CLAIMED)
95 hw_led_state &= ~GPIO_GREEN_LED;
96 break;
97
98 case led_amber_on:
99 if (led_state & LED_STATE_CLAIMED)
100 hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
101 break;
102
103 case led_amber_off:
104 if (led_state & LED_STATE_CLAIMED)
105 hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
106 break;
107
108 case led_red_on:
109 if (led_state & LED_STATE_CLAIMED)
110 hw_led_state |= GPIO_RED_LED;
111 break;
112
113 case led_red_off:
114 if (led_state & LED_STATE_CLAIMED)
115 hw_led_state &= ~GPIO_RED_LED;
116 break;
117
118 default:
119 break;
120 }
121
122 spin_unlock_irqrestore(&leds_lock, flags);
123
124 if (led_state & LED_STATE_ENABLED) {
125 spin_lock_irqsave(&gpio_lock, flags);
126 gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
127 spin_unlock_irqrestore(&gpio_lock, flags);
128 }
129}
130
131static int __init leds_init(void)
132{
133 if (machine_is_netwinder())
134 leds_event = netwinder_leds_event;
135
136 leds_event(led_start);
137
138 return 0;
139}
140
141__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c
new file mode 100644
index 000000000000..e263d6d54a0f
--- /dev/null
+++ b/arch/arm/mach-footbridge/netwinder-pci.c
@@ -0,0 +1,62 @@
1/*
2 * linux/arch/arm/mach-footbridge/netwinder-pci.c
3 *
4 * PCI bios-type initialisation for PCI machines
5 *
6 * Bits taken from various places.
7 */
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11
12#include <asm/irq.h>
13#include <asm/mach/pci.h>
14#include <asm/mach-types.h>
15
16/*
17 * We now use the slot ID instead of the device identifiers to select
18 * which interrupt is routed where.
19 */
20static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
21{
22 switch (slot) {
23 case 0: /* host bridge */
24 return 0;
25
26 case 9: /* CyberPro */
27 return IRQ_NETWINDER_VGA;
28
29 case 10: /* DC21143 */
30 return IRQ_NETWINDER_ETHER100;
31
32 case 12: /* Winbond 553 */
33 return IRQ_ISA_HARDDISK1;
34
35 case 13: /* Winbond 89C940F */
36 return IRQ_NETWINDER_ETHER10;
37
38 default:
39 printk(KERN_ERR "PCI: unknown device in slot %s\n",
40 pci_name(dev));
41 return 0;
42 }
43}
44
45static struct hw_pci netwinder_pci __initdata = {
46 .swizzle = pci_std_swizzle,
47 .map_irq = netwinder_map_irq,
48 .nr_controllers = 1,
49 .setup = dc21285_setup,
50 .scan = dc21285_scan_bus,
51 .preinit = dc21285_preinit,
52 .postinit = dc21285_postinit,
53};
54
55static int __init netwinder_pci_init(void)
56{
57 if (machine_is_netwinder())
58 pci_common_init(&netwinder_pci);
59 return 0;
60}
61
62subsys_initcall(netwinder_pci_init);
diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c
new file mode 100644
index 000000000000..d5fca95afdad
--- /dev/null
+++ b/arch/arm/mach-footbridge/personal-pci.c
@@ -0,0 +1,56 @@
1/*
2 * linux/arch/arm/mach-footbridge/personal-pci.c
3 *
4 * PCI bios-type initialisation for PCI machines
5 *
6 * Bits taken from various places.
7 */
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11
12#include <asm/irq.h>
13#include <asm/mach/pci.h>
14#include <asm/mach-types.h>
15
16static int irqmap_personal_server[] __initdata = {
17 IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
18 IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
19};
20
21static int __init personal_server_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
22{
23 unsigned char line;
24
25 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
26
27 if (line > 0x40 && line <= 0x5f) {
28 /* line corresponds to the bit controlling this interrupt
29 * in the footbridge. Ignore the first 8 interrupt bits,
30 * look up the rest in the map. IN0 is bit number 8
31 */
32 return irqmap_personal_server[(line & 0x1f) - 8];
33 } else if (line == 0) {
34 /* no interrupt */
35 return 0;
36 } else
37 return irqmap_personal_server[(line - 1) & 3];
38}
39
40static struct hw_pci personal_server_pci __initdata = {
41 .map_irq = personal_server_map_irq,
42 .nr_controllers = 1,
43 .setup = dc21285_setup,
44 .scan = dc21285_scan_bus,
45 .preinit = dc21285_preinit,
46 .postinit = dc21285_postinit,
47};
48
49static int __init personal_pci_init(void)
50{
51 if (machine_is_personal_server())
52 pci_common_init(&personal_server_pci);
53 return 0;
54}
55
56subsys_initcall(personal_pci_init);
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
new file mode 100644
index 000000000000..415086d7bbee
--- /dev/null
+++ b/arch/arm/mach-footbridge/personal.c
@@ -0,0 +1,23 @@
1/*
2 * linux/arch/arm/mach-footbridge/personal.c
3 *
4 * Personal server (Skiff) machine fixup
5 */
6#include <linux/init.h>
7
8#include <asm/hardware/dec21285.h>
9#include <asm/mach-types.h>
10
11#include <asm/mach/arch.h>
12
13#include "common.h"
14
15MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
16 MAINTAINER("Jamey Hicks / George France")
17 BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
18 BOOT_PARAMS(0x00000100)
19 MAPIO(footbridge_map_io)
20 INITIRQ(footbridge_init_irq)
21 .timer = &footbridge_timer,
22MACHINE_END
23
diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c
new file mode 100644
index 000000000000..2c64a0b0502e
--- /dev/null
+++ b/arch/arm/mach-footbridge/time.c
@@ -0,0 +1,180 @@
1/*
2 * linux/include/asm-arm/arch-ebsa285/time.h
3 *
4 * Copyright (C) 1998 Russell King.
5 * Copyright (C) 1998 Phil Blundell
6 *
7 * CATS has a real-time clock, though the evaluation board doesn't.
8 *
9 * Changelog:
10 * 21-Mar-1998 RMK Created
11 * 27-Aug-1998 PJB CATS support
12 * 28-Dec-1998 APH Made leds optional
13 * 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder
14 * 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in
15 */
16
17#define RTC_PORT(x) (rtc_base+(x))
18#define RTC_ALWAYS_BCD 0
19
20#include <linux/timex.h>
21#include <linux/init.h>
22#include <linux/sched.h>
23#include <linux/mc146818rtc.h>
24#include <linux/bcd.h>
25
26#include <asm/hardware.h>
27#include <asm/io.h>
28
29#include <asm/mach/time.h>
30#include "common.h"
31
32static int rtc_base;
33
34static unsigned long __init get_isa_cmos_time(void)
35{
36 unsigned int year, mon, day, hour, min, sec;
37 int i;
38
39 // check to see if the RTC makes sense.....
40 if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
41 return mktime(1970, 1, 1, 0, 0, 0);
42
43 /* The Linux interpretation of the CMOS clock register contents:
44 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
45 * RTC registers show the second which has precisely just started.
46 * Let's hope other operating systems interpret the RTC the same way.
47 */
48 /* read RTC exactly on falling edge of update flag */
49 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
50 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
51 break;
52
53 for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
54 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
55 break;
56
57 do { /* Isn't this overkill ? UIP above should guarantee consistency */
58 sec = CMOS_READ(RTC_SECONDS);
59 min = CMOS_READ(RTC_MINUTES);
60 hour = CMOS_READ(RTC_HOURS);
61 day = CMOS_READ(RTC_DAY_OF_MONTH);
62 mon = CMOS_READ(RTC_MONTH);
63 year = CMOS_READ(RTC_YEAR);
64 } while (sec != CMOS_READ(RTC_SECONDS));
65
66 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
67 BCD_TO_BIN(sec);
68 BCD_TO_BIN(min);
69 BCD_TO_BIN(hour);
70 BCD_TO_BIN(day);
71 BCD_TO_BIN(mon);
72 BCD_TO_BIN(year);
73 }
74 if ((year += 1900) < 1970)
75 year += 100;
76 return mktime(year, mon, day, hour, min, sec);
77}
78
79static int set_isa_cmos_time(void)
80{
81 int retval = 0;
82 int real_seconds, real_minutes, cmos_minutes;
83 unsigned char save_control, save_freq_select;
84 unsigned long nowtime = xtime.tv_sec;
85
86 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
87 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
88
89 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
90 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
91
92 cmos_minutes = CMOS_READ(RTC_MINUTES);
93 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
94 BCD_TO_BIN(cmos_minutes);
95
96 /*
97 * since we're only adjusting minutes and seconds,
98 * don't interfere with hour overflow. This avoids
99 * messing with unknown time zones but requires your
100 * RTC not to be off by more than 15 minutes
101 */
102 real_seconds = nowtime % 60;
103 real_minutes = nowtime / 60;
104 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
105 real_minutes += 30; /* correct for half hour time zone */
106 real_minutes %= 60;
107
108 if (abs(real_minutes - cmos_minutes) < 30) {
109 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
110 BIN_TO_BCD(real_seconds);
111 BIN_TO_BCD(real_minutes);
112 }
113 CMOS_WRITE(real_seconds,RTC_SECONDS);
114 CMOS_WRITE(real_minutes,RTC_MINUTES);
115 } else
116 retval = -1;
117
118 /* The following flags have to be released exactly in this order,
119 * otherwise the DS12887 (popular MC146818A clone with integrated
120 * battery and quartz) will not reset the oscillator and will not
121 * update precisely 500 ms later. You won't find this mentioned in
122 * the Dallas Semiconductor data sheets, but who believes data
123 * sheets anyway ... -- Markus Kuhn
124 */
125 CMOS_WRITE(save_control, RTC_CONTROL);
126 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
127
128 return retval;
129}
130
131void __init isa_rtc_init(void)
132{
133 if (machine_is_co285() ||
134 machine_is_personal_server())
135 /*
136 * Add-in 21285s shouldn't access the RTC
137 */
138 rtc_base = 0;
139 else
140 rtc_base = 0x70;
141
142 if (rtc_base) {
143 int reg_d, reg_b;
144
145 /*
146 * Probe for the RTC.
147 */
148 reg_d = CMOS_READ(RTC_REG_D);
149
150 /*
151 * make sure the divider is set
152 */
153 CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
154
155 /*
156 * Set control reg B
157 * (24 hour mode, update enabled)
158 */
159 reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
160 reg_b |= 2;
161 CMOS_WRITE(reg_b, RTC_REG_B);
162
163 if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
164 CMOS_READ(RTC_REG_B) == reg_b) {
165 struct timespec tv;
166
167 /*
168 * We have a RTC. Check the battery
169 */
170 if ((reg_d & 0x80) == 0)
171 printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
172
173 tv.tv_nsec = 0;
174 tv.tv_sec = get_isa_cmos_time();
175 do_settimeofday(&tv);
176 set_rtc = set_isa_cmos_time;
177 } else
178 rtc_base = 0;
179 }
180}