diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 18:40:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 18:40:39 -0500 |
commit | ea14fad0d416354a4e9bb1a04f32acba706f9548 (patch) | |
tree | 2c8acc5331f189aef1d40ddce3f40d6be9314e77 /arch/arm/mach-iop13xx | |
parent | 6ee7e78e7c78d871409ad4df30551c9355be7d0e (diff) | |
parent | 6705cda24fad1cb0ac82ac4f312df8ec735b39b0 (diff) |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (76 commits)
[ARM] 4002/1: S3C24XX: leave parent IRQs unmasked
[ARM] 4001/1: S3C24XX: shorten reboot time
[ARM] 3983/2: remove unused argument to __bug()
[ARM] 4000/1: Osiris: add third serial port in
[ARM] 3999/1: RX3715: suspend to RAM support
[ARM] 3998/1: VR1000: LED platform devices
[ARM] 3995/1: iop13xx: add iop13xx support
[ARM] 3968/1: iop13xx: add iop13xx_defconfig
[ARM] Update mach-types
[ARM] Allow gcc to optimise arm_add_memory a little more
[ARM] 3991/1: i.MX/MX1 high resolution time source
[ARM] 3990/1: i.MX/MX1 more precise PLL decode
[ARM] 3986/1: H1940: suspend to RAM support
[ARM] 3985/1: ixp4xx clocksource cleanup
[ARM] 3984/1: ixp4xx/nslu2: Fix disk LED numbering (take 2)
[ARM] 3994/1: ixp23xx: fix handling of pci master aborts
[ARM] 3981/1: sched_clock for PXA2xx
[ARM] 3980/1: extend the ARM Versatile sched_clock implementation from 32 to 63 bit
[ARM] 3979/1: extend the SA11x0 sched_clock implementation from 32 to 63 bit period
[ARM] 3978/1: macro to provide a 63-bit value from a 32-bit hardware counter
...
Diffstat (limited to 'arch/arm/mach-iop13xx')
-rw-r--r-- | arch/arm/mach-iop13xx/Kconfig | 20 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/Makefile | 12 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/io.c | 93 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/iq81340mc.c | 98 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/iq81340sc.c | 100 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/irq.c | 286 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/pci.c | 1113 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/setup.c | 406 | ||||
-rw-r--r-- | arch/arm/mach-iop13xx/time.c | 102 |
10 files changed, 2233 insertions, 0 deletions
diff --git a/arch/arm/mach-iop13xx/Kconfig b/arch/arm/mach-iop13xx/Kconfig new file mode 100644 index 000000000000..40c2d689f2eb --- /dev/null +++ b/arch/arm/mach-iop13xx/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | if ARCH_IOP13XX | ||
2 | |||
3 | menu "IOP13XX Implementation Options" | ||
4 | |||
5 | comment "IOP13XX Platform Support" | ||
6 | |||
7 | config MACH_IQ81340SC | ||
8 | bool "Enable IQ81340SC Hardware Support" | ||
9 | help | ||
10 | Say Y here if you want to support running on the Intel IQ81340SC | ||
11 | evaluation kit. | ||
12 | |||
13 | config MACH_IQ81340MC | ||
14 | bool "Enable IQ81340MC Hardware Support" | ||
15 | help | ||
16 | Say Y here if you want to support running on the Intel IQ81340MC | ||
17 | evaluation kit. | ||
18 | |||
19 | endmenu | ||
20 | endif | ||
diff --git a/arch/arm/mach-iop13xx/Makefile b/arch/arm/mach-iop13xx/Makefile new file mode 100644 index 000000000000..c3d6c08f2d4c --- /dev/null +++ b/arch/arm/mach-iop13xx/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | obj-y := | ||
2 | obj-m := | ||
3 | obj-n := | ||
4 | obj- := | ||
5 | |||
6 | obj-$(CONFIG_ARCH_IOP13XX) += setup.o | ||
7 | obj-$(CONFIG_ARCH_IOP13XX) += irq.o | ||
8 | obj-$(CONFIG_ARCH_IOP13XX) += time.o | ||
9 | obj-$(CONFIG_ARCH_IOP13XX) += pci.o | ||
10 | obj-$(CONFIG_ARCH_IOP13XX) += io.o | ||
11 | obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o | ||
12 | obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o | ||
diff --git a/arch/arm/mach-iop13xx/Makefile.boot b/arch/arm/mach-iop13xx/Makefile.boot new file mode 100644 index 000000000000..0b0e19fdfe6c --- /dev/null +++ b/arch/arm/mach-iop13xx/Makefile.boot | |||
@@ -0,0 +1,3 @@ | |||
1 | zreladdr-y := 0x00008000 | ||
2 | params_phys-y := 0x00000100 | ||
3 | initrd_phys-y := 0x00800000 | ||
diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c new file mode 100644 index 000000000000..fbf9f88e46ea --- /dev/null +++ b/arch/arm/mach-iop13xx/io.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * iop13xx custom ioremap implementation | ||
3 | * Copyright (c) 2005-2006, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
16 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/io.h> | ||
23 | |||
24 | void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size, | ||
25 | unsigned long flags) | ||
26 | { | ||
27 | void __iomem * retval; | ||
28 | |||
29 | switch (cookie) { | ||
30 | case IOP13XX_PCIX_LOWER_MEM_RA ... IOP13XX_PCIX_UPPER_MEM_RA: | ||
31 | if (unlikely(!iop13xx_atux_mem_base)) | ||
32 | retval = NULL; | ||
33 | else | ||
34 | retval = (void *)(iop13xx_atux_mem_base + | ||
35 | (cookie - IOP13XX_PCIX_LOWER_MEM_RA)); | ||
36 | break; | ||
37 | case IOP13XX_PCIE_LOWER_MEM_RA ... IOP13XX_PCIE_UPPER_MEM_RA: | ||
38 | if (unlikely(!iop13xx_atue_mem_base)) | ||
39 | retval = NULL; | ||
40 | else | ||
41 | retval = (void *)(iop13xx_atue_mem_base + | ||
42 | (cookie - IOP13XX_PCIE_LOWER_MEM_RA)); | ||
43 | break; | ||
44 | case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA: | ||
45 | retval = __ioremap(IOP13XX_PBI_LOWER_MEM_PA + | ||
46 | (cookie - IOP13XX_PBI_LOWER_MEM_RA), | ||
47 | size, flags); | ||
48 | break; | ||
49 | case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA: | ||
50 | retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie); | ||
51 | break; | ||
52 | case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA: | ||
53 | retval = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(cookie); | ||
54 | break; | ||
55 | case IOP13XX_PMMR_PHYS_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_PA: | ||
56 | retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie); | ||
57 | break; | ||
58 | default: | ||
59 | retval = __ioremap(cookie, size, flags); | ||
60 | } | ||
61 | |||
62 | return retval; | ||
63 | } | ||
64 | EXPORT_SYMBOL(__iop13xx_ioremap); | ||
65 | |||
66 | void __iop13xx_iounmap(void __iomem *addr) | ||
67 | { | ||
68 | extern void __iounmap(volatile void __iomem *addr); | ||
69 | |||
70 | if (iop13xx_atue_mem_base) | ||
71 | if (addr >= (void __iomem *) iop13xx_atue_mem_base && | ||
72 | addr < (void __iomem *) (iop13xx_atue_mem_base + | ||
73 | iop13xx_atue_mem_size)) | ||
74 | goto skip; | ||
75 | |||
76 | if (iop13xx_atux_mem_base) | ||
77 | if (addr >= (void __iomem *) iop13xx_atux_mem_base && | ||
78 | addr < (void __iomem *) (iop13xx_atux_mem_base + | ||
79 | iop13xx_atux_mem_size)) | ||
80 | goto skip; | ||
81 | |||
82 | switch ((u32) addr) { | ||
83 | case IOP13XX_PCIE_LOWER_IO_VA ... IOP13XX_PCIE_UPPER_IO_VA: | ||
84 | case IOP13XX_PCIX_LOWER_IO_VA ... IOP13XX_PCIX_UPPER_IO_VA: | ||
85 | case IOP13XX_PMMR_VIRT_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_VA: | ||
86 | goto skip; | ||
87 | } | ||
88 | __iounmap(addr); | ||
89 | |||
90 | skip: | ||
91 | return; | ||
92 | } | ||
93 | EXPORT_SYMBOL(__iop13xx_iounmap); | ||
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c new file mode 100644 index 000000000000..ee595786cd22 --- /dev/null +++ b/arch/arm/mach-iop13xx/iq81340mc.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * iq81340mc board support | ||
3 | * Copyright (c) 2005-2006, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
16 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/pci.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/mach/pci.h> | ||
24 | #include <asm/mach-types.h> | ||
25 | #include <asm/mach/arch.h> | ||
26 | #include <asm/arch/pci.h> | ||
27 | #include <asm/mach/time.h> | ||
28 | |||
29 | extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */ | ||
30 | |||
31 | static int __init | ||
32 | iq81340mc_pcix_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) | ||
33 | { | ||
34 | switch (idsel) { | ||
35 | case 1: | ||
36 | switch (pin) { | ||
37 | case 1: return ATUX_INTB; | ||
38 | case 2: return ATUX_INTC; | ||
39 | case 3: return ATUX_INTD; | ||
40 | case 4: return ATUX_INTA; | ||
41 | default: return -1; | ||
42 | } | ||
43 | case 2: | ||
44 | switch (pin) { | ||
45 | case 1: return ATUX_INTC; | ||
46 | case 2: return ATUX_INTD; | ||
47 | case 3: return ATUX_INTC; | ||
48 | case 4: return ATUX_INTD; | ||
49 | default: return -1; | ||
50 | } | ||
51 | default: return -1; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static struct hw_pci iq81340mc_pci __initdata = { | ||
56 | .swizzle = pci_std_swizzle, | ||
57 | .nr_controllers = 0, | ||
58 | .setup = iop13xx_pci_setup, | ||
59 | .map_irq = iq81340mc_pcix_map_irq, | ||
60 | .scan = iop13xx_scan_bus, | ||
61 | .preinit = iop13xx_pci_init, | ||
62 | }; | ||
63 | |||
64 | static int __init iq81340mc_pci_init(void) | ||
65 | { | ||
66 | iop13xx_atu_select(&iq81340mc_pci); | ||
67 | pci_common_init(&iq81340mc_pci); | ||
68 | iop13xx_map_pci_memory(); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static void __init iq81340mc_init(void) | ||
74 | { | ||
75 | iop13xx_platform_init(); | ||
76 | iq81340mc_pci_init(); | ||
77 | } | ||
78 | |||
79 | static void __init iq81340mc_timer_init(void) | ||
80 | { | ||
81 | iop13xx_init_time(400000000); | ||
82 | } | ||
83 | |||
84 | static struct sys_timer iq81340mc_timer = { | ||
85 | .init = iq81340mc_timer_init, | ||
86 | .offset = iop13xx_gettimeoffset, | ||
87 | }; | ||
88 | |||
89 | MACHINE_START(IQ81340MC, "Intel IQ81340MC") | ||
90 | /* Maintainer: Dan Williams <dan.j.williams@intel.com> */ | ||
91 | .phys_io = PHYS_IO, | ||
92 | .io_pg_offst = IO_PG_OFFSET, | ||
93 | .map_io = iop13xx_map_io, | ||
94 | .init_irq = iop13xx_init_irq, | ||
95 | .timer = &iq81340mc_timer, | ||
96 | .boot_params = BOOT_PARAM_OFFSET, | ||
97 | .init_machine = iq81340mc_init, | ||
98 | MACHINE_END | ||
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c new file mode 100644 index 000000000000..6677e14b61bf --- /dev/null +++ b/arch/arm/mach-iop13xx/iq81340sc.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * iq81340sc board support | ||
3 | * Copyright (c) 2005-2006, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
16 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/pci.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/mach/pci.h> | ||
24 | #include <asm/mach-types.h> | ||
25 | #include <asm/mach/arch.h> | ||
26 | #include <asm/arch/pci.h> | ||
27 | #include <asm/mach/time.h> | ||
28 | |||
29 | extern int init_atu; | ||
30 | |||
31 | static int __init | ||
32 | iq81340sc_atux_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) | ||
33 | { | ||
34 | WARN_ON(idsel < 1 || idsel > 2); | ||
35 | |||
36 | switch (idsel) { | ||
37 | case 1: | ||
38 | switch (pin) { | ||
39 | case 1: return ATUX_INTB; | ||
40 | case 2: return ATUX_INTC; | ||
41 | case 3: return ATUX_INTD; | ||
42 | case 4: return ATUX_INTA; | ||
43 | default: return -1; | ||
44 | } | ||
45 | case 2: | ||
46 | switch (pin) { | ||
47 | case 1: return ATUX_INTC; | ||
48 | case 2: return ATUX_INTC; | ||
49 | case 3: return ATUX_INTC; | ||
50 | case 4: return ATUX_INTC; | ||
51 | default: return -1; | ||
52 | } | ||
53 | default: return -1; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | static struct hw_pci iq81340sc_pci __initdata = { | ||
58 | .swizzle = pci_std_swizzle, | ||
59 | .nr_controllers = 0, | ||
60 | .setup = iop13xx_pci_setup, | ||
61 | .scan = iop13xx_scan_bus, | ||
62 | .map_irq = iq81340sc_atux_map_irq, | ||
63 | .preinit = iop13xx_pci_init | ||
64 | }; | ||
65 | |||
66 | static int __init iq81340sc_pci_init(void) | ||
67 | { | ||
68 | iop13xx_atu_select(&iq81340sc_pci); | ||
69 | pci_common_init(&iq81340sc_pci); | ||
70 | iop13xx_map_pci_memory(); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static void __init iq81340sc_init(void) | ||
76 | { | ||
77 | iop13xx_platform_init(); | ||
78 | iq81340sc_pci_init(); | ||
79 | } | ||
80 | |||
81 | static void __init iq81340sc_timer_init(void) | ||
82 | { | ||
83 | iop13xx_init_time(400000000); | ||
84 | } | ||
85 | |||
86 | static struct sys_timer iq81340sc_timer = { | ||
87 | .init = iq81340sc_timer_init, | ||
88 | .offset = iop13xx_gettimeoffset, | ||
89 | }; | ||
90 | |||
91 | MACHINE_START(IQ81340SC, "Intel IQ81340SC") | ||
92 | /* Maintainer: Dan Williams <dan.j.williams@intel.com> */ | ||
93 | .phys_io = PHYS_IO, | ||
94 | .io_pg_offst = IO_PG_OFFSET, | ||
95 | .map_io = iop13xx_map_io, | ||
96 | .init_irq = iop13xx_init_irq, | ||
97 | .timer = &iq81340sc_timer, | ||
98 | .boot_params = BOOT_PARAM_OFFSET, | ||
99 | .init_machine = iq81340sc_init, | ||
100 | MACHINE_END | ||
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c new file mode 100644 index 000000000000..c4d9c8c5579c --- /dev/null +++ b/arch/arm/mach-iop13xx/irq.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * iop13xx IRQ handling / support functions | ||
3 | * Copyright (c) 2005-2006, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
16 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/sysctl.h> | ||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/mach/irq.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/arch/irqs.h> | ||
29 | |||
30 | /* INTCTL0 CP6 R0 Page 4 | ||
31 | */ | ||
32 | static inline u32 read_intctl_0(void) | ||
33 | { | ||
34 | u32 val; | ||
35 | asm volatile("mrc p6, 0, %0, c0, c4, 0":"=r" (val)); | ||
36 | return val; | ||
37 | } | ||
38 | static inline void write_intctl_0(u32 val) | ||
39 | { | ||
40 | asm volatile("mcr p6, 0, %0, c0, c4, 0"::"r" (val)); | ||
41 | } | ||
42 | |||
43 | /* INTCTL1 CP6 R1 Page 4 | ||
44 | */ | ||
45 | static inline u32 read_intctl_1(void) | ||
46 | { | ||
47 | u32 val; | ||
48 | asm volatile("mrc p6, 0, %0, c1, c4, 0":"=r" (val)); | ||
49 | return val; | ||
50 | } | ||
51 | static inline void write_intctl_1(u32 val) | ||
52 | { | ||
53 | asm volatile("mcr p6, 0, %0, c1, c4, 0"::"r" (val)); | ||
54 | } | ||
55 | |||
56 | /* INTCTL2 CP6 R2 Page 4 | ||
57 | */ | ||
58 | static inline u32 read_intctl_2(void) | ||
59 | { | ||
60 | u32 val; | ||
61 | asm volatile("mrc p6, 0, %0, c2, c4, 0":"=r" (val)); | ||
62 | return val; | ||
63 | } | ||
64 | static inline void write_intctl_2(u32 val) | ||
65 | { | ||
66 | asm volatile("mcr p6, 0, %0, c2, c4, 0"::"r" (val)); | ||
67 | } | ||
68 | |||
69 | /* INTCTL3 CP6 R3 Page 4 | ||
70 | */ | ||
71 | static inline u32 read_intctl_3(void) | ||
72 | { | ||
73 | u32 val; | ||
74 | asm volatile("mrc p6, 0, %0, c3, c4, 0":"=r" (val)); | ||
75 | return val; | ||
76 | } | ||
77 | static inline void write_intctl_3(u32 val) | ||
78 | { | ||
79 | asm volatile("mcr p6, 0, %0, c3, c4, 0"::"r" (val)); | ||
80 | } | ||
81 | |||
82 | /* INTSTR0 CP6 R0 Page 5 | ||
83 | */ | ||
84 | static inline u32 read_intstr_0(void) | ||
85 | { | ||
86 | u32 val; | ||
87 | asm volatile("mrc p6, 0, %0, c0, c5, 0":"=r" (val)); | ||
88 | return val; | ||
89 | } | ||
90 | static inline void write_intstr_0(u32 val) | ||
91 | { | ||
92 | asm volatile("mcr p6, 0, %0, c0, c5, 0"::"r" (val)); | ||
93 | } | ||
94 | |||
95 | /* INTSTR1 CP6 R1 Page 5 | ||
96 | */ | ||
97 | static inline u32 read_intstr_1(void) | ||
98 | { | ||
99 | u32 val; | ||
100 | asm volatile("mrc p6, 0, %0, c1, c5, 0":"=r" (val)); | ||
101 | return val; | ||
102 | } | ||
103 | static void write_intstr_1(u32 val) | ||
104 | { | ||
105 | asm volatile("mcr p6, 0, %0, c1, c5, 0"::"r" (val)); | ||
106 | } | ||
107 | |||
108 | /* INTSTR2 CP6 R2 Page 5 | ||
109 | */ | ||
110 | static inline u32 read_intstr_2(void) | ||
111 | { | ||
112 | u32 val; | ||
113 | asm volatile("mrc p6, 0, %0, c2, c5, 0":"=r" (val)); | ||
114 | return val; | ||
115 | } | ||
116 | static void write_intstr_2(u32 val) | ||
117 | { | ||
118 | asm volatile("mcr p6, 0, %0, c2, c5, 0"::"r" (val)); | ||
119 | } | ||
120 | |||
121 | /* INTSTR3 CP6 R3 Page 5 | ||
122 | */ | ||
123 | static inline u32 read_intstr_3(void) | ||
124 | { | ||
125 | u32 val; | ||
126 | asm volatile("mrc p6, 0, %0, c3, c5, 0":"=r" (val)); | ||
127 | return val; | ||
128 | } | ||
129 | static void write_intstr_3(u32 val) | ||
130 | { | ||
131 | asm volatile("mcr p6, 0, %0, c3, c5, 0"::"r" (val)); | ||
132 | } | ||
133 | |||
134 | /* INTBASE CP6 R0 Page 2 | ||
135 | */ | ||
136 | static inline u32 read_intbase(void) | ||
137 | { | ||
138 | u32 val; | ||
139 | asm volatile("mrc p6, 0, %0, c0, c2, 0":"=r" (val)); | ||
140 | return val; | ||
141 | } | ||
142 | static void write_intbase(u32 val) | ||
143 | { | ||
144 | asm volatile("mcr p6, 0, %0, c0, c2, 0"::"r" (val)); | ||
145 | } | ||
146 | |||
147 | /* INTSIZE CP6 R2 Page 2 | ||
148 | */ | ||
149 | static inline u32 read_intsize(void) | ||
150 | { | ||
151 | u32 val; | ||
152 | asm volatile("mrc p6, 0, %0, c2, c2, 0":"=r" (val)); | ||
153 | return val; | ||
154 | } | ||
155 | static void write_intsize(u32 val) | ||
156 | { | ||
157 | asm volatile("mcr p6, 0, %0, c2, c2, 0"::"r" (val)); | ||
158 | } | ||
159 | |||
160 | /* 0 = Interrupt Masked and 1 = Interrupt not masked */ | ||
161 | static void | ||
162 | iop13xx_irq_mask0 (unsigned int irq) | ||
163 | { | ||
164 | u32 cp_flags = iop13xx_cp6_save(); | ||
165 | write_intctl_0(read_intctl_0() & ~(1 << (irq - 0))); | ||
166 | iop13xx_cp6_restore(cp_flags); | ||
167 | } | ||
168 | |||
169 | static void | ||
170 | iop13xx_irq_mask1 (unsigned int irq) | ||
171 | { | ||
172 | u32 cp_flags = iop13xx_cp6_save(); | ||
173 | write_intctl_1(read_intctl_1() & ~(1 << (irq - 32))); | ||
174 | iop13xx_cp6_restore(cp_flags); | ||
175 | } | ||
176 | |||
177 | static void | ||
178 | iop13xx_irq_mask2 (unsigned int irq) | ||
179 | { | ||
180 | u32 cp_flags = iop13xx_cp6_save(); | ||
181 | write_intctl_2(read_intctl_2() & ~(1 << (irq - 64))); | ||
182 | iop13xx_cp6_restore(cp_flags); | ||
183 | } | ||
184 | |||
185 | static void | ||
186 | iop13xx_irq_mask3 (unsigned int irq) | ||
187 | { | ||
188 | u32 cp_flags = iop13xx_cp6_save(); | ||
189 | write_intctl_3(read_intctl_3() & ~(1 << (irq - 96))); | ||
190 | iop13xx_cp6_restore(cp_flags); | ||
191 | } | ||
192 | |||
193 | static void | ||
194 | iop13xx_irq_unmask0(unsigned int irq) | ||
195 | { | ||
196 | u32 cp_flags = iop13xx_cp6_save(); | ||
197 | write_intctl_0(read_intctl_0() | (1 << (irq - 0))); | ||
198 | iop13xx_cp6_restore(cp_flags); | ||
199 | } | ||
200 | |||
201 | static void | ||
202 | iop13xx_irq_unmask1(unsigned int irq) | ||
203 | { | ||
204 | u32 cp_flags = iop13xx_cp6_save(); | ||
205 | write_intctl_1(read_intctl_1() | (1 << (irq - 32))); | ||
206 | iop13xx_cp6_restore(cp_flags); | ||
207 | } | ||
208 | |||
209 | static void | ||
210 | iop13xx_irq_unmask2(unsigned int irq) | ||
211 | { | ||
212 | u32 cp_flags = iop13xx_cp6_save(); | ||
213 | write_intctl_2(read_intctl_2() | (1 << (irq - 64))); | ||
214 | iop13xx_cp6_restore(cp_flags); | ||
215 | } | ||
216 | |||
217 | static void | ||
218 | iop13xx_irq_unmask3(unsigned int irq) | ||
219 | { | ||
220 | u32 cp_flags = iop13xx_cp6_save(); | ||
221 | write_intctl_3(read_intctl_3() | (1 << (irq - 96))); | ||
222 | iop13xx_cp6_restore(cp_flags); | ||
223 | } | ||
224 | |||
225 | static struct irqchip iop13xx_irqchip0 = { | ||
226 | .ack = iop13xx_irq_mask0, | ||
227 | .mask = iop13xx_irq_mask0, | ||
228 | .unmask = iop13xx_irq_unmask0, | ||
229 | }; | ||
230 | |||
231 | static struct irqchip iop13xx_irqchip1 = { | ||
232 | .ack = iop13xx_irq_mask1, | ||
233 | .mask = iop13xx_irq_mask1, | ||
234 | .unmask = iop13xx_irq_unmask1, | ||
235 | }; | ||
236 | |||
237 | static struct irqchip iop13xx_irqchip2 = { | ||
238 | .ack = iop13xx_irq_mask2, | ||
239 | .mask = iop13xx_irq_mask2, | ||
240 | .unmask = iop13xx_irq_unmask2, | ||
241 | }; | ||
242 | |||
243 | static struct irqchip iop13xx_irqchip3 = { | ||
244 | .ack = iop13xx_irq_mask3, | ||
245 | .mask = iop13xx_irq_mask3, | ||
246 | .unmask = iop13xx_irq_unmask3, | ||
247 | }; | ||
248 | |||
249 | void __init iop13xx_init_irq(void) | ||
250 | { | ||
251 | unsigned int i; | ||
252 | |||
253 | u32 cp_flags = iop13xx_cp6_save(); | ||
254 | |||
255 | /* disable all interrupts */ | ||
256 | write_intctl_0(0); | ||
257 | write_intctl_1(0); | ||
258 | write_intctl_2(0); | ||
259 | write_intctl_3(0); | ||
260 | |||
261 | /* treat all as IRQ */ | ||
262 | write_intstr_0(0); | ||
263 | write_intstr_1(0); | ||
264 | write_intstr_2(0); | ||
265 | write_intstr_3(0); | ||
266 | |||
267 | /* initialize the interrupt vector generator */ | ||
268 | write_intbase(INTBASE); | ||
269 | write_intsize(INTSIZE_4); | ||
270 | |||
271 | for(i = 0; i < NR_IOP13XX_IRQS; i++) { | ||
272 | if (i < 32) | ||
273 | set_irq_chip(i, &iop13xx_irqchip0); | ||
274 | else if (i < 64) | ||
275 | set_irq_chip(i, &iop13xx_irqchip1); | ||
276 | else if (i < 96) | ||
277 | set_irq_chip(i, &iop13xx_irqchip2); | ||
278 | else | ||
279 | set_irq_chip(i, &iop13xx_irqchip3); | ||
280 | |||
281 | set_irq_handler(i, do_level_IRQ); | ||
282 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); | ||
283 | } | ||
284 | |||
285 | iop13xx_cp6_restore(cp_flags); | ||
286 | } | ||
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c new file mode 100644 index 000000000000..89ec70ea3187 --- /dev/null +++ b/arch/arm/mach-iop13xx/pci.c | |||
@@ -0,0 +1,1113 @@ | |||
1 | /* | ||
2 | * iop13xx PCI support | ||
3 | * Copyright (c) 2005-2006, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
16 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/pci.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | #include <asm/irq.h> | ||
24 | #include <asm/hardware.h> | ||
25 | #include <asm/sizes.h> | ||
26 | #include <asm/mach/pci.h> | ||
27 | #include <asm/arch/pci.h> | ||
28 | |||
29 | #define IOP13XX_PCI_DEBUG 0 | ||
30 | #define PRINTK(x...) ((void)(IOP13XX_PCI_DEBUG && printk(x))) | ||
31 | |||
32 | u32 iop13xx_atux_pmmr_offset; /* This offset can change based on strapping */ | ||
33 | u32 iop13xx_atue_pmmr_offset; /* This offset can change based on strapping */ | ||
34 | static struct pci_bus *pci_bus_atux = 0; | ||
35 | static struct pci_bus *pci_bus_atue = 0; | ||
36 | u32 iop13xx_atue_mem_base; | ||
37 | u32 iop13xx_atux_mem_base; | ||
38 | size_t iop13xx_atue_mem_size; | ||
39 | size_t iop13xx_atux_mem_size; | ||
40 | unsigned long iop13xx_pcibios_min_io = 0; | ||
41 | unsigned long iop13xx_pcibios_min_mem = 0; | ||
42 | |||
43 | EXPORT_SYMBOL(iop13xx_atue_mem_base); | ||
44 | EXPORT_SYMBOL(iop13xx_atux_mem_base); | ||
45 | EXPORT_SYMBOL(iop13xx_atue_mem_size); | ||
46 | EXPORT_SYMBOL(iop13xx_atux_mem_size); | ||
47 | |||
48 | int init_atu = 0; /* Flag to select which ATU(s) to initialize / disable */ | ||
49 | static unsigned long atux_trhfa_timeout = 0; /* Trhfa = RST# high to first | ||
50 | access */ | ||
51 | |||
52 | /* Scan the initialized busses and ioremap the requested memory range | ||
53 | */ | ||
54 | void iop13xx_map_pci_memory(void) | ||
55 | { | ||
56 | int atu; | ||
57 | struct pci_bus *bus; | ||
58 | struct pci_dev *dev; | ||
59 | resource_size_t end = 0; | ||
60 | |||
61 | for (atu = 0; atu < 2; atu++) { | ||
62 | bus = atu ? pci_bus_atue : pci_bus_atux; | ||
63 | if (bus) { | ||
64 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
65 | int i; | ||
66 | int max = 7; | ||
67 | |||
68 | if (dev->subordinate) | ||
69 | max = DEVICE_COUNT_RESOURCE; | ||
70 | |||
71 | for (i = 0; i < max; i++) { | ||
72 | struct resource *res = &dev->resource[i]; | ||
73 | if (res->flags & IORESOURCE_MEM) | ||
74 | end = max(res->end, end); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | switch(atu) { | ||
79 | case 0: | ||
80 | iop13xx_atux_mem_size = | ||
81 | (end - IOP13XX_PCIX_LOWER_MEM_RA) + 1; | ||
82 | |||
83 | /* 16MB align the request */ | ||
84 | if (iop13xx_atux_mem_size & (SZ_16M - 1)) { | ||
85 | iop13xx_atux_mem_size &= ~(SZ_16M - 1); | ||
86 | iop13xx_atux_mem_size += SZ_16M; | ||
87 | } | ||
88 | |||
89 | if (end) { | ||
90 | iop13xx_atux_mem_base = | ||
91 | (u32) __ioremap_pfn( | ||
92 | __phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA) | ||
93 | , 0, iop13xx_atux_mem_size, 0); | ||
94 | if (!iop13xx_atux_mem_base) { | ||
95 | printk("%s: atux allocation " | ||
96 | "failed\n", __FUNCTION__); | ||
97 | BUG(); | ||
98 | } | ||
99 | } else | ||
100 | iop13xx_atux_mem_size = 0; | ||
101 | PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n", | ||
102 | __FUNCTION__, atu, iop13xx_atux_mem_size, | ||
103 | iop13xx_atux_mem_base); | ||
104 | break; | ||
105 | case 1: | ||
106 | iop13xx_atue_mem_size = | ||
107 | (end - IOP13XX_PCIE_LOWER_MEM_RA) + 1; | ||
108 | |||
109 | /* 16MB align the request */ | ||
110 | if (iop13xx_atue_mem_size & (SZ_16M - 1)) { | ||
111 | iop13xx_atue_mem_size &= ~(SZ_16M - 1); | ||
112 | iop13xx_atue_mem_size += SZ_16M; | ||
113 | } | ||
114 | |||
115 | if (end) { | ||
116 | iop13xx_atue_mem_base = | ||
117 | (u32) __ioremap_pfn( | ||
118 | __phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA) | ||
119 | , 0, iop13xx_atue_mem_size, 0); | ||
120 | if (!iop13xx_atue_mem_base) { | ||
121 | printk("%s: atue allocation " | ||
122 | "failed\n", __FUNCTION__); | ||
123 | BUG(); | ||
124 | } | ||
125 | } else | ||
126 | iop13xx_atue_mem_size = 0; | ||
127 | PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n", | ||
128 | __FUNCTION__, atu, iop13xx_atue_mem_size, | ||
129 | iop13xx_atue_mem_base); | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | printk("%s: Initialized (%uM @ resource/virtual: %08lx/%08x)\n", | ||
134 | atu ? "ATUE" : "ATUX", | ||
135 | (atu ? iop13xx_atue_mem_size : iop13xx_atux_mem_size) / | ||
136 | SZ_1M, | ||
137 | atu ? IOP13XX_PCIE_LOWER_MEM_RA : | ||
138 | IOP13XX_PCIX_LOWER_MEM_RA, | ||
139 | atu ? iop13xx_atue_mem_base : | ||
140 | iop13xx_atux_mem_base); | ||
141 | end = 0; | ||
142 | } | ||
143 | |||
144 | } | ||
145 | } | ||
146 | |||
147 | static inline int iop13xx_atu_function(int atu) | ||
148 | { | ||
149 | int func = 0; | ||
150 | /* the function number depends on the value of the | ||
151 | * IOP13XX_INTERFACE_SEL_PCIX reset strap | ||
152 | * see C-Spec section 3.17 | ||
153 | */ | ||
154 | switch(atu) { | ||
155 | case IOP13XX_INIT_ATU_ATUX: | ||
156 | if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) | ||
157 | func = 5; | ||
158 | else | ||
159 | func = 0; | ||
160 | break; | ||
161 | case IOP13XX_INIT_ATU_ATUE: | ||
162 | if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) | ||
163 | func = 0; | ||
164 | else | ||
165 | func = 5; | ||
166 | break; | ||
167 | default: | ||
168 | BUG(); | ||
169 | } | ||
170 | |||
171 | return func; | ||
172 | } | ||
173 | |||
174 | /* iop13xx_atux_cfg_address - format a configuration address for atux | ||
175 | * @bus: Target bus to access | ||
176 | * @devfn: Combined device number and function number | ||
177 | * @where: Desired register's address offset | ||
178 | * | ||
179 | * Convert the parameters to a configuration address formatted | ||
180 | * according the PCI-X 2.0 specification | ||
181 | */ | ||
182 | static u32 iop13xx_atux_cfg_address(struct pci_bus *bus, int devfn, int where) | ||
183 | { | ||
184 | struct pci_sys_data *sys = bus->sysdata; | ||
185 | u32 addr; | ||
186 | |||
187 | if (sys->busnr == bus->number) | ||
188 | addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11); | ||
189 | else | ||
190 | addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1; | ||
191 | |||
192 | addr |= PCI_FUNC(devfn) << 8 | ((where & 0xff) & ~3); | ||
193 | addr |= ((where & 0xf00) >> 8) << 24; /* upper register number */ | ||
194 | |||
195 | return addr; | ||
196 | } | ||
197 | |||
198 | /* iop13xx_atue_cfg_address - format a configuration address for atue | ||
199 | * @bus: Target bus to access | ||
200 | * @devfn: Combined device number and function number | ||
201 | * @where: Desired register's address offset | ||
202 | * | ||
203 | * Convert the parameters to an address usable by the ATUE_OCCAR | ||
204 | */ | ||
205 | static u32 iop13xx_atue_cfg_address(struct pci_bus *bus, int devfn, int where) | ||
206 | { | ||
207 | struct pci_sys_data *sys = bus->sysdata; | ||
208 | u32 addr; | ||
209 | |||
210 | PRINTK("iop13xx_atue_cfg_address: bus: %d dev: %d func: %d", | ||
211 | bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
212 | addr = ((u32) bus->number) << IOP13XX_ATUE_OCCAR_BUS_NUM | | ||
213 | ((u32) PCI_SLOT(devfn)) << IOP13XX_ATUE_OCCAR_DEV_NUM | | ||
214 | ((u32) PCI_FUNC(devfn)) << IOP13XX_ATUE_OCCAR_FUNC_NUM | | ||
215 | (where & ~0x3); | ||
216 | |||
217 | if (sys->busnr != bus->number) | ||
218 | addr |= 1; /* type 1 access */ | ||
219 | |||
220 | return addr; | ||
221 | } | ||
222 | |||
223 | /* This routine checks the status of the last configuration cycle. If an error | ||
224 | * was detected it returns >0, else it returns a 0. The errors being checked | ||
225 | * are parity, master abort, target abort (master and target). These types of | ||
226 | * errors occure during a config cycle where there is no device, like during | ||
227 | * the discovery stage. | ||
228 | */ | ||
229 | static int iop13xx_atux_pci_status(int clear) | ||
230 | { | ||
231 | unsigned int status; | ||
232 | int err = 0; | ||
233 | |||
234 | /* | ||
235 | * Check the status registers. | ||
236 | */ | ||
237 | status = __raw_readw(IOP13XX_ATUX_ATUSR); | ||
238 | if (status & IOP_PCI_STATUS_ERROR) | ||
239 | { | ||
240 | PRINTK("\t\t\tPCI error: ATUSR %#08x", status); | ||
241 | if(clear) | ||
242 | __raw_writew(status & IOP_PCI_STATUS_ERROR, | ||
243 | IOP13XX_ATUX_ATUSR); | ||
244 | err = 1; | ||
245 | } | ||
246 | status = __raw_readl(IOP13XX_ATUX_ATUISR); | ||
247 | if (status & IOP13XX_ATUX_ATUISR_ERROR) | ||
248 | { | ||
249 | PRINTK("\t\t\tPCI error interrupt: ATUISR %#08x", status); | ||
250 | if(clear) | ||
251 | __raw_writel(status & IOP13XX_ATUX_ATUISR_ERROR, | ||
252 | IOP13XX_ATUX_ATUISR); | ||
253 | err = 1; | ||
254 | } | ||
255 | return err; | ||
256 | } | ||
257 | |||
258 | /* Simply write the address register and read the configuration | ||
259 | * data. Note that the data dependency on %0 encourages an abort | ||
260 | * to be detected before we return. | ||
261 | */ | ||
262 | static inline u32 iop13xx_atux_read(unsigned long addr) | ||
263 | { | ||
264 | u32 val; | ||
265 | |||
266 | __asm__ __volatile__( | ||
267 | "str %1, [%2]\n\t" | ||
268 | "ldr %0, [%3]\n\t" | ||
269 | "mov %0, %0\n\t" | ||
270 | : "=r" (val) | ||
271 | : "r" (addr), "r" (IOP13XX_ATUX_OCCAR), "r" (IOP13XX_ATUX_OCCDR)); | ||
272 | |||
273 | return val; | ||
274 | } | ||
275 | |||
276 | /* The read routines must check the error status of the last configuration | ||
277 | * cycle. If there was an error, the routine returns all hex f's. | ||
278 | */ | ||
279 | static int | ||
280 | iop13xx_atux_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
281 | int size, u32 *value) | ||
282 | { | ||
283 | unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where); | ||
284 | u32 val = iop13xx_atux_read(addr) >> ((where & 3) * 8); | ||
285 | |||
286 | if (iop13xx_atux_pci_status(1) || is_atux_occdr_error()) { | ||
287 | __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, | ||
288 | IOP13XX_XBG_BECSR); | ||
289 | val = 0xffffffff; | ||
290 | } | ||
291 | |||
292 | *value = val; | ||
293 | |||
294 | return PCIBIOS_SUCCESSFUL; | ||
295 | } | ||
296 | |||
297 | static int | ||
298 | iop13xx_atux_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
299 | int size, u32 value) | ||
300 | { | ||
301 | unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where); | ||
302 | u32 val; | ||
303 | |||
304 | if (size != 4) { | ||
305 | val = iop13xx_atux_read(addr); | ||
306 | if (!iop13xx_atux_pci_status(1) == 0) | ||
307 | return PCIBIOS_SUCCESSFUL; | ||
308 | |||
309 | where = (where & 3) * 8; | ||
310 | |||
311 | if (size == 1) | ||
312 | val &= ~(0xff << where); | ||
313 | else | ||
314 | val &= ~(0xffff << where); | ||
315 | |||
316 | __raw_writel(val | value << where, IOP13XX_ATUX_OCCDR); | ||
317 | } else { | ||
318 | __raw_writel(addr, IOP13XX_ATUX_OCCAR); | ||
319 | __raw_writel(value, IOP13XX_ATUX_OCCDR); | ||
320 | } | ||
321 | |||
322 | return PCIBIOS_SUCCESSFUL; | ||
323 | } | ||
324 | |||
325 | static struct pci_ops iop13xx_atux_ops = { | ||
326 | .read = iop13xx_atux_read_config, | ||
327 | .write = iop13xx_atux_write_config, | ||
328 | }; | ||
329 | |||
330 | /* This routine checks the status of the last configuration cycle. If an error | ||
331 | * was detected it returns >0, else it returns a 0. The errors being checked | ||
332 | * are parity, master abort, target abort (master and target). These types of | ||
333 | * errors occure during a config cycle where there is no device, like during | ||
334 | * the discovery stage. | ||
335 | */ | ||
336 | static int iop13xx_atue_pci_status(int clear) | ||
337 | { | ||
338 | unsigned int status; | ||
339 | int err = 0; | ||
340 | |||
341 | /* | ||
342 | * Check the status registers. | ||
343 | */ | ||
344 | |||
345 | /* standard pci status register */ | ||
346 | status = __raw_readw(IOP13XX_ATUE_ATUSR); | ||
347 | if (status & IOP_PCI_STATUS_ERROR) { | ||
348 | PRINTK("\t\t\tPCI error: ATUSR %#08x", status); | ||
349 | if(clear) | ||
350 | __raw_writew(status & IOP_PCI_STATUS_ERROR, | ||
351 | IOP13XX_ATUE_ATUSR); | ||
352 | err++; | ||
353 | } | ||
354 | |||
355 | /* check the normal status bits in the ATUISR */ | ||
356 | status = __raw_readl(IOP13XX_ATUE_ATUISR); | ||
357 | if (status & IOP13XX_ATUE_ATUISR_ERROR) { | ||
358 | PRINTK("\t\t\tPCI error: ATUISR %#08x", status); | ||
359 | if (clear) | ||
360 | __raw_writew(status & IOP13XX_ATUE_ATUISR_ERROR, | ||
361 | IOP13XX_ATUE_ATUISR); | ||
362 | err++; | ||
363 | |||
364 | /* check the PCI-E status if the ATUISR reports an interface error */ | ||
365 | if (status & IOP13XX_ATUE_STAT_PCI_IFACE_ERR) { | ||
366 | /* get the unmasked errors */ | ||
367 | status = __raw_readl(IOP13XX_ATUE_PIE_STS) & | ||
368 | ~(__raw_readl(IOP13XX_ATUE_PIE_MSK)); | ||
369 | |||
370 | if (status) { | ||
371 | PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x", | ||
372 | __raw_readl(IOP13XX_ATUE_PIE_STS)); | ||
373 | err++; | ||
374 | } else { | ||
375 | PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x", | ||
376 | __raw_readl(IOP13XX_ATUE_PIE_STS)); | ||
377 | PRINTK("\t\t\tPCI-E error: ATUE_PIE_MSK %#08x", | ||
378 | __raw_readl(IOP13XX_ATUE_PIE_MSK)); | ||
379 | BUG(); | ||
380 | } | ||
381 | |||
382 | if(clear) | ||
383 | __raw_writel(status, IOP13XX_ATUE_PIE_STS); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | return err; | ||
388 | } | ||
389 | |||
390 | static inline int __init | ||
391 | iop13xx_pcie_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) | ||
392 | { | ||
393 | WARN_ON(idsel != 0); | ||
394 | |||
395 | switch (pin) { | ||
396 | case 1: return ATUE_INTA; | ||
397 | case 2: return ATUE_INTB; | ||
398 | case 3: return ATUE_INTC; | ||
399 | case 4: return ATUE_INTD; | ||
400 | default: return -1; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | static inline u32 iop13xx_atue_read(unsigned long addr) | ||
405 | { | ||
406 | u32 val; | ||
407 | |||
408 | __raw_writel(addr, IOP13XX_ATUE_OCCAR); | ||
409 | val = __raw_readl(IOP13XX_ATUE_OCCDR); | ||
410 | |||
411 | rmb(); | ||
412 | |||
413 | return val; | ||
414 | } | ||
415 | |||
416 | /* The read routines must check the error status of the last configuration | ||
417 | * cycle. If there was an error, the routine returns all hex f's. | ||
418 | */ | ||
419 | static int | ||
420 | iop13xx_atue_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
421 | int size, u32 *value) | ||
422 | { | ||
423 | u32 val; | ||
424 | unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where); | ||
425 | |||
426 | /* Hide device numbers > 0 on the local PCI-E bus (Type 0 access) */ | ||
427 | if (!PCI_SLOT(devfn) || (addr & 1)) { | ||
428 | val = iop13xx_atue_read(addr) >> ((where & 3) * 8); | ||
429 | if( iop13xx_atue_pci_status(1) || is_atue_occdr_error() ) { | ||
430 | __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, | ||
431 | IOP13XX_XBG_BECSR); | ||
432 | val = 0xffffffff; | ||
433 | } | ||
434 | |||
435 | PRINTK("addr=%#0lx, val=%#010x", addr, val); | ||
436 | } else | ||
437 | val = 0xffffffff; | ||
438 | |||
439 | *value = val; | ||
440 | |||
441 | return PCIBIOS_SUCCESSFUL; | ||
442 | } | ||
443 | |||
444 | static int | ||
445 | iop13xx_atue_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
446 | int size, u32 value) | ||
447 | { | ||
448 | unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where); | ||
449 | u32 val; | ||
450 | |||
451 | if (size != 4) { | ||
452 | val = iop13xx_atue_read(addr); | ||
453 | if (!iop13xx_atue_pci_status(1) == 0) | ||
454 | return PCIBIOS_SUCCESSFUL; | ||
455 | |||
456 | where = (where & 3) * 8; | ||
457 | |||
458 | if (size == 1) | ||
459 | val &= ~(0xff << where); | ||
460 | else | ||
461 | val &= ~(0xffff << where); | ||
462 | |||
463 | __raw_writel(val | value << where, IOP13XX_ATUE_OCCDR); | ||
464 | } else { | ||
465 | __raw_writel(addr, IOP13XX_ATUE_OCCAR); | ||
466 | __raw_writel(value, IOP13XX_ATUE_OCCDR); | ||
467 | } | ||
468 | |||
469 | return PCIBIOS_SUCCESSFUL; | ||
470 | } | ||
471 | |||
472 | static struct pci_ops iop13xx_atue_ops = { | ||
473 | .read = iop13xx_atue_read_config, | ||
474 | .write = iop13xx_atue_write_config, | ||
475 | }; | ||
476 | |||
477 | /* When a PCI device does not exist during config cycles, the XScale gets a | ||
478 | * bus error instead of returning 0xffffffff. We can't rely on the ATU status | ||
479 | * bits to tell us that it was indeed a configuration cycle that caused this | ||
480 | * error especially in the case when the ATUE link is down. Instead we rely | ||
481 | * on data from the south XSI bridge to validate the abort | ||
482 | */ | ||
483 | int | ||
484 | iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | ||
485 | { | ||
486 | PRINTK("Data abort: address = 0x%08lx " | ||
487 | "fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx", | ||
488 | addr, fsr, regs->ARM_pc, regs->ARM_lr); | ||
489 | |||
490 | PRINTK("IOP13XX_XBG_BECSR: %#10x", __raw_readl(IOP13XX_XBG_BECSR)); | ||
491 | PRINTK("IOP13XX_XBG_BERAR: %#10x", __raw_readl(IOP13XX_XBG_BERAR)); | ||
492 | PRINTK("IOP13XX_XBG_BERUAR: %#10x", __raw_readl(IOP13XX_XBG_BERUAR)); | ||
493 | |||
494 | /* If it was an imprecise abort, then we need to correct the | ||
495 | * return address to be _after_ the instruction. | ||
496 | */ | ||
497 | if (fsr & (1 << 10)) | ||
498 | regs->ARM_pc += 4; | ||
499 | |||
500 | if (is_atue_occdr_error() || is_atux_occdr_error()) | ||
501 | return 0; | ||
502 | else | ||
503 | return 1; | ||
504 | } | ||
505 | |||
506 | /* Scan an IOP13XX PCI bus. nr selects which ATU we use. | ||
507 | */ | ||
508 | struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) | ||
509 | { | ||
510 | int which_atu; | ||
511 | struct pci_bus *bus = NULL; | ||
512 | |||
513 | switch (init_atu) { | ||
514 | case IOP13XX_INIT_ATU_ATUX: | ||
515 | which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX; | ||
516 | break; | ||
517 | case IOP13XX_INIT_ATU_ATUE: | ||
518 | which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE; | ||
519 | break; | ||
520 | case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE): | ||
521 | which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX; | ||
522 | break; | ||
523 | default: | ||
524 | which_atu = 0; | ||
525 | } | ||
526 | |||
527 | if (!which_atu) { | ||
528 | BUG(); | ||
529 | return NULL; | ||
530 | } | ||
531 | |||
532 | switch (which_atu) { | ||
533 | case IOP13XX_INIT_ATU_ATUX: | ||
534 | if (time_after_eq(jiffies + msecs_to_jiffies(1000), | ||
535 | atux_trhfa_timeout)) /* ensure not wrap */ | ||
536 | while(time_before(jiffies, atux_trhfa_timeout)) | ||
537 | udelay(100); | ||
538 | |||
539 | bus = pci_bus_atux = pci_scan_bus(sys->busnr, | ||
540 | &iop13xx_atux_ops, | ||
541 | sys); | ||
542 | break; | ||
543 | case IOP13XX_INIT_ATU_ATUE: | ||
544 | bus = pci_bus_atue = pci_scan_bus(sys->busnr, | ||
545 | &iop13xx_atue_ops, | ||
546 | sys); | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | return bus; | ||
551 | } | ||
552 | |||
553 | /* This function is called from iop13xx_pci_init() after assigning valid | ||
554 | * values to iop13xx_atue_pmmr_offset. This is the location for common | ||
555 | * setup of ATUE for all IOP13XX implementations. | ||
556 | */ | ||
557 | void __init iop13xx_atue_setup(void) | ||
558 | { | ||
559 | int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUE); | ||
560 | u32 reg_val; | ||
561 | |||
562 | /* BAR 1 (1:1 mapping with Physical RAM) */ | ||
563 | /* Set limit and enable */ | ||
564 | __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1, | ||
565 | IOP13XX_ATUE_IALR1); | ||
566 | __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1); | ||
567 | |||
568 | /* Set base at the top of the reserved address space */ | ||
569 | __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 | | ||
570 | PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUE_IABAR1); | ||
571 | |||
572 | /* 1:1 mapping with physical ram | ||
573 | * (leave big endian byte swap disabled) | ||
574 | */ | ||
575 | __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1); | ||
576 | __raw_writel(PHYS_OFFSET, IOP13XX_ATUE_IATVR1); | ||
577 | |||
578 | /* Outbound window 1 (PCIX/PCIE memory window) */ | ||
579 | /* 32 bit Address Space */ | ||
580 | __raw_writel(0x0, IOP13XX_ATUE_OUMWTVR1); | ||
581 | /* PA[35:32] */ | ||
582 | __raw_writel(IOP13XX_ATUE_OUMBAR_ENABLE | | ||
583 | (IOP13XX_PCIE_MEM_PHYS_OFFSET >> 32), | ||
584 | IOP13XX_ATUE_OUMBAR1); | ||
585 | |||
586 | /* Setup the I/O Bar | ||
587 | * A[35-16] in 31-12 | ||
588 | */ | ||
589 | __raw_writel(((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000), | ||
590 | IOP13XX_ATUE_OIOBAR); | ||
591 | __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR); | ||
592 | |||
593 | /* clear startup errors */ | ||
594 | iop13xx_atue_pci_status(1); | ||
595 | |||
596 | /* OIOBAR function number | ||
597 | */ | ||
598 | reg_val = __raw_readl(IOP13XX_ATUE_OIOBAR); | ||
599 | reg_val &= ~0x7; | ||
600 | reg_val |= func; | ||
601 | __raw_writel(reg_val, IOP13XX_ATUE_OIOBAR); | ||
602 | |||
603 | /* OUMBAR function numbers | ||
604 | */ | ||
605 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0); | ||
606 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
607 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
608 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
609 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0); | ||
610 | |||
611 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1); | ||
612 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
613 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
614 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
615 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1); | ||
616 | |||
617 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2); | ||
618 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
619 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
620 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
621 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2); | ||
622 | |||
623 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3); | ||
624 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
625 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
626 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
627 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3); | ||
628 | |||
629 | /* Enable inbound and outbound cycles | ||
630 | */ | ||
631 | reg_val = __raw_readw(IOP13XX_ATUE_ATUCMD); | ||
632 | reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | ||
633 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; | ||
634 | __raw_writew(reg_val, IOP13XX_ATUE_ATUCMD); | ||
635 | |||
636 | reg_val = __raw_readl(IOP13XX_ATUE_ATUCR); | ||
637 | reg_val |= IOP13XX_ATUE_ATUCR_OUT_EN | | ||
638 | IOP13XX_ATUE_ATUCR_IVM; | ||
639 | __raw_writel(reg_val, IOP13XX_ATUE_ATUCR); | ||
640 | } | ||
641 | |||
642 | void __init iop13xx_atue_disable(void) | ||
643 | { | ||
644 | u32 reg_val; | ||
645 | |||
646 | __raw_writew(0x0, IOP13XX_ATUE_ATUCMD); | ||
647 | __raw_writel(IOP13XX_ATUE_ATUCR_IVM, IOP13XX_ATUE_ATUCR); | ||
648 | |||
649 | /* wait for cycles to quiesce */ | ||
650 | while (__raw_readl(IOP13XX_ATUE_PCSR) & (IOP13XX_ATUE_PCSR_OUT_Q_BUSY | | ||
651 | IOP13XX_ATUE_PCSR_IN_Q_BUSY | | ||
652 | IOP13XX_ATUE_PCSR_LLRB_BUSY)) | ||
653 | cpu_relax(); | ||
654 | |||
655 | /* BAR 0 ( Disabled ) */ | ||
656 | __raw_writel(0x0, IOP13XX_ATUE_IAUBAR0); | ||
657 | __raw_writel(0x0, IOP13XX_ATUE_IABAR0); | ||
658 | __raw_writel(0x0, IOP13XX_ATUE_IAUTVR0); | ||
659 | __raw_writel(0x0, IOP13XX_ATUE_IATVR0); | ||
660 | __raw_writel(0x0, IOP13XX_ATUE_IALR0); | ||
661 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0); | ||
662 | reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; | ||
663 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0); | ||
664 | |||
665 | /* BAR 1 ( Disabled ) */ | ||
666 | __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1); | ||
667 | __raw_writel(0x0, IOP13XX_ATUE_IABAR1); | ||
668 | __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1); | ||
669 | __raw_writel(0x0, IOP13XX_ATUE_IATVR1); | ||
670 | __raw_writel(0x0, IOP13XX_ATUE_IALR1); | ||
671 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1); | ||
672 | reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; | ||
673 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1); | ||
674 | |||
675 | /* BAR 2 ( Disabled ) */ | ||
676 | __raw_writel(0x0, IOP13XX_ATUE_IAUBAR2); | ||
677 | __raw_writel(0x0, IOP13XX_ATUE_IABAR2); | ||
678 | __raw_writel(0x0, IOP13XX_ATUE_IAUTVR2); | ||
679 | __raw_writel(0x0, IOP13XX_ATUE_IATVR2); | ||
680 | __raw_writel(0x0, IOP13XX_ATUE_IALR2); | ||
681 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2); | ||
682 | reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; | ||
683 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2); | ||
684 | |||
685 | /* BAR 3 ( Disabled ) */ | ||
686 | reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3); | ||
687 | reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; | ||
688 | __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3); | ||
689 | |||
690 | /* Setup the I/O Bar | ||
691 | * A[35-16] in 31-12 | ||
692 | */ | ||
693 | __raw_writel((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000, | ||
694 | IOP13XX_ATUE_OIOBAR); | ||
695 | __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR); | ||
696 | } | ||
697 | |||
698 | /* This function is called from iop13xx_pci_init() after assigning valid | ||
699 | * values to iop13xx_atux_pmmr_offset. This is the location for common | ||
700 | * setup of ATUX for all IOP13XX implementations. | ||
701 | */ | ||
702 | void __init iop13xx_atux_setup(void) | ||
703 | { | ||
704 | u32 reg_val; | ||
705 | int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX); | ||
706 | |||
707 | /* Take PCI-X bus out of reset if bootloader hasn't already. | ||
708 | * According to spec, we should wait for 2^25 PCI clocks to meet | ||
709 | * the PCI timing parameter Trhfa (RST# high to first access). | ||
710 | * This is rarely necessary and often ignored. | ||
711 | */ | ||
712 | reg_val = __raw_readl(IOP13XX_ATUX_PCSR); | ||
713 | if (reg_val & IOP13XX_ATUX_PCSR_P_RSTOUT) { | ||
714 | int msec = (reg_val >> IOP13XX_ATUX_PCSR_FREQ_OFFSET) & 0x7; | ||
715 | msec = 1000 / (8-msec); /* bits 100=133MHz, 111=>33MHz */ | ||
716 | __raw_writel(reg_val & ~IOP13XX_ATUX_PCSR_P_RSTOUT, | ||
717 | IOP13XX_ATUX_PCSR); | ||
718 | atux_trhfa_timeout = jiffies + msecs_to_jiffies(msec); | ||
719 | } | ||
720 | else | ||
721 | atux_trhfa_timeout = jiffies; | ||
722 | |||
723 | /* BAR 1 (1:1 mapping with Physical RAM) */ | ||
724 | /* Set limit and enable */ | ||
725 | __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1, | ||
726 | IOP13XX_ATUX_IALR1); | ||
727 | __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1); | ||
728 | |||
729 | /* Set base at the top of the reserved address space */ | ||
730 | __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 | | ||
731 | PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUX_IABAR1); | ||
732 | |||
733 | /* 1:1 mapping with physical ram | ||
734 | * (leave big endian byte swap disabled) | ||
735 | */ | ||
736 | __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1); | ||
737 | __raw_writel(PHYS_OFFSET, IOP13XX_ATUX_IATVR1); | ||
738 | |||
739 | /* Outbound window 1 (PCIX/PCIE memory window) */ | ||
740 | /* 32 bit Address Space */ | ||
741 | __raw_writel(0x0, IOP13XX_ATUX_OUMWTVR1); | ||
742 | /* PA[35:32] */ | ||
743 | __raw_writel(IOP13XX_ATUX_OUMBAR_ENABLE | | ||
744 | IOP13XX_PCIX_MEM_PHYS_OFFSET >> 32, | ||
745 | IOP13XX_ATUX_OUMBAR1); | ||
746 | |||
747 | /* Setup the I/O Bar | ||
748 | * A[35-16] in 31-12 | ||
749 | */ | ||
750 | __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000, | ||
751 | IOP13XX_ATUX_OIOBAR); | ||
752 | __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR); | ||
753 | |||
754 | /* clear startup errors */ | ||
755 | iop13xx_atux_pci_status(1); | ||
756 | |||
757 | /* OIOBAR function number | ||
758 | */ | ||
759 | reg_val = __raw_readl(IOP13XX_ATUX_OIOBAR); | ||
760 | reg_val &= ~0x7; | ||
761 | reg_val |= func; | ||
762 | __raw_writel(reg_val, IOP13XX_ATUX_OIOBAR); | ||
763 | |||
764 | /* OUMBAR function numbers | ||
765 | */ | ||
766 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0); | ||
767 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
768 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
769 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
770 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0); | ||
771 | |||
772 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1); | ||
773 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
774 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
775 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
776 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1); | ||
777 | |||
778 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2); | ||
779 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
780 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
781 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
782 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2); | ||
783 | |||
784 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3); | ||
785 | reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << | ||
786 | IOP13XX_ATU_OUMBAR_FUNC_NUM); | ||
787 | reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; | ||
788 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3); | ||
789 | |||
790 | /* Enable inbound and outbound cycles | ||
791 | */ | ||
792 | reg_val = __raw_readw(IOP13XX_ATUX_ATUCMD); | ||
793 | reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | ||
794 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; | ||
795 | __raw_writew(reg_val, IOP13XX_ATUX_ATUCMD); | ||
796 | |||
797 | reg_val = __raw_readl(IOP13XX_ATUX_ATUCR); | ||
798 | reg_val |= IOP13XX_ATUX_ATUCR_OUT_EN; | ||
799 | __raw_writel(reg_val, IOP13XX_ATUX_ATUCR); | ||
800 | } | ||
801 | |||
802 | void __init iop13xx_atux_disable(void) | ||
803 | { | ||
804 | u32 reg_val; | ||
805 | |||
806 | __raw_writew(0x0, IOP13XX_ATUX_ATUCMD); | ||
807 | __raw_writel(0x0, IOP13XX_ATUX_ATUCR); | ||
808 | |||
809 | /* wait for cycles to quiesce */ | ||
810 | while (__raw_readl(IOP13XX_ATUX_PCSR) & (IOP13XX_ATUX_PCSR_OUT_Q_BUSY | | ||
811 | IOP13XX_ATUX_PCSR_IN_Q_BUSY)) | ||
812 | cpu_relax(); | ||
813 | |||
814 | /* BAR 0 ( Disabled ) */ | ||
815 | __raw_writel(0x0, IOP13XX_ATUX_IAUBAR0); | ||
816 | __raw_writel(0x0, IOP13XX_ATUX_IABAR0); | ||
817 | __raw_writel(0x0, IOP13XX_ATUX_IAUTVR0); | ||
818 | __raw_writel(0x0, IOP13XX_ATUX_IATVR0); | ||
819 | __raw_writel(0x0, IOP13XX_ATUX_IALR0); | ||
820 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0); | ||
821 | reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; | ||
822 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0); | ||
823 | |||
824 | /* BAR 1 ( Disabled ) */ | ||
825 | __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1); | ||
826 | __raw_writel(0x0, IOP13XX_ATUX_IABAR1); | ||
827 | __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1); | ||
828 | __raw_writel(0x0, IOP13XX_ATUX_IATVR1); | ||
829 | __raw_writel(0x0, IOP13XX_ATUX_IALR1); | ||
830 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1); | ||
831 | reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; | ||
832 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1); | ||
833 | |||
834 | /* BAR 2 ( Disabled ) */ | ||
835 | __raw_writel(0x0, IOP13XX_ATUX_IAUBAR2); | ||
836 | __raw_writel(0x0, IOP13XX_ATUX_IABAR2); | ||
837 | __raw_writel(0x0, IOP13XX_ATUX_IAUTVR2); | ||
838 | __raw_writel(0x0, IOP13XX_ATUX_IATVR2); | ||
839 | __raw_writel(0x0, IOP13XX_ATUX_IALR2); | ||
840 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2); | ||
841 | reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; | ||
842 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2); | ||
843 | |||
844 | /* BAR 3 ( Disabled ) */ | ||
845 | __raw_writel(0x0, IOP13XX_ATUX_IAUBAR3); | ||
846 | __raw_writel(0x0, IOP13XX_ATUX_IABAR3); | ||
847 | __raw_writel(0x0, IOP13XX_ATUX_IAUTVR3); | ||
848 | __raw_writel(0x0, IOP13XX_ATUX_IATVR3); | ||
849 | __raw_writel(0x0, IOP13XX_ATUX_IALR3); | ||
850 | reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3); | ||
851 | reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; | ||
852 | __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3); | ||
853 | |||
854 | /* Setup the I/O Bar | ||
855 | * A[35-16] in 31-12 | ||
856 | */ | ||
857 | __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000, | ||
858 | IOP13XX_ATUX_OIOBAR); | ||
859 | __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR); | ||
860 | } | ||
861 | |||
862 | void __init iop13xx_set_atu_mmr_bases(void) | ||
863 | { | ||
864 | /* Based on ESSR0, determine the ATU X/E offsets */ | ||
865 | switch(__raw_readl(IOP13XX_ESSR0) & | ||
866 | (IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX)) { | ||
867 | /* both asserted */ | ||
868 | case 0: | ||
869 | iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET; | ||
870 | iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; | ||
871 | break; | ||
872 | /* IOP13XX_CONTROLLER_ONLY = deasserted | ||
873 | * IOP13XX_INTERFACE_SEL_PCIX = asserted | ||
874 | */ | ||
875 | case IOP13XX_CONTROLLER_ONLY: | ||
876 | iop13xx_atux_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET; | ||
877 | iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; | ||
878 | break; | ||
879 | /* IOP13XX_CONTROLLER_ONLY = asserted | ||
880 | * IOP13XX_INTERFACE_SEL_PCIX = deasserted | ||
881 | */ | ||
882 | case IOP13XX_INTERFACE_SEL_PCIX: | ||
883 | iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET; | ||
884 | iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; | ||
885 | break; | ||
886 | /* both deasserted */ | ||
887 | case IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX: | ||
888 | iop13xx_atux_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; | ||
889 | iop13xx_atue_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET; | ||
890 | break; | ||
891 | default: | ||
892 | BUG(); | ||
893 | } | ||
894 | } | ||
895 | |||
896 | void __init iop13xx_atu_select(struct hw_pci *plat_pci) | ||
897 | { | ||
898 | int i; | ||
899 | |||
900 | /* set system defaults | ||
901 | * note: if "iop13xx_init_atu=" is specified this autodetect | ||
902 | * sequence will be bypassed | ||
903 | */ | ||
904 | if (init_atu == IOP13XX_INIT_ATU_DEFAULT) { | ||
905 | /* check for single/dual interface */ | ||
906 | if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) { | ||
907 | /* ATUE must be present check the device id | ||
908 | * to see if ATUX is present. | ||
909 | */ | ||
910 | init_atu |= IOP13XX_INIT_ATU_ATUE; | ||
911 | switch (__raw_readw(IOP13XX_ATUE_DID) & 0xf0) { | ||
912 | case 0x70: | ||
913 | case 0x80: | ||
914 | case 0xc0: | ||
915 | init_atu |= IOP13XX_INIT_ATU_ATUX; | ||
916 | break; | ||
917 | } | ||
918 | } else { | ||
919 | /* ATUX must be present check the device id | ||
920 | * to see if ATUE is present. | ||
921 | */ | ||
922 | init_atu |= IOP13XX_INIT_ATU_ATUX; | ||
923 | switch (__raw_readw(IOP13XX_ATUX_DID) & 0xf0) { | ||
924 | case 0x70: | ||
925 | case 0x80: | ||
926 | case 0xc0: | ||
927 | init_atu |= IOP13XX_INIT_ATU_ATUE; | ||
928 | break; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | /* check central resource and root complex capability */ | ||
933 | if (init_atu & IOP13XX_INIT_ATU_ATUX) | ||
934 | if (!(__raw_readl(IOP13XX_ATUX_PCSR) & | ||
935 | IOP13XX_ATUX_PCSR_CENTRAL_RES)) | ||
936 | init_atu &= ~IOP13XX_INIT_ATU_ATUX; | ||
937 | |||
938 | if (init_atu & IOP13XX_INIT_ATU_ATUE) | ||
939 | if (__raw_readl(IOP13XX_ATUE_PCSR) & | ||
940 | IOP13XX_ATUE_PCSR_END_POINT) | ||
941 | init_atu &= ~IOP13XX_INIT_ATU_ATUE; | ||
942 | } | ||
943 | |||
944 | for (i = 0; i < 2; i++) { | ||
945 | if((init_atu & (1 << i)) == (1 << i)) | ||
946 | plat_pci->nr_controllers++; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | void __init iop13xx_pci_init(void) | ||
951 | { | ||
952 | /* clear pre-existing south bridge errors */ | ||
953 | __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR); | ||
954 | |||
955 | /* Setup the Min Address for PCI memory... */ | ||
956 | iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA; | ||
957 | |||
958 | /* if Linux is given control of an ATU | ||
959 | * clear out its prior configuration, | ||
960 | * otherwise do not touch the registers | ||
961 | */ | ||
962 | if (init_atu & IOP13XX_INIT_ATU_ATUE) { | ||
963 | iop13xx_atue_disable(); | ||
964 | iop13xx_atue_setup(); | ||
965 | } | ||
966 | |||
967 | if (init_atu & IOP13XX_INIT_ATU_ATUX) { | ||
968 | iop13xx_atux_disable(); | ||
969 | iop13xx_atux_setup(); | ||
970 | } | ||
971 | |||
972 | hook_fault_code(16+6, iop13xx_pci_abort, SIGBUS, | ||
973 | "imprecise external abort"); | ||
974 | } | ||
975 | |||
976 | /* intialize the pci memory space. handle any combination of | ||
977 | * atue and atux enabled/disabled | ||
978 | */ | ||
979 | int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) | ||
980 | { | ||
981 | struct resource *res; | ||
982 | int which_atu; | ||
983 | u32 pcixsr, pcsr; | ||
984 | |||
985 | if (nr > 1) | ||
986 | return 0; | ||
987 | |||
988 | res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL); | ||
989 | if (!res) | ||
990 | panic("PCI: unable to alloc resources"); | ||
991 | |||
992 | memset(res, 0, sizeof(struct resource) * 2); | ||
993 | |||
994 | /* 'nr' assumptions: | ||
995 | * ATUX is always 0 | ||
996 | * ATUE is 1 when ATUX is also enabled | ||
997 | * ATUE is 0 when ATUX is disabled | ||
998 | */ | ||
999 | switch(init_atu) { | ||
1000 | case IOP13XX_INIT_ATU_ATUX: | ||
1001 | which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX; | ||
1002 | break; | ||
1003 | case IOP13XX_INIT_ATU_ATUE: | ||
1004 | which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE; | ||
1005 | break; | ||
1006 | case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE): | ||
1007 | which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX; | ||
1008 | break; | ||
1009 | default: | ||
1010 | which_atu = 0; | ||
1011 | } | ||
1012 | |||
1013 | if (!which_atu) | ||
1014 | return 0; | ||
1015 | |||
1016 | switch(which_atu) { | ||
1017 | case IOP13XX_INIT_ATU_ATUX: | ||
1018 | pcixsr = __raw_readl(IOP13XX_ATUX_PCIXSR); | ||
1019 | pcixsr &= ~0xffff; | ||
1020 | pcixsr |= sys->busnr << IOP13XX_ATUX_PCIXSR_BUS_NUM | | ||
1021 | 0 << IOP13XX_ATUX_PCIXSR_DEV_NUM | | ||
1022 | iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX) | ||
1023 | << IOP13XX_ATUX_PCIXSR_FUNC_NUM; | ||
1024 | __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR); | ||
1025 | |||
1026 | res[0].start = IOP13XX_PCIX_LOWER_IO_PA; | ||
1027 | res[0].end = IOP13XX_PCIX_UPPER_IO_PA; | ||
1028 | res[0].name = "IQ81340 ATUX PCI I/O Space"; | ||
1029 | res[0].flags = IORESOURCE_IO; | ||
1030 | |||
1031 | res[1].start = IOP13XX_PCIX_LOWER_MEM_RA; | ||
1032 | res[1].end = IOP13XX_PCIX_UPPER_MEM_RA; | ||
1033 | res[1].name = "IQ81340 ATUX PCI Memory Space"; | ||
1034 | res[1].flags = IORESOURCE_MEM; | ||
1035 | sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET; | ||
1036 | sys->io_offset = IOP13XX_PCIX_IO_OFFSET; | ||
1037 | break; | ||
1038 | case IOP13XX_INIT_ATU_ATUE: | ||
1039 | /* Note: the function number field in the PCSR is ro */ | ||
1040 | pcsr = __raw_readl(IOP13XX_ATUE_PCSR); | ||
1041 | pcsr &= ~(0xfff8 << 16); | ||
1042 | pcsr |= sys->busnr << IOP13XX_ATUE_PCSR_BUS_NUM | | ||
1043 | 0 << IOP13XX_ATUE_PCSR_DEV_NUM; | ||
1044 | |||
1045 | __raw_writel(pcsr, IOP13XX_ATUE_PCSR); | ||
1046 | |||
1047 | res[0].start = IOP13XX_PCIE_LOWER_IO_PA; | ||
1048 | res[0].end = IOP13XX_PCIE_UPPER_IO_PA; | ||
1049 | res[0].name = "IQ81340 ATUE PCI I/O Space"; | ||
1050 | res[0].flags = IORESOURCE_IO; | ||
1051 | |||
1052 | res[1].start = IOP13XX_PCIE_LOWER_MEM_RA; | ||
1053 | res[1].end = IOP13XX_PCIE_UPPER_MEM_RA; | ||
1054 | res[1].name = "IQ81340 ATUE PCI Memory Space"; | ||
1055 | res[1].flags = IORESOURCE_MEM; | ||
1056 | sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET; | ||
1057 | sys->io_offset = IOP13XX_PCIE_IO_OFFSET; | ||
1058 | sys->map_irq = iop13xx_pcie_map_irq; | ||
1059 | break; | ||
1060 | default: | ||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1064 | request_resource(&ioport_resource, &res[0]); | ||
1065 | request_resource(&iomem_resource, &res[1]); | ||
1066 | |||
1067 | sys->resource[0] = &res[0]; | ||
1068 | sys->resource[1] = &res[1]; | ||
1069 | sys->resource[2] = NULL; | ||
1070 | |||
1071 | return 1; | ||
1072 | } | ||
1073 | |||
1074 | u16 iop13xx_dev_id(void) | ||
1075 | { | ||
1076 | if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) | ||
1077 | return __raw_readw(IOP13XX_ATUE_DID); | ||
1078 | else | ||
1079 | return __raw_readw(IOP13XX_ATUX_DID); | ||
1080 | } | ||
1081 | |||
1082 | static int __init iop13xx_init_atu_setup(char *str) | ||
1083 | { | ||
1084 | init_atu = IOP13XX_INIT_ATU_NONE; | ||
1085 | if (str) { | ||
1086 | while (*str != '\0') { | ||
1087 | switch (*str) { | ||
1088 | case 'x': | ||
1089 | case 'X': | ||
1090 | init_atu |= IOP13XX_INIT_ATU_ATUX; | ||
1091 | init_atu &= ~IOP13XX_INIT_ATU_NONE; | ||
1092 | break; | ||
1093 | case 'e': | ||
1094 | case 'E': | ||
1095 | init_atu |= IOP13XX_INIT_ATU_ATUE; | ||
1096 | init_atu &= ~IOP13XX_INIT_ATU_NONE; | ||
1097 | break; | ||
1098 | case ',': | ||
1099 | case '=': | ||
1100 | break; | ||
1101 | default: | ||
1102 | PRINTK("\"iop13xx_init_atu\" malformed at " | ||
1103 | "character: \'%c\'", *str); | ||
1104 | *(str + 1) = '\0'; | ||
1105 | init_atu = IOP13XX_INIT_ATU_DEFAULT; | ||
1106 | } | ||
1107 | str++; | ||
1108 | } | ||
1109 | } | ||
1110 | return 1; | ||
1111 | } | ||
1112 | |||
1113 | __setup("iop13xx_init_atu", iop13xx_init_atu_setup); | ||
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c new file mode 100644 index 000000000000..3756d2ccb1a7 --- /dev/null +++ b/arch/arm/mach-iop13xx/setup.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* | ||
2 | * iop13xx platform Initialization | ||
3 | * Copyright (c) 2005-2006, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
16 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/serial_8250.h> | ||
21 | #ifdef CONFIG_MTD_PHYSMAP | ||
22 | #include <linux/mtd/physmap.h> | ||
23 | #endif | ||
24 | #include <asm/mach/map.h> | ||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/irq.h> | ||
27 | |||
28 | #define IOP13XX_UART_XTAL 33334000 | ||
29 | #define IOP13XX_SETUP_DEBUG 0 | ||
30 | #define PRINTK(x...) ((void)(IOP13XX_SETUP_DEBUG && printk(x))) | ||
31 | |||
32 | /* Standard IO mapping for all IOP13XX based systems | ||
33 | */ | ||
34 | static struct map_desc iop13xx_std_desc[] __initdata = { | ||
35 | { /* mem mapped registers */ | ||
36 | .virtual = IOP13XX_PMMR_VIRT_MEM_BASE, | ||
37 | .pfn = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE), | ||
38 | .length = IOP13XX_PMMR_SIZE, | ||
39 | .type = MT_DEVICE, | ||
40 | }, { /* PCIE IO space */ | ||
41 | .virtual = IOP13XX_PCIE_LOWER_IO_VA, | ||
42 | .pfn = __phys_to_pfn(IOP13XX_PCIE_LOWER_IO_PA), | ||
43 | .length = IOP13XX_PCIX_IO_WINDOW_SIZE, | ||
44 | .type = MT_DEVICE, | ||
45 | }, { /* PCIX IO space */ | ||
46 | .virtual = IOP13XX_PCIX_LOWER_IO_VA, | ||
47 | .pfn = __phys_to_pfn(IOP13XX_PCIX_LOWER_IO_PA), | ||
48 | .length = IOP13XX_PCIX_IO_WINDOW_SIZE, | ||
49 | .type = MT_DEVICE, | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | static struct resource iop13xx_uart0_resources[] = { | ||
54 | [0] = { | ||
55 | .start = IOP13XX_UART0_PHYS, | ||
56 | .end = IOP13XX_UART0_PHYS + 0x3f, | ||
57 | .flags = IORESOURCE_MEM, | ||
58 | }, | ||
59 | [1] = { | ||
60 | .start = IRQ_IOP13XX_UART0, | ||
61 | .end = IRQ_IOP13XX_UART0, | ||
62 | .flags = IORESOURCE_IRQ | ||
63 | } | ||
64 | }; | ||
65 | |||
66 | static struct resource iop13xx_uart1_resources[] = { | ||
67 | [0] = { | ||
68 | .start = IOP13XX_UART1_PHYS, | ||
69 | .end = IOP13XX_UART1_PHYS + 0x3f, | ||
70 | .flags = IORESOURCE_MEM, | ||
71 | }, | ||
72 | [1] = { | ||
73 | .start = IRQ_IOP13XX_UART1, | ||
74 | .end = IRQ_IOP13XX_UART1, | ||
75 | .flags = IORESOURCE_IRQ | ||
76 | } | ||
77 | }; | ||
78 | |||
79 | static struct plat_serial8250_port iop13xx_uart0_data[] = { | ||
80 | { | ||
81 | .membase = (char*)(IOP13XX_UART0_VIRT), | ||
82 | .mapbase = (IOP13XX_UART0_PHYS), | ||
83 | .irq = IRQ_IOP13XX_UART0, | ||
84 | .uartclk = IOP13XX_UART_XTAL, | ||
85 | .regshift = 2, | ||
86 | .iotype = UPIO_MEM, | ||
87 | .flags = UPF_SKIP_TEST, | ||
88 | }, | ||
89 | { }, | ||
90 | }; | ||
91 | |||
92 | static struct plat_serial8250_port iop13xx_uart1_data[] = { | ||
93 | { | ||
94 | .membase = (char*)(IOP13XX_UART1_VIRT), | ||
95 | .mapbase = (IOP13XX_UART1_PHYS), | ||
96 | .irq = IRQ_IOP13XX_UART1, | ||
97 | .uartclk = IOP13XX_UART_XTAL, | ||
98 | .regshift = 2, | ||
99 | .iotype = UPIO_MEM, | ||
100 | .flags = UPF_SKIP_TEST, | ||
101 | }, | ||
102 | { }, | ||
103 | }; | ||
104 | |||
105 | /* The ids are fixed up later in iop13xx_platform_init */ | ||
106 | static struct platform_device iop13xx_uart0 = { | ||
107 | .name = "serial8250", | ||
108 | .id = 0, | ||
109 | .dev.platform_data = iop13xx_uart0_data, | ||
110 | .num_resources = 2, | ||
111 | .resource = iop13xx_uart0_resources, | ||
112 | }; | ||
113 | |||
114 | static struct platform_device iop13xx_uart1 = { | ||
115 | .name = "serial8250", | ||
116 | .id = 0, | ||
117 | .dev.platform_data = iop13xx_uart1_data, | ||
118 | .num_resources = 2, | ||
119 | .resource = iop13xx_uart1_resources | ||
120 | }; | ||
121 | |||
122 | static struct resource iop13xx_i2c_0_resources[] = { | ||
123 | [0] = { | ||
124 | .start = IOP13XX_I2C0_PHYS, | ||
125 | .end = IOP13XX_I2C0_PHYS + 0x18, | ||
126 | .flags = IORESOURCE_MEM, | ||
127 | }, | ||
128 | [1] = { | ||
129 | .start = IRQ_IOP13XX_I2C_0, | ||
130 | .end = IRQ_IOP13XX_I2C_0, | ||
131 | .flags = IORESOURCE_IRQ | ||
132 | } | ||
133 | }; | ||
134 | |||
135 | static struct resource iop13xx_i2c_1_resources[] = { | ||
136 | [0] = { | ||
137 | .start = IOP13XX_I2C1_PHYS, | ||
138 | .end = IOP13XX_I2C1_PHYS + 0x18, | ||
139 | .flags = IORESOURCE_MEM, | ||
140 | }, | ||
141 | [1] = { | ||
142 | .start = IRQ_IOP13XX_I2C_1, | ||
143 | .end = IRQ_IOP13XX_I2C_1, | ||
144 | .flags = IORESOURCE_IRQ | ||
145 | } | ||
146 | }; | ||
147 | |||
148 | static struct resource iop13xx_i2c_2_resources[] = { | ||
149 | [0] = { | ||
150 | .start = IOP13XX_I2C2_PHYS, | ||
151 | .end = IOP13XX_I2C2_PHYS + 0x18, | ||
152 | .flags = IORESOURCE_MEM, | ||
153 | }, | ||
154 | [1] = { | ||
155 | .start = IRQ_IOP13XX_I2C_2, | ||
156 | .end = IRQ_IOP13XX_I2C_2, | ||
157 | .flags = IORESOURCE_IRQ | ||
158 | } | ||
159 | }; | ||
160 | |||
161 | /* I2C controllers. The IOP13XX uses the same block as the IOP3xx, so | ||
162 | * we just use the same device name. | ||
163 | */ | ||
164 | |||
165 | /* The ids are fixed up later in iop13xx_platform_init */ | ||
166 | static struct platform_device iop13xx_i2c_0_controller = { | ||
167 | .name = "IOP3xx-I2C", | ||
168 | .id = 0, | ||
169 | .num_resources = 2, | ||
170 | .resource = iop13xx_i2c_0_resources | ||
171 | }; | ||
172 | |||
173 | static struct platform_device iop13xx_i2c_1_controller = { | ||
174 | .name = "IOP3xx-I2C", | ||
175 | .id = 0, | ||
176 | .num_resources = 2, | ||
177 | .resource = iop13xx_i2c_1_resources | ||
178 | }; | ||
179 | |||
180 | static struct platform_device iop13xx_i2c_2_controller = { | ||
181 | .name = "IOP3xx-I2C", | ||
182 | .id = 0, | ||
183 | .num_resources = 2, | ||
184 | .resource = iop13xx_i2c_2_resources | ||
185 | }; | ||
186 | |||
187 | #ifdef CONFIG_MTD_PHYSMAP | ||
188 | /* PBI Flash Device | ||
189 | */ | ||
190 | static struct physmap_flash_data iq8134x_flash_data = { | ||
191 | .width = 2, | ||
192 | }; | ||
193 | |||
194 | static struct resource iq8134x_flash_resource = { | ||
195 | .start = IQ81340_FLASHBASE, | ||
196 | .end = 0, | ||
197 | .flags = IORESOURCE_MEM, | ||
198 | }; | ||
199 | |||
200 | static struct platform_device iq8134x_flash = { | ||
201 | .name = "physmap-flash", | ||
202 | .id = 0, | ||
203 | .dev = { .platform_data = &iq8134x_flash_data, }, | ||
204 | .num_resources = 1, | ||
205 | .resource = &iq8134x_flash_resource, | ||
206 | }; | ||
207 | |||
208 | static unsigned long iq8134x_probe_flash_size(void) | ||
209 | { | ||
210 | uint8_t __iomem *flash_addr = ioremap(IQ81340_FLASHBASE, PAGE_SIZE); | ||
211 | int i; | ||
212 | char query[3]; | ||
213 | unsigned long size = 0; | ||
214 | int width = iq8134x_flash_data.width; | ||
215 | |||
216 | if (flash_addr) { | ||
217 | /* send CFI 'query' command */ | ||
218 | writew(0x98, flash_addr); | ||
219 | |||
220 | /* check for CFI compliance */ | ||
221 | for (i = 0; i < 3 * width; i += width) | ||
222 | query[i / width] = readb(flash_addr + (0x10 * width) + i); | ||
223 | |||
224 | /* read the size */ | ||
225 | if (memcmp(query, "QRY", 3) == 0) | ||
226 | size = 1 << readb(flash_addr + (0x27 * width)); | ||
227 | |||
228 | /* send CFI 'read array' command */ | ||
229 | writew(0xff, flash_addr); | ||
230 | |||
231 | iounmap(flash_addr); | ||
232 | } | ||
233 | |||
234 | return size; | ||
235 | } | ||
236 | #endif | ||
237 | |||
238 | void __init iop13xx_map_io(void) | ||
239 | { | ||
240 | /* Initialize the Static Page Table maps */ | ||
241 | iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc)); | ||
242 | } | ||
243 | |||
244 | static int init_uart = 0; | ||
245 | static int init_i2c = 0; | ||
246 | |||
247 | void __init iop13xx_platform_init(void) | ||
248 | { | ||
249 | int i; | ||
250 | u32 uart_idx, i2c_idx, plat_idx; | ||
251 | struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES]; | ||
252 | |||
253 | /* set the bases so we can read the device id */ | ||
254 | iop13xx_set_atu_mmr_bases(); | ||
255 | |||
256 | memset(iop13xx_devices, 0, sizeof(iop13xx_devices)); | ||
257 | |||
258 | if (init_uart == IOP13XX_INIT_UART_DEFAULT) { | ||
259 | switch (iop13xx_dev_id()) { | ||
260 | /* enable both uarts on iop341 and iop342 */ | ||
261 | case 0x3380: | ||
262 | case 0x3384: | ||
263 | case 0x3388: | ||
264 | case 0x338c: | ||
265 | case 0x3382: | ||
266 | case 0x3386: | ||
267 | case 0x338a: | ||
268 | case 0x338e: | ||
269 | init_uart |= IOP13XX_INIT_UART_0; | ||
270 | init_uart |= IOP13XX_INIT_UART_1; | ||
271 | break; | ||
272 | /* only enable uart 1 */ | ||
273 | default: | ||
274 | init_uart |= IOP13XX_INIT_UART_1; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | if (init_i2c == IOP13XX_INIT_I2C_DEFAULT) { | ||
279 | switch (iop13xx_dev_id()) { | ||
280 | /* enable all i2c units on iop341 and iop342 */ | ||
281 | case 0x3380: | ||
282 | case 0x3384: | ||
283 | case 0x3388: | ||
284 | case 0x338c: | ||
285 | case 0x3382: | ||
286 | case 0x3386: | ||
287 | case 0x338a: | ||
288 | case 0x338e: | ||
289 | init_i2c |= IOP13XX_INIT_I2C_0; | ||
290 | init_i2c |= IOP13XX_INIT_I2C_1; | ||
291 | init_i2c |= IOP13XX_INIT_I2C_2; | ||
292 | break; | ||
293 | /* only enable i2c 1 and 2 */ | ||
294 | default: | ||
295 | init_i2c |= IOP13XX_INIT_I2C_1; | ||
296 | init_i2c |= IOP13XX_INIT_I2C_2; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | plat_idx = 0; | ||
301 | uart_idx = 0; | ||
302 | i2c_idx = 0; | ||
303 | |||
304 | /* uart 1 (if enabled) is ttyS0 */ | ||
305 | if (init_uart & IOP13XX_INIT_UART_1) { | ||
306 | PRINTK("Adding uart1 to platform device list\n"); | ||
307 | iop13xx_uart1.id = uart_idx++; | ||
308 | iop13xx_devices[plat_idx++] = &iop13xx_uart1; | ||
309 | } | ||
310 | if (init_uart & IOP13XX_INIT_UART_0) { | ||
311 | PRINTK("Adding uart0 to platform device list\n"); | ||
312 | iop13xx_uart0.id = uart_idx++; | ||
313 | iop13xx_devices[plat_idx++] = &iop13xx_uart0; | ||
314 | } | ||
315 | |||
316 | for(i = 0; i < IQ81340_NUM_I2C; i++) { | ||
317 | if ((init_i2c & (1 << i)) && IOP13XX_SETUP_DEBUG) | ||
318 | printk("Adding i2c%d to platform device list\n", i); | ||
319 | switch(init_i2c & (1 << i)) { | ||
320 | case IOP13XX_INIT_I2C_0: | ||
321 | iop13xx_i2c_0_controller.id = i2c_idx++; | ||
322 | iop13xx_devices[plat_idx++] = | ||
323 | &iop13xx_i2c_0_controller; | ||
324 | break; | ||
325 | case IOP13XX_INIT_I2C_1: | ||
326 | iop13xx_i2c_1_controller.id = i2c_idx++; | ||
327 | iop13xx_devices[plat_idx++] = | ||
328 | &iop13xx_i2c_1_controller; | ||
329 | break; | ||
330 | case IOP13XX_INIT_I2C_2: | ||
331 | iop13xx_i2c_2_controller.id = i2c_idx++; | ||
332 | iop13xx_devices[plat_idx++] = | ||
333 | &iop13xx_i2c_2_controller; | ||
334 | break; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | #ifdef CONFIG_MTD_PHYSMAP | ||
339 | iq8134x_flash_resource.end = iq8134x_flash_resource.start + | ||
340 | iq8134x_probe_flash_size(); | ||
341 | if (iq8134x_flash_resource.end > iq8134x_flash_resource.start) | ||
342 | iop13xx_devices[plat_idx++] = &iq8134x_flash; | ||
343 | else | ||
344 | printk(KERN_ERR "%s: Failed to probe flash size\n", __FUNCTION__); | ||
345 | #endif | ||
346 | |||
347 | platform_add_devices(iop13xx_devices, plat_idx); | ||
348 | } | ||
349 | |||
350 | static int __init iop13xx_init_uart_setup(char *str) | ||
351 | { | ||
352 | if (str) { | ||
353 | while (*str != '\0') { | ||
354 | switch(*str) { | ||
355 | case '0': | ||
356 | init_uart |= IOP13XX_INIT_UART_0; | ||
357 | break; | ||
358 | case '1': | ||
359 | init_uart |= IOP13XX_INIT_UART_1; | ||
360 | break; | ||
361 | case ',': | ||
362 | case '=': | ||
363 | break; | ||
364 | default: | ||
365 | PRINTK("\"iop13xx_init_uart\" malformed" | ||
366 | " at character: \'%c\'", *str); | ||
367 | *(str + 1) = '\0'; | ||
368 | init_uart = IOP13XX_INIT_UART_DEFAULT; | ||
369 | } | ||
370 | str++; | ||
371 | } | ||
372 | } | ||
373 | return 1; | ||
374 | } | ||
375 | |||
376 | static int __init iop13xx_init_i2c_setup(char *str) | ||
377 | { | ||
378 | if (str) { | ||
379 | while (*str != '\0') { | ||
380 | switch(*str) { | ||
381 | case '0': | ||
382 | init_i2c |= IOP13XX_INIT_I2C_0; | ||
383 | break; | ||
384 | case '1': | ||
385 | init_i2c |= IOP13XX_INIT_I2C_1; | ||
386 | break; | ||
387 | case '2': | ||
388 | init_i2c |= IOP13XX_INIT_I2C_2; | ||
389 | break; | ||
390 | case ',': | ||
391 | case '=': | ||
392 | break; | ||
393 | default: | ||
394 | PRINTK("\"iop13xx_init_i2c\" malformed" | ||
395 | " at character: \'%c\'", *str); | ||
396 | *(str + 1) = '\0'; | ||
397 | init_i2c = IOP13XX_INIT_I2C_DEFAULT; | ||
398 | } | ||
399 | str++; | ||
400 | } | ||
401 | } | ||
402 | return 1; | ||
403 | } | ||
404 | |||
405 | __setup("iop13xx_init_uart", iop13xx_init_uart_setup); | ||
406 | __setup("iop13xx_init_i2c", iop13xx_init_i2c_setup); | ||
diff --git a/arch/arm/mach-iop13xx/time.c b/arch/arm/mach-iop13xx/time.c new file mode 100644 index 000000000000..8b21365f653f --- /dev/null +++ b/arch/arm/mach-iop13xx/time.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-iop13xx/time.c | ||
3 | * | ||
4 | * Timer code for IOP13xx (copied from IOP32x/IOP33x implementation) | ||
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 | #include <asm/io.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/mach/irq.h> | ||
25 | #include <asm/mach/time.h> | ||
26 | |||
27 | static unsigned long ticks_per_jiffy; | ||
28 | static unsigned long ticks_per_usec; | ||
29 | static unsigned long next_jiffy_time; | ||
30 | |||
31 | static inline u32 read_tcr1(void) | ||
32 | { | ||
33 | u32 val; | ||
34 | asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val)); | ||
35 | return val; | ||
36 | } | ||
37 | |||
38 | unsigned long iop13xx_gettimeoffset(void) | ||
39 | { | ||
40 | unsigned long offset; | ||
41 | u32 cp_flags; | ||
42 | |||
43 | cp_flags = iop13xx_cp6_save(); | ||
44 | offset = next_jiffy_time - read_tcr1(); | ||
45 | iop13xx_cp6_restore(cp_flags); | ||
46 | |||
47 | return offset / ticks_per_usec; | ||
48 | } | ||
49 | |||
50 | static irqreturn_t | ||
51 | iop13xx_timer_interrupt(int irq, void *dev_id) | ||
52 | { | ||
53 | u32 cp_flags = iop13xx_cp6_save(); | ||
54 | |||
55 | write_seqlock(&xtime_lock); | ||
56 | |||
57 | asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (1)); | ||
58 | |||
59 | while ((signed long)(next_jiffy_time - read_tcr1()) | ||
60 | >= ticks_per_jiffy) { | ||
61 | timer_tick(); | ||
62 | next_jiffy_time -= ticks_per_jiffy; | ||
63 | } | ||
64 | |||
65 | write_sequnlock(&xtime_lock); | ||
66 | |||
67 | iop13xx_cp6_restore(cp_flags); | ||
68 | |||
69 | return IRQ_HANDLED; | ||
70 | } | ||
71 | |||
72 | static struct irqaction iop13xx_timer_irq = { | ||
73 | .name = "IOP13XX Timer Tick", | ||
74 | .handler = iop13xx_timer_interrupt, | ||
75 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
76 | }; | ||
77 | |||
78 | void __init iop13xx_init_time(unsigned long tick_rate) | ||
79 | { | ||
80 | u32 timer_ctl; | ||
81 | u32 cp_flags; | ||
82 | |||
83 | ticks_per_jiffy = (tick_rate + HZ/2) / HZ; | ||
84 | ticks_per_usec = tick_rate / 1000000; | ||
85 | next_jiffy_time = 0xffffffff; | ||
86 | |||
87 | timer_ctl = IOP13XX_TMR_EN | IOP13XX_TMR_PRIVILEGED | | ||
88 | IOP13XX_TMR_RELOAD | IOP13XX_TMR_RATIO_1_1; | ||
89 | |||
90 | /* | ||
91 | * We use timer 0 for our timer interrupt, and timer 1 as | ||
92 | * monotonic counter for tracking missed jiffies. | ||
93 | */ | ||
94 | cp_flags = iop13xx_cp6_save(); | ||
95 | asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (ticks_per_jiffy - 1)); | ||
96 | asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (timer_ctl)); | ||
97 | asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (0xffffffff)); | ||
98 | asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (timer_ctl)); | ||
99 | iop13xx_cp6_restore(cp_flags); | ||
100 | |||
101 | setup_irq(IRQ_IOP13XX_TIMER0, &iop13xx_timer_irq); | ||
102 | } | ||