aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-iop3xx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/arm/mach-iop3xx
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/arm/mach-iop3xx')
-rw-r--r--arch/arm/mach-iop3xx/Kconfig63
-rw-r--r--arch/arm/mach-iop3xx/Makefile23
-rw-r--r--arch/arm/mach-iop3xx/Makefile.boot9
-rw-r--r--arch/arm/mach-iop3xx/common.c74
-rw-r--r--arch/arm/mach-iop3xx/iop321-irq.c96
-rw-r--r--arch/arm/mach-iop3xx/iop321-pci.c220
-rw-r--r--arch/arm/mach-iop3xx/iop321-setup.c169
-rw-r--r--arch/arm/mach-iop3xx/iop321-time.c109
-rw-r--r--arch/arm/mach-iop3xx/iop331-irq.c127
-rw-r--r--arch/arm/mach-iop3xx/iop331-pci.c222
-rw-r--r--arch/arm/mach-iop3xx/iop331-setup.c177
-rw-r--r--arch/arm/mach-iop3xx/iop331-time.c107
-rw-r--r--arch/arm/mach-iop3xx/iq31244-mm.c44
-rw-r--r--arch/arm/mach-iop3xx/iq31244-pci.c129
-rw-r--r--arch/arm/mach-iop3xx/iq80321-mm.c44
-rw-r--r--arch/arm/mach-iop3xx/iq80321-pci.c123
-rw-r--r--arch/arm/mach-iop3xx/iq80331-mm.c36
-rw-r--r--arch/arm/mach-iop3xx/iq80331-pci.c119
-rw-r--r--arch/arm/mach-iop3xx/iq80332-mm.c36
-rw-r--r--arch/arm/mach-iop3xx/iq80332-pci.c125
20 files changed, 2052 insertions, 0 deletions
diff --git a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig
new file mode 100644
index 000000000000..2bfe8c729f9f
--- /dev/null
+++ b/arch/arm/mach-iop3xx/Kconfig
@@ -0,0 +1,63 @@
1if ARCH_IOP3XX
2
3menu "IOP3xx Implementation Options"
4
5comment "IOP3xx Platform Types"
6
7config ARCH_IQ80321
8 bool "Enable support for IQ80321"
9 select ARCH_IOP321
10 help
11 Say Y here if you want to run your kernel on the Intel IQ80321
12 evaluation kit for the IOP321 chipset.
13
14config ARCH_IQ31244
15 bool "Enable support for IQ31244"
16 select ARCH_IOP321
17 help
18 Say Y here if you want to run your kernel on the Intel IQ31244
19 evaluation kit for the IOP321 chipset.
20
21config ARCH_IQ80331
22 bool "Enable support for IQ80331"
23 select ARCH_IOP331
24 help
25 Say Y here if you want to run your kernel on the Intel IQ80331
26 evaluation kit for the IOP331 chipset.
27
28config MACH_IQ80332
29 bool "Enable support for IQ80332"
30 select ARCH_IOP331
31 help
32 Say Y here if you want to run your kernel on the Intel IQ80332
33 evaluation kit for the IOP332 chipset
34
35config ARCH_EP80219
36 bool "Enable support for EP80219"
37 select ARCH_IOP321
38 select ARCH_IQ31244
39
40# Which IOP variant are we running?
41config ARCH_IOP321
42 bool
43 help
44 The IQ80321 uses the IOP321 variant.
45 The IQ31244 and EP80219 uses the IOP321 variant.
46
47config ARCH_IOP331
48 bool
49 default ARCH_IQ80331
50 help
51 The IQ80331, IQ80332, and IQ80333 uses the IOP331 variant.
52
53comment "IOP3xx Chipset Features"
54
55config IOP331_STEPD
56 bool "Chip stepping D of the IOP80331 processor or IOP80333"
57 depends on (ARCH_IOP331)
58 help
59 Say Y here if you have StepD of the IOP80331 or IOP8033
60 based platforms.
61
62endmenu
63endif
diff --git a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile
new file mode 100644
index 000000000000..b17eb1f46102
--- /dev/null
+++ b/arch/arm/mach-iop3xx/Makefile
@@ -0,0 +1,23 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Object file lists.
6
7obj-y := common.o
8
9obj-m :=
10obj-n :=
11obj- :=
12
13obj-$(CONFIG_ARCH_IOP321) += iop321-setup.o iop321-irq.o iop321-pci.o iop321-time.o
14
15obj-$(CONFIG_ARCH_IOP331) += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
16
17obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
18
19obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
20
21obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o
22
23obj-$(CONFIG_MACH_IQ80332) += iq80332-mm.o iq80332-pci.o
diff --git a/arch/arm/mach-iop3xx/Makefile.boot b/arch/arm/mach-iop3xx/Makefile.boot
new file mode 100644
index 000000000000..6387aa20461b
--- /dev/null
+++ b/arch/arm/mach-iop3xx/Makefile.boot
@@ -0,0 +1,9 @@
1 zreladdr-y := 0xa0008000
2params_phys-y := 0xa0000100
3initrd_phys-y := 0xa0800000
4ifeq ($(CONFIG_ARCH_IOP331),y)
5 zreladdr-y := 0x00008000
6params_phys-y := 0x00000100
7initrd_phys-y := 0x00800000
8endif
9
diff --git a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c
new file mode 100644
index 000000000000..bda7394ec06c
--- /dev/null
+++ b/arch/arm/mach-iop3xx/common.c
@@ -0,0 +1,74 @@
1/*
2 * arch/arm/mach-iop3xx/common.c
3 *
4 * Common routines shared across all IOP3xx implementations
5 *
6 * Author: Deepak Saxena <dsaxena@mvista.com>
7 *
8 * Copyright 2003 (c) MontaVista, Software, Inc.
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14
15#include <linux/config.h>
16#include <linux/delay.h>
17#include <asm/hardware.h>
18
19/*
20 * Shared variables
21 */
22unsigned long iop3xx_pcibios_min_io = 0;
23unsigned long iop3xx_pcibios_min_mem = 0;
24
25#ifdef CONFIG_ARCH_EP80219
26#include <linux/kernel.h>
27/*
28 * Default power-off for EP80219
29 */
30#include <asm/mach-types.h>
31
32static inline void ep80219_send_to_pic(__u8 c) {
33}
34
35void ep80219_power_off(void)
36{
37 /*
38 * This function will send a SHUTDOWN_COMPLETE message to the PIC controller
39 * over I2C. We are not using the i2c subsystem since we are going to power
40 * off and it may be removed
41 */
42
43 /* Send the Address byte w/ the start condition */
44 *IOP321_IDBR1 = 0x60;
45 *IOP321_ICR1 = 0xE9;
46 mdelay(1);
47
48 /* Send the START_MSG byte w/ no start or stop condition */
49 *IOP321_IDBR1 = 0x0F;
50 *IOP321_ICR1 = 0xE8;
51 mdelay(1);
52
53 /* Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or stop condition */
54 *IOP321_IDBR1 = 0x03;
55 *IOP321_ICR1 = 0xE8;
56 mdelay(1);
57
58 /* Send an ignored byte w/ stop condition */
59 *IOP321_IDBR1 = 0x00;
60 *IOP321_ICR1 = 0xEA;
61
62 while (1) ;
63}
64
65#include <linux/init.h>
66#include <linux/pm.h>
67
68static int __init ep80219_init(void)
69{
70 pm_power_off = ep80219_power_off;
71 return 0;
72}
73arch_initcall(ep80219_init);
74#endif
diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
new file mode 100644
index 000000000000..d42aae6aef03
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop321-irq.c
@@ -0,0 +1,96 @@
1/*
2 * linux/arch/arm/mach-iop3xx/iop321-irq.c
3 *
4 * Generic IOP321 IRQ handling functionality
5 *
6 * Author: Rory Bolt <rorybolt@pacbell.net>
7 * Copyright (C) 2002 Rory Bolt
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Added IOP3XX chipset and IQ80321 board masking code.
14 *
15 */
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/list.h>
19
20#include <asm/mach/irq.h>
21#include <asm/irq.h>
22#include <asm/hardware.h>
23
24#include <asm/mach-types.h>
25
26static u32 iop321_mask /* = 0 */;
27
28static inline void intctl_write(u32 val)
29{
30 asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
31}
32
33static inline void intstr_write(u32 val)
34{
35 asm volatile("mcr p6,0,%0,c4,c0,0"::"r" (val));
36}
37
38static void
39iop321_irq_mask (unsigned int irq)
40{
41
42 iop321_mask &= ~(1 << (irq - IOP321_IRQ_OFS));
43
44 intctl_write(iop321_mask);
45}
46
47static void
48iop321_irq_unmask (unsigned int irq)
49{
50 iop321_mask |= (1 << (irq - IOP321_IRQ_OFS));
51
52 intctl_write(iop321_mask);
53}
54
55struct irqchip ext_chip = {
56 .ack = iop321_irq_mask,
57 .mask = iop321_irq_mask,
58 .unmask = iop321_irq_unmask,
59};
60
61void __init iop321_init_irq(void)
62{
63 unsigned int i, tmp;
64
65 /* Enable access to coprocessor 6 for dealing with IRQs.
66 * From RMK:
67 * Basically, the Intel documentation here is poor. It appears that
68 * you need to set the bit to be able to access the coprocessor from
69 * SVC mode. Whether that allows access from user space or not is
70 * unclear.
71 */
72 asm volatile (
73 "mrc p15, 0, %0, c15, c1, 0\n\t"
74 "orr %0, %0, %1\n\t"
75 "mcr p15, 0, %0, c15, c1, 0\n\t"
76 /* The action is delayed, so we have to do this: */
77 "mrc p15, 0, %0, c15, c1, 0\n\t"
78 "mov %0, %0\n\t"
79 "sub pc, pc, #4"
80 : "=r" (tmp) : "i" (1 << 6) );
81
82 intctl_write(0); // disable all interrupts
83 intstr_write(0); // treat all as IRQ
84 if(machine_is_iq80321() ||
85 machine_is_iq31244()) // all interrupts are inputs to chip
86 *IOP321_PCIIRSR = 0x0f;
87
88 for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++)
89 {
90 set_irq_chip(i, &ext_chip);
91 set_irq_handler(i, do_level_IRQ);
92 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
93
94 }
95}
96
diff --git a/arch/arm/mach-iop3xx/iop321-pci.c b/arch/arm/mach-iop3xx/iop321-pci.c
new file mode 100644
index 000000000000..8ba6a0e23134
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop321-pci.c
@@ -0,0 +1,220 @@
1/*
2 * arch/arm/mach-iop3xx/iop321-pci.c
3 *
4 * PCI support for the Intel IOP321 chipset
5 *
6 * Author: Rory Bolt <rorybolt@pacbell.net>
7 * Copyright (C) 2002 Rory Bolt
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/slab.h>
17#include <linux/mm.h>
18#include <linux/init.h>
19#include <linux/ioport.h>
20
21#include <asm/io.h>
22#include <asm/irq.h>
23#include <asm/system.h>
24#include <asm/hardware.h>
25#include <asm/mach/pci.h>
26
27#include <asm/arch/iop321.h>
28
29// #define DEBUG
30
31#ifdef DEBUG
32#define DBG(x...) printk(x)
33#else
34#define DBG(x...) do { } while (0)
35#endif
36
37/*
38 * This routine builds either a type0 or type1 configuration command. If the
39 * bus is on the 80321 then a type0 made, else a type1 is created.
40 */
41static u32 iop321_cfg_address(struct pci_bus *bus, int devfn, int where)
42{
43 struct pci_sys_data *sys = bus->sysdata;
44 u32 addr;
45
46 if (sys->busnr == bus->number)
47 addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
48 else
49 addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
50
51 addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
52
53 return addr;
54}
55
56/*
57 * This routine checks the status of the last configuration cycle. If an error
58 * was detected it returns a 1, else it returns a 0. The errors being checked
59 * are parity, master abort, target abort (master and target). These types of
60 * errors occure during a config cycle where there is no device, like during
61 * the discovery stage.
62 */
63static int iop321_pci_status(void)
64{
65 unsigned int status;
66 int ret = 0;
67
68 /*
69 * Check the status registers.
70 */
71 status = *IOP321_ATUSR;
72 if (status & 0xf900)
73 {
74 DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
75 *IOP321_ATUSR = status & 0xf900;
76 ret = 1;
77 }
78 status = *IOP321_ATUISR;
79 if (status & 0x679f)
80 {
81 DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
82 *IOP321_ATUISR = status & 0x679f;
83 ret = 1;
84 }
85 return ret;
86}
87
88/*
89 * Simply write the address register and read the configuration
90 * data. Note that the 4 nop's ensure that we are able to handle
91 * a delayed abort (in theory.)
92 */
93static inline u32 iop321_read(unsigned long addr)
94{
95 u32 val;
96
97 __asm__ __volatile__(
98 "str %1, [%2]\n\t"
99 "ldr %0, [%3]\n\t"
100 "nop\n\t"
101 "nop\n\t"
102 "nop\n\t"
103 "nop\n\t"
104 : "=r" (val)
105 : "r" (addr), "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
106
107 return val;
108}
109
110/*
111 * The read routines must check the error status of the last configuration
112 * cycle. If there was an error, the routine returns all hex f's.
113 */
114static int
115iop321_read_config(struct pci_bus *bus, unsigned int devfn, int where,
116 int size, u32 *value)
117{
118 unsigned long addr = iop321_cfg_address(bus, devfn, where);
119 u32 val = iop321_read(addr) >> ((where & 3) * 8);
120
121 if( iop321_pci_status() )
122 val = 0xffffffff;
123
124 *value = val;
125
126 return PCIBIOS_SUCCESSFUL;
127}
128
129static int
130iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where,
131 int size, u32 value)
132{
133 unsigned long addr = iop321_cfg_address(bus, devfn, where);
134 u32 val;
135
136 if (size != 4) {
137 val = iop321_read(addr);
138 if (!iop321_pci_status() == 0)
139 return PCIBIOS_SUCCESSFUL;
140
141 where = (where & 3) * 8;
142
143 if (size == 1)
144 val &= ~(0xff << where);
145 else
146 val &= ~(0xffff << where);
147
148 *IOP321_OCCDR = val | value << where;
149 } else {
150 asm volatile(
151 "str %1, [%2]\n\t"
152 "str %0, [%3]\n\t"
153 "nop\n\t"
154 "nop\n\t"
155 "nop\n\t"
156 "nop\n\t"
157 :
158 : "r" (value), "r" (addr),
159 "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
160 }
161
162 return PCIBIOS_SUCCESSFUL;
163}
164
165static struct pci_ops iop321_ops = {
166 .read = iop321_read_config,
167 .write = iop321_write_config,
168};
169
170/*
171 * When a PCI device does not exist during config cycles, the 80200 gets a
172 * bus error instead of returning 0xffffffff. This handler simply returns.
173 */
174int
175iop321_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
176{
177 DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
178 addr, fsr, regs->ARM_pc, regs->ARM_lr);
179
180 /*
181 * If it was an imprecise abort, then we need to correct the
182 * return address to be _after_ the instruction.
183 */
184 if (fsr & (1 << 10))
185 regs->ARM_pc += 4;
186
187 return 0;
188}
189
190/*
191 * Scan an IOP321 PCI bus. sys->bus defines which bus we scan.
192 */
193struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *sys)
194{
195 return pci_scan_bus(sys->busnr, &iop321_ops, sys);
196}
197
198void iop321_init(void)
199{
200 DBG("PCI: Intel 80321 PCI init code.\n");
201 DBG("ATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD);
202 DBG("ATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n",
203 *IOP321_OMWTVR0,
204 *IOP321_OIOWTVR);
205 DBG("ATU: IOP321_ATUCR=0x%08x\n", *IOP321_ATUCR);
206 DBG("ATU: IOP321_IABAR0=0x%08x IOP321_IALR0=0x%08x IOP321_IATVR0=%08x\n",
207 *IOP321_IABAR0, *IOP321_IALR0, *IOP321_IATVR0);
208 DBG("ATU: IOP321_OMWTVR0=0x%08x\n", *IOP321_OMWTVR0);
209 DBG("ATU: IOP321_IABAR1=0x%08x IOP321_IALR1=0x%08x\n",
210 *IOP321_IABAR1, *IOP321_IALR1);
211 DBG("ATU: IOP321_ERBAR=0x%08x IOP321_ERLR=0x%08x IOP321_ERTVR=%08x\n",
212 *IOP321_ERBAR, *IOP321_ERLR, *IOP321_ERTVR);
213 DBG("ATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n",
214 *IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2);
215 DBG("ATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n",
216 *IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3);
217
218 hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort");
219}
220
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
new file mode 100644
index 000000000000..bf23e0fd2843
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop321-setup.c
@@ -0,0 +1,169 @@
1/*
2 * linux/arch/arm/mach-iop3xx/iop321-setup.c
3 *
4 * Author: Nicolas Pitre <nico@cam.org>
5 * Copyright (C) 2001 MontaVista Software, Inc.
6 * Copyright (C) 2004 Intel Corporation.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13#include <linux/mm.h>
14#include <linux/init.h>
15#include <linux/config.h>
16#include <linux/init.h>
17#include <linux/major.h>
18#include <linux/fs.h>
19#include <linux/device.h>
20#include <linux/serial.h>
21#include <linux/tty.h>
22#include <linux/serial_core.h>
23
24#include <asm/io.h>
25#include <asm/pgtable.h>
26#include <asm/page.h>
27#include <asm/mach/map.h>
28#include <asm/setup.h>
29#include <asm/system.h>
30#include <asm/memory.h>
31#include <asm/hardware.h>
32#include <asm/mach-types.h>
33#include <asm/mach/arch.h>
34
35#define IOP321_UART_XTAL 1843200
36
37/*
38 * Standard IO mapping for all IOP321 based systems
39 */
40static struct map_desc iop321_std_desc[] __initdata = {
41 /* virtual physical length type */
42
43 /* mem mapped registers */
44 { IOP321_VIRT_MEM_BASE, IOP321_PHYS_MEM_BASE, 0x00002000, MT_DEVICE },
45
46 /* PCI IO space */
47 { IOP321_PCI_LOWER_IO_VA, IOP321_PCI_LOWER_IO_PA, IOP321_PCI_IO_WINDOW_SIZE, MT_DEVICE }
48};
49
50#ifdef CONFIG_ARCH_IQ80321
51#define UARTBASE IQ80321_UART
52#define IRQ_UART IRQ_IQ80321_UART
53#endif
54
55#ifdef CONFIG_ARCH_IQ31244
56#define UARTBASE IQ31244_UART
57#define IRQ_UART IRQ_IQ31244_UART
58#endif
59
60static struct uart_port iop321_serial_ports[] = {
61 {
62 .membase = (char*)(UARTBASE),
63 .mapbase = (UARTBASE),
64 .irq = IRQ_UART,
65 .flags = UPF_SKIP_TEST,
66 .iotype = UPIO_MEM,
67 .regshift = 0,
68 .uartclk = IOP321_UART_XTAL,
69 .line = 0,
70 .type = PORT_16550A,
71 .fifosize = 16
72 }
73};
74
75static struct resource iop32x_i2c_0_resources[] = {
76 [0] = {
77 .start = 0xfffff680,
78 .end = 0xfffff698,
79 .flags = IORESOURCE_MEM,
80 },
81 [1] = {
82 .start = IRQ_IOP321_I2C_0,
83 .end = IRQ_IOP321_I2C_0,
84 .flags = IORESOURCE_IRQ
85 }
86};
87
88static struct resource iop32x_i2c_1_resources[] = {
89 [0] = {
90 .start = 0xfffff6a0,
91 .end = 0xfffff6b8,
92 .flags = IORESOURCE_MEM,
93 },
94 [1] = {
95 .start = IRQ_IOP321_I2C_1,
96 .end = IRQ_IOP321_I2C_1,
97 .flags = IORESOURCE_IRQ
98 }
99};
100
101static struct platform_device iop32x_i2c_0_controller = {
102 .name = "IOP3xx-I2C",
103 .id = 0,
104 .num_resources = 2,
105 .resource = iop32x_i2c_0_resources
106};
107
108static struct platform_device iop32x_i2c_1_controller = {
109 .name = "IOP3xx-I2C",
110 .id = 1,
111 .num_resources = 2,
112 .resource = iop32x_i2c_1_resources
113};
114
115static struct platform_device *iop32x_devices[] __initdata = {
116 &iop32x_i2c_0_controller,
117 &iop32x_i2c_1_controller
118};
119
120void __init iop32x_init(void)
121{
122 if(iop_is_321())
123 {
124 platform_add_devices(iop32x_devices,
125 ARRAY_SIZE(iop32x_devices));
126 }
127}
128
129void __init iop321_map_io(void)
130{
131 iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
132 early_serial_setup(&iop321_serial_ports[0]);
133}
134
135#ifdef CONFIG_ARCH_IQ80321
136extern void iq80321_map_io(void);
137extern struct sys_timer iop321_timer;
138extern void iop321_init_time(void);
139#endif
140
141#ifdef CONFIG_ARCH_IQ31244
142extern void iq31244_map_io(void);
143extern struct sys_timer iop321_timer;
144extern void iop321_init_time(void);
145#endif
146
147#if defined(CONFIG_ARCH_IQ80321)
148MACHINE_START(IQ80321, "Intel IQ80321")
149 MAINTAINER("Intel Corporation")
150 BOOT_MEM(PHYS_OFFSET, IQ80321_UART, IQ80321_UART)
151 MAPIO(iq80321_map_io)
152 INITIRQ(iop321_init_irq)
153 .timer = &iop321_timer,
154 BOOT_PARAMS(0xa0000100)
155 INIT_MACHINE(iop32x_init)
156MACHINE_END
157#elif defined(CONFIG_ARCH_IQ31244)
158MACHINE_START(IQ31244, "Intel IQ31244")
159 MAINTAINER("Intel Corp.")
160 BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART)
161 MAPIO(iq31244_map_io)
162 INITIRQ(iop321_init_irq)
163 .timer = &iop321_timer,
164 BOOT_PARAMS(0xa0000100)
165 INIT_MACHINE(iop32x_init)
166MACHINE_END
167#else
168#error No machine descriptor defined for this IOP3XX implementation
169#endif
diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
new file mode 100644
index 000000000000..9b7dd64d1b8f
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop321-time.c
@@ -0,0 +1,109 @@
1/*
2 * arch/arm/mach-iop3xx/iop321-time.c
3 *
4 * Timer code for IOP321 based systems
5 *
6 * Author: Deepak Saxena <dsaxena@mvista.com>
7 *
8 * Copyright 2002-2003 MontaVista Software Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/interrupt.h>
18#include <linux/time.h>
19#include <linux/init.h>
20#include <linux/timex.h>
21
22#include <asm/hardware.h>
23#include <asm/io.h>
24#include <asm/irq.h>
25#include <asm/uaccess.h>
26#include <asm/mach-types.h>
27#include <asm/mach/irq.h>
28#include <asm/mach/time.h>
29
30#define IOP321_TIME_SYNC 0
31
32static inline unsigned long get_elapsed(void)
33{
34 return LATCH - *IOP321_TU_TCR0;
35}
36
37static unsigned long iop321_gettimeoffset(void)
38{
39 unsigned long elapsed, usec;
40 u32 tisr1, tisr2;
41
42 /*
43 * If an interrupt was pending before we read the timer,
44 * we've already wrapped. Factor this into the time.
45 * If an interrupt was pending after we read the timer,
46 * it may have wrapped between checking the interrupt
47 * status and reading the timer. Re-read the timer to
48 * be sure its value is after the wrap.
49 */
50
51 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
52 elapsed = get_elapsed();
53 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
54
55 if(tisr1 & 1)
56 elapsed += LATCH;
57 else if (tisr2 & 1)
58 elapsed = LATCH + get_elapsed();
59
60 /*
61 * Now convert them to usec.
62 */
63 usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
64
65 return usec;
66}
67
68static irqreturn_t
69iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
70{
71 u32 tisr;
72
73 write_seqlock(&xtime_lock);
74
75 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
76 tisr |= 1;
77 asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
78
79 timer_tick(regs);
80
81 write_sequnlock(&xtime_lock);
82
83 return IRQ_HANDLED;
84}
85
86static struct irqaction iop321_timer_irq = {
87 .name = "IOP321 Timer Tick",
88 .handler = iop321_timer_interrupt,
89 .flags = SA_INTERRUPT
90};
91
92static void __init iop321_timer_init(void)
93{
94 u32 timer_ctl;
95
96 setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
97
98 timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
99 IOP321_TMR_RATIO_1_1;
100
101 asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
102
103 asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
104}
105
106struct sys_timer iop321_timer = {
107 .init = &iop321_timer_init,
108 .offset = iop321_gettimeoffset,
109};
diff --git a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
new file mode 100644
index 000000000000..f4d4321737a4
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop331-irq.c
@@ -0,0 +1,127 @@
1/*
2 * linux/arch/arm/mach-iop3xx/iop331-irq.c
3 *
4 * Generic IOP331 IRQ handling functionality
5 *
6 * Author: Dave Jiang <dave.jiang@intel.com>
7 * Copyright (C) 2003 Intel Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 *
14 */
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/list.h>
18
19#include <asm/mach/irq.h>
20#include <asm/irq.h>
21#include <asm/hardware.h>
22
23#include <asm/mach-types.h>
24
25static u32 iop331_mask0 = 0;
26static u32 iop331_mask1 = 0;
27
28static inline void intctl_write0(u32 val)
29{
30 // INTCTL0
31 asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
32}
33
34static inline void intctl_write1(u32 val)
35{
36 // INTCTL1
37 asm volatile("mcr p6,0,%0,c1,c0,0"::"r" (val));
38}
39
40static inline void intstr_write0(u32 val)
41{
42 // INTSTR0
43 asm volatile("mcr p6,0,%0,c2,c0,0"::"r" (val));
44}
45
46static inline void intstr_write1(u32 val)
47{
48 // INTSTR1
49 asm volatile("mcr p6,0,%0,c3,c0,0"::"r" (val));
50}
51
52static void
53iop331_irq_mask1 (unsigned int irq)
54{
55 iop331_mask0 &= ~(1 << (irq - IOP331_IRQ_OFS));
56 intctl_write0(iop331_mask0);
57}
58
59static void
60iop331_irq_mask2 (unsigned int irq)
61{
62 iop331_mask1 &= ~(1 << (irq - IOP331_IRQ_OFS - 32));
63 intctl_write1(iop331_mask1);
64}
65
66static void
67iop331_irq_unmask1(unsigned int irq)
68{
69 iop331_mask0 |= (1 << (irq - IOP331_IRQ_OFS));
70 intctl_write0(iop331_mask0);
71}
72
73static void
74iop331_irq_unmask2(unsigned int irq)
75{
76 iop331_mask1 |= (1 << (irq - IOP331_IRQ_OFS - 32));
77 intctl_write1(iop331_mask1);
78}
79
80struct irqchip iop331_irqchip1 = {
81 .ack = iop331_irq_mask1,
82 .mask = iop331_irq_mask1,
83 .unmask = iop331_irq_unmask1,
84};
85
86struct irqchip iop331_irqchip2 = {
87 .ack = iop331_irq_mask2,
88 .mask = iop331_irq_mask2,
89 .unmask = iop331_irq_unmask2,
90};
91
92void __init iop331_init_irq(void)
93{
94 unsigned int i, tmp;
95
96 /* Enable access to coprocessor 6 for dealing with IRQs.
97 * From RMK:
98 * Basically, the Intel documentation here is poor. It appears that
99 * you need to set the bit to be able to access the coprocessor from
100 * SVC mode. Whether that allows access from user space or not is
101 * unclear.
102 */
103 asm volatile (
104 "mrc p15, 0, %0, c15, c1, 0\n\t"
105 "orr %0, %0, %1\n\t"
106 "mcr p15, 0, %0, c15, c1, 0\n\t"
107 /* The action is delayed, so we have to do this: */
108 "mrc p15, 0, %0, c15, c1, 0\n\t"
109 "mov %0, %0\n\t"
110 "sub pc, pc, #4"
111 : "=r" (tmp) : "i" (1 << 6) );
112
113 intctl_write0(0); // disable all interrupts
114 intctl_write1(0);
115 intstr_write0(0); // treat all as IRQ
116 intstr_write1(0);
117 if(machine_is_iq80331()) // all interrupts are inputs to chip
118 *IOP331_PCIIRSR = 0x0f;
119
120 for(i = IOP331_IRQ_OFS; i < NR_IOP331_IRQS; i++)
121 {
122 set_irq_chip(i, (i < 32) ? &iop331_irqchip1 : &iop331_irqchip2);
123 set_irq_handler(i, do_level_IRQ);
124 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
125 }
126}
127
diff --git a/arch/arm/mach-iop3xx/iop331-pci.c b/arch/arm/mach-iop3xx/iop331-pci.c
new file mode 100644
index 000000000000..44dd213b48a3
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop331-pci.c
@@ -0,0 +1,222 @@
1/*
2 * arch/arm/mach-iop3xx/iop331-pci.c
3 *
4 * PCI support for the Intel IOP331 chipset
5 *
6 * Author: Dave Jiang (dave.jiang@intel.com)
7 * Copyright (C) 2003, 2004 Intel Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/slab.h>
17#include <linux/mm.h>
18#include <linux/init.h>
19#include <linux/ioport.h>
20
21#include <asm/io.h>
22#include <asm/irq.h>
23#include <asm/system.h>
24#include <asm/hardware.h>
25#include <asm/mach/pci.h>
26
27#include <asm/arch/iop331.h>
28
29#undef DEBUG
30#undef DEBUG1
31
32#ifdef DEBUG
33#define DBG(x...) printk(x)
34#else
35#define DBG(x...) do { } while (0)
36#endif
37
38#ifdef DEBUG1
39#define DBG1(x...) printk(x)
40#else
41#define DBG1(x...) do { } while (0)
42#endif
43
44/*
45 * This routine builds either a type0 or type1 configuration command. If the
46 * bus is on the 80331 then a type0 made, else a type1 is created.
47 */
48static u32 iop331_cfg_address(struct pci_bus *bus, int devfn, int where)
49{
50 struct pci_sys_data *sys = bus->sysdata;
51 u32 addr;
52
53 if (sys->busnr == bus->number)
54 addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
55 else
56 addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
57
58 addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
59
60 return addr;
61}
62
63/*
64 * This routine checks the status of the last configuration cycle. If an error
65 * was detected it returns a 1, else it returns a 0. The errors being checked
66 * are parity, master abort, target abort (master and target). These types of
67 * errors occure during a config cycle where there is no device, like during
68 * the discovery stage.
69 */
70static int iop331_pci_status(void)
71{
72 unsigned int status;
73 int ret = 0;
74
75 /*
76 * Check the status registers.
77 */
78 status = *IOP331_ATUSR;
79 if (status & 0xf900)
80 {
81 DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
82 *IOP331_ATUSR = status & 0xf900;
83 ret = 1;
84 }
85 status = *IOP331_ATUISR;
86 if (status & 0x679f)
87 {
88 DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
89 *IOP331_ATUISR = status & 0x679f;
90 ret = 1;
91 }
92 return ret;
93}
94
95/*
96 * Simply write the address register and read the configuration
97 * data. Note that the 4 nop's ensure that we are able to handle
98 * a delayed abort (in theory.)
99 */
100static inline u32 iop331_read(unsigned long addr)
101{
102 u32 val;
103
104 __asm__ __volatile__(
105 "str %1, [%2]\n\t"
106 "ldr %0, [%3]\n\t"
107 "nop\n\t"
108 "nop\n\t"
109 "nop\n\t"
110 "nop\n\t"
111 : "=r" (val)
112 : "r" (addr), "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
113
114 return val;
115}
116
117/*
118 * The read routines must check the error status of the last configuration
119 * cycle. If there was an error, the routine returns all hex f's.
120 */
121static int
122iop331_read_config(struct pci_bus *bus, unsigned int devfn, int where,
123 int size, u32 *value)
124{
125 unsigned long addr = iop331_cfg_address(bus, devfn, where);
126 u32 val = iop331_read(addr) >> ((where & 3) * 8);
127
128 if( iop331_pci_status() )
129 val = 0xffffffff;
130
131 *value = val;
132
133 return PCIBIOS_SUCCESSFUL;
134}
135
136static int
137iop331_write_config(struct pci_bus *bus, unsigned int devfn, int where,
138 int size, u32 value)
139{
140 unsigned long addr = iop331_cfg_address(bus, devfn, where);
141 u32 val;
142
143 if (size != 4) {
144 val = iop331_read(addr);
145 if (!iop331_pci_status() == 0)
146 return PCIBIOS_SUCCESSFUL;
147
148 where = (where & 3) * 8;
149
150 if (size == 1)
151 val &= ~(0xff << where);
152 else
153 val &= ~(0xffff << where);
154
155 *IOP331_OCCDR = val | value << where;
156 } else {
157 asm volatile(
158 "str %1, [%2]\n\t"
159 "str %0, [%3]\n\t"
160 "nop\n\t"
161 "nop\n\t"
162 "nop\n\t"
163 "nop\n\t"
164 :
165 : "r" (value), "r" (addr),
166 "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
167 }
168
169 return PCIBIOS_SUCCESSFUL;
170}
171
172static struct pci_ops iop331_ops = {
173 .read = iop331_read_config,
174 .write = iop331_write_config,
175};
176
177/*
178 * When a PCI device does not exist during config cycles, the XScale gets a
179 * bus error instead of returning 0xffffffff. This handler simply returns.
180 */
181int
182iop331_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
183{
184 DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
185 addr, fsr, regs->ARM_pc, regs->ARM_lr);
186
187 /*
188 * If it was an imprecise abort, then we need to correct the
189 * return address to be _after_ the instruction.
190 */
191 if (fsr & (1 << 10))
192 regs->ARM_pc += 4;
193
194 return 0;
195}
196
197/*
198 * Scan an IOP331 PCI bus. sys->bus defines which bus we scan.
199 */
200struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *sys)
201{
202 return pci_scan_bus(sys->busnr, &iop331_ops, sys);
203}
204
205void iop331_init(void)
206{
207 DBG1("PCI: Intel 80331 PCI init code.\n");
208 DBG1("\tATU: IOP331_ATUCMD=0x%04x\n", *IOP331_ATUCMD);
209 DBG1("\tATU: IOP331_OMWTVR0=0x%04x, IOP331_OIOWTVR=0x%04x\n",
210 *IOP331_OMWTVR0,
211 *IOP331_OIOWTVR);
212 DBG1("\tATU: IOP331_OMWTVR1=0x%04x\n", *IOP331_OMWTVR1);
213 DBG1("\tATU: IOP331_ATUCR=0x%08x\n", *IOP331_ATUCR);
214 DBG1("\tATU: IOP331_IABAR0=0x%08x IOP331_IALR0=0x%08x IOP331_IATVR0=%08x\n", *IOP331_IABAR0, *IOP331_IALR0, *IOP331_IATVR0);
215 DBG1("\tATU: IOP31_IABAR1=0x%08x IOP331_IALR1=0x%08x\n", *IOP331_IABAR1, *IOP331_IALR1);
216 DBG1("\tATU: IOP331_ERBAR=0x%08x IOP331_ERLR=0x%08x IOP331_ERTVR=%08x\n", *IOP331_ERBAR, *IOP331_ERLR, *IOP331_ERTVR);
217 DBG1("\tATU: IOP331_IABAR2=0x%08x IOP331_IALR2=0x%08x IOP331_IATVR2=%08x\n", *IOP331_IABAR2, *IOP331_IALR2, *IOP331_IATVR2);
218 DBG1("\tATU: IOP331_IABAR3=0x%08x IOP331_IALR3=0x%08x IOP331_IATVR3=%08x\n", *IOP331_IABAR3, *IOP331_IALR3, *IOP331_IATVR3);
219
220 hook_fault_code(16+6, iop331_pci_abort, SIGBUS, "imprecise external abort");
221}
222
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
new file mode 100644
index 000000000000..622e7914819a
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop331-setup.c
@@ -0,0 +1,177 @@
1/*
2 * linux/arch/arm/mach-iop3xx/iop331-setup.c
3 *
4 * Author: Dave Jiang (dave.jiang@intel.com)
5 * Copyright (C) 2004 Intel Corporation.
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 */
12#include <linux/mm.h>
13#include <linux/init.h>
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/major.h>
17#include <linux/fs.h>
18#include <linux/device.h>
19#include <linux/serial.h>
20#include <linux/tty.h>
21#include <linux/serial_core.h>
22
23#include <asm/io.h>
24#include <asm/pgtable.h>
25#include <asm/page.h>
26#include <asm/mach/map.h>
27#include <asm/setup.h>
28#include <asm/system.h>
29#include <asm/memory.h>
30#include <asm/hardware.h>
31#include <asm/mach-types.h>
32#include <asm/mach/arch.h>
33
34#define IOP331_UART_XTAL 33334000
35
36/*
37 * Standard IO mapping for all IOP331 based systems
38 */
39static struct map_desc iop331_std_desc[] __initdata = {
40 /* virtual physical length type */
41
42 /* mem mapped registers */
43 { IOP331_VIRT_MEM_BASE, IOP331_PHYS_MEM_BASE, 0x00002000, MT_DEVICE },
44
45 /* PCI IO space */
46 { IOP331_PCI_LOWER_IO_VA, IOP331_PCI_LOWER_IO_PA, IOP331_PCI_IO_WINDOW_SIZE, MT_DEVICE }
47};
48
49static struct uart_port iop331_serial_ports[] = {
50 {
51 .membase = (char*)(IOP331_UART0_VIRT),
52 .mapbase = (IOP331_UART0_PHYS),
53 .irq = IRQ_IOP331_UART0,
54 .flags = UPF_SKIP_TEST,
55 .iotype = UPIO_MEM,
56 .regshift = 2,
57 .uartclk = IOP331_UART_XTAL,
58 .line = 0,
59 .type = PORT_XSCALE,
60 .fifosize = 32
61 } , {
62 .membase = (char*)(IOP331_UART1_VIRT),
63 .mapbase = (IOP331_UART1_PHYS),
64 .irq = IRQ_IOP331_UART1,
65 .flags = UPF_SKIP_TEST,
66 .iotype = UPIO_MEM,
67 .regshift = 2,
68 .uartclk = IOP331_UART_XTAL,
69 .line = 1,
70 .type = PORT_XSCALE,
71 .fifosize = 32
72 }
73};
74
75static struct resource iop33x_i2c_0_resources[] = {
76 [0] = {
77 .start = 0xfffff680,
78 .end = 0xfffff698,
79 .flags = IORESOURCE_MEM,
80 },
81 [1] = {
82 .start = IRQ_IOP331_I2C_0,
83 .end = IRQ_IOP331_I2C_0,
84 .flags = IORESOURCE_IRQ
85 }
86};
87
88static struct resource iop33x_i2c_1_resources[] = {
89 [0] = {
90 .start = 0xfffff6a0,
91 .end = 0xfffff6b8,
92 .flags = IORESOURCE_MEM,
93 },
94 [1] = {
95 .start = IRQ_IOP331_I2C_1,
96 .end = IRQ_IOP331_I2C_1,
97 .flags = IORESOURCE_IRQ
98 }
99};
100
101static struct platform_device iop33x_i2c_0_controller = {
102 .name = "IOP3xx-I2C",
103 .id = 0,
104 .num_resources = 2,
105 .resource = iop33x_i2c_0_resources
106};
107
108static struct platform_device iop33x_i2c_1_controller = {
109 .name = "IOP3xx-I2C",
110 .id = 1,
111 .num_resources = 2,
112 .resource = iop33x_i2c_1_resources
113};
114
115static struct platform_device *iop33x_devices[] __initdata = {
116 &iop33x_i2c_0_controller,
117 &iop33x_i2c_1_controller
118};
119
120void __init iop33x_init(void)
121{
122 if(iop_is_331())
123 {
124 platform_add_devices(iop33x_devices,
125 ARRAY_SIZE(iop33x_devices));
126 }
127}
128
129void __init iop331_map_io(void)
130{
131 iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
132 early_serial_setup(&iop331_serial_ports[0]);
133 early_serial_setup(&iop331_serial_ports[1]);
134}
135
136#ifdef CONFIG_ARCH_IOP331
137extern void iop331_init_irq(void);
138extern struct sys_timer iop331_timer;
139#endif
140
141#ifdef CONFIG_ARCH_IQ80331
142extern void iq80331_map_io(void);
143#endif
144
145#ifdef CONFIG_MACH_IQ80332
146extern void iq80332_map_io(void);
147#endif
148
149#if defined(CONFIG_ARCH_IQ80331)
150MACHINE_START(IQ80331, "Intel IQ80331")
151 MAINTAINER("Intel Corp.")
152 BOOT_MEM(PHYS_OFFSET, 0xfefff000, 0xfffff000) // virtual, physical
153 //BOOT_MEM(PHYS_OFFSET, IOP331_UART0_VIRT, IOP331_UART0_PHYS)
154 MAPIO(iq80331_map_io)
155 INITIRQ(iop331_init_irq)
156 .timer = &iop331_timer,
157 BOOT_PARAMS(0x0100)
158 INIT_MACHINE(iop33x_init)
159MACHINE_END
160
161#elif defined(CONFIG_MACH_IQ80332)
162MACHINE_START(IQ80332, "Intel IQ80332")
163 MAINTAINER("Intel Corp.")
164 BOOT_MEM(PHYS_OFFSET, 0xfefff000, 0xfffff000) // virtual, physical
165 //BOOT_MEM(PHYS_OFFSET, IOP331_UART0_VIRT, IOP331_UART0_PHYS)
166 MAPIO(iq80332_map_io)
167 INITIRQ(iop331_init_irq)
168 .timer = &iop331_timer,
169 BOOT_PARAMS(0x0100)
170 INIT_MACHINE(iop33x_init)
171MACHINE_END
172
173#else
174#error No machine descriptor defined for this IOP3XX implementation
175#endif
176
177
diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
new file mode 100644
index 000000000000..e01696769263
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iop331-time.c
@@ -0,0 +1,107 @@
1/*
2 * arch/arm/mach-iop3xx/iop331-time.c
3 *
4 * Timer code for IOP331 based systems
5 *
6 * Author: Dave Jiang <dave.jiang@intel.com>
7 *
8 * Copyright 2003 Intel Corp.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/interrupt.h>
18#include <linux/time.h>
19#include <linux/init.h>
20#include <linux/timex.h>
21
22#include <asm/hardware.h>
23#include <asm/io.h>
24#include <asm/irq.h>
25#include <asm/uaccess.h>
26#include <asm/mach-types.h>
27#include <asm/mach/irq.h>
28#include <asm/mach/time.h>
29
30static inline unsigned long get_elapsed(void)
31{
32 return LATCH - *IOP331_TU_TCR0;
33}
34
35static unsigned long iop331_gettimeoffset(void)
36{
37 unsigned long elapsed, usec;
38 u32 tisr1, tisr2;
39
40 /*
41 * If an interrupt was pending before we read the timer,
42 * we've already wrapped. Factor this into the time.
43 * If an interrupt was pending after we read the timer,
44 * it may have wrapped between checking the interrupt
45 * status and reading the timer. Re-read the timer to
46 * be sure its value is after the wrap.
47 */
48
49 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
50 elapsed = get_elapsed();
51 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
52
53 if(tisr1 & 1)
54 elapsed += LATCH;
55 else if (tisr2 & 1)
56 elapsed = LATCH + get_elapsed();
57
58 /*
59 * Now convert them to usec.
60 */
61 usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
62
63 return usec;
64}
65
66static irqreturn_t
67iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
68{
69 u32 tisr;
70
71 write_seqlock(&xtime_lock);
72
73 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
74 tisr |= 1;
75 asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
76
77 timer_tick(regs);
78
79 write_sequnlock(&xtime_lock);
80 return IRQ_HANDLED;
81}
82
83static struct irqaction iop331_timer_irq = {
84 .name = "IOP331 Timer Tick",
85 .handler = iop331_timer_interrupt,
86 .flags = SA_INTERRUPT
87};
88
89static void __init iop331_timer_init(void)
90{
91 u32 timer_ctl;
92
93 setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq);
94
95 timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD |
96 IOP331_TMR_RATIO_1_1;
97
98 asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
99
100 asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
101
102}
103
104struct sys_timer iop331_timer = {
105 .init = iop331_timer_init,
106 .offset = iop331_gettimeoffset,
107};
diff --git a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c
new file mode 100644
index 000000000000..b01042f7de71
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq31244-mm.c
@@ -0,0 +1,44 @@
1/*
2 * linux/arch/arm/mach-iop3xx/mm.c
3 *
4 * Low level memory initialization for iq80321 platform
5 *
6 * Author: Rory Bolt <rorybolt@pacbell.net>
7 * Copyright (C) 2002 Rory Bolt
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#include <linux/mm.h>
17#include <linux/init.h>
18
19#include <asm/io.h>
20#include <asm/pgtable.h>
21#include <asm/page.h>
22
23#include <asm/mach/map.h>
24#include <asm/mach-types.h>
25
26
27/*
28 * IQ80321 specific IO mappings
29 *
30 * We use RedBoot's setup for the onboard devices.
31 */
32static struct map_desc iq31244_io_desc[] __initdata = {
33 /* virtual physical length type */
34
35 /* on-board devices */
36 { IQ31244_UART, IQ31244_UART, 0x00100000, MT_DEVICE }
37};
38
39void __init iq31244_map_io(void)
40{
41 iop321_map_io();
42
43 iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
44}
diff --git a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c
new file mode 100644
index 000000000000..f997daa800bf
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq31244-pci.c
@@ -0,0 +1,129 @@
1/*
2 * arch/arm/mach-iop3xx/iq80321-pci.c
3 *
4 * PCI support for the Intel IQ80321 reference board
5 *
6 * Author: Rory Bolt <rorybolt@pacbell.net>
7 * Copyright (C) 2002 Rory Bolt
8 * Copyright (C) 2004 Intel Corp.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17
18#include <asm/hardware.h>
19#include <asm/irq.h>
20#include <asm/mach/pci.h>
21#include <asm/mach-types.h>
22
23/*
24 * The following macro is used to lookup irqs in a standard table
25 * format for those systems that do not already have PCI
26 * interrupts properly routed. We assume 1 <= pin <= 4
27 */
28#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
29({ int _ctl_ = -1; \
30 unsigned int _idsel = idsel - minid; \
31 if (_idsel <= maxid) \
32 _ctl_ = pci_irq_table[_idsel][pin-1]; \
33 _ctl_; })
34
35#define INTA IRQ_IQ31244_INTA
36#define INTB IRQ_IQ31244_INTB
37#define INTC IRQ_IQ31244_INTC
38#define INTD IRQ_IQ31244_INTD
39
40#define INTE IRQ_IQ31244_I82546
41
42static inline int __init
43iq31244_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
44{
45 static int pci_irq_table[][4] = {
46 /*
47 * PCI IDSEL/INTPIN->INTLINE
48 * A B C D
49 */
50#ifdef CONFIG_ARCH_EP80219
51 {INTB, INTB, INTB, INTB}, /* CFlash */
52 {INTE, INTE, INTE, INTE}, /* 82551 Pro 100 */
53 {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
54 {INTC, INTC, INTC, INTC}, /* SATA */
55#else
56 {INTB, INTB, INTB, INTB}, /* CFlash */
57 {INTC, INTC, INTC, INTC}, /* SATA */
58 {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
59 {INTE, INTE, INTE, INTE}, /* 82546 GigE */
60#endif // CONFIG_ARCH_EP80219
61 };
62
63 BUG_ON(pin < 1 || pin > 4);
64
65 return PCI_IRQ_TABLE_LOOKUP(0, 7);
66}
67
68static int iq31244_setup(int nr, struct pci_sys_data *sys)
69{
70 struct resource *res;
71
72 if(nr != 0)
73 return 0;
74
75 res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
76 if (!res)
77 panic("PCI: unable to alloc resources");
78
79 memset(res, 0, sizeof(struct resource) * 2);
80
81 res[0].start = IOP321_PCI_LOWER_IO_VA;
82 res[0].end = IOP321_PCI_UPPER_IO_VA;
83 res[0].name = "IQ31244 PCI I/O Space";
84 res[0].flags = IORESOURCE_IO;
85
86 res[1].start = IOP321_PCI_LOWER_MEM_PA;
87 res[1].end = IOP321_PCI_UPPER_MEM_PA;
88 res[1].name = "IQ31244 PCI Memory Space";
89 res[1].flags = IORESOURCE_MEM;
90
91 request_resource(&ioport_resource, &res[0]);
92 request_resource(&iomem_resource, &res[1]);
93
94 sys->mem_offset = IOP321_PCI_MEM_OFFSET;
95 sys->io_offset = IOP321_PCI_IO_OFFSET;
96
97 sys->resource[0] = &res[0];
98 sys->resource[1] = &res[1];
99 sys->resource[2] = NULL;
100
101 return 1;
102}
103
104static void iq31244_preinit(void)
105{
106 iop321_init();
107}
108
109static struct hw_pci iq31244_pci __initdata = {
110 .swizzle = pci_std_swizzle,
111 .nr_controllers = 1,
112 .setup = iq31244_setup,
113 .scan = iop321_scan_bus,
114 .preinit = iq31244_preinit,
115 .map_irq = iq31244_map_irq
116};
117
118static int __init iq31244_pci_init(void)
119{
120 if (machine_is_iq31244())
121 pci_common_init(&iq31244_pci);
122 return 0;
123}
124
125subsys_initcall(iq31244_pci_init);
126
127
128
129
diff --git a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c
new file mode 100644
index 000000000000..1580c7ed2b9d
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq80321-mm.c
@@ -0,0 +1,44 @@
1/*
2 * linux/arch/arm/mach-iop3xx/mm.c
3 *
4 * Low level memory initialization for iq80321 platform
5 *
6 * Author: Rory Bolt <rorybolt@pacbell.net>
7 * Copyright (C) 2002 Rory Bolt
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#include <linux/mm.h>
17#include <linux/init.h>
18
19#include <asm/io.h>
20#include <asm/pgtable.h>
21#include <asm/page.h>
22
23#include <asm/mach/map.h>
24#include <asm/mach-types.h>
25
26
27/*
28 * IQ80321 specific IO mappings
29 *
30 * We use RedBoot's setup for the onboard devices.
31 */
32static struct map_desc iq80321_io_desc[] __initdata = {
33 /* virtual physical length type */
34
35 /* on-board devices */
36 { IQ80321_UART, IQ80321_UART, 0x00100000, MT_DEVICE }
37};
38
39void __init iq80321_map_io(void)
40{
41 iop321_map_io();
42
43 iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
44}
diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c
new file mode 100644
index 000000000000..79fea3d20b66
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq80321-pci.c
@@ -0,0 +1,123 @@
1/*
2 * arch/arm/mach-iop3xx/iq80321-pci.c
3 *
4 * PCI support for the Intel IQ80321 reference board
5 *
6 * Author: Rory Bolt <rorybolt@pacbell.net>
7 * Copyright (C) 2002 Rory Bolt
8 * Copyright (C) 2004 Intel Corp.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17
18#include <asm/hardware.h>
19#include <asm/irq.h>
20#include <asm/mach/pci.h>
21#include <asm/mach-types.h>
22
23/*
24 * The following macro is used to lookup irqs in a standard table
25 * format for those systems that do not already have PCI
26 * interrupts properly routed. We assume 1 <= pin <= 4
27 */
28#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
29({ int _ctl_ = -1; \
30 unsigned int _idsel = idsel - minid; \
31 if (_idsel <= maxid) \
32 _ctl_ = pci_irq_table[_idsel][pin-1]; \
33 _ctl_; })
34
35#define INTA IRQ_IQ80321_INTA
36#define INTB IRQ_IQ80321_INTB
37#define INTC IRQ_IQ80321_INTC
38#define INTD IRQ_IQ80321_INTD
39
40#define INTE IRQ_IQ80321_I82544
41
42static inline int __init
43iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
44{
45 static int pci_irq_table[][4] = {
46 /*
47 * PCI IDSEL/INTPIN->INTLINE
48 * A B C D
49 */
50 {INTE, INTE, INTE, INTE}, /* Gig-E */
51 {-1, -1, -1, -1}, /* Unused */
52 {INTC, INTD, INTA, INTB}, /* PCI-X Slot */
53 {-1, -1, -1, -1},
54 };
55
56 BUG_ON(pin < 1 || pin > 4);
57
58// return PCI_IRQ_TABLE_LOOKUP(4, 7);
59 return pci_irq_table[idsel%4][pin-1];
60}
61
62static int iq80321_setup(int nr, struct pci_sys_data *sys)
63{
64 struct resource *res;
65
66 if(nr != 0)
67 return 0;
68
69 res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
70 if (!res)
71 panic("PCI: unable to alloc resources");
72
73 memset(res, 0, sizeof(struct resource) * 2);
74
75 res[0].start = IOP321_PCI_LOWER_IO_VA;
76 res[0].end = IOP321_PCI_UPPER_IO_VA;
77 res[0].name = "IQ80321 PCI I/O Space";
78 res[0].flags = IORESOURCE_IO;
79
80 res[1].start = IOP321_PCI_LOWER_MEM_PA;
81 res[1].end = IOP321_PCI_UPPER_MEM_PA;
82 res[1].name = "IQ80321 PCI Memory Space";
83 res[1].flags = IORESOURCE_MEM;
84
85 request_resource(&ioport_resource, &res[0]);
86 request_resource(&iomem_resource, &res[1]);
87
88 sys->mem_offset = IOP321_PCI_MEM_OFFSET;
89 sys->io_offset = IOP321_PCI_IO_OFFSET;
90
91 sys->resource[0] = &res[0];
92 sys->resource[1] = &res[1];
93 sys->resource[2] = NULL;
94
95 return 1;
96}
97
98static void iq80321_preinit(void)
99{
100 iop321_init();
101}
102
103static struct hw_pci iq80321_pci __initdata = {
104 .swizzle = pci_std_swizzle,
105 .nr_controllers = 1,
106 .setup = iq80321_setup,
107 .scan = iop321_scan_bus,
108 .preinit = iq80321_preinit,
109 .map_irq = iq80321_map_irq
110};
111
112static int __init iq80321_pci_init(void)
113{
114 if (machine_is_iq80321())
115 pci_common_init(&iq80321_pci);
116 return 0;
117}
118
119subsys_initcall(iq80321_pci_init);
120
121
122
123
diff --git a/arch/arm/mach-iop3xx/iq80331-mm.c b/arch/arm/mach-iop3xx/iq80331-mm.c
new file mode 100644
index 000000000000..ee8c333e115f
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq80331-mm.c
@@ -0,0 +1,36 @@
1/*
2 * linux/arch/arm/mach-iop3xx/mm.c
3 *
4 * Low level memory initialization for iq80331 platform
5 *
6 * Author: Dave Jiang <dave.jiang@intel.com>
7 * Copyright (C) 2003 Intel Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#include <linux/mm.h>
17#include <linux/init.h>
18
19#include <asm/io.h>
20#include <asm/pgtable.h>
21#include <asm/page.h>
22
23#include <asm/mach/map.h>
24#include <asm/mach-types.h>
25
26
27/*
28 * IQ80331 specific IO mappings
29 *
30 * We use RedBoot's setup for the onboard devices.
31 */
32
33void __init iq80331_map_io(void)
34{
35 iop331_map_io();
36}
diff --git a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c
new file mode 100644
index 000000000000..f37a0e26b466
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq80331-pci.c
@@ -0,0 +1,119 @@
1/*
2 * arch/arm/mach-iop3xx/iq80331-pci.c
3 *
4 * PCI support for the Intel IQ80331 reference board
5 *
6 * Author: Dave Jiang <dave.jiang@intel.com>
7 * Copyright (C) 2003, 2004 Intel Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/init.h>
16
17#include <asm/hardware.h>
18#include <asm/irq.h>
19#include <asm/mach/pci.h>
20#include <asm/mach-types.h>
21
22/*
23 * The following macro is used to lookup irqs in a standard table
24 * format for those systems that do not already have PCI
25 * interrupts properly routed. We assume 1 <= pin <= 4
26 */
27#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
28({ int _ctl_ = -1; \
29 unsigned int _idsel = idsel - minid; \
30 if (_idsel <= maxid) \
31 _ctl_ = pci_irq_table[_idsel][pin-1]; \
32 _ctl_; })
33
34#define INTA IRQ_IQ80331_INTA
35#define INTB IRQ_IQ80331_INTB
36#define INTC IRQ_IQ80331_INTC
37#define INTD IRQ_IQ80331_INTD
38
39//#define INTE IRQ_IQ80331_I82544
40
41static inline int __init
42iq80331_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
43{
44 static int pci_irq_table[][4] = {
45 /*
46 * PCI IDSEL/INTPIN->INTLINE
47 * A B C D
48 */
49 {INTB, INTC, INTD, INTA}, /* PCI-X Slot */
50 {INTC, INTC, INTC, INTC}, /* GigE */
51 };
52
53 BUG_ON(pin < 1 || pin > 4);
54
55 return PCI_IRQ_TABLE_LOOKUP(1, 7);
56}
57
58static int iq80331_setup(int nr, struct pci_sys_data *sys)
59{
60 struct resource *res;
61
62 if(nr != 0)
63 return 0;
64
65 res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
66 if (!res)
67 panic("PCI: unable to alloc resources");
68
69 memset(res, 0, sizeof(struct resource) * 2);
70
71 res[0].start = IOP331_PCI_LOWER_IO_VA;
72 res[0].end = IOP331_PCI_UPPER_IO_VA;
73 res[0].name = "IQ80331 PCI I/O Space";
74 res[0].flags = IORESOURCE_IO;
75
76 res[1].start = IOP331_PCI_LOWER_MEM_PA;
77 res[1].end = IOP331_PCI_UPPER_MEM_PA;
78 res[1].name = "IQ80331 PCI Memory Space";
79 res[1].flags = IORESOURCE_MEM;
80
81 request_resource(&ioport_resource, &res[0]);
82 request_resource(&iomem_resource, &res[1]);
83
84 sys->mem_offset = IOP331_PCI_MEM_OFFSET;
85 sys->io_offset = IOP331_PCI_IO_OFFSET;
86
87 sys->resource[0] = &res[0];
88 sys->resource[1] = &res[1];
89 sys->resource[2] = NULL;
90
91 return 1;
92}
93
94static void iq80331_preinit(void)
95{
96 iop331_init();
97}
98
99static struct hw_pci iq80331_pci __initdata = {
100 .swizzle = pci_std_swizzle,
101 .nr_controllers = 1,
102 .setup = iq80331_setup,
103 .scan = iop331_scan_bus,
104 .preinit = iq80331_preinit,
105 .map_irq = iq80331_map_irq
106};
107
108static int __init iq80331_pci_init(void)
109{
110 if (machine_is_iq80331())
111 pci_common_init(&iq80331_pci);
112 return 0;
113}
114
115subsys_initcall(iq80331_pci_init);
116
117
118
119
diff --git a/arch/arm/mach-iop3xx/iq80332-mm.c b/arch/arm/mach-iop3xx/iq80332-mm.c
new file mode 100644
index 000000000000..084afcdfb1eb
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq80332-mm.c
@@ -0,0 +1,36 @@
1/*
2 * linux/arch/arm/mach-iop3xx/mm.c
3 *
4 * Low level memory initialization for iq80332 platform
5 *
6 * Author: Dave Jiang <dave.jiang@intel.com>
7 * Copyright (C) 2004 Intel Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#include <linux/mm.h>
17#include <linux/init.h>
18
19#include <asm/io.h>
20#include <asm/pgtable.h>
21#include <asm/page.h>
22
23#include <asm/mach/map.h>
24#include <asm/mach-types.h>
25
26
27/*
28 * IQ80332 specific IO mappings
29 *
30 * We use RedBoot's setup for the onboard devices.
31 */
32
33void __init iq80332_map_io(void)
34{
35 iop331_map_io();
36}
diff --git a/arch/arm/mach-iop3xx/iq80332-pci.c b/arch/arm/mach-iop3xx/iq80332-pci.c
new file mode 100644
index 000000000000..b9807aa2aade
--- /dev/null
+++ b/arch/arm/mach-iop3xx/iq80332-pci.c
@@ -0,0 +1,125 @@
1/*
2 * arch/arm/mach-iop3xx/iq80332-pci.c
3 *
4 * PCI support for the Intel IQ80332 reference board
5 *
6 * Author: Dave Jiang <dave.jiang@intel.com>
7 * Copyright (C) 2004 Intel Corp.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/init.h>
16
17#include <asm/hardware.h>
18#include <asm/irq.h>
19#include <asm/mach/pci.h>
20#include <asm/mach-types.h>
21
22/*
23 * The following macro is used to lookup irqs in a standard table
24 * format for those systems that do not already have PCI
25 * interrupts properly routed. We assume 1 <= pin <= 4
26 */
27#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
28({ int _ctl_ = -1; \
29 unsigned int _idsel = idsel - minid; \
30 if (_idsel <= maxid) \
31 _ctl_ = pci_irq_table[_idsel][pin-1]; \
32 _ctl_; })
33
34#define INTA IRQ_IQ80332_INTA
35#define INTB IRQ_IQ80332_INTB
36#define INTC IRQ_IQ80332_INTC
37#define INTD IRQ_IQ80332_INTD
38
39//#define INTE IRQ_IQ80332_I82544
40
41static inline int __init
42iq80332_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
43{
44 static int pci_irq_table[][8] = {
45 /*
46 * PCI IDSEL/INTPIN->INTLINE
47 * A B C D
48 */
49 {-1, -1, -1, -1},
50 {-1, -1, -1, -1},
51 {-1, -1, -1, -1},
52 {INTA, INTB, INTC, INTD}, /* PCI-X Slot */
53 {-1, -1, -1, -1},
54 {INTC, INTC, INTC, INTC}, /* GigE */
55 {-1, -1, -1, -1},
56 {-1, -1, -1, -1},
57 };
58
59 BUG_ON(pin < 1 || pin > 4);
60
61 return PCI_IRQ_TABLE_LOOKUP(1, 7);
62}
63
64static int iq80332_setup(int nr, struct pci_sys_data *sys)
65{
66 struct resource *res;
67
68 if(nr != 0)
69 return 0;
70
71 res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
72 if (!res)
73 panic("PCI: unable to alloc resources");
74
75 memset(res, 0, sizeof(struct resource) * 2);
76
77 res[0].start = IOP331_PCI_LOWER_IO_VA;
78 res[0].end = IOP331_PCI_UPPER_IO_VA;
79 res[0].name = "IQ80332 PCI I/O Space";
80 res[0].flags = IORESOURCE_IO;
81
82 res[1].start = IOP331_PCI_LOWER_MEM_PA;
83 res[1].end = IOP331_PCI_UPPER_MEM_PA;
84 res[1].name = "IQ80332 PCI Memory Space";
85 res[1].flags = IORESOURCE_MEM;
86
87 request_resource(&ioport_resource, &res[0]);
88 request_resource(&iomem_resource, &res[1]);
89
90 sys->mem_offset = IOP331_PCI_MEM_OFFSET;
91 sys->io_offset = IOP331_PCI_IO_OFFSET;
92
93 sys->resource[0] = &res[0];
94 sys->resource[1] = &res[1];
95 sys->resource[2] = NULL;
96
97 return 1;
98}
99
100static void iq80332_preinit(void)
101{
102 iop331_init();
103}
104
105static struct hw_pci iq80332_pci __initdata = {
106 .swizzle = pci_std_swizzle,
107 .nr_controllers = 1,
108 .setup = iq80332_setup,
109 .scan = iop331_scan_bus,
110 .preinit = iq80332_preinit,
111 .map_irq = iq80332_map_irq
112};
113
114static int __init iq80332_pci_init(void)
115{
116 if (machine_is_iq80332())
117 pci_common_init(&iq80332_pci);
118 return 0;
119}
120
121subsys_initcall(iq80332_pci_init);
122
123
124
125