aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-iop32x
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-09-18 18:10:26 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-09-25 05:25:36 -0400
commit3f7e5815f4b774270e6506962de37af85aa9c830 (patch)
tree7e4a2b0d6f8b9f1a21ba7a4eb8baf1a1ec04d4f9 /arch/arm/mach-iop32x
parent98954df6917cb8f7e65f4f0f79ed641112fcf6b6 (diff)
[ARM] 3817/1: iop3xx: split the iop3xx mach into iop32x and iop33x
Split the iop3xx mach type into iop32x and iop33x -- split the config symbols, and move the code in the mach-iop3xx directory to the mach-iop32x and mach-iop33x directories. Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-iop32x')
-rw-r--r--arch/arm/mach-iop32x/Kconfig28
-rw-r--r--arch/arm/mach-iop32x/Makefile11
-rw-r--r--arch/arm/mach-iop32x/Makefile.boot3
-rw-r--r--arch/arm/mach-iop32x/common.c72
-rw-r--r--arch/arm/mach-iop32x/iq31244-mm.c45
-rw-r--r--arch/arm/mach-iop32x/iq31244-pci.c129
-rw-r--r--arch/arm/mach-iop32x/iq80321-mm.c45
-rw-r--r--arch/arm/mach-iop32x/iq80321-pci.c123
-rw-r--r--arch/arm/mach-iop32x/irq.c97
-rw-r--r--arch/arm/mach-iop32x/pci.c220
-rw-r--r--arch/arm/mach-iop32x/setup.c173
-rw-r--r--arch/arm/mach-iop32x/time.c108
12 files changed, 1054 insertions, 0 deletions
diff --git a/arch/arm/mach-iop32x/Kconfig b/arch/arm/mach-iop32x/Kconfig
new file mode 100644
index 000000000000..21e3e8c8c2ad
--- /dev/null
+++ b/arch/arm/mach-iop32x/Kconfig
@@ -0,0 +1,28 @@
1if ARCH_IOP32X
2
3menu "IOP32x Implementation Options"
4
5comment "IOP32x Platform Types"
6
7config ARCH_IQ80321
8 bool "Enable support for IQ80321"
9 help
10 Say Y here if you want to run your kernel on the Intel IQ80321
11 evaluation kit for the IOP321 chipset.
12
13config ARCH_IQ31244
14 bool "Enable support for IQ31244"
15 help
16 Say Y here if you want to run your kernel on the Intel IQ31244
17 evaluation kit for the IOP321 chipset.
18
19config ARCH_EP80219
20 bool "Enable support for EP80219"
21 select ARCH_IQ31244
22 help
23 Say Y here if you want to run your kernel on the Intel EP80219
24 evaluation kit for the Intel 80219 chipset (a IOP321 variant).
25
26endmenu
27
28endif
diff --git a/arch/arm/mach-iop32x/Makefile b/arch/arm/mach-iop32x/Makefile
new file mode 100644
index 000000000000..94144f7efa6c
--- /dev/null
+++ b/arch/arm/mach-iop32x/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for the linux kernel.
3#
4
5obj-y := common.o setup.o irq.o pci.o time.o
6obj-m :=
7obj-n :=
8obj- :=
9
10obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
11obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
diff --git a/arch/arm/mach-iop32x/Makefile.boot b/arch/arm/mach-iop32x/Makefile.boot
new file mode 100644
index 000000000000..47000dccd61f
--- /dev/null
+++ b/arch/arm/mach-iop32x/Makefile.boot
@@ -0,0 +1,3 @@
1 zreladdr-y := 0xa0008000
2params_phys-y := 0xa0000100
3initrd_phys-y := 0xa0800000
diff --git a/arch/arm/mach-iop32x/common.c b/arch/arm/mach-iop32x/common.c
new file mode 100644
index 000000000000..8044af6a54e1
--- /dev/null
+++ b/arch/arm/mach-iop32x/common.c
@@ -0,0 +1,72 @@
1/*
2 * arch/arm/mach-iop32x/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/delay.h>
16#include <asm/hardware.h>
17
18/*
19 * Shared variables
20 */
21unsigned long iop3xx_pcibios_min_io = 0;
22unsigned long iop3xx_pcibios_min_mem = 0;
23
24#ifdef CONFIG_ARCH_EP80219
25#include <linux/kernel.h>
26/*
27 * Default power-off for EP80219
28 */
29
30static inline void ep80219_send_to_pic(__u8 c) {
31}
32
33void ep80219_power_off(void)
34{
35 /*
36 * This function will send a SHUTDOWN_COMPLETE message to the PIC controller
37 * over I2C. We are not using the i2c subsystem since we are going to power
38 * off and it may be removed
39 */
40
41 /* Send the Address byte w/ the start condition */
42 *IOP321_IDBR1 = 0x60;
43 *IOP321_ICR1 = 0xE9;
44 mdelay(1);
45
46 /* Send the START_MSG byte w/ no start or stop condition */
47 *IOP321_IDBR1 = 0x0F;
48 *IOP321_ICR1 = 0xE8;
49 mdelay(1);
50
51 /* Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or stop condition */
52 *IOP321_IDBR1 = 0x03;
53 *IOP321_ICR1 = 0xE8;
54 mdelay(1);
55
56 /* Send an ignored byte w/ stop condition */
57 *IOP321_IDBR1 = 0x00;
58 *IOP321_ICR1 = 0xEA;
59
60 while (1) ;
61}
62
63#include <linux/init.h>
64#include <linux/pm.h>
65
66static int __init ep80219_init(void)
67{
68 pm_power_off = ep80219_power_off;
69 return 0;
70}
71arch_initcall(ep80219_init);
72#endif
diff --git a/arch/arm/mach-iop32x/iq31244-mm.c b/arch/arm/mach-iop32x/iq31244-mm.c
new file mode 100644
index 000000000000..ffc6692c95ad
--- /dev/null
+++ b/arch/arm/mach-iop32x/iq31244-mm.c
@@ -0,0 +1,45 @@
1/*
2 * linux/arch/arm/mach-iop32x/iq31244-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
25
26/*
27 * IQ80321 specific IO mappings
28 *
29 * We use RedBoot's setup for the onboard devices.
30 */
31static struct map_desc iq31244_io_desc[] __initdata = {
32 { /* on-board devices */
33 .virtual = IQ31244_UART,
34 .pfn = __phys_to_pfn(IQ31244_UART),
35 .length = 0x00100000,
36 .type = MT_DEVICE
37 }
38};
39
40void __init iq31244_map_io(void)
41{
42 iop321_map_io();
43
44 iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
45}
diff --git a/arch/arm/mach-iop32x/iq31244-pci.c b/arch/arm/mach-iop32x/iq31244-pci.c
new file mode 100644
index 000000000000..e447c8103ecd
--- /dev/null
+++ b/arch/arm/mach-iop32x/iq31244-pci.c
@@ -0,0 +1,129 @@
1/*
2 * arch/arm/mach-iop32x/iq31244-pci.c
3 *
4 * PCI support for the Intel IQ31244 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#include <linux/string.h>
18#include <linux/slab.h>
19
20#include <asm/hardware.h>
21#include <asm/irq.h>
22#include <asm/mach/pci.h>
23#include <asm/mach-types.h>
24
25/*
26 * The following macro is used to lookup irqs in a standard table
27 * format for those systems that do not already have PCI
28 * interrupts properly routed. We assume 1 <= pin <= 4
29 */
30#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
31({ int _ctl_ = -1; \
32 unsigned int _idsel = idsel - minid; \
33 if (_idsel <= maxid) \
34 _ctl_ = pci_irq_table[_idsel][pin-1]; \
35 _ctl_; })
36
37#define INTA IRQ_IQ31244_INTA
38#define INTB IRQ_IQ31244_INTB
39#define INTC IRQ_IQ31244_INTC
40#define INTD IRQ_IQ31244_INTD
41
42#define INTE IRQ_IQ31244_I82546
43
44static inline int __init
45iq31244_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
46{
47 static int pci_irq_table[][4] = {
48 /*
49 * PCI IDSEL/INTPIN->INTLINE
50 * A B C D
51 */
52#ifdef CONFIG_ARCH_EP80219
53 {INTB, INTB, INTB, INTB}, /* CFlash */
54 {INTE, INTE, INTE, INTE}, /* 82551 Pro 100 */
55 {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
56 {INTC, INTC, INTC, INTC}, /* SATA */
57#else
58 {INTB, INTB, INTB, INTB}, /* CFlash */
59 {INTC, INTC, INTC, INTC}, /* SATA */
60 {INTD, INTD, INTD, INTD}, /* PCI-X Slot */
61 {INTE, INTE, INTE, INTE}, /* 82546 GigE */
62#endif // CONFIG_ARCH_EP80219
63 };
64
65 BUG_ON(pin < 1 || pin > 4);
66
67 return PCI_IRQ_TABLE_LOOKUP(0, 7);
68}
69
70static int iq31244_setup(int nr, struct pci_sys_data *sys)
71{
72 struct resource *res;
73
74 if(nr != 0)
75 return 0;
76
77 res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
78 if (!res)
79 panic("PCI: unable to alloc resources");
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-iop32x/iq80321-mm.c b/arch/arm/mach-iop32x/iq80321-mm.c
new file mode 100644
index 000000000000..5f702a7ff622
--- /dev/null
+++ b/arch/arm/mach-iop32x/iq80321-mm.c
@@ -0,0 +1,45 @@
1/*
2 * linux/arch/arm/mach-iop32x/iq80321-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
25
26/*
27 * IQ80321 specific IO mappings
28 *
29 * We use RedBoot's setup for the onboard devices.
30 */
31static struct map_desc iq80321_io_desc[] __initdata = {
32 { /* on-board devices */
33 .virtual = IQ80321_UART,
34 .pfn = __phys_to_pfn(IQ80321_UART),
35 .length = 0x00100000,
36 .type = MT_DEVICE
37 }
38};
39
40void __init iq80321_map_io(void)
41{
42 iop321_map_io();
43
44 iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
45}
diff --git a/arch/arm/mach-iop32x/iq80321-pci.c b/arch/arm/mach-iop32x/iq80321-pci.c
new file mode 100644
index 000000000000..8767950e131f
--- /dev/null
+++ b/arch/arm/mach-iop32x/iq80321-pci.c
@@ -0,0 +1,123 @@
1/*
2 * arch/arm/mach-iop32x/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#include <linux/string.h>
18#include <linux/slab.h>
19
20#include <asm/hardware.h>
21#include <asm/irq.h>
22#include <asm/mach/pci.h>
23#include <asm/mach-types.h>
24
25/*
26 * The following macro is used to lookup irqs in a standard table
27 * format for those systems that do not already have PCI
28 * interrupts properly routed. We assume 1 <= pin <= 4
29 */
30#define PCI_IRQ_TABLE_LOOKUP(minid,maxid) \
31({ int _ctl_ = -1; \
32 unsigned int _idsel = idsel - minid; \
33 if (_idsel <= maxid) \
34 _ctl_ = pci_irq_table[_idsel][pin-1]; \
35 _ctl_; })
36
37#define INTA IRQ_IQ80321_INTA
38#define INTB IRQ_IQ80321_INTB
39#define INTC IRQ_IQ80321_INTC
40#define INTD IRQ_IQ80321_INTD
41
42#define INTE IRQ_IQ80321_I82544
43
44static inline int __init
45iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
46{
47 static int pci_irq_table[][4] = {
48 /*
49 * PCI IDSEL/INTPIN->INTLINE
50 * A B C D
51 */
52 {INTE, INTE, INTE, INTE}, /* Gig-E */
53 {-1, -1, -1, -1}, /* Unused */
54 {INTC, INTD, INTA, INTB}, /* PCI-X Slot */
55 {-1, -1, -1, -1},
56 };
57
58 BUG_ON(pin < 1 || pin > 4);
59
60// return PCI_IRQ_TABLE_LOOKUP(4, 7);
61 return pci_irq_table[idsel%4][pin-1];
62}
63
64static int iq80321_setup(int nr, struct pci_sys_data *sys)
65{
66 struct resource *res;
67
68 if(nr != 0)
69 return 0;
70
71 res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
72 if (!res)
73 panic("PCI: unable to alloc resources");
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-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
new file mode 100644
index 000000000000..c5f633d2d632
--- /dev/null
+++ b/arch/arm/mach-iop32x/irq.c
@@ -0,0 +1,97 @@
1/*
2 * linux/arch/arm/mach-iop32x/irq.c
3 *
4 * Generic IOP32X 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 irq_chip ext_chip = {
56 .name = "IOP",
57 .ack = iop321_irq_mask,
58 .mask = iop321_irq_mask,
59 .unmask = iop321_irq_unmask,
60};
61
62void __init iop321_init_irq(void)
63{
64 unsigned int i, tmp;
65
66 /* Enable access to coprocessor 6 for dealing with IRQs.
67 * From RMK:
68 * Basically, the Intel documentation here is poor. It appears that
69 * you need to set the bit to be able to access the coprocessor from
70 * SVC mode. Whether that allows access from user space or not is
71 * unclear.
72 */
73 asm volatile (
74 "mrc p15, 0, %0, c15, c1, 0\n\t"
75 "orr %0, %0, %1\n\t"
76 "mcr p15, 0, %0, c15, c1, 0\n\t"
77 /* The action is delayed, so we have to do this: */
78 "mrc p15, 0, %0, c15, c1, 0\n\t"
79 "mov %0, %0\n\t"
80 "sub pc, pc, #4"
81 : "=r" (tmp) : "i" (1 << 6) );
82
83 intctl_write(0); // disable all interrupts
84 intstr_write(0); // treat all as IRQ
85 if(machine_is_iq80321() ||
86 machine_is_iq31244()) // all interrupts are inputs to chip
87 *IOP321_PCIIRSR = 0x0f;
88
89 for(i = IOP321_IRQ_OFS; i < NR_IRQS; i++)
90 {
91 set_irq_chip(i, &ext_chip);
92 set_irq_handler(i, do_level_IRQ);
93 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
94
95 }
96}
97
diff --git a/arch/arm/mach-iop32x/pci.c b/arch/arm/mach-iop32x/pci.c
new file mode 100644
index 000000000000..1a7c683673f2
--- /dev/null
+++ b/arch/arm/mach-iop32x/pci.c
@@ -0,0 +1,220 @@
1/*
2 * arch/arm/mach-iop32x/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-iop32x/setup.c b/arch/arm/mach-iop32x/setup.c
new file mode 100644
index 000000000000..729678799271
--- /dev/null
+++ b/arch/arm/mach-iop32x/setup.c
@@ -0,0 +1,173 @@
1/*
2 * linux/arch/arm/mach-iop32x/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/major.h>
16#include <linux/fs.h>
17#include <linux/platform_device.h>
18#include <linux/serial.h>
19#include <linux/tty.h>
20#include <linux/serial_core.h>
21
22#include <asm/io.h>
23#include <asm/pgtable.h>
24#include <asm/page.h>
25#include <asm/mach/map.h>
26#include <asm/setup.h>
27#include <asm/system.h>
28#include <asm/memory.h>
29#include <asm/hardware.h>
30#include <asm/mach-types.h>
31#include <asm/mach/arch.h>
32
33#define IOP321_UART_XTAL 1843200
34
35/*
36 * Standard IO mapping for all IOP321 based systems
37 */
38static struct map_desc iop321_std_desc[] __initdata = {
39 { /* mem mapped registers */
40 .virtual = IOP321_VIRT_MEM_BASE,
41 .pfn = __phys_to_pfn(IOP321_PHYS_MEM_BASE),
42 .length = 0x00002000,
43 .type = MT_DEVICE
44 }, { /* PCI IO space */
45 .virtual = IOP321_PCI_LOWER_IO_VA,
46 .pfn = __phys_to_pfn(IOP321_PCI_LOWER_IO_PA),
47 .length = IOP321_PCI_IO_WINDOW_SIZE,
48 .type = MT_DEVICE
49 }
50};
51
52#ifdef CONFIG_ARCH_IQ80321
53#define UARTBASE IQ80321_UART
54#define IRQ_UART IRQ_IQ80321_UART
55#endif
56
57#ifdef CONFIG_ARCH_IQ31244
58#define UARTBASE IQ31244_UART
59#define IRQ_UART IRQ_IQ31244_UART
60#endif
61
62static struct uart_port iop321_serial_ports[] = {
63 {
64 .membase = (char*)(UARTBASE),
65 .mapbase = (UARTBASE),
66 .irq = IRQ_UART,
67 .flags = UPF_SKIP_TEST,
68 .iotype = UPIO_MEM,
69 .regshift = 0,
70 .uartclk = IOP321_UART_XTAL,
71 .line = 0,
72 .type = PORT_16550A,
73 .fifosize = 16
74 }
75};
76
77static struct resource iop32x_i2c_0_resources[] = {
78 [0] = {
79 .start = 0xfffff680,
80 .end = 0xfffff698,
81 .flags = IORESOURCE_MEM,
82 },
83 [1] = {
84 .start = IRQ_IOP321_I2C_0,
85 .end = IRQ_IOP321_I2C_0,
86 .flags = IORESOURCE_IRQ
87 }
88};
89
90static struct resource iop32x_i2c_1_resources[] = {
91 [0] = {
92 .start = 0xfffff6a0,
93 .end = 0xfffff6b8,
94 .flags = IORESOURCE_MEM,
95 },
96 [1] = {
97 .start = IRQ_IOP321_I2C_1,
98 .end = IRQ_IOP321_I2C_1,
99 .flags = IORESOURCE_IRQ
100 }
101};
102
103static struct platform_device iop32x_i2c_0_controller = {
104 .name = "IOP3xx-I2C",
105 .id = 0,
106 .num_resources = 2,
107 .resource = iop32x_i2c_0_resources
108};
109
110static struct platform_device iop32x_i2c_1_controller = {
111 .name = "IOP3xx-I2C",
112 .id = 1,
113 .num_resources = 2,
114 .resource = iop32x_i2c_1_resources
115};
116
117static struct platform_device *iop32x_devices[] __initdata = {
118 &iop32x_i2c_0_controller,
119 &iop32x_i2c_1_controller
120};
121
122void __init iop32x_init(void)
123{
124 if(iop_is_321())
125 {
126 platform_add_devices(iop32x_devices,
127 ARRAY_SIZE(iop32x_devices));
128 }
129}
130
131void __init iop321_map_io(void)
132{
133 iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
134 early_serial_setup(&iop321_serial_ports[0]);
135}
136
137#ifdef CONFIG_ARCH_IQ80321
138extern void iq80321_map_io(void);
139extern struct sys_timer iop321_timer;
140extern void iop321_init_time(void);
141#endif
142
143#ifdef CONFIG_ARCH_IQ31244
144extern void iq31244_map_io(void);
145extern struct sys_timer iop321_timer;
146extern void iop321_init_time(void);
147#endif
148
149#if defined(CONFIG_ARCH_IQ80321)
150MACHINE_START(IQ80321, "Intel IQ80321")
151 /* Maintainer: Intel Corporation */
152 .phys_io = IQ80321_UART,
153 .io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc,
154 .map_io = iq80321_map_io,
155 .init_irq = iop321_init_irq,
156 .timer = &iop321_timer,
157 .boot_params = 0xa0000100,
158 .init_machine = iop32x_init,
159MACHINE_END
160#elif defined(CONFIG_ARCH_IQ31244)
161MACHINE_START(IQ31244, "Intel IQ31244")
162 /* Maintainer: Intel Corp. */
163 .phys_io = IQ31244_UART,
164 .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
165 .map_io = iq31244_map_io,
166 .init_irq = iop321_init_irq,
167 .timer = &iop321_timer,
168 .boot_params = 0xa0000100,
169 .init_machine = iop32x_init,
170MACHINE_END
171#else
172#error No machine descriptor defined for this IOP3XX implementation
173#endif
diff --git a/arch/arm/mach-iop32x/time.c b/arch/arm/mach-iop32x/time.c
new file mode 100644
index 000000000000..3cabbbca0a02
--- /dev/null
+++ b/arch/arm/mach-iop32x/time.c
@@ -0,0 +1,108 @@
1/*
2 * arch/arm/mach-iop32x/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/irq.h>
27#include <asm/mach/time.h>
28
29#define IOP321_TIME_SYNC 0
30
31static inline unsigned long get_elapsed(void)
32{
33 return LATCH - *IOP321_TU_TCR0;
34}
35
36static unsigned long iop321_gettimeoffset(void)
37{
38 unsigned long elapsed, usec;
39 u32 tisr1, tisr2;
40
41 /*
42 * If an interrupt was pending before we read the timer,
43 * we've already wrapped. Factor this into the time.
44 * If an interrupt was pending after we read the timer,
45 * it may have wrapped between checking the interrupt
46 * status and reading the timer. Re-read the timer to
47 * be sure its value is after the wrap.
48 */
49
50 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
51 elapsed = get_elapsed();
52 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
53
54 if(tisr1 & 1)
55 elapsed += LATCH;
56 else if (tisr2 & 1)
57 elapsed = LATCH + get_elapsed();
58
59 /*
60 * Now convert them to usec.
61 */
62 usec = (unsigned long)(elapsed / (CLOCK_TICK_RATE/1000000));
63
64 return usec;
65}
66
67static irqreturn_t
68iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
69{
70 u32 tisr;
71
72 write_seqlock(&xtime_lock);
73
74 asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
75 tisr |= 1;
76 asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
77
78 timer_tick(regs);
79
80 write_sequnlock(&xtime_lock);
81
82 return IRQ_HANDLED;
83}
84
85static struct irqaction iop321_timer_irq = {
86 .name = "IOP321 Timer Tick",
87 .handler = iop321_timer_interrupt,
88 .flags = IRQF_DISABLED | IRQF_TIMER,
89};
90
91static void __init iop321_timer_init(void)
92{
93 u32 timer_ctl;
94
95 setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
96
97 timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
98 IOP321_TMR_RATIO_1_1;
99
100 asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
101
102 asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
103}
104
105struct sys_timer iop321_timer = {
106 .init = &iop321_timer_init,
107 .offset = iop321_gettimeoffset,
108};