diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/platforms | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'arch/powerpc/platforms')
162 files changed, 6213 insertions, 3430 deletions
diff --git a/arch/powerpc/platforms/4xx/Kconfig b/arch/powerpc/platforms/40x/Kconfig index ded357c17414..47b3b0a3864a 100644 --- a/arch/powerpc/platforms/4xx/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig | |||
@@ -1,16 +1,3 @@ | |||
1 | config 4xx | ||
2 | bool | ||
3 | depends on 40x || 44x | ||
4 | default y | ||
5 | |||
6 | config BOOKE | ||
7 | bool | ||
8 | depends on 44x | ||
9 | default y | ||
10 | |||
11 | menu "AMCC 40x options" | ||
12 | depends on 40x | ||
13 | |||
14 | #config BUBINGA | 1 | #config BUBINGA |
15 | # bool "Bubinga" | 2 | # bool "Bubinga" |
16 | # depends on 40x | 3 | # depends on 40x |
@@ -42,6 +29,13 @@ menu "AMCC 40x options" | |||
42 | # help | 29 | # help |
43 | # This option enables support for the extra features of the EP405PC board. | 30 | # This option enables support for the extra features of the EP405PC board. |
44 | 31 | ||
32 | config KILAUEA | ||
33 | bool "Kilauea" | ||
34 | depends on 40x | ||
35 | default n | ||
36 | help | ||
37 | This option enables support for the AMCC PPC405EX evaluation board. | ||
38 | |||
45 | #config REDWOOD_5 | 39 | #config REDWOOD_5 |
46 | # bool "Redwood-5" | 40 | # bool "Redwood-5" |
47 | # depends on 40x | 41 | # depends on 40x |
@@ -66,23 +60,30 @@ menu "AMCC 40x options" | |||
66 | # help | 60 | # help |
67 | # This option enables support for the IBM PPC405GPr evaluation board. | 61 | # This option enables support for the IBM PPC405GPr evaluation board. |
68 | 62 | ||
69 | #config WALNUT | 63 | config WALNUT |
70 | # bool "Walnut" | 64 | bool "Walnut" |
71 | # depends on 40x | 65 | depends on 40x |
72 | # default y | 66 | default y |
73 | # select 405GP | 67 | select 405GP |
74 | # help | 68 | help |
75 | # This option enables support for the IBM PPC405GP evaluation board. | 69 | This option enables support for the IBM PPC405GP evaluation board. |
76 | 70 | ||
77 | #config XILINX_ML300 | 71 | config XILINX_VIRTEX_GENERIC_BOARD |
78 | # bool "Xilinx-ML300" | 72 | bool "Generic Xilinx Virtex board" |
79 | # depends on 40x | 73 | depends on 40x |
80 | # default y | 74 | default n |
81 | # select VIRTEX_II_PRO | 75 | select XILINX_VIRTEX_II_PRO |
82 | # help | 76 | select XILINX_VIRTEX_4_FX |
83 | # This option enables support for the Xilinx ML300 evaluation board. | 77 | help |
78 | This option enables generic support for Xilinx Virtex based boards. | ||
79 | |||
80 | The generic virtex board support matches any device tree which | ||
81 | specifies 'xilinx,virtex' in its compatible field. This includes | ||
82 | the Xilinx ML3xx and ML4xx reference designs using the powerpc | ||
83 | core. | ||
84 | 84 | ||
85 | endmenu | 85 | Most Virtex designs should use this unless it needs to do some |
86 | special configuration at board probe time. | ||
86 | 87 | ||
87 | # 40x specific CPU modules, selected based on the board above. | 88 | # 40x specific CPU modules, selected based on the board above. |
88 | config NP405H | 89 | config NP405H |
@@ -106,11 +107,19 @@ config 405EP | |||
106 | config 405GPR | 107 | config 405GPR |
107 | bool | 108 | bool |
108 | 109 | ||
109 | config VIRTEX_II_PRO | 110 | config XILINX_VIRTEX |
111 | bool | ||
112 | |||
113 | config XILINX_VIRTEX_II_PRO | ||
110 | bool | 114 | bool |
115 | select XILINX_VIRTEX | ||
111 | select IBM405_ERR77 | 116 | select IBM405_ERR77 |
112 | select IBM405_ERR51 | 117 | select IBM405_ERR51 |
113 | 118 | ||
119 | config XILINX_VIRTEX_4_FX | ||
120 | bool | ||
121 | select XILINX_VIRTEX | ||
122 | |||
114 | config STB03xxx | 123 | config STB03xxx |
115 | bool | 124 | bool |
116 | select IBM405_ERR77 | 125 | select IBM405_ERR77 |
@@ -126,73 +135,6 @@ config IBM405_ERR77 | |||
126 | config IBM405_ERR51 | 135 | config IBM405_ERR51 |
127 | bool | 136 | bool |
128 | 137 | ||
129 | menu "AMCC 44x options" | ||
130 | depends on 44x | ||
131 | |||
132 | #config BAMBOO | ||
133 | # bool "Bamboo" | ||
134 | # depends on 44x | ||
135 | # default n | ||
136 | # select 440EP | ||
137 | # help | ||
138 | # This option enables support for the IBM PPC440EP evaluation board. | ||
139 | |||
140 | config EBONY | ||
141 | bool "Ebony" | ||
142 | depends on 44x | ||
143 | default y | ||
144 | select 440GP | ||
145 | help | ||
146 | This option enables support for the IBM PPC440GP evaluation board. | ||
147 | |||
148 | #config LUAN | ||
149 | # bool "Luan" | ||
150 | # depends on 44x | ||
151 | # default n | ||
152 | # select 440SP | ||
153 | # help | ||
154 | # This option enables support for the IBM PPC440SP evaluation board. | ||
155 | |||
156 | #config OCOTEA | ||
157 | # bool "Ocotea" | ||
158 | # depends on 44x | ||
159 | # default n | ||
160 | # select 440GX | ||
161 | # help | ||
162 | # This option enables support for the IBM PPC440GX evaluation board. | ||
163 | |||
164 | endmenu | ||
165 | |||
166 | # 44x specific CPU modules, selected based on the board above. | ||
167 | config 440EP | ||
168 | bool | ||
169 | select PPC_FPU | ||
170 | select IBM440EP_ERR42 | ||
171 | |||
172 | config 440GP | ||
173 | bool | ||
174 | select IBM_NEW_EMAC_ZMII | ||
175 | |||
176 | config 440GX | ||
177 | bool | ||
178 | |||
179 | config 440SP | ||
180 | bool | ||
181 | |||
182 | config 440A | ||
183 | bool | ||
184 | depends on 440GX | ||
185 | default y | ||
186 | |||
187 | # 44x errata/workaround config symbols, selected by the CPU models above | ||
188 | config IBM440EP_ERR42 | ||
189 | bool | ||
190 | |||
191 | #config XILINX_OCP | ||
192 | # bool | ||
193 | # depends on XILINX_ML300 | ||
194 | # default y | ||
195 | |||
196 | #config BIOS_FIXUP | 138 | #config BIOS_FIXUP |
197 | # bool | 139 | # bool |
198 | # depends on BUBINGA || EP405 || SYCAMORE || WALNUT | 140 | # depends on BUBINGA || EP405 || SYCAMORE || WALNUT |
diff --git a/arch/powerpc/platforms/40x/Makefile b/arch/powerpc/platforms/40x/Makefile new file mode 100644 index 000000000000..51dadeee6fc6 --- /dev/null +++ b/arch/powerpc/platforms/40x/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_KILAUEA) += kilauea.o | ||
2 | obj-$(CONFIG_WALNUT) += walnut.o | ||
3 | obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o | ||
diff --git a/arch/powerpc/platforms/40x/kilauea.c b/arch/powerpc/platforms/40x/kilauea.c new file mode 100644 index 000000000000..1bffdbdd21b1 --- /dev/null +++ b/arch/powerpc/platforms/40x/kilauea.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Kilauea board specific routines | ||
3 | * | ||
4 | * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de> | ||
5 | * | ||
6 | * Based on the Walnut code by | ||
7 | * Josh Boyer <jwboyer@linux.vnet.ibm.com> | ||
8 | * Copyright 2007 IBM Corporation | ||
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 | #include <linux/init.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <asm/machdep.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/udbg.h> | ||
20 | #include <asm/time.h> | ||
21 | #include <asm/uic.h> | ||
22 | |||
23 | static struct of_device_id kilauea_of_bus[] = { | ||
24 | { .compatible = "ibm,plb4", }, | ||
25 | { .compatible = "ibm,opb", }, | ||
26 | { .compatible = "ibm,ebc", }, | ||
27 | {}, | ||
28 | }; | ||
29 | |||
30 | static int __init kilauea_device_probe(void) | ||
31 | { | ||
32 | if (!machine_is(kilauea)) | ||
33 | return 0; | ||
34 | |||
35 | of_platform_bus_probe(NULL, kilauea_of_bus, NULL); | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | device_initcall(kilauea_device_probe); | ||
40 | |||
41 | static int __init kilauea_probe(void) | ||
42 | { | ||
43 | unsigned long root = of_get_flat_dt_root(); | ||
44 | |||
45 | if (!of_flat_dt_is_compatible(root, "amcc,kilauea")) | ||
46 | return 0; | ||
47 | |||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | define_machine(kilauea) { | ||
52 | .name = "Kilauea", | ||
53 | .probe = kilauea_probe, | ||
54 | .progress = udbg_progress, | ||
55 | .init_IRQ = uic_init_tree, | ||
56 | .get_irq = uic_get_irq, | ||
57 | .calibrate_decr = generic_calibrate_decr, | ||
58 | }; | ||
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c new file mode 100644 index 000000000000..14bbc328170f --- /dev/null +++ b/arch/powerpc/platforms/40x/virtex.c | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Xilinx Virtex (IIpro & 4FX) based board support | ||
3 | * | ||
4 | * Copyright 2007 Secret Lab Technologies Ltd. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/of_platform.h> | ||
13 | #include <asm/machdep.h> | ||
14 | #include <asm/prom.h> | ||
15 | #include <asm/time.h> | ||
16 | #include <asm/xilinx_intc.h> | ||
17 | |||
18 | static int __init virtex_device_probe(void) | ||
19 | { | ||
20 | if (!machine_is(virtex)) | ||
21 | return 0; | ||
22 | |||
23 | of_platform_bus_probe(NULL, NULL, NULL); | ||
24 | |||
25 | return 0; | ||
26 | } | ||
27 | device_initcall(virtex_device_probe); | ||
28 | |||
29 | static int __init virtex_probe(void) | ||
30 | { | ||
31 | unsigned long root = of_get_flat_dt_root(); | ||
32 | |||
33 | if (!of_flat_dt_is_compatible(root, "xilinx,virtex")) | ||
34 | return 0; | ||
35 | |||
36 | return 1; | ||
37 | } | ||
38 | |||
39 | define_machine(virtex) { | ||
40 | .name = "Xilinx Virtex", | ||
41 | .probe = virtex_probe, | ||
42 | .init_IRQ = xilinx_intc_init_tree, | ||
43 | .get_irq = xilinx_intc_get_irq, | ||
44 | .calibrate_decr = generic_calibrate_decr, | ||
45 | }; | ||
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c new file mode 100644 index 000000000000..eb0c136b1c44 --- /dev/null +++ b/arch/powerpc/platforms/40x/walnut.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Architecture- / platform-specific boot-time initialization code for | ||
3 | * IBM PowerPC 4xx based boards. Adapted from original | ||
4 | * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek | ||
5 | * <dan@net4x.com>. | ||
6 | * | ||
7 | * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu> | ||
8 | * | ||
9 | * Rewritten and ported to the merged powerpc tree: | ||
10 | * Copyright 2007 IBM Corporation | ||
11 | * Josh Boyer <jwboyer@linux.vnet.ibm.com> | ||
12 | * | ||
13 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
14 | * the terms of the GNU General Public License version 2. This program | ||
15 | * is licensed "as is" without any warranty of any kind, whether express | ||
16 | * or implied. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/prom.h> | ||
22 | #include <asm/udbg.h> | ||
23 | #include <asm/time.h> | ||
24 | #include <asm/uic.h> | ||
25 | #include <asm/of_platform.h> | ||
26 | |||
27 | static struct of_device_id walnut_of_bus[] = { | ||
28 | { .compatible = "ibm,plb3", }, | ||
29 | { .compatible = "ibm,opb", }, | ||
30 | { .compatible = "ibm,ebc", }, | ||
31 | {}, | ||
32 | }; | ||
33 | |||
34 | static int __init walnut_device_probe(void) | ||
35 | { | ||
36 | if (!machine_is(walnut)) | ||
37 | return 0; | ||
38 | |||
39 | /* FIXME: do bus probe here */ | ||
40 | of_platform_bus_probe(NULL, walnut_of_bus, NULL); | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | device_initcall(walnut_device_probe); | ||
45 | |||
46 | static int __init walnut_probe(void) | ||
47 | { | ||
48 | unsigned long root = of_get_flat_dt_root(); | ||
49 | |||
50 | if (!of_flat_dt_is_compatible(root, "ibm,walnut")) | ||
51 | return 0; | ||
52 | |||
53 | return 1; | ||
54 | } | ||
55 | |||
56 | define_machine(walnut) { | ||
57 | .name = "Walnut", | ||
58 | .probe = walnut_probe, | ||
59 | .progress = udbg_progress, | ||
60 | .init_IRQ = uic_init_tree, | ||
61 | .get_irq = uic_get_irq, | ||
62 | .calibrate_decr = generic_calibrate_decr, | ||
63 | }; | ||
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 8e66949e7c67..51f3ea40a285 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
@@ -1,10 +1,10 @@ | |||
1 | #config BAMBOO | 1 | config BAMBOO |
2 | # bool "Bamboo" | 2 | bool "Bamboo" |
3 | # depends on 44x | 3 | depends on 44x |
4 | # default n | 4 | default n |
5 | # select 440EP | 5 | select 440EP |
6 | # help | 6 | help |
7 | # This option enables support for the IBM PPC440EP evaluation board. | 7 | This option enables support for the IBM PPC440EP evaluation board. |
8 | 8 | ||
9 | config EBONY | 9 | config EBONY |
10 | bool "Ebony" | 10 | bool "Ebony" |
@@ -14,6 +14,14 @@ config EBONY | |||
14 | help | 14 | help |
15 | This option enables support for the IBM PPC440GP evaluation board. | 15 | This option enables support for the IBM PPC440GP evaluation board. |
16 | 16 | ||
17 | config SEQUOIA | ||
18 | bool "Sequoia" | ||
19 | depends on 44x | ||
20 | default n | ||
21 | select 440EPX | ||
22 | help | ||
23 | This option enables support for the AMCC PPC440EPX evaluation board. | ||
24 | |||
17 | #config LUAN | 25 | #config LUAN |
18 | # bool "Luan" | 26 | # bool "Luan" |
19 | # depends on 44x | 27 | # depends on 44x |
@@ -35,6 +43,14 @@ config 440EP | |||
35 | bool | 43 | bool |
36 | select PPC_FPU | 44 | select PPC_FPU |
37 | select IBM440EP_ERR42 | 45 | select IBM440EP_ERR42 |
46 | # select IBM_NEW_EMAC_ZMII | ||
47 | |||
48 | config 440EPX | ||
49 | bool | ||
50 | select PPC_FPU | ||
51 | # Disabled until the new EMAC Driver is merged. | ||
52 | # select IBM_NEW_EMAC_EMAC4 | ||
53 | # select IBM_NEW_EMAC_ZMII | ||
38 | 54 | ||
39 | config 440GP | 55 | config 440GP |
40 | bool | 56 | bool |
@@ -48,7 +64,7 @@ config 440SP | |||
48 | 64 | ||
49 | config 440A | 65 | config 440A |
50 | bool | 66 | bool |
51 | depends on 440GX | 67 | depends on 440GX || 440EPX |
52 | default y | 68 | default y |
53 | 69 | ||
54 | # 44x errata/workaround config symbols, selected by the CPU models above | 70 | # 44x errata/workaround config symbols, selected by the CPU models above |
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile index 41d0a18a0e44..10ce6740cc7d 100644 --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile | |||
@@ -1,2 +1,4 @@ | |||
1 | obj-$(CONFIG_44x) := misc_44x.o | 1 | obj-$(CONFIG_44x) := misc_44x.o |
2 | obj-$(CONFIG_EBONY) += ebony.o | 2 | obj-$(CONFIG_EBONY) += ebony.o |
3 | obj-$(CONFIG_BAMBOO) += bamboo.o | ||
4 | obj-$(CONFIG_SEQUOIA) += sequoia.o | ||
diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c new file mode 100644 index 000000000000..470e1a3fd755 --- /dev/null +++ b/arch/powerpc/platforms/44x/bamboo.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Bamboo board specific routines | ||
3 | * | ||
4 | * Wade Farnsworth <wfarnsworth@mvista.com> | ||
5 | * Copyright 2004 MontaVista Software Inc. | ||
6 | * | ||
7 | * Rewritten and ported to the merged powerpc tree: | ||
8 | * Josh Boyer <jwboyer@linux.vnet.ibm.com> | ||
9 | * Copyright 2007 IBM Corporation | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | #include <linux/init.h> | ||
17 | #include <asm/machdep.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/udbg.h> | ||
20 | #include <asm/time.h> | ||
21 | #include <asm/uic.h> | ||
22 | #include <asm/of_platform.h> | ||
23 | #include "44x.h" | ||
24 | |||
25 | static struct of_device_id bamboo_of_bus[] = { | ||
26 | { .compatible = "ibm,plb4", }, | ||
27 | { .compatible = "ibm,opb", }, | ||
28 | { .compatible = "ibm,ebc", }, | ||
29 | {}, | ||
30 | }; | ||
31 | |||
32 | static int __init bamboo_device_probe(void) | ||
33 | { | ||
34 | if (!machine_is(bamboo)) | ||
35 | return 0; | ||
36 | |||
37 | of_platform_bus_probe(NULL, bamboo_of_bus, NULL); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | device_initcall(bamboo_device_probe); | ||
42 | |||
43 | static int __init bamboo_probe(void) | ||
44 | { | ||
45 | unsigned long root = of_get_flat_dt_root(); | ||
46 | |||
47 | if (!of_flat_dt_is_compatible(root, "amcc,bamboo")) | ||
48 | return 0; | ||
49 | |||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | define_machine(bamboo) { | ||
54 | .name = "Bamboo", | ||
55 | .probe = bamboo_probe, | ||
56 | .progress = udbg_progress, | ||
57 | .init_IRQ = uic_init_tree, | ||
58 | .get_irq = uic_get_irq, | ||
59 | .restart = ppc44x_reset_system, | ||
60 | .calibrate_decr = generic_calibrate_decr, | ||
61 | }; | ||
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c index 5a7fec8d10d3..40e18fcb666c 100644 --- a/arch/powerpc/platforms/44x/ebony.c +++ b/arch/powerpc/platforms/44x/ebony.c | |||
@@ -57,14 +57,9 @@ static int __init ebony_probe(void) | |||
57 | return 1; | 57 | return 1; |
58 | } | 58 | } |
59 | 59 | ||
60 | static void __init ebony_setup_arch(void) | ||
61 | { | ||
62 | } | ||
63 | |||
64 | define_machine(ebony) { | 60 | define_machine(ebony) { |
65 | .name = "Ebony", | 61 | .name = "Ebony", |
66 | .probe = ebony_probe, | 62 | .probe = ebony_probe, |
67 | .setup_arch = ebony_setup_arch, | ||
68 | .progress = udbg_progress, | 63 | .progress = udbg_progress, |
69 | .init_IRQ = uic_init_tree, | 64 | .init_IRQ = uic_init_tree, |
70 | .get_irq = uic_get_irq, | 65 | .get_irq = uic_get_irq, |
diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c new file mode 100644 index 000000000000..30700b31d43b --- /dev/null +++ b/arch/powerpc/platforms/44x/sequoia.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Sequoia board specific routines | ||
3 | * | ||
4 | * Valentine Barshak <vbarshak@ru.mvista.com> | ||
5 | * Copyright 2007 MontaVista Software Inc. | ||
6 | * | ||
7 | * Based on the Bamboo code by | ||
8 | * Josh Boyer <jwboyer@linux.vnet.ibm.com> | ||
9 | * Copyright 2007 IBM Corporation | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | #include <linux/init.h> | ||
17 | #include <asm/machdep.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/udbg.h> | ||
20 | #include <asm/time.h> | ||
21 | #include <asm/uic.h> | ||
22 | #include <asm/of_platform.h> | ||
23 | #include "44x.h" | ||
24 | |||
25 | static struct of_device_id sequoia_of_bus[] = { | ||
26 | { .compatible = "ibm,plb4", }, | ||
27 | { .compatible = "ibm,opb", }, | ||
28 | { .compatible = "ibm,ebc", }, | ||
29 | {}, | ||
30 | }; | ||
31 | |||
32 | static int __init sequoia_device_probe(void) | ||
33 | { | ||
34 | if (!machine_is(sequoia)) | ||
35 | return 0; | ||
36 | |||
37 | of_platform_bus_probe(NULL, sequoia_of_bus, NULL); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | device_initcall(sequoia_device_probe); | ||
42 | |||
43 | static int __init sequoia_probe(void) | ||
44 | { | ||
45 | unsigned long root = of_get_flat_dt_root(); | ||
46 | |||
47 | if (!of_flat_dt_is_compatible(root, "amcc,sequoia")) | ||
48 | return 0; | ||
49 | |||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | define_machine(sequoia) { | ||
54 | .name = "Sequoia", | ||
55 | .probe = sequoia_probe, | ||
56 | .progress = udbg_progress, | ||
57 | .init_IRQ = uic_init_tree, | ||
58 | .get_irq = uic_get_irq, | ||
59 | .restart = ppc44x_reset_system, | ||
60 | .calibrate_decr = generic_calibrate_decr, | ||
61 | }; | ||
diff --git a/arch/powerpc/platforms/4xx/Makefile b/arch/powerpc/platforms/4xx/Makefile deleted file mode 100644 index 79ff6b1e887c..000000000000 --- a/arch/powerpc/platforms/4xx/Makefile +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | # empty makefile so make clean works \ No newline at end of file | ||
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 3ffaa066c2c8..2938d4927b83 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config PPC_MPC52xx | 1 | config PPC_MPC52xx |
2 | bool | 2 | bool |
3 | select FSL_SOC | 3 | select FSL_SOC |
4 | select PPC_CLOCK | ||
4 | default n | 5 | default n |
5 | 6 | ||
6 | config PPC_MPC5200 | 7 | config PPC_MPC5200 |
@@ -30,6 +31,7 @@ config PPC_EFIKA | |||
30 | config PPC_LITE5200 | 31 | config PPC_LITE5200 |
31 | bool "Freescale Lite5200 Eval Board" | 32 | bool "Freescale Lite5200 Eval Board" |
32 | depends on PPC_MULTIPLATFORM && PPC32 | 33 | depends on PPC_MULTIPLATFORM && PPC32 |
34 | select WANT_DEVICE_TREE | ||
33 | select PPC_MPC5200 | 35 | select PPC_MPC5200 |
34 | default n | 36 | default n |
35 | 37 | ||
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index b91e39c84d46..307dbc178091 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile | |||
@@ -10,3 +10,6 @@ obj-$(CONFIG_PPC_EFIKA) += efika.o | |||
10 | obj-$(CONFIG_PPC_LITE5200) += lite5200.o | 10 | obj-$(CONFIG_PPC_LITE5200) += lite5200.o |
11 | 11 | ||
12 | obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o | 12 | obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o |
13 | ifeq ($(CONFIG_PPC_LITE5200),y) | ||
14 | obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o | ||
15 | endif | ||
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 4be6e7a17b66..a0da70c8b502 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -9,33 +9,16 @@ | |||
9 | * kind, whether express or implied. | 9 | * kind, whether express or implied. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/reboot.h> | ||
16 | #include <linux/init.h> | 12 | #include <linux/init.h> |
17 | #include <linux/utsrelease.h> | 13 | #include <linux/utsrelease.h> |
18 | #include <linux/seq_file.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/root_dev.h> | ||
21 | #include <linux/initrd.h> | ||
22 | #include <linux/timer.h> | ||
23 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
24 | 15 | #include <linux/of.h> | |
25 | #include <asm/io.h> | ||
26 | #include <asm/irq.h> | ||
27 | #include <asm/sections.h> | ||
28 | #include <asm/pci-bridge.h> | ||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
31 | #include <asm/time.h> | 17 | #include <asm/time.h> |
32 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
33 | #include <asm/rtas.h> | 19 | #include <asm/rtas.h> |
34 | #include <asm/of_device.h> | ||
35 | #include <asm/of_platform.h> | ||
36 | #include <asm/mpc52xx.h> | 20 | #include <asm/mpc52xx.h> |
37 | 21 | ||
38 | |||
39 | #define EFIKA_PLATFORM_NAME "Efika" | 22 | #define EFIKA_PLATFORM_NAME "Efika" |
40 | 23 | ||
41 | 24 | ||
@@ -78,8 +61,8 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, | |||
78 | } | 61 | } |
79 | 62 | ||
80 | static struct pci_ops rtas_pci_ops = { | 63 | static struct pci_ops rtas_pci_ops = { |
81 | rtas_read_config, | 64 | .read = rtas_read_config, |
82 | rtas_write_config | 65 | .write = rtas_write_config, |
83 | }; | 66 | }; |
84 | 67 | ||
85 | 68 | ||
@@ -197,15 +180,6 @@ static void __init efika_setup_arch(void) | |||
197 | { | 180 | { |
198 | rtas_initialize(); | 181 | rtas_initialize(); |
199 | 182 | ||
200 | #ifdef CONFIG_BLK_DEV_INITRD | ||
201 | initrd_below_start_ok = 1; | ||
202 | |||
203 | if (initrd_start) | ||
204 | ROOT_DEV = Root_RAM0; | ||
205 | else | ||
206 | #endif | ||
207 | ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ | ||
208 | |||
209 | efika_pcisetup(); | 183 | efika_pcisetup(); |
210 | 184 | ||
211 | #ifdef CONFIG_PM | 185 | #ifdef CONFIG_PM |
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 5c46e898fd45..0caa3d955c3b 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c | |||
@@ -15,33 +15,13 @@ | |||
15 | 15 | ||
16 | #undef DEBUG | 16 | #undef DEBUG |
17 | 17 | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | 18 | #include <linux/init.h> |
21 | #include <linux/errno.h> | ||
22 | #include <linux/reboot.h> | ||
23 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
24 | #include <linux/kdev_t.h> | 20 | #include <linux/of.h> |
25 | #include <linux/major.h> | ||
26 | #include <linux/console.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/initrd.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/atomic.h> | ||
34 | #include <asm/time.h> | 21 | #include <asm/time.h> |
35 | #include <asm/io.h> | 22 | #include <asm/io.h> |
36 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
37 | #include <asm/ipic.h> | ||
38 | #include <asm/bootinfo.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
41 | #include <asm/udbg.h> | ||
42 | #include <sysdev/fsl_soc.h> | ||
43 | #include <asm/of_platform.h> | ||
44 | |||
45 | #include <asm/mpc52xx.h> | 25 | #include <asm/mpc52xx.h> |
46 | 26 | ||
47 | /* ************************************************************************ | 27 | /* ************************************************************************ |
@@ -50,19 +30,56 @@ | |||
50 | * | 30 | * |
51 | */ | 31 | */ |
52 | 32 | ||
33 | /* | ||
34 | * Fix clock configuration. | ||
35 | * | ||
36 | * Firmware is supposed to be responsible for this. If you are creating a | ||
37 | * new board port, do *NOT* duplicate this code. Fix your boot firmware | ||
38 | * to set it correctly in the first place | ||
39 | */ | ||
40 | static void __init | ||
41 | lite5200_fix_clock_config(void) | ||
42 | { | ||
43 | struct mpc52xx_cdm __iomem *cdm; | ||
44 | |||
45 | /* Map zones */ | ||
46 | cdm = mpc52xx_find_and_map("mpc5200-cdm"); | ||
47 | if (!cdm) { | ||
48 | printk(KERN_ERR "%s() failed; expect abnormal behaviour\n", | ||
49 | __FUNCTION__); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | /* Use internal 48 Mhz */ | ||
54 | out_8(&cdm->ext_48mhz_en, 0x00); | ||
55 | out_8(&cdm->fd_enable, 0x01); | ||
56 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | ||
57 | out_be16(&cdm->fd_counters, 0x0001); | ||
58 | else | ||
59 | out_be16(&cdm->fd_counters, 0x5555); | ||
60 | |||
61 | /* Unmap the regs */ | ||
62 | iounmap(cdm); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * Fix setting of port_config register. | ||
67 | * | ||
68 | * Firmware is supposed to be responsible for this. If you are creating a | ||
69 | * new board port, do *NOT* duplicate this code. Fix your boot firmware | ||
70 | * to set it correctly in the first place | ||
71 | */ | ||
53 | static void __init | 72 | static void __init |
54 | lite5200_setup_cpu(void) | 73 | lite5200_fix_port_config(void) |
55 | { | 74 | { |
56 | struct mpc52xx_gpio __iomem *gpio; | 75 | struct mpc52xx_gpio __iomem *gpio; |
57 | u32 port_config; | 76 | u32 port_config; |
58 | 77 | ||
59 | /* Map zones */ | ||
60 | gpio = mpc52xx_find_and_map("mpc5200-gpio"); | 78 | gpio = mpc52xx_find_and_map("mpc5200-gpio"); |
61 | if (!gpio) { | 79 | if (!gpio) { |
62 | printk(KERN_ERR __FILE__ ": " | 80 | printk(KERN_ERR "%s() failed. expect abnormal behavior\n", |
63 | "Error while mapping GPIO register for port config. " | 81 | __FUNCTION__); |
64 | "Expect some abnormal behavior\n"); | 82 | return; |
65 | goto error; | ||
66 | } | 83 | } |
67 | 84 | ||
68 | /* Set port config */ | 85 | /* Set port config */ |
@@ -81,12 +98,10 @@ lite5200_setup_cpu(void) | |||
81 | out_be32(&gpio->port_config, port_config); | 98 | out_be32(&gpio->port_config, port_config); |
82 | 99 | ||
83 | /* Unmap zone */ | 100 | /* Unmap zone */ |
84 | error: | ||
85 | iounmap(gpio); | 101 | iounmap(gpio); |
86 | } | 102 | } |
87 | 103 | ||
88 | #ifdef CONFIG_PM | 104 | #ifdef CONFIG_PM |
89 | static u32 descr_a; | ||
90 | static void lite5200_suspend_prepare(void __iomem *mbar) | 105 | static void lite5200_suspend_prepare(void __iomem *mbar) |
91 | { | 106 | { |
92 | u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ | 107 | u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ |
@@ -97,42 +112,41 @@ static void lite5200_suspend_prepare(void __iomem *mbar) | |||
97 | * power down usb port | 112 | * power down usb port |
98 | * this needs to be called before of-ohci suspend code | 113 | * this needs to be called before of-ohci suspend code |
99 | */ | 114 | */ |
100 | descr_a = in_be32(mbar + 0x1048); | 115 | |
101 | out_be32(mbar + 0x1048, (descr_a & ~0x200) | 0x100); | 116 | /* set ports to "power switched" and "powered at the same time" |
117 | * USB Rh descriptor A: NPS = 0, PSM = 0 */ | ||
118 | out_be32(mbar + 0x1048, in_be32(mbar + 0x1048) & ~0x300); | ||
119 | /* USB Rh status: LPS = 1 - turn off power */ | ||
120 | out_be32(mbar + 0x1050, 0x00000001); | ||
102 | } | 121 | } |
103 | 122 | ||
104 | static void lite5200_resume_finish(void __iomem *mbar) | 123 | static void lite5200_resume_finish(void __iomem *mbar) |
105 | { | 124 | { |
106 | out_be32(mbar + 0x1048, descr_a); | 125 | /* USB Rh status: LPSC = 1 - turn on power */ |
126 | out_be32(mbar + 0x1050, 0x00010000); | ||
107 | } | 127 | } |
108 | #endif | 128 | #endif |
109 | 129 | ||
110 | static void __init lite5200_setup_arch(void) | 130 | static void __init lite5200_setup_arch(void) |
111 | { | 131 | { |
132 | #ifdef CONFIG_PCI | ||
112 | struct device_node *np; | 133 | struct device_node *np; |
134 | #endif | ||
113 | 135 | ||
114 | if (ppc_md.progress) | 136 | if (ppc_md.progress) |
115 | ppc_md.progress("lite5200_setup_arch()", 0); | 137 | ppc_md.progress("lite5200_setup_arch()", 0); |
116 | 138 | ||
117 | np = of_find_node_by_type(NULL, "cpu"); | 139 | /* Fix things that firmware should have done. */ |
118 | if (np) { | 140 | lite5200_fix_clock_config(); |
119 | const unsigned int *fp = | 141 | lite5200_fix_port_config(); |
120 | of_get_property(np, "clock-frequency", NULL); | ||
121 | if (fp != 0) | ||
122 | loops_per_jiffy = *fp / HZ; | ||
123 | else | ||
124 | loops_per_jiffy = 50000000 / HZ; | ||
125 | of_node_put(np); | ||
126 | } | ||
127 | 142 | ||
128 | /* CPU & Port mux setup */ | 143 | /* Some mpc5200 & mpc5200b related configuration */ |
129 | mpc52xx_setup_cpu(); /* Generic */ | 144 | mpc5200_setup_xlb_arbiter(); |
130 | lite5200_setup_cpu(); /* Platorm specific */ | ||
131 | 145 | ||
132 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM |
133 | mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; | 147 | mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; |
134 | mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; | 148 | mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; |
135 | mpc52xx_pm_init(); | 149 | lite5200_pm_init(); |
136 | #endif | 150 | #endif |
137 | 151 | ||
138 | #ifdef CONFIG_PCI | 152 | #ifdef CONFIG_PCI |
@@ -156,20 +170,6 @@ static void __init lite5200_setup_arch(void) | |||
156 | 170 | ||
157 | } | 171 | } |
158 | 172 | ||
159 | static void lite5200_show_cpuinfo(struct seq_file *m) | ||
160 | { | ||
161 | struct device_node* np = of_find_all_nodes(NULL); | ||
162 | const char *model = NULL; | ||
163 | |||
164 | if (np) | ||
165 | model = of_get_property(np, "model", NULL); | ||
166 | |||
167 | seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); | ||
168 | seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown"); | ||
169 | |||
170 | of_node_put(np); | ||
171 | } | ||
172 | |||
173 | /* | 173 | /* |
174 | * Called very early, MMU is off, device-tree isn't unflattened | 174 | * Called very early, MMU is off, device-tree isn't unflattened |
175 | */ | 175 | */ |
@@ -193,6 +193,5 @@ define_machine(lite5200) { | |||
193 | .init = mpc52xx_declare_of_platform_devices, | 193 | .init = mpc52xx_declare_of_platform_devices, |
194 | .init_IRQ = mpc52xx_init_irq, | 194 | .init_IRQ = mpc52xx_init_irq, |
195 | .get_irq = mpc52xx_get_irq, | 195 | .get_irq = mpc52xx_get_irq, |
196 | .show_cpuinfo = lite5200_show_cpuinfo, | ||
197 | .calibrate_decr = generic_calibrate_decr, | 196 | .calibrate_decr = generic_calibrate_decr, |
198 | }; | 197 | }; |
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c new file mode 100644 index 000000000000..f26afcd41757 --- /dev/null +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c | |||
@@ -0,0 +1,213 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/pm.h> | ||
3 | #include <asm/io.h> | ||
4 | #include <asm/time.h> | ||
5 | #include <asm/mpc52xx.h> | ||
6 | #include "mpc52xx_pic.h" | ||
7 | |||
8 | /* defined in lite5200_sleep.S and only used here */ | ||
9 | extern void lite5200_low_power(void __iomem *sram, void __iomem *mbar); | ||
10 | |||
11 | static struct mpc52xx_cdm __iomem *cdm; | ||
12 | static struct mpc52xx_intr __iomem *pic; | ||
13 | static struct mpc52xx_sdma __iomem *bes; | ||
14 | static struct mpc52xx_xlb __iomem *xlb; | ||
15 | static struct mpc52xx_gpio __iomem *gps; | ||
16 | static struct mpc52xx_gpio_wkup __iomem *gpw; | ||
17 | static void __iomem *sram; | ||
18 | static const int sram_size = 0x4000; /* 16 kBytes */ | ||
19 | static void __iomem *mbar; | ||
20 | |||
21 | static int lite5200_pm_valid(suspend_state_t state) | ||
22 | { | ||
23 | switch (state) { | ||
24 | case PM_SUSPEND_STANDBY: | ||
25 | case PM_SUSPEND_MEM: | ||
26 | return 1; | ||
27 | default: | ||
28 | return 0; | ||
29 | } | ||
30 | } | ||
31 | |||
32 | static int lite5200_pm_prepare(suspend_state_t state) | ||
33 | { | ||
34 | /* deep sleep? let mpc52xx code handle that */ | ||
35 | if (state == PM_SUSPEND_STANDBY) | ||
36 | return mpc52xx_pm_prepare(state); | ||
37 | |||
38 | if (state != PM_SUSPEND_MEM) | ||
39 | return -EINVAL; | ||
40 | |||
41 | /* map registers */ | ||
42 | mbar = mpc52xx_find_and_map("mpc5200"); | ||
43 | if (!mbar) { | ||
44 | printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); | ||
45 | return -ENOSYS; | ||
46 | } | ||
47 | |||
48 | cdm = mbar + 0x200; | ||
49 | pic = mbar + 0x500; | ||
50 | gps = mbar + 0xb00; | ||
51 | gpw = mbar + 0xc00; | ||
52 | bes = mbar + 0x1200; | ||
53 | xlb = mbar + 0x1f00; | ||
54 | sram = mbar + 0x8000; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | /* save and restore registers not bound to any real devices */ | ||
60 | static struct mpc52xx_cdm scdm; | ||
61 | static struct mpc52xx_intr spic; | ||
62 | static struct mpc52xx_sdma sbes; | ||
63 | static struct mpc52xx_xlb sxlb; | ||
64 | static struct mpc52xx_gpio sgps; | ||
65 | static struct mpc52xx_gpio_wkup sgpw; | ||
66 | |||
67 | static void lite5200_save_regs(void) | ||
68 | { | ||
69 | _memcpy_fromio(&spic, pic, sizeof(*pic)); | ||
70 | _memcpy_fromio(&sbes, bes, sizeof(*bes)); | ||
71 | _memcpy_fromio(&scdm, cdm, sizeof(*cdm)); | ||
72 | _memcpy_fromio(&sxlb, xlb, sizeof(*xlb)); | ||
73 | _memcpy_fromio(&sgps, gps, sizeof(*gps)); | ||
74 | _memcpy_fromio(&sgpw, gpw, sizeof(*gpw)); | ||
75 | |||
76 | _memcpy_fromio(saved_sram, sram, sram_size); | ||
77 | } | ||
78 | |||
79 | static void lite5200_restore_regs(void) | ||
80 | { | ||
81 | int i; | ||
82 | _memcpy_toio(sram, saved_sram, sram_size); | ||
83 | |||
84 | |||
85 | /* | ||
86 | * GPIOs. Interrupt Master Enable has higher address then other | ||
87 | * registers, so just memcpy is ok. | ||
88 | */ | ||
89 | _memcpy_toio(gpw, &sgpw, sizeof(*gpw)); | ||
90 | _memcpy_toio(gps, &sgps, sizeof(*gps)); | ||
91 | |||
92 | |||
93 | /* XLB Arbitrer */ | ||
94 | out_be32(&xlb->snoop_window, sxlb.snoop_window); | ||
95 | out_be32(&xlb->master_priority, sxlb.master_priority); | ||
96 | out_be32(&xlb->master_pri_enable, sxlb.master_pri_enable); | ||
97 | |||
98 | /* enable */ | ||
99 | out_be32(&xlb->int_enable, sxlb.int_enable); | ||
100 | out_be32(&xlb->config, sxlb.config); | ||
101 | |||
102 | |||
103 | /* CDM - Clock Distribution Module */ | ||
104 | out_8(&cdm->ipb_clk_sel, scdm.ipb_clk_sel); | ||
105 | out_8(&cdm->pci_clk_sel, scdm.pci_clk_sel); | ||
106 | |||
107 | out_8(&cdm->ext_48mhz_en, scdm.ext_48mhz_en); | ||
108 | out_8(&cdm->fd_enable, scdm.fd_enable); | ||
109 | out_be16(&cdm->fd_counters, scdm.fd_counters); | ||
110 | |||
111 | out_be32(&cdm->clk_enables, scdm.clk_enables); | ||
112 | |||
113 | out_8(&cdm->osc_disable, scdm.osc_disable); | ||
114 | |||
115 | out_be16(&cdm->mclken_div_psc1, scdm.mclken_div_psc1); | ||
116 | out_be16(&cdm->mclken_div_psc2, scdm.mclken_div_psc2); | ||
117 | out_be16(&cdm->mclken_div_psc3, scdm.mclken_div_psc3); | ||
118 | out_be16(&cdm->mclken_div_psc6, scdm.mclken_div_psc6); | ||
119 | |||
120 | |||
121 | /* BESTCOMM */ | ||
122 | out_be32(&bes->taskBar, sbes.taskBar); | ||
123 | out_be32(&bes->currentPointer, sbes.currentPointer); | ||
124 | out_be32(&bes->endPointer, sbes.endPointer); | ||
125 | out_be32(&bes->variablePointer, sbes.variablePointer); | ||
126 | |||
127 | out_8(&bes->IntVect1, sbes.IntVect1); | ||
128 | out_8(&bes->IntVect2, sbes.IntVect2); | ||
129 | out_be16(&bes->PtdCntrl, sbes.PtdCntrl); | ||
130 | |||
131 | for (i=0; i<32; i++) | ||
132 | out_8(&bes->ipr[i], sbes.ipr[i]); | ||
133 | |||
134 | out_be32(&bes->cReqSelect, sbes.cReqSelect); | ||
135 | out_be32(&bes->task_size0, sbes.task_size0); | ||
136 | out_be32(&bes->task_size1, sbes.task_size1); | ||
137 | out_be32(&bes->MDEDebug, sbes.MDEDebug); | ||
138 | out_be32(&bes->ADSDebug, sbes.ADSDebug); | ||
139 | out_be32(&bes->Value1, sbes.Value1); | ||
140 | out_be32(&bes->Value2, sbes.Value2); | ||
141 | out_be32(&bes->Control, sbes.Control); | ||
142 | out_be32(&bes->Status, sbes.Status); | ||
143 | out_be32(&bes->PTDDebug, sbes.PTDDebug); | ||
144 | |||
145 | /* restore tasks */ | ||
146 | for (i=0; i<16; i++) | ||
147 | out_be16(&bes->tcr[i], sbes.tcr[i]); | ||
148 | |||
149 | /* enable interrupts */ | ||
150 | out_be32(&bes->IntPend, sbes.IntPend); | ||
151 | out_be32(&bes->IntMask, sbes.IntMask); | ||
152 | |||
153 | |||
154 | /* PIC */ | ||
155 | out_be32(&pic->per_pri1, spic.per_pri1); | ||
156 | out_be32(&pic->per_pri2, spic.per_pri2); | ||
157 | out_be32(&pic->per_pri3, spic.per_pri3); | ||
158 | |||
159 | out_be32(&pic->main_pri1, spic.main_pri1); | ||
160 | out_be32(&pic->main_pri2, spic.main_pri2); | ||
161 | |||
162 | out_be32(&pic->enc_status, spic.enc_status); | ||
163 | |||
164 | /* unmask and enable interrupts */ | ||
165 | out_be32(&pic->per_mask, spic.per_mask); | ||
166 | out_be32(&pic->main_mask, spic.main_mask); | ||
167 | out_be32(&pic->ctrl, spic.ctrl); | ||
168 | } | ||
169 | |||
170 | static int lite5200_pm_enter(suspend_state_t state) | ||
171 | { | ||
172 | /* deep sleep? let mpc52xx code handle that */ | ||
173 | if (state == PM_SUSPEND_STANDBY) { | ||
174 | return mpc52xx_pm_enter(state); | ||
175 | } | ||
176 | |||
177 | lite5200_save_regs(); | ||
178 | |||
179 | /* effectively save FP regs */ | ||
180 | enable_kernel_fp(); | ||
181 | |||
182 | lite5200_low_power(sram, mbar); | ||
183 | |||
184 | lite5200_restore_regs(); | ||
185 | |||
186 | /* restart jiffies */ | ||
187 | wakeup_decrementer(); | ||
188 | |||
189 | iounmap(mbar); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int lite5200_pm_finish(suspend_state_t state) | ||
194 | { | ||
195 | /* deep sleep? let mpc52xx code handle that */ | ||
196 | if (state == PM_SUSPEND_STANDBY) { | ||
197 | return mpc52xx_pm_finish(state); | ||
198 | } | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static struct pm_ops lite5200_pm_ops = { | ||
203 | .valid = lite5200_pm_valid, | ||
204 | .prepare = lite5200_pm_prepare, | ||
205 | .enter = lite5200_pm_enter, | ||
206 | .finish = lite5200_pm_finish, | ||
207 | }; | ||
208 | |||
209 | int __init lite5200_pm_init(void) | ||
210 | { | ||
211 | pm_set_ops(&lite5200_pm_ops); | ||
212 | return 0; | ||
213 | } | ||
diff --git a/arch/powerpc/platforms/52xx/lite5200_sleep.S b/arch/powerpc/platforms/52xx/lite5200_sleep.S new file mode 100644 index 000000000000..08ab6fefcf7a --- /dev/null +++ b/arch/powerpc/platforms/52xx/lite5200_sleep.S | |||
@@ -0,0 +1,412 @@ | |||
1 | #include <asm/reg.h> | ||
2 | #include <asm/ppc_asm.h> | ||
3 | #include <asm/processor.h> | ||
4 | #include <asm/cache.h> | ||
5 | |||
6 | |||
7 | #define SDRAM_CTRL 0x104 | ||
8 | #define SC_MODE_EN (1<<31) | ||
9 | #define SC_CKE (1<<30) | ||
10 | #define SC_REF_EN (1<<28) | ||
11 | #define SC_SOFT_PRE (1<<1) | ||
12 | |||
13 | #define GPIOW_GPIOE 0xc00 | ||
14 | #define GPIOW_DDR 0xc08 | ||
15 | #define GPIOW_DVO 0xc0c | ||
16 | |||
17 | #define CDM_CE 0x214 | ||
18 | #define CDM_SDRAM (1<<3) | ||
19 | |||
20 | |||
21 | /* helpers... beware: r10 and r4 are overwritten */ | ||
22 | #define SAVE_SPRN(reg, addr) \ | ||
23 | mfspr r10, SPRN_##reg; \ | ||
24 | stw r10, ((addr)*4)(r4); | ||
25 | |||
26 | #define LOAD_SPRN(reg, addr) \ | ||
27 | lwz r10, ((addr)*4)(r4); \ | ||
28 | mtspr SPRN_##reg, r10; \ | ||
29 | sync; \ | ||
30 | isync; | ||
31 | |||
32 | |||
33 | .data | ||
34 | registers: | ||
35 | .space 0x5c*4 | ||
36 | .text | ||
37 | |||
38 | /* ---------------------------------------------------------------------- */ | ||
39 | /* low-power mode with help of M68HLC908QT1 */ | ||
40 | |||
41 | .globl lite5200_low_power | ||
42 | lite5200_low_power: | ||
43 | |||
44 | mr r7, r3 /* save SRAM va */ | ||
45 | mr r8, r4 /* save MBAR va */ | ||
46 | |||
47 | /* setup wakeup address for u-boot at physical location 0x0 */ | ||
48 | lis r3, CONFIG_KERNEL_START@h | ||
49 | lis r4, lite5200_wakeup@h | ||
50 | ori r4, r4, lite5200_wakeup@l | ||
51 | sub r4, r4, r3 | ||
52 | stw r4, 0(r3) | ||
53 | |||
54 | |||
55 | /* | ||
56 | * save stuff BDI overwrites | ||
57 | * 0xf0 (0xe0->0x100 gets overwritten when BDI connected; | ||
58 | * even when CONFIG_BDI* is disabled and MMU XLAT commented; heisenbug?)) | ||
59 | * WARNING: self-refresh doesn't seem to work when BDI2000 is connected, | ||
60 | * possibly because BDI sets SDRAM registers before wakeup code does | ||
61 | */ | ||
62 | lis r4, registers@h | ||
63 | ori r4, r4, registers@l | ||
64 | lwz r10, 0xf0(r3) | ||
65 | stw r10, (0x1d*4)(r4) | ||
66 | |||
67 | /* save registers to r4 [destroys r10] */ | ||
68 | SAVE_SPRN(LR, 0x1c) | ||
69 | bl save_regs | ||
70 | |||
71 | /* flush caches [destroys r3, r4] */ | ||
72 | bl flush_data_cache | ||
73 | |||
74 | |||
75 | /* copy code to sram */ | ||
76 | mr r4, r7 | ||
77 | li r3, (sram_code_end - sram_code)/4 | ||
78 | mtctr r3 | ||
79 | lis r3, sram_code@h | ||
80 | ori r3, r3, sram_code@l | ||
81 | 1: | ||
82 | lwz r5, 0(r3) | ||
83 | stw r5, 0(r4) | ||
84 | addi r3, r3, 4 | ||
85 | addi r4, r4, 4 | ||
86 | bdnz 1b | ||
87 | |||
88 | /* get tb_ticks_per_usec */ | ||
89 | lis r3, tb_ticks_per_usec@h | ||
90 | lwz r11, tb_ticks_per_usec@l(r3) | ||
91 | |||
92 | /* disable I and D caches */ | ||
93 | mfspr r3, SPRN_HID0 | ||
94 | ori r3, r3, HID0_ICE | HID0_DCE | ||
95 | xori r3, r3, HID0_ICE | HID0_DCE | ||
96 | sync; isync; | ||
97 | mtspr SPRN_HID0, r3 | ||
98 | sync; isync; | ||
99 | |||
100 | /* jump to sram */ | ||
101 | mtlr r7 | ||
102 | blrl | ||
103 | /* doesn't return */ | ||
104 | |||
105 | |||
106 | sram_code: | ||
107 | /* self refresh */ | ||
108 | lwz r4, SDRAM_CTRL(r8) | ||
109 | |||
110 | /* send NOP (precharge) */ | ||
111 | oris r4, r4, SC_MODE_EN@h /* mode_en */ | ||
112 | stw r4, SDRAM_CTRL(r8) | ||
113 | sync | ||
114 | |||
115 | ori r4, r4, SC_SOFT_PRE /* soft_pre */ | ||
116 | stw r4, SDRAM_CTRL(r8) | ||
117 | sync | ||
118 | xori r4, r4, SC_SOFT_PRE | ||
119 | |||
120 | xoris r4, r4, SC_MODE_EN@h /* !mode_en */ | ||
121 | stw r4, SDRAM_CTRL(r8) | ||
122 | sync | ||
123 | |||
124 | /* delay (for NOP to finish) */ | ||
125 | li r12, 1 | ||
126 | bl udelay | ||
127 | |||
128 | /* | ||
129 | * mode_en must not be set when enabling self-refresh | ||
130 | * send AR with CKE low (self-refresh) | ||
131 | */ | ||
132 | oris r4, r4, (SC_REF_EN | SC_CKE)@h | ||
133 | xoris r4, r4, (SC_CKE)@h /* ref_en !cke */ | ||
134 | stw r4, SDRAM_CTRL(r8) | ||
135 | sync | ||
136 | |||
137 | /* delay (after !CKE there should be two cycles) */ | ||
138 | li r12, 1 | ||
139 | bl udelay | ||
140 | |||
141 | /* disable clock */ | ||
142 | lwz r4, CDM_CE(r8) | ||
143 | ori r4, r4, CDM_SDRAM | ||
144 | xori r4, r4, CDM_SDRAM | ||
145 | stw r4, CDM_CE(r8) | ||
146 | sync | ||
147 | |||
148 | /* delay a bit */ | ||
149 | li r12, 1 | ||
150 | bl udelay | ||
151 | |||
152 | |||
153 | /* turn off with QT chip */ | ||
154 | li r4, 0x02 | ||
155 | stb r4, GPIOW_GPIOE(r8) /* enable gpio_wkup1 */ | ||
156 | sync | ||
157 | |||
158 | stb r4, GPIOW_DVO(r8) /* "output" high */ | ||
159 | sync | ||
160 | stb r4, GPIOW_DDR(r8) /* output */ | ||
161 | sync | ||
162 | stb r4, GPIOW_DVO(r8) /* output high */ | ||
163 | sync | ||
164 | |||
165 | /* 10uS delay */ | ||
166 | li r12, 10 | ||
167 | bl udelay | ||
168 | |||
169 | /* turn off */ | ||
170 | li r4, 0 | ||
171 | stb r4, GPIOW_DVO(r8) /* output low */ | ||
172 | sync | ||
173 | |||
174 | /* wait until we're offline */ | ||
175 | 1: | ||
176 | b 1b | ||
177 | |||
178 | |||
179 | /* local udelay in sram is needed */ | ||
180 | udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */ | ||
181 | mullw r12, r12, r11 | ||
182 | mftb r13 /* start */ | ||
183 | addi r12, r13, r12 /* end */ | ||
184 | 1: | ||
185 | mftb r13 /* current */ | ||
186 | cmp cr0, r13, r12 | ||
187 | blt 1b | ||
188 | blr | ||
189 | |||
190 | sram_code_end: | ||
191 | |||
192 | |||
193 | |||
194 | /* uboot jumps here on resume */ | ||
195 | lite5200_wakeup: | ||
196 | bl restore_regs | ||
197 | |||
198 | |||
199 | /* HIDs, MSR */ | ||
200 | LOAD_SPRN(HID1, 0x19) | ||
201 | LOAD_SPRN(HID2, 0x1a) | ||
202 | |||
203 | |||
204 | /* address translation is tricky (see turn_on_mmu) */ | ||
205 | mfmsr r10 | ||
206 | ori r10, r10, MSR_DR | MSR_IR | ||
207 | |||
208 | |||
209 | mtspr SPRN_SRR1, r10 | ||
210 | lis r10, mmu_on@h | ||
211 | ori r10, r10, mmu_on@l | ||
212 | mtspr SPRN_SRR0, r10 | ||
213 | sync | ||
214 | rfi | ||
215 | mmu_on: | ||
216 | /* kernel offset (r4 is still set from restore_registers) */ | ||
217 | addis r4, r4, CONFIG_KERNEL_START@h | ||
218 | |||
219 | |||
220 | /* restore MSR */ | ||
221 | lwz r10, (4*0x1b)(r4) | ||
222 | mtmsr r10 | ||
223 | sync; isync; | ||
224 | |||
225 | /* invalidate caches */ | ||
226 | mfspr r10, SPRN_HID0 | ||
227 | ori r5, r10, HID0_ICFI | HID0_DCI | ||
228 | mtspr SPRN_HID0, r5 /* invalidate caches */ | ||
229 | sync; isync; | ||
230 | mtspr SPRN_HID0, r10 | ||
231 | sync; isync; | ||
232 | |||
233 | /* enable caches */ | ||
234 | lwz r10, (4*0x18)(r4) | ||
235 | mtspr SPRN_HID0, r10 /* restore (enable caches, DPM) */ | ||
236 | /* ^ this has to be after address translation set in MSR */ | ||
237 | sync | ||
238 | isync | ||
239 | |||
240 | |||
241 | /* restore 0xf0 (BDI2000) */ | ||
242 | lis r3, CONFIG_KERNEL_START@h | ||
243 | lwz r10, (0x1d*4)(r4) | ||
244 | stw r10, 0xf0(r3) | ||
245 | |||
246 | LOAD_SPRN(LR, 0x1c) | ||
247 | |||
248 | |||
249 | blr | ||
250 | |||
251 | |||
252 | /* ---------------------------------------------------------------------- */ | ||
253 | /* boring code: helpers */ | ||
254 | |||
255 | /* save registers */ | ||
256 | #define SAVE_BAT(n, addr) \ | ||
257 | SAVE_SPRN(DBAT##n##L, addr); \ | ||
258 | SAVE_SPRN(DBAT##n##U, addr+1); \ | ||
259 | SAVE_SPRN(IBAT##n##L, addr+2); \ | ||
260 | SAVE_SPRN(IBAT##n##U, addr+3); | ||
261 | |||
262 | #define SAVE_SR(n, addr) \ | ||
263 | mfsr r10, n; \ | ||
264 | stw r10, ((addr)*4)(r4); | ||
265 | |||
266 | #define SAVE_4SR(n, addr) \ | ||
267 | SAVE_SR(n, addr); \ | ||
268 | SAVE_SR(n+1, addr+1); \ | ||
269 | SAVE_SR(n+2, addr+2); \ | ||
270 | SAVE_SR(n+3, addr+3); | ||
271 | |||
272 | save_regs: | ||
273 | stw r0, 0(r4) | ||
274 | stw r1, 0x4(r4) | ||
275 | stw r2, 0x8(r4) | ||
276 | stmw r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */ | ||
277 | |||
278 | SAVE_SPRN(HID0, 0x18) | ||
279 | SAVE_SPRN(HID1, 0x19) | ||
280 | SAVE_SPRN(HID2, 0x1a) | ||
281 | mfmsr r10 | ||
282 | stw r10, (4*0x1b)(r4) | ||
283 | /*SAVE_SPRN(LR, 0x1c) have to save it before the call */ | ||
284 | /* 0x1d reserved by 0xf0 */ | ||
285 | SAVE_SPRN(RPA, 0x1e) | ||
286 | SAVE_SPRN(SDR1, 0x1f) | ||
287 | |||
288 | /* save MMU regs */ | ||
289 | SAVE_BAT(0, 0x20) | ||
290 | SAVE_BAT(1, 0x24) | ||
291 | SAVE_BAT(2, 0x28) | ||
292 | SAVE_BAT(3, 0x2c) | ||
293 | SAVE_BAT(4, 0x30) | ||
294 | SAVE_BAT(5, 0x34) | ||
295 | SAVE_BAT(6, 0x38) | ||
296 | SAVE_BAT(7, 0x3c) | ||
297 | |||
298 | SAVE_4SR(0, 0x40) | ||
299 | SAVE_4SR(4, 0x44) | ||
300 | SAVE_4SR(8, 0x48) | ||
301 | SAVE_4SR(12, 0x4c) | ||
302 | |||
303 | SAVE_SPRN(SPRG0, 0x50) | ||
304 | SAVE_SPRN(SPRG1, 0x51) | ||
305 | SAVE_SPRN(SPRG2, 0x52) | ||
306 | SAVE_SPRN(SPRG3, 0x53) | ||
307 | SAVE_SPRN(SPRG4, 0x54) | ||
308 | SAVE_SPRN(SPRG5, 0x55) | ||
309 | SAVE_SPRN(SPRG6, 0x56) | ||
310 | SAVE_SPRN(SPRG7, 0x57) | ||
311 | |||
312 | SAVE_SPRN(IABR, 0x58) | ||
313 | SAVE_SPRN(DABR, 0x59) | ||
314 | SAVE_SPRN(TBRL, 0x5a) | ||
315 | SAVE_SPRN(TBRU, 0x5b) | ||
316 | |||
317 | blr | ||
318 | |||
319 | |||
320 | /* restore registers */ | ||
321 | #define LOAD_BAT(n, addr) \ | ||
322 | LOAD_SPRN(DBAT##n##L, addr); \ | ||
323 | LOAD_SPRN(DBAT##n##U, addr+1); \ | ||
324 | LOAD_SPRN(IBAT##n##L, addr+2); \ | ||
325 | LOAD_SPRN(IBAT##n##U, addr+3); | ||
326 | |||
327 | #define LOAD_SR(n, addr) \ | ||
328 | lwz r10, ((addr)*4)(r4); \ | ||
329 | mtsr n, r10; | ||
330 | |||
331 | #define LOAD_4SR(n, addr) \ | ||
332 | LOAD_SR(n, addr); \ | ||
333 | LOAD_SR(n+1, addr+1); \ | ||
334 | LOAD_SR(n+2, addr+2); \ | ||
335 | LOAD_SR(n+3, addr+3); | ||
336 | |||
337 | restore_regs: | ||
338 | lis r4, registers@h | ||
339 | ori r4, r4, registers@l | ||
340 | |||
341 | /* MMU is not up yet */ | ||
342 | subis r4, r4, CONFIG_KERNEL_START@h | ||
343 | |||
344 | lwz r0, 0(r4) | ||
345 | lwz r1, 0x4(r4) | ||
346 | lwz r2, 0x8(r4) | ||
347 | lmw r11, 0xc(r4) | ||
348 | |||
349 | /* | ||
350 | * these are a bit tricky | ||
351 | * | ||
352 | * 0x18 - HID0 | ||
353 | * 0x19 - HID1 | ||
354 | * 0x1a - HID2 | ||
355 | * 0x1b - MSR | ||
356 | * 0x1c - LR | ||
357 | * 0x1d - reserved by 0xf0 (BDI2000) | ||
358 | */ | ||
359 | LOAD_SPRN(RPA, 0x1e); | ||
360 | LOAD_SPRN(SDR1, 0x1f); | ||
361 | |||
362 | /* restore MMU regs */ | ||
363 | LOAD_BAT(0, 0x20) | ||
364 | LOAD_BAT(1, 0x24) | ||
365 | LOAD_BAT(2, 0x28) | ||
366 | LOAD_BAT(3, 0x2c) | ||
367 | LOAD_BAT(4, 0x30) | ||
368 | LOAD_BAT(5, 0x34) | ||
369 | LOAD_BAT(6, 0x38) | ||
370 | LOAD_BAT(7, 0x3c) | ||
371 | |||
372 | LOAD_4SR(0, 0x40) | ||
373 | LOAD_4SR(4, 0x44) | ||
374 | LOAD_4SR(8, 0x48) | ||
375 | LOAD_4SR(12, 0x4c) | ||
376 | |||
377 | /* rest of regs */ | ||
378 | LOAD_SPRN(SPRG0, 0x50); | ||
379 | LOAD_SPRN(SPRG1, 0x51); | ||
380 | LOAD_SPRN(SPRG2, 0x52); | ||
381 | LOAD_SPRN(SPRG3, 0x53); | ||
382 | LOAD_SPRN(SPRG4, 0x54); | ||
383 | LOAD_SPRN(SPRG5, 0x55); | ||
384 | LOAD_SPRN(SPRG6, 0x56); | ||
385 | LOAD_SPRN(SPRG7, 0x57); | ||
386 | |||
387 | LOAD_SPRN(IABR, 0x58); | ||
388 | LOAD_SPRN(DABR, 0x59); | ||
389 | LOAD_SPRN(TBWL, 0x5a); /* these two have separate R/W regs */ | ||
390 | LOAD_SPRN(TBWU, 0x5b); | ||
391 | |||
392 | blr | ||
393 | |||
394 | |||
395 | |||
396 | /* cache flushing code. copied from arch/ppc/boot/util.S */ | ||
397 | #define NUM_CACHE_LINES (128*8) | ||
398 | |||
399 | /* | ||
400 | * Flush data cache | ||
401 | * Do this by just reading lots of stuff into the cache. | ||
402 | */ | ||
403 | flush_data_cache: | ||
404 | lis r3,CONFIG_KERNEL_START@h | ||
405 | ori r3,r3,CONFIG_KERNEL_START@l | ||
406 | li r4,NUM_CACHE_LINES | ||
407 | mtctr r4 | ||
408 | 1: | ||
409 | lwz r4,0(r3) | ||
410 | addi r3,r3,L1_CACHE_BYTES /* Next line, please */ | ||
411 | bdnz 1b | ||
412 | blr | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 2dd415ff55a9..3bc201e07e6b 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c | |||
@@ -13,10 +13,9 @@ | |||
13 | #undef DEBUG | 13 | #undef DEBUG |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | 16 | #include <linux/of_platform.h> | |
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
19 | #include <asm/of_platform.h> | ||
20 | #include <asm/mpc52xx.h> | 19 | #include <asm/mpc52xx.h> |
21 | 20 | ||
22 | 21 | ||
@@ -76,44 +75,33 @@ mpc52xx_find_ipb_freq(struct device_node *node) | |||
76 | EXPORT_SYMBOL(mpc52xx_find_ipb_freq); | 75 | EXPORT_SYMBOL(mpc52xx_find_ipb_freq); |
77 | 76 | ||
78 | 77 | ||
78 | /* | ||
79 | * Configure the XLB arbiter settings to match what Linux expects. | ||
80 | */ | ||
79 | void __init | 81 | void __init |
80 | mpc52xx_setup_cpu(void) | 82 | mpc5200_setup_xlb_arbiter(void) |
81 | { | 83 | { |
82 | struct mpc52xx_cdm __iomem *cdm; | ||
83 | struct mpc52xx_xlb __iomem *xlb; | 84 | struct mpc52xx_xlb __iomem *xlb; |
84 | 85 | ||
85 | /* Map zones */ | ||
86 | cdm = mpc52xx_find_and_map("mpc5200-cdm"); | ||
87 | xlb = mpc52xx_find_and_map("mpc5200-xlb"); | 86 | xlb = mpc52xx_find_and_map("mpc5200-xlb"); |
88 | 87 | if (!xlb) { | |
89 | if (!cdm || !xlb) { | ||
90 | printk(KERN_ERR __FILE__ ": " | 88 | printk(KERN_ERR __FILE__ ": " |
91 | "Error while mapping CDM/XLB during mpc52xx_setup_cpu. " | 89 | "Error mapping XLB in mpc52xx_setup_cpu(). " |
92 | "Expect some abnormal behavior\n"); | 90 | "Expect some abnormal behavior\n"); |
93 | goto unmap_regs; | 91 | return; |
94 | } | 92 | } |
95 | 93 | ||
96 | /* Use internal 48 Mhz */ | ||
97 | out_8(&cdm->ext_48mhz_en, 0x00); | ||
98 | out_8(&cdm->fd_enable, 0x01); | ||
99 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | ||
100 | out_be16(&cdm->fd_counters, 0x0001); | ||
101 | else | ||
102 | out_be16(&cdm->fd_counters, 0x5555); | ||
103 | |||
104 | /* Configure the XLB Arbiter priorities */ | 94 | /* Configure the XLB Arbiter priorities */ |
105 | out_be32(&xlb->master_pri_enable, 0xff); | 95 | out_be32(&xlb->master_pri_enable, 0xff); |
106 | out_be32(&xlb->master_priority, 0x11111111); | 96 | out_be32(&xlb->master_priority, 0x11111111); |
107 | 97 | ||
108 | /* Disable XLB pipelining */ | 98 | /* Disable XLB pipelining |
109 | /* (cfr errate 292. We could do this only just before ATA PIO | 99 | * (cfr errate 292. We could do this only just before ATA PIO |
110 | transaction and re-enable it afterwards ...) */ | 100 | * transaction and re-enable it afterwards ...) |
101 | */ | ||
111 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); | 102 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); |
112 | 103 | ||
113 | /* Unmap zones */ | 104 | iounmap(xlb); |
114 | unmap_regs: | ||
115 | if (cdm) iounmap(cdm); | ||
116 | if (xlb) iounmap(xlb); | ||
117 | } | 105 | } |
118 | 106 | ||
119 | void __init | 107 | void __init |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index fbfff95b4437..61100f270c68 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c | |||
@@ -18,19 +18,9 @@ | |||
18 | 18 | ||
19 | #undef DEBUG | 19 | #undef DEBUG |
20 | 20 | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/signal.h> | ||
25 | #include <linux/stddef.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
28 | #include <linux/hardirq.h> | 22 | #include <linux/of.h> |
29 | |||
30 | #include <asm/io.h> | 23 | #include <asm/io.h> |
31 | #include <asm/processor.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/irq.h> | ||
34 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
35 | #include <asm/mpc52xx.h> | 25 | #include <asm/mpc52xx.h> |
36 | #include "mpc52xx_pic.h" | 26 | #include "mpc52xx_pic.h" |
@@ -242,12 +232,6 @@ static struct irq_chip mpc52xx_sdma_irqchip = { | |||
242 | * irq_host | 232 | * irq_host |
243 | */ | 233 | */ |
244 | 234 | ||
245 | static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node) | ||
246 | { | ||
247 | pr_debug("%s: node=%p\n", __func__, node); | ||
248 | return mpc52xx_irqhost->host_data == node; | ||
249 | } | ||
250 | |||
251 | static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, | 235 | static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, |
252 | u32 * intspec, unsigned int intsize, | 236 | u32 * intspec, unsigned int intsize, |
253 | irq_hw_number_t * out_hwirq, | 237 | irq_hw_number_t * out_hwirq, |
@@ -368,7 +352,6 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, | |||
368 | } | 352 | } |
369 | 353 | ||
370 | static struct irq_host_ops mpc52xx_irqhost_ops = { | 354 | static struct irq_host_ops mpc52xx_irqhost_ops = { |
371 | .match = mpc52xx_irqhost_match, | ||
372 | .xlate = mpc52xx_irqhost_xlate, | 355 | .xlate = mpc52xx_irqhost_xlate, |
373 | .map = mpc52xx_irqhost_map, | 356 | .map = mpc52xx_irqhost_map, |
374 | }; | 357 | }; |
@@ -420,14 +403,13 @@ void __init mpc52xx_init_irq(void) | |||
420 | * hw irq information provided by the ofw to linux virq | 403 | * hw irq information provided by the ofw to linux virq |
421 | */ | 404 | */ |
422 | 405 | ||
423 | mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, | 406 | mpc52xx_irqhost = irq_alloc_host(picnode, IRQ_HOST_MAP_LINEAR, |
424 | MPC52xx_IRQ_HIGHTESTHWIRQ, | 407 | MPC52xx_IRQ_HIGHTESTHWIRQ, |
425 | &mpc52xx_irqhost_ops, -1); | 408 | &mpc52xx_irqhost_ops, -1); |
426 | 409 | ||
427 | if (!mpc52xx_irqhost) | 410 | if (!mpc52xx_irqhost) |
428 | panic(__FILE__ ": Cannot allocate the IRQ host\n"); | 411 | panic(__FILE__ ": Cannot allocate the IRQ host\n"); |
429 | 412 | ||
430 | mpc52xx_irqhost->host_data = picnode; | ||
431 | printk(KERN_INFO "MPC52xx PIC is up and running!\n"); | 413 | printk(KERN_INFO "MPC52xx PIC is up and running!\n"); |
432 | } | 414 | } |
433 | 415 | ||
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 89fde43895c5..541fbb815631 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig | |||
@@ -1,17 +1,30 @@ | |||
1 | choice | 1 | choice |
2 | prompt "82xx Board Type" | 2 | prompt "82xx Board Type" |
3 | depends on PPC_82xx | 3 | depends on PPC_82xx |
4 | default MPC82xx_ADS | 4 | default MPC8272_ADS |
5 | 5 | ||
6 | config MPC82xx_ADS | 6 | config MPC8272_ADS |
7 | bool "Freescale MPC82xx ADS" | 7 | bool "Freescale MPC8272 ADS" |
8 | select DEFAULT_UIMAGE | 8 | select DEFAULT_UIMAGE |
9 | select PQ2ADS | 9 | select PQ2ADS |
10 | select 8272 | 10 | select 8272 |
11 | select 8260 | 11 | select 8260 |
12 | select FSL_SOC | 12 | select FSL_SOC |
13 | select PQ2_ADS_PCI_PIC if PCI | ||
14 | select PPC_CPM_NEW_BINDING | ||
13 | help | 15 | help |
14 | This option enables support for the MPC8272 ADS board | 16 | This option enables support for the MPC8272 ADS board |
17 | |||
18 | config PQ2FADS | ||
19 | bool "Freescale PQ2FADS" | ||
20 | select DEFAULT_UIMAGE | ||
21 | select PQ2ADS | ||
22 | select 8260 | ||
23 | select FSL_SOC | ||
24 | select PQ2_ADS_PCI_PIC if PCI | ||
25 | select PPC_CPM_NEW_BINDING | ||
26 | help | ||
27 | This option enables support for the PQ2FADS board | ||
15 | 28 | ||
16 | endchoice | 29 | endchoice |
17 | 30 | ||
@@ -34,3 +47,6 @@ config 8272 | |||
34 | help | 47 | help |
35 | The MPC8272 CPM has a different internal dpram setup than other CPM2 | 48 | The MPC8272 CPM has a different internal dpram setup than other CPM2 |
36 | devices | 49 | devices |
50 | |||
51 | config PQ2_ADS_PCI_PIC | ||
52 | bool | ||
diff --git a/arch/powerpc/platforms/82xx/Makefile b/arch/powerpc/platforms/82xx/Makefile index d9fd4c84d2e0..68c8b0c9772b 100644 --- a/arch/powerpc/platforms/82xx/Makefile +++ b/arch/powerpc/platforms/82xx/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 82xx linux kernel. | 2 | # Makefile for the PowerPC 82xx linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_PPC_82xx) += mpc82xx.o | 4 | obj-$(CONFIG_MPC8272_ADS) += mpc8272_ads.o |
5 | obj-$(CONFIG_MPC82xx_ADS) += mpc82xx_ads.o | 5 | obj-$(CONFIG_CPM2) += pq2.o |
6 | obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o | ||
7 | obj-$(CONFIG_PQ2FADS) += pq2fads.o | ||
diff --git a/arch/powerpc/platforms/82xx/m82xx_pci.h b/arch/powerpc/platforms/82xx/m82xx_pci.h index 9cd8893b5a32..65e38a7ff48f 100644 --- a/arch/powerpc/platforms/82xx/m82xx_pci.h +++ b/arch/powerpc/platforms/82xx/m82xx_pci.h | |||
@@ -8,8 +8,6 @@ | |||
8 | * 2 of the License, or (at your option) any later version. | 8 | * 2 of the License, or (at your option) any later version. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <asm/m8260_pci.h> | ||
12 | |||
13 | #define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET) | 11 | #define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET) |
14 | 12 | ||
15 | #ifndef _IO_BASE | 13 | #ifndef _IO_BASE |
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c new file mode 100644 index 000000000000..fd83440eb287 --- /dev/null +++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * MPC8272 ADS board support | ||
3 | * | ||
4 | * Copyright 2007 Freescale Semiconductor, Inc. | ||
5 | * Author: Scott Wood <scottwood@freescale.com> | ||
6 | * | ||
7 | * Based on code by Vitaly Bordug <vbordug@ru.mvista.com> | ||
8 | * Copyright (c) 2006 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/init.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/fsl_devices.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <asm/cpm2.h> | ||
23 | #include <asm/udbg.h> | ||
24 | #include <asm/machdep.h> | ||
25 | #include <asm/time.h> | ||
26 | |||
27 | #include <platforms/82xx/pq2.h> | ||
28 | |||
29 | #include <sysdev/fsl_soc.h> | ||
30 | #include <sysdev/cpm2_pic.h> | ||
31 | |||
32 | #include "pq2ads.h" | ||
33 | #include "pq2.h" | ||
34 | |||
35 | static void __init mpc8272_ads_pic_init(void) | ||
36 | { | ||
37 | struct device_node *np = of_find_compatible_node(NULL, NULL, | ||
38 | "fsl,cpm2-pic"); | ||
39 | if (!np) { | ||
40 | printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n"); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | cpm2_pic_init(np); | ||
45 | of_node_put(np); | ||
46 | |||
47 | /* Initialize stuff for the 82xx CPLD IC and install demux */ | ||
48 | pq2ads_pci_init_irq(); | ||
49 | } | ||
50 | |||
51 | struct cpm_pin { | ||
52 | int port, pin, flags; | ||
53 | }; | ||
54 | |||
55 | static struct cpm_pin mpc8272_ads_pins[] = { | ||
56 | /* SCC1 */ | ||
57 | {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
58 | {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
59 | |||
60 | /* SCC4 */ | ||
61 | {3, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
62 | {3, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
63 | |||
64 | /* FCC1 */ | ||
65 | {0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
66 | {0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
67 | {0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
68 | {0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
69 | {0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
70 | {0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
71 | {0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
72 | {0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
73 | {0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, | ||
74 | {0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, | ||
75 | {0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
76 | {0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
77 | {0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, | ||
78 | {0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, | ||
79 | {2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
80 | {2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
81 | |||
82 | /* FCC2 */ | ||
83 | {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
84 | {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
85 | {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
86 | {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
87 | {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
88 | {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
89 | {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
90 | {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
91 | {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
92 | {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
93 | {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
94 | {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
95 | {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
96 | {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
97 | {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
98 | {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
99 | }; | ||
100 | |||
101 | static void __init init_ioports(void) | ||
102 | { | ||
103 | int i; | ||
104 | |||
105 | for (i = 0; i < ARRAY_SIZE(mpc8272_ads_pins); i++) { | ||
106 | struct cpm_pin *pin = &mpc8272_ads_pins[i]; | ||
107 | cpm2_set_pin(pin->port, pin->pin, pin->flags); | ||
108 | } | ||
109 | |||
110 | cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX); | ||
111 | cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX); | ||
112 | cpm2_clk_setup(CPM_CLK_SCC4, CPM_BRG4, CPM_CLK_RX); | ||
113 | cpm2_clk_setup(CPM_CLK_SCC4, CPM_BRG4, CPM_CLK_TX); | ||
114 | cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK11, CPM_CLK_RX); | ||
115 | cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_TX); | ||
116 | cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK15, CPM_CLK_RX); | ||
117 | cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK16, CPM_CLK_TX); | ||
118 | } | ||
119 | |||
120 | static void __init mpc8272_ads_setup_arch(void) | ||
121 | { | ||
122 | struct device_node *np; | ||
123 | __be32 __iomem *bcsr; | ||
124 | |||
125 | if (ppc_md.progress) | ||
126 | ppc_md.progress("mpc8272_ads_setup_arch()", 0); | ||
127 | |||
128 | cpm2_reset(); | ||
129 | |||
130 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc8272ads-bcsr"); | ||
131 | if (!np) { | ||
132 | printk(KERN_ERR "No bcsr in device tree\n"); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | bcsr = of_iomap(np, 0); | ||
137 | if (!bcsr) { | ||
138 | printk(KERN_ERR "Cannot map BCSR registers\n"); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | of_node_put(np); | ||
143 | |||
144 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); | ||
145 | setbits32(&bcsr[1], BCSR1_FETH_RST); | ||
146 | |||
147 | clrbits32(&bcsr[3], BCSR3_FETHIEN2); | ||
148 | setbits32(&bcsr[3], BCSR3_FETH2_RST); | ||
149 | |||
150 | iounmap(bcsr); | ||
151 | |||
152 | init_ioports(); | ||
153 | pq2_init_pci(); | ||
154 | |||
155 | if (ppc_md.progress) | ||
156 | ppc_md.progress("mpc8272_ads_setup_arch(), finish", 0); | ||
157 | } | ||
158 | |||
159 | static struct of_device_id __initdata of_bus_ids[] = { | ||
160 | { .name = "soc", }, | ||
161 | { .name = "cpm", }, | ||
162 | { .name = "localbus", }, | ||
163 | {}, | ||
164 | }; | ||
165 | |||
166 | static int __init declare_of_platform_devices(void) | ||
167 | { | ||
168 | if (!machine_is(mpc8272_ads)) | ||
169 | return 0; | ||
170 | |||
171 | /* Publish the QE devices */ | ||
172 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
173 | return 0; | ||
174 | } | ||
175 | device_initcall(declare_of_platform_devices); | ||
176 | |||
177 | /* | ||
178 | * Called very early, device-tree isn't unflattened | ||
179 | */ | ||
180 | static int __init mpc8272_ads_probe(void) | ||
181 | { | ||
182 | unsigned long root = of_get_flat_dt_root(); | ||
183 | return of_flat_dt_is_compatible(root, "fsl,mpc8272ads"); | ||
184 | } | ||
185 | |||
186 | define_machine(mpc8272_ads) | ||
187 | { | ||
188 | .name = "Freescale MPC8272 ADS", | ||
189 | .probe = mpc8272_ads_probe, | ||
190 | .setup_arch = mpc8272_ads_setup_arch, | ||
191 | .init_IRQ = mpc8272_ads_pic_init, | ||
192 | .get_irq = cpm2_get_irq, | ||
193 | .calibrate_decr = generic_calibrate_decr, | ||
194 | .restart = pq2_restart, | ||
195 | .progress = udbg_progress, | ||
196 | }; | ||
diff --git a/arch/powerpc/platforms/82xx/mpc82xx.c b/arch/powerpc/platforms/82xx/mpc82xx.c deleted file mode 100644 index cc9900d2e5ee..000000000000 --- a/arch/powerpc/platforms/82xx/mpc82xx.c +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
1 | /* | ||
2 | * MPC82xx setup and early boot code plus other random bits. | ||
3 | * | ||
4 | * Author: Vitaly Bordug <vbordug@ru.mvista.com> | ||
5 | * | ||
6 | * Copyright (c) 2006 MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/stddef.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/reboot.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/kdev_t.h> | ||
22 | #include <linux/major.h> | ||
23 | #include <linux/console.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | #include <linux/root_dev.h> | ||
27 | #include <linux/initrd.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/fsl_devices.h> | ||
30 | #include <linux/fs_uart_pd.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/pgtable.h> | ||
34 | #include <asm/page.h> | ||
35 | #include <asm/atomic.h> | ||
36 | #include <asm/time.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/machdep.h> | ||
39 | #include <asm/bootinfo.h> | ||
40 | #include <asm/pci-bridge.h> | ||
41 | #include <asm/mpc8260.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <mm/mmu_decl.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/cpm2.h> | ||
46 | #include <asm/udbg.h> | ||
47 | #include <asm/i8259.h> | ||
48 | #include <linux/fs_enet_pd.h> | ||
49 | |||
50 | #include <sysdev/fsl_soc.h> | ||
51 | #include <sysdev/cpm2_pic.h> | ||
52 | |||
53 | #include "pq2ads.h" | ||
54 | |||
55 | static int __init get_freq(char *name, unsigned long *val) | ||
56 | { | ||
57 | struct device_node *cpu; | ||
58 | const unsigned int *fp; | ||
59 | int found = 0; | ||
60 | |||
61 | /* The cpu node should have timebase and clock frequency properties */ | ||
62 | cpu = of_find_node_by_type(NULL, "cpu"); | ||
63 | |||
64 | if (cpu) { | ||
65 | fp = of_get_property(cpu, name, NULL); | ||
66 | if (fp) { | ||
67 | found = 1; | ||
68 | *val = *fp; | ||
69 | } | ||
70 | |||
71 | of_node_put(cpu); | ||
72 | } | ||
73 | |||
74 | return found; | ||
75 | } | ||
76 | |||
77 | void __init m82xx_calibrate_decr(void) | ||
78 | { | ||
79 | ppc_tb_freq = 125000000; | ||
80 | if (!get_freq("bus-frequency", &ppc_tb_freq)) { | ||
81 | printk(KERN_ERR "WARNING: Estimating decrementer frequency " | ||
82 | "(not found)\n"); | ||
83 | } | ||
84 | ppc_tb_freq /= 4; | ||
85 | ppc_proc_freq = 1000000000; | ||
86 | if (!get_freq("clock-frequency", &ppc_proc_freq)) | ||
87 | printk(KERN_ERR "WARNING: Estimating processor frequency" | ||
88 | "(not found)\n"); | ||
89 | } | ||
90 | |||
91 | void mpc82xx_ads_show_cpuinfo(struct seq_file *m) | ||
92 | { | ||
93 | uint pvid, svid, phid1; | ||
94 | uint memsize = total_memory; | ||
95 | |||
96 | pvid = mfspr(SPRN_PVR); | ||
97 | svid = mfspr(SPRN_SVR); | ||
98 | |||
99 | seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); | ||
100 | seq_printf(m, "Machine\t\t: %s\n", CPUINFO_MACHINE); | ||
101 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
102 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
103 | |||
104 | /* Display cpu Pll setting */ | ||
105 | phid1 = mfspr(SPRN_HID1); | ||
106 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
107 | |||
108 | /* Display the amount of memory */ | ||
109 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
110 | } | ||
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c deleted file mode 100644 index 2d1b05b9f8ef..000000000000 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ /dev/null | |||
@@ -1,641 +0,0 @@ | |||
1 | /* | ||
2 | * MPC82xx_ads setup and early boot code plus other random bits. | ||
3 | * | ||
4 | * Author: Vitaly Bordug <vbordug@ru.mvista.com> | ||
5 | * m82xx_restart fix by Wade Farnsworth <wfarnsworth@mvista.com> | ||
6 | * | ||
7 | * Copyright (c) 2006 MontaVista Software, Inc. | ||
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 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/kdev_t.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/root_dev.h> | ||
28 | #include <linux/initrd.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/fsl_devices.h> | ||
31 | #include <linux/fs_uart_pd.h> | ||
32 | |||
33 | #include <asm/system.h> | ||
34 | #include <asm/pgtable.h> | ||
35 | #include <asm/page.h> | ||
36 | #include <asm/atomic.h> | ||
37 | #include <asm/time.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/machdep.h> | ||
40 | #include <asm/bootinfo.h> | ||
41 | #include <asm/pci-bridge.h> | ||
42 | #include <asm/mpc8260.h> | ||
43 | #include <asm/irq.h> | ||
44 | #include <mm/mmu_decl.h> | ||
45 | #include <asm/prom.h> | ||
46 | #include <asm/cpm2.h> | ||
47 | #include <asm/udbg.h> | ||
48 | #include <asm/i8259.h> | ||
49 | #include <linux/fs_enet_pd.h> | ||
50 | |||
51 | #include <sysdev/fsl_soc.h> | ||
52 | #include <sysdev/cpm2_pic.h> | ||
53 | |||
54 | #include "pq2ads.h" | ||
55 | |||
56 | #ifdef CONFIG_PCI | ||
57 | static uint pci_clk_frq; | ||
58 | static struct { | ||
59 | unsigned long *pci_int_stat_reg; | ||
60 | unsigned long *pci_int_mask_reg; | ||
61 | } pci_regs; | ||
62 | |||
63 | static unsigned long pci_int_base; | ||
64 | static struct irq_host *pci_pic_host; | ||
65 | static struct device_node *pci_pic_node; | ||
66 | #endif | ||
67 | |||
68 | static void __init mpc82xx_ads_pic_init(void) | ||
69 | { | ||
70 | struct device_node *np = of_find_compatible_node(NULL, "cpm-pic", "CPM2"); | ||
71 | struct resource r; | ||
72 | cpm2_map_t *cpm_reg; | ||
73 | |||
74 | if (np == NULL) { | ||
75 | printk(KERN_ERR "PIC init: can not find cpm-pic node\n"); | ||
76 | return; | ||
77 | } | ||
78 | if (of_address_to_resource(np, 0, &r)) { | ||
79 | printk(KERN_ERR "PIC init: invalid resource\n"); | ||
80 | of_node_put(np); | ||
81 | return; | ||
82 | } | ||
83 | cpm2_pic_init(np); | ||
84 | of_node_put(np); | ||
85 | |||
86 | /* Initialize the default interrupt mapping priorities, | ||
87 | * in case the boot rom changed something on us. | ||
88 | */ | ||
89 | cpm_reg = (cpm2_map_t *) ioremap(get_immrbase(), sizeof(cpm2_map_t)); | ||
90 | cpm_reg->im_intctl.ic_siprr = 0x05309770; | ||
91 | iounmap(cpm_reg); | ||
92 | #ifdef CONFIG_PCI | ||
93 | /* Initialize stuff for the 82xx CPLD IC and install demux */ | ||
94 | m82xx_pci_init_irq(); | ||
95 | #endif | ||
96 | } | ||
97 | |||
98 | static void init_fcc1_ioports(struct fs_platform_info *fpi) | ||
99 | { | ||
100 | struct io_port *io; | ||
101 | u32 tempval; | ||
102 | cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); | ||
103 | struct device_node *np; | ||
104 | struct resource r; | ||
105 | u32 *bcsr; | ||
106 | |||
107 | np = of_find_node_by_type(NULL, "memory"); | ||
108 | if (!np) { | ||
109 | printk(KERN_INFO "No memory node in device tree\n"); | ||
110 | return; | ||
111 | } | ||
112 | if (of_address_to_resource(np, 1, &r)) { | ||
113 | printk(KERN_INFO "No memory reg property [1] in devicetree\n"); | ||
114 | return; | ||
115 | } | ||
116 | of_node_put(np); | ||
117 | bcsr = ioremap(r.start + 4, sizeof(u32)); | ||
118 | io = &immap->im_ioport; | ||
119 | |||
120 | /* Enable the PHY */ | ||
121 | clrbits32(bcsr, BCSR1_FETHIEN); | ||
122 | setbits32(bcsr, BCSR1_FETH_RST); | ||
123 | |||
124 | /* FCC1 pins are on port A/C. */ | ||
125 | /* Configure port A and C pins for FCC1 Ethernet. */ | ||
126 | |||
127 | tempval = in_be32(&io->iop_pdira); | ||
128 | tempval &= ~PA1_DIRA0; | ||
129 | tempval |= PA1_DIRA1; | ||
130 | out_be32(&io->iop_pdira, tempval); | ||
131 | |||
132 | tempval = in_be32(&io->iop_psora); | ||
133 | tempval &= ~PA1_PSORA0; | ||
134 | tempval |= PA1_PSORA1; | ||
135 | out_be32(&io->iop_psora, tempval); | ||
136 | |||
137 | setbits32(&io->iop_ppara, PA1_DIRA0 | PA1_DIRA1); | ||
138 | |||
139 | /* Alter clocks */ | ||
140 | tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8); | ||
141 | |||
142 | clrbits32(&io->iop_psorc, tempval); | ||
143 | clrbits32(&io->iop_pdirc, tempval); | ||
144 | setbits32(&io->iop_pparc, tempval); | ||
145 | |||
146 | cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_rx, CPM_CLK_RX); | ||
147 | cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_tx, CPM_CLK_TX); | ||
148 | |||
149 | iounmap(bcsr); | ||
150 | iounmap(immap); | ||
151 | } | ||
152 | |||
153 | static void init_fcc2_ioports(struct fs_platform_info *fpi) | ||
154 | { | ||
155 | cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); | ||
156 | struct device_node *np; | ||
157 | struct resource r; | ||
158 | u32 *bcsr; | ||
159 | |||
160 | struct io_port *io; | ||
161 | u32 tempval; | ||
162 | |||
163 | np = of_find_node_by_type(NULL, "memory"); | ||
164 | if (!np) { | ||
165 | printk(KERN_INFO "No memory node in device tree\n"); | ||
166 | return; | ||
167 | } | ||
168 | if (of_address_to_resource(np, 1, &r)) { | ||
169 | printk(KERN_INFO "No memory reg property [1] in devicetree\n"); | ||
170 | return; | ||
171 | } | ||
172 | of_node_put(np); | ||
173 | io = &immap->im_ioport; | ||
174 | bcsr = ioremap(r.start + 12, sizeof(u32)); | ||
175 | |||
176 | /* Enable the PHY */ | ||
177 | clrbits32(bcsr, BCSR3_FETHIEN2); | ||
178 | setbits32(bcsr, BCSR3_FETH2_RST); | ||
179 | |||
180 | /* FCC2 are port B/C. */ | ||
181 | /* Configure port A and C pins for FCC2 Ethernet. */ | ||
182 | |||
183 | tempval = in_be32(&io->iop_pdirb); | ||
184 | tempval &= ~PB2_DIRB0; | ||
185 | tempval |= PB2_DIRB1; | ||
186 | out_be32(&io->iop_pdirb, tempval); | ||
187 | |||
188 | tempval = in_be32(&io->iop_psorb); | ||
189 | tempval &= ~PB2_PSORB0; | ||
190 | tempval |= PB2_PSORB1; | ||
191 | out_be32(&io->iop_psorb, tempval); | ||
192 | |||
193 | setbits32(&io->iop_pparb, PB2_DIRB0 | PB2_DIRB1); | ||
194 | |||
195 | tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8); | ||
196 | |||
197 | /* Alter clocks */ | ||
198 | clrbits32(&io->iop_psorc, tempval); | ||
199 | clrbits32(&io->iop_pdirc, tempval); | ||
200 | setbits32(&io->iop_pparc, tempval); | ||
201 | |||
202 | cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_rx, CPM_CLK_RX); | ||
203 | cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_tx, CPM_CLK_TX); | ||
204 | |||
205 | iounmap(bcsr); | ||
206 | iounmap(immap); | ||
207 | } | ||
208 | |||
209 | void init_fcc_ioports(struct fs_platform_info *fpi) | ||
210 | { | ||
211 | int fcc_no = fs_get_fcc_index(fpi->fs_no); | ||
212 | |||
213 | switch (fcc_no) { | ||
214 | case 0: | ||
215 | init_fcc1_ioports(fpi); | ||
216 | break; | ||
217 | case 1: | ||
218 | init_fcc2_ioports(fpi); | ||
219 | break; | ||
220 | default: | ||
221 | printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n"); | ||
222 | return; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void init_scc1_uart_ioports(struct fs_uart_platform_info *data) | ||
227 | { | ||
228 | cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); | ||
229 | |||
230 | /* SCC1 is only on port D */ | ||
231 | setbits32(&immap->im_ioport.iop_ppard, 0x00000003); | ||
232 | clrbits32(&immap->im_ioport.iop_psord, 0x00000001); | ||
233 | setbits32(&immap->im_ioport.iop_psord, 0x00000002); | ||
234 | clrbits32(&immap->im_ioport.iop_pdird, 0x00000001); | ||
235 | setbits32(&immap->im_ioport.iop_pdird, 0x00000002); | ||
236 | |||
237 | clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx))); | ||
238 | clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx))); | ||
239 | setbits32(&immap->im_cpmux.cmx_scr, | ||
240 | ((data->clk_tx - 1) << (4 - data->clk_tx))); | ||
241 | setbits32(&immap->im_cpmux.cmx_scr, | ||
242 | ((data->clk_rx - 1) << (4 - data->clk_rx))); | ||
243 | |||
244 | iounmap(immap); | ||
245 | } | ||
246 | |||
247 | static void init_scc4_uart_ioports(struct fs_uart_platform_info *data) | ||
248 | { | ||
249 | cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); | ||
250 | |||
251 | setbits32(&immap->im_ioport.iop_ppard, 0x00000600); | ||
252 | clrbits32(&immap->im_ioport.iop_psord, 0x00000600); | ||
253 | clrbits32(&immap->im_ioport.iop_pdird, 0x00000200); | ||
254 | setbits32(&immap->im_ioport.iop_pdird, 0x00000400); | ||
255 | |||
256 | clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx))); | ||
257 | clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx))); | ||
258 | setbits32(&immap->im_cpmux.cmx_scr, | ||
259 | ((data->clk_tx - 1) << (4 - data->clk_tx))); | ||
260 | setbits32(&immap->im_cpmux.cmx_scr, | ||
261 | ((data->clk_rx - 1) << (4 - data->clk_rx))); | ||
262 | |||
263 | iounmap(immap); | ||
264 | } | ||
265 | |||
266 | void init_scc_ioports(struct fs_uart_platform_info *data) | ||
267 | { | ||
268 | int scc_no = fs_get_scc_index(data->fs_no); | ||
269 | |||
270 | switch (scc_no) { | ||
271 | case 0: | ||
272 | init_scc1_uart_ioports(data); | ||
273 | data->brg = data->clk_rx; | ||
274 | break; | ||
275 | case 3: | ||
276 | init_scc4_uart_ioports(data); | ||
277 | data->brg = data->clk_rx; | ||
278 | break; | ||
279 | default: | ||
280 | printk(KERN_ERR "init_scc_ioports: invalid SCC number\n"); | ||
281 | return; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | void __init m82xx_board_setup(void) | ||
286 | { | ||
287 | cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); | ||
288 | struct device_node *np; | ||
289 | struct resource r; | ||
290 | u32 *bcsr; | ||
291 | |||
292 | np = of_find_node_by_type(NULL, "memory"); | ||
293 | if (!np) { | ||
294 | printk(KERN_INFO "No memory node in device tree\n"); | ||
295 | return; | ||
296 | } | ||
297 | if (of_address_to_resource(np, 1, &r)) { | ||
298 | printk(KERN_INFO "No memory reg property [1] in devicetree\n"); | ||
299 | return; | ||
300 | } | ||
301 | of_node_put(np); | ||
302 | bcsr = ioremap(r.start + 4, sizeof(u32)); | ||
303 | /* Enable the 2nd UART port */ | ||
304 | clrbits32(bcsr, BCSR1_RS232_EN2); | ||
305 | |||
306 | #ifdef CONFIG_SERIAL_CPM_SCC1 | ||
307 | clrbits32((u32 *) & immap->im_scc[0].scc_sccm, | ||
308 | UART_SCCM_TX | UART_SCCM_RX); | ||
309 | clrbits32((u32 *) & immap->im_scc[0].scc_gsmrl, | ||
310 | SCC_GSMRL_ENR | SCC_GSMRL_ENT); | ||
311 | #endif | ||
312 | |||
313 | #ifdef CONFIG_SERIAL_CPM_SCC2 | ||
314 | clrbits32((u32 *) & immap->im_scc[1].scc_sccm, | ||
315 | UART_SCCM_TX | UART_SCCM_RX); | ||
316 | clrbits32((u32 *) & immap->im_scc[1].scc_gsmrl, | ||
317 | SCC_GSMRL_ENR | SCC_GSMRL_ENT); | ||
318 | #endif | ||
319 | |||
320 | #ifdef CONFIG_SERIAL_CPM_SCC3 | ||
321 | clrbits32((u32 *) & immap->im_scc[2].scc_sccm, | ||
322 | UART_SCCM_TX | UART_SCCM_RX); | ||
323 | clrbits32((u32 *) & immap->im_scc[2].scc_gsmrl, | ||
324 | SCC_GSMRL_ENR | SCC_GSMRL_ENT); | ||
325 | #endif | ||
326 | |||
327 | #ifdef CONFIG_SERIAL_CPM_SCC4 | ||
328 | clrbits32((u32 *) & immap->im_scc[3].scc_sccm, | ||
329 | UART_SCCM_TX | UART_SCCM_RX); | ||
330 | clrbits32((u32 *) & immap->im_scc[3].scc_gsmrl, | ||
331 | SCC_GSMRL_ENR | SCC_GSMRL_ENT); | ||
332 | #endif | ||
333 | |||
334 | iounmap(bcsr); | ||
335 | iounmap(immap); | ||
336 | } | ||
337 | |||
338 | #ifdef CONFIG_PCI | ||
339 | static void m82xx_pci_mask_irq(unsigned int irq) | ||
340 | { | ||
341 | int bit = irq - pci_int_base; | ||
342 | |||
343 | *pci_regs.pci_int_mask_reg |= (1 << (31 - bit)); | ||
344 | return; | ||
345 | } | ||
346 | |||
347 | static void m82xx_pci_unmask_irq(unsigned int irq) | ||
348 | { | ||
349 | int bit = irq - pci_int_base; | ||
350 | |||
351 | *pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit)); | ||
352 | return; | ||
353 | } | ||
354 | |||
355 | static void m82xx_pci_mask_and_ack(unsigned int irq) | ||
356 | { | ||
357 | int bit = irq - pci_int_base; | ||
358 | |||
359 | *pci_regs.pci_int_mask_reg |= (1 << (31 - bit)); | ||
360 | return; | ||
361 | } | ||
362 | |||
363 | static void m82xx_pci_end_irq(unsigned int irq) | ||
364 | { | ||
365 | int bit = irq - pci_int_base; | ||
366 | |||
367 | *pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit)); | ||
368 | return; | ||
369 | } | ||
370 | |||
371 | struct hw_interrupt_type m82xx_pci_ic = { | ||
372 | .typename = "MPC82xx ADS PCI", | ||
373 | .name = "MPC82xx ADS PCI", | ||
374 | .enable = m82xx_pci_unmask_irq, | ||
375 | .disable = m82xx_pci_mask_irq, | ||
376 | .ack = m82xx_pci_mask_and_ack, | ||
377 | .end = m82xx_pci_end_irq, | ||
378 | .mask = m82xx_pci_mask_irq, | ||
379 | .mask_ack = m82xx_pci_mask_and_ack, | ||
380 | .unmask = m82xx_pci_unmask_irq, | ||
381 | .eoi = m82xx_pci_end_irq, | ||
382 | }; | ||
383 | |||
384 | static void | ||
385 | m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
386 | { | ||
387 | unsigned long stat, mask, pend; | ||
388 | int bit; | ||
389 | |||
390 | for (;;) { | ||
391 | stat = *pci_regs.pci_int_stat_reg; | ||
392 | mask = *pci_regs.pci_int_mask_reg; | ||
393 | pend = stat & ~mask & 0xf0000000; | ||
394 | if (!pend) | ||
395 | break; | ||
396 | for (bit = 0; pend != 0; ++bit, pend <<= 1) { | ||
397 | if (pend & 0x80000000) | ||
398 | __do_IRQ(pci_int_base + bit); | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static int pci_pic_host_match(struct irq_host *h, struct device_node *node) | ||
404 | { | ||
405 | return node == pci_pic_node; | ||
406 | } | ||
407 | |||
408 | static int pci_pic_host_map(struct irq_host *h, unsigned int virq, | ||
409 | irq_hw_number_t hw) | ||
410 | { | ||
411 | get_irq_desc(virq)->status |= IRQ_LEVEL; | ||
412 | set_irq_chip(virq, &m82xx_pci_ic); | ||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static void pci_host_unmap(struct irq_host *h, unsigned int virq) | ||
417 | { | ||
418 | /* remove chip and handler */ | ||
419 | set_irq_chip(virq, NULL); | ||
420 | } | ||
421 | |||
422 | static struct irq_host_ops pci_pic_host_ops = { | ||
423 | .match = pci_pic_host_match, | ||
424 | .map = pci_pic_host_map, | ||
425 | .unmap = pci_host_unmap, | ||
426 | }; | ||
427 | |||
428 | void m82xx_pci_init_irq(void) | ||
429 | { | ||
430 | int irq; | ||
431 | cpm2_map_t *immap; | ||
432 | struct device_node *np; | ||
433 | struct resource r; | ||
434 | const u32 *regs; | ||
435 | unsigned int size; | ||
436 | const u32 *irq_map; | ||
437 | int i; | ||
438 | unsigned int irq_max, irq_min; | ||
439 | |||
440 | if ((np = of_find_node_by_type(NULL, "soc")) == NULL) { | ||
441 | printk(KERN_INFO "No SOC node in device tree\n"); | ||
442 | return; | ||
443 | } | ||
444 | memset(&r, 0, sizeof(r)); | ||
445 | if (of_address_to_resource(np, 0, &r)) { | ||
446 | printk(KERN_INFO "No SOC reg property in device tree\n"); | ||
447 | return; | ||
448 | } | ||
449 | immap = ioremap(r.start, sizeof(*immap)); | ||
450 | of_node_put(np); | ||
451 | |||
452 | /* install the demultiplexer for the PCI cascade interrupt */ | ||
453 | np = of_find_node_by_type(NULL, "pci"); | ||
454 | if (!np) { | ||
455 | printk(KERN_INFO "No pci node on device tree\n"); | ||
456 | iounmap(immap); | ||
457 | return; | ||
458 | } | ||
459 | irq_map = of_get_property(np, "interrupt-map", &size); | ||
460 | if ((!irq_map) || (size <= 7)) { | ||
461 | printk(KERN_INFO "No interrupt-map property of pci node\n"); | ||
462 | iounmap(immap); | ||
463 | return; | ||
464 | } | ||
465 | size /= sizeof(irq_map[0]); | ||
466 | for (i = 0, irq_max = 0, irq_min = 512; i < size; i += 7, irq_map += 7) { | ||
467 | if (irq_map[5] < irq_min) | ||
468 | irq_min = irq_map[5]; | ||
469 | if (irq_map[5] > irq_max) | ||
470 | irq_max = irq_map[5]; | ||
471 | } | ||
472 | pci_int_base = irq_min; | ||
473 | irq = irq_of_parse_and_map(np, 0); | ||
474 | set_irq_chained_handler(irq, m82xx_pci_irq_demux); | ||
475 | of_node_put(np); | ||
476 | np = of_find_node_by_type(NULL, "pci-pic"); | ||
477 | if (!np) { | ||
478 | printk(KERN_INFO "No pci pic node on device tree\n"); | ||
479 | iounmap(immap); | ||
480 | return; | ||
481 | } | ||
482 | pci_pic_node = of_node_get(np); | ||
483 | /* PCI interrupt controller registers: status and mask */ | ||
484 | regs = of_get_property(np, "reg", &size); | ||
485 | if ((!regs) || (size <= 2)) { | ||
486 | printk(KERN_INFO "No reg property in pci pic node\n"); | ||
487 | iounmap(immap); | ||
488 | return; | ||
489 | } | ||
490 | pci_regs.pci_int_stat_reg = | ||
491 | ioremap(regs[0], sizeof(*pci_regs.pci_int_stat_reg)); | ||
492 | pci_regs.pci_int_mask_reg = | ||
493 | ioremap(regs[1], sizeof(*pci_regs.pci_int_mask_reg)); | ||
494 | of_node_put(np); | ||
495 | /* configure chip select for PCI interrupt controller */ | ||
496 | immap->im_memctl.memc_br3 = regs[0] | 0x00001801; | ||
497 | immap->im_memctl.memc_or3 = 0xffff8010; | ||
498 | /* make PCI IRQ level sensitive */ | ||
499 | immap->im_intctl.ic_siexr &= ~(1 << (14 - (irq - SIU_INT_IRQ1))); | ||
500 | |||
501 | /* mask all PCI interrupts */ | ||
502 | *pci_regs.pci_int_mask_reg |= 0xfff00000; | ||
503 | iounmap(immap); | ||
504 | pci_pic_host = | ||
505 | irq_alloc_host(IRQ_HOST_MAP_LINEAR, irq_max - irq_min + 1, | ||
506 | &pci_pic_host_ops, irq_max + 1); | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | static int m82xx_pci_exclude_device(struct pci_controller *hose, | ||
511 | u_char bus, u_char devfn) | ||
512 | { | ||
513 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
514 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
515 | else | ||
516 | return PCIBIOS_SUCCESSFUL; | ||
517 | } | ||
518 | |||
519 | static void __init mpc82xx_add_bridge(struct device_node *np) | ||
520 | { | ||
521 | int len; | ||
522 | struct pci_controller *hose; | ||
523 | struct resource r; | ||
524 | const int *bus_range; | ||
525 | const uint *ptr; | ||
526 | |||
527 | memset(&r, 0, sizeof(r)); | ||
528 | if (of_address_to_resource(np, 0, &r)) { | ||
529 | printk(KERN_INFO "No PCI reg property in device tree\n"); | ||
530 | return; | ||
531 | } | ||
532 | if (!(ptr = of_get_property(np, "clock-frequency", NULL))) { | ||
533 | printk(KERN_INFO "No clock-frequency property in PCI node"); | ||
534 | return; | ||
535 | } | ||
536 | pci_clk_frq = *ptr; | ||
537 | of_node_put(np); | ||
538 | bus_range = of_get_property(np, "bus-range", &len); | ||
539 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
540 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | ||
541 | " bus 0\n", np->full_name); | ||
542 | } | ||
543 | |||
544 | pci_assign_all_buses = 1; | ||
545 | |||
546 | hose = pcibios_alloc_controller(np); | ||
547 | |||
548 | if (!hose) | ||
549 | return; | ||
550 | |||
551 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
552 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
553 | |||
554 | setup_indirect_pci(hose, | ||
555 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), | ||
556 | r.start + offsetof(pci_cpm2_t, pci_cfg_data), | ||
557 | 0); | ||
558 | |||
559 | pci_process_bridge_OF_ranges(hose, np, 1); | ||
560 | } | ||
561 | #endif | ||
562 | |||
563 | /* | ||
564 | * Setup the architecture | ||
565 | */ | ||
566 | static void __init mpc82xx_ads_setup_arch(void) | ||
567 | { | ||
568 | #ifdef CONFIG_PCI | ||
569 | struct device_node *np; | ||
570 | #endif | ||
571 | |||
572 | if (ppc_md.progress) | ||
573 | ppc_md.progress("mpc82xx_ads_setup_arch()", 0); | ||
574 | cpm2_reset(); | ||
575 | |||
576 | /* Map I/O region to a 256MB BAT */ | ||
577 | |||
578 | m82xx_board_setup(); | ||
579 | |||
580 | #ifdef CONFIG_PCI | ||
581 | ppc_md.pci_exclude_device = m82xx_pci_exclude_device; | ||
582 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | ||
583 | mpc82xx_add_bridge(np); | ||
584 | |||
585 | of_node_put(np); | ||
586 | #endif | ||
587 | |||
588 | #ifdef CONFIG_ROOT_NFS | ||
589 | ROOT_DEV = Root_NFS; | ||
590 | #else | ||
591 | ROOT_DEV = Root_HDA1; | ||
592 | #endif | ||
593 | |||
594 | if (ppc_md.progress) | ||
595 | ppc_md.progress("mpc82xx_ads_setup_arch(), finish", 0); | ||
596 | } | ||
597 | |||
598 | /* | ||
599 | * Called very early, device-tree isn't unflattened | ||
600 | */ | ||
601 | static int __init mpc82xx_ads_probe(void) | ||
602 | { | ||
603 | /* We always match for now, eventually we should look at | ||
604 | * the flat dev tree to ensure this is the board we are | ||
605 | * supposed to run on | ||
606 | */ | ||
607 | return 1; | ||
608 | } | ||
609 | |||
610 | #define RMR_CSRE 0x00000001 | ||
611 | static void m82xx_restart(char *cmd) | ||
612 | { | ||
613 | __volatile__ unsigned char dummy; | ||
614 | |||
615 | local_irq_disable(); | ||
616 | ((cpm2_map_t *) cpm2_immr)->im_clkrst.car_rmr |= RMR_CSRE; | ||
617 | |||
618 | /* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */ | ||
619 | mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR)); | ||
620 | dummy = ((cpm2_map_t *) cpm2_immr)->im_clkrst.res[0]; | ||
621 | printk("Restart failed\n"); | ||
622 | while (1) ; | ||
623 | } | ||
624 | |||
625 | static void m82xx_halt(void) | ||
626 | { | ||
627 | local_irq_disable(); | ||
628 | while (1) ; | ||
629 | } | ||
630 | |||
631 | define_machine(mpc82xx_ads) | ||
632 | { | ||
633 | .name = "MPC82xx ADS", | ||
634 | .probe = mpc82xx_ads_probe, | ||
635 | .setup_arch = mpc82xx_ads_setup_arch, | ||
636 | .init_IRQ = mpc82xx_ads_pic_init, | ||
637 | .show_cpuinfo = mpc82xx_ads_show_cpuinfo, | ||
638 | .get_irq = cpm2_get_irq, | ||
639 | .calibrate_decr = m82xx_calibrate_decr, | ||
640 | .restart = m82xx_restart,.halt = m82xx_halt, | ||
641 | }; | ||
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c new file mode 100644 index 000000000000..a497cbaa1ac5 --- /dev/null +++ b/arch/powerpc/platforms/82xx/pq2.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Common PowerQUICC II code. | ||
3 | * | ||
4 | * Author: Scott Wood <scottwood@freescale.com> | ||
5 | * Copyright (c) 2007 Freescale Semiconductor | ||
6 | * | ||
7 | * Based on code by Vitaly Bordug <vbordug@ru.mvista.com> | ||
8 | * pq2_restart fix by Wade Farnsworth <wfarnsworth@mvista.com> | ||
9 | * Copyright (c) 2006 MontaVista Software, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <asm/cpm2.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/pci-bridge.h> | ||
20 | #include <asm/system.h> | ||
21 | |||
22 | #include <platforms/82xx/pq2.h> | ||
23 | |||
24 | #define RMR_CSRE 0x00000001 | ||
25 | |||
26 | void pq2_restart(char *cmd) | ||
27 | { | ||
28 | local_irq_disable(); | ||
29 | setbits32(&cpm2_immr->im_clkrst.car_rmr, RMR_CSRE); | ||
30 | |||
31 | /* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */ | ||
32 | mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR)); | ||
33 | in_8(&cpm2_immr->im_clkrst.res[0]); | ||
34 | |||
35 | panic("Restart failed\n"); | ||
36 | } | ||
37 | |||
38 | #ifdef CONFIG_PCI | ||
39 | static int pq2_pci_exclude_device(struct pci_controller *hose, | ||
40 | u_char bus, u8 devfn) | ||
41 | { | ||
42 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
43 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
44 | else | ||
45 | return PCIBIOS_SUCCESSFUL; | ||
46 | } | ||
47 | |||
48 | static void __init pq2_pci_add_bridge(struct device_node *np) | ||
49 | { | ||
50 | struct pci_controller *hose; | ||
51 | struct resource r; | ||
52 | |||
53 | if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b) | ||
54 | goto err; | ||
55 | |||
56 | pci_assign_all_buses = 1; | ||
57 | |||
58 | hose = pcibios_alloc_controller(np); | ||
59 | if (!hose) | ||
60 | return; | ||
61 | |||
62 | hose->arch_data = np; | ||
63 | |||
64 | setup_indirect_pci(hose, r.start + 0x100, r.start + 0x104, 0); | ||
65 | pci_process_bridge_OF_ranges(hose, np, 1); | ||
66 | |||
67 | return; | ||
68 | |||
69 | err: | ||
70 | printk(KERN_ERR "No valid PCI reg property in device tree\n"); | ||
71 | } | ||
72 | |||
73 | void __init pq2_init_pci(void) | ||
74 | { | ||
75 | struct device_node *np = NULL; | ||
76 | |||
77 | ppc_md.pci_exclude_device = pq2_pci_exclude_device; | ||
78 | |||
79 | while ((np = of_find_compatible_node(np, NULL, "fsl,pq2-pci"))) | ||
80 | pq2_pci_add_bridge(np); | ||
81 | } | ||
82 | #endif | ||
diff --git a/arch/powerpc/platforms/82xx/pq2.h b/arch/powerpc/platforms/82xx/pq2.h new file mode 100644 index 000000000000..a41f84ae2325 --- /dev/null +++ b/arch/powerpc/platforms/82xx/pq2.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef _PQ2_H | ||
2 | #define _PQ2_H | ||
3 | |||
4 | void pq2_restart(char *cmd); | ||
5 | |||
6 | #ifdef CONFIG_PCI | ||
7 | int pq2ads_pci_init_irq(void); | ||
8 | void pq2_init_pci(void); | ||
9 | #else | ||
10 | static inline int pq2ads_pci_init_irq(void) | ||
11 | { | ||
12 | return 0; | ||
13 | } | ||
14 | |||
15 | static inline void pq2_init_pci(void) | ||
16 | { | ||
17 | } | ||
18 | #endif | ||
19 | |||
20 | #endif | ||
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c new file mode 100644 index 000000000000..a8013816125c --- /dev/null +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * PQ2 ADS-style PCI interrupt controller | ||
3 | * | ||
4 | * Copyright 2007 Freescale Semiconductor, Inc. | ||
5 | * Author: Scott Wood <scottwood@freescale.com> | ||
6 | * | ||
7 | * Loosely based on mpc82xx ADS support by Vitaly Bordug <vbordug@ru.mvista.com> | ||
8 | * Copyright (c) 2006 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 version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/bootmem.h> | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | #include <asm/prom.h> | ||
23 | #include <asm/cpm2.h> | ||
24 | |||
25 | #include "pq2.h" | ||
26 | |||
27 | static DEFINE_SPINLOCK(pci_pic_lock); | ||
28 | |||
29 | struct pq2ads_pci_pic { | ||
30 | struct device_node *node; | ||
31 | struct irq_host *host; | ||
32 | |||
33 | struct { | ||
34 | u32 stat; | ||
35 | u32 mask; | ||
36 | } __iomem *regs; | ||
37 | }; | ||
38 | |||
39 | #define NUM_IRQS 32 | ||
40 | |||
41 | static void pq2ads_pci_mask_irq(unsigned int virq) | ||
42 | { | ||
43 | struct pq2ads_pci_pic *priv = get_irq_chip_data(virq); | ||
44 | int irq = NUM_IRQS - virq_to_hw(virq) - 1; | ||
45 | |||
46 | if (irq != -1) { | ||
47 | unsigned long flags; | ||
48 | spin_lock_irqsave(&pci_pic_lock, flags); | ||
49 | |||
50 | setbits32(&priv->regs->mask, 1 << irq); | ||
51 | mb(); | ||
52 | |||
53 | spin_unlock_irqrestore(&pci_pic_lock, flags); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | static void pq2ads_pci_unmask_irq(unsigned int virq) | ||
58 | { | ||
59 | struct pq2ads_pci_pic *priv = get_irq_chip_data(virq); | ||
60 | int irq = NUM_IRQS - virq_to_hw(virq) - 1; | ||
61 | |||
62 | if (irq != -1) { | ||
63 | unsigned long flags; | ||
64 | |||
65 | spin_lock_irqsave(&pci_pic_lock, flags); | ||
66 | clrbits32(&priv->regs->mask, 1 << irq); | ||
67 | spin_unlock_irqrestore(&pci_pic_lock, flags); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static struct irq_chip pq2ads_pci_ic = { | ||
72 | .typename = "PQ2 ADS PCI", | ||
73 | .name = "PQ2 ADS PCI", | ||
74 | .end = pq2ads_pci_unmask_irq, | ||
75 | .mask = pq2ads_pci_mask_irq, | ||
76 | .mask_ack = pq2ads_pci_mask_irq, | ||
77 | .ack = pq2ads_pci_mask_irq, | ||
78 | .unmask = pq2ads_pci_unmask_irq, | ||
79 | .enable = pq2ads_pci_unmask_irq, | ||
80 | .disable = pq2ads_pci_mask_irq | ||
81 | }; | ||
82 | |||
83 | static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
84 | { | ||
85 | struct pq2ads_pci_pic *priv = desc->handler_data; | ||
86 | u32 stat, mask, pend; | ||
87 | int bit; | ||
88 | |||
89 | for (;;) { | ||
90 | stat = in_be32(&priv->regs->stat); | ||
91 | mask = in_be32(&priv->regs->mask); | ||
92 | |||
93 | pend = stat & ~mask; | ||
94 | |||
95 | if (!pend) | ||
96 | break; | ||
97 | |||
98 | for (bit = 0; pend != 0; ++bit, pend <<= 1) { | ||
99 | if (pend & 0x80000000) { | ||
100 | int virq = irq_linear_revmap(priv->host, bit); | ||
101 | generic_handle_irq(virq); | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static int pci_pic_host_map(struct irq_host *h, unsigned int virq, | ||
108 | irq_hw_number_t hw) | ||
109 | { | ||
110 | get_irq_desc(virq)->status |= IRQ_LEVEL; | ||
111 | set_irq_chip_data(virq, h->host_data); | ||
112 | set_irq_chip(virq, &pq2ads_pci_ic); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void pci_host_unmap(struct irq_host *h, unsigned int virq) | ||
117 | { | ||
118 | /* remove chip and handler */ | ||
119 | set_irq_chip_data(virq, NULL); | ||
120 | set_irq_chip(virq, NULL); | ||
121 | } | ||
122 | |||
123 | static struct irq_host_ops pci_pic_host_ops = { | ||
124 | .map = pci_pic_host_map, | ||
125 | .unmap = pci_host_unmap, | ||
126 | }; | ||
127 | |||
128 | int __init pq2ads_pci_init_irq(void) | ||
129 | { | ||
130 | struct pq2ads_pci_pic *priv; | ||
131 | struct irq_host *host; | ||
132 | struct device_node *np; | ||
133 | int ret = -ENODEV; | ||
134 | int irq; | ||
135 | |||
136 | np = of_find_compatible_node(NULL, NULL, "fsl,pq2ads-pci-pic"); | ||
137 | if (!np) { | ||
138 | printk(KERN_ERR "No pci pic node in device tree.\n"); | ||
139 | of_node_put(np); | ||
140 | goto out; | ||
141 | } | ||
142 | |||
143 | irq = irq_of_parse_and_map(np, 0); | ||
144 | if (irq == NO_IRQ) { | ||
145 | printk(KERN_ERR "No interrupt in pci pic node.\n"); | ||
146 | of_node_put(np); | ||
147 | goto out; | ||
148 | } | ||
149 | |||
150 | priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic)); | ||
151 | if (!priv) { | ||
152 | of_node_put(np); | ||
153 | ret = -ENOMEM; | ||
154 | goto out_unmap_irq; | ||
155 | } | ||
156 | |||
157 | /* PCI interrupt controller registers: status and mask */ | ||
158 | priv->regs = of_iomap(np, 0); | ||
159 | if (!priv->regs) { | ||
160 | printk(KERN_ERR "Cannot map PCI PIC registers.\n"); | ||
161 | goto out_free_bootmem; | ||
162 | } | ||
163 | |||
164 | /* mask all PCI interrupts */ | ||
165 | out_be32(&priv->regs->mask, ~0); | ||
166 | mb(); | ||
167 | |||
168 | host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, NUM_IRQS, | ||
169 | &pci_pic_host_ops, NUM_IRQS); | ||
170 | if (!host) { | ||
171 | ret = -ENOMEM; | ||
172 | goto out_unmap_regs; | ||
173 | } | ||
174 | |||
175 | host->host_data = priv; | ||
176 | |||
177 | priv->host = host; | ||
178 | host->host_data = priv; | ||
179 | set_irq_data(irq, priv); | ||
180 | set_irq_chained_handler(irq, pq2ads_pci_irq_demux); | ||
181 | |||
182 | of_node_put(np); | ||
183 | return 0; | ||
184 | |||
185 | out_unmap_regs: | ||
186 | iounmap(priv->regs); | ||
187 | out_free_bootmem: | ||
188 | free_bootmem((unsigned long)priv, | ||
189 | sizeof(sizeof(struct pq2ads_pci_pic))); | ||
190 | of_node_put(np); | ||
191 | out_unmap_irq: | ||
192 | irq_dispose_mapping(irq); | ||
193 | out: | ||
194 | return ret; | ||
195 | } | ||
diff --git a/arch/powerpc/platforms/82xx/pq2ads.h b/arch/powerpc/platforms/82xx/pq2ads.h index 5b5cca6c8c88..984db42cc8e7 100644 --- a/arch/powerpc/platforms/82xx/pq2ads.h +++ b/arch/powerpc/platforms/82xx/pq2ads.h | |||
@@ -23,11 +23,6 @@ | |||
23 | #define __MACH_ADS8260_DEFS | 23 | #define __MACH_ADS8260_DEFS |
24 | 24 | ||
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <asm/ppcboot.h> | ||
27 | |||
28 | /* For our show_cpuinfo hooks. */ | ||
29 | #define CPUINFO_VENDOR "Freescale Semiconductor" | ||
30 | #define CPUINFO_MACHINE "PQ2 ADS PowerPC" | ||
31 | 26 | ||
32 | /* Backword-compatibility stuff for the drivers */ | 27 | /* Backword-compatibility stuff for the drivers */ |
33 | #define CPM_MAP_ADDR ((uint)0xf0000000) | 28 | #define CPM_MAP_ADDR ((uint)0xf0000000) |
@@ -58,9 +53,5 @@ | |||
58 | #define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET) | 53 | #define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET) |
59 | #define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET) | 54 | #define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET) |
60 | 55 | ||
61 | void m82xx_pci_init_irq(void); | ||
62 | void mpc82xx_ads_show_cpuinfo(struct seq_file*); | ||
63 | void m82xx_calibrate_decr(void); | ||
64 | |||
65 | #endif /* __MACH_ADS8260_DEFS */ | 56 | #endif /* __MACH_ADS8260_DEFS */ |
66 | #endif /* __KERNEL__ */ | 57 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c new file mode 100644 index 000000000000..4f457a9c79ae --- /dev/null +++ b/arch/powerpc/platforms/82xx/pq2fads.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * PQ2FADS board support | ||
3 | * | ||
4 | * Copyright 2007 Freescale Semiconductor, Inc. | ||
5 | * Author: Scott Wood <scottwood@freescale.com> | ||
6 | * | ||
7 | * Loosely based on mp82xx ADS support by Vitaly Bordug <vbordug@ru.mvista.com> | ||
8 | * Copyright (c) 2006 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 version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/fsl_devices.h> | ||
18 | |||
19 | #include <asm/io.h> | ||
20 | #include <asm/cpm2.h> | ||
21 | #include <asm/udbg.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/of_platform.h> | ||
24 | #include <asm/time.h> | ||
25 | |||
26 | #include <sysdev/fsl_soc.h> | ||
27 | #include <sysdev/cpm2_pic.h> | ||
28 | |||
29 | #include "pq2ads.h" | ||
30 | #include "pq2.h" | ||
31 | |||
32 | static void __init pq2fads_pic_init(void) | ||
33 | { | ||
34 | struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic"); | ||
35 | if (!np) { | ||
36 | printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n"); | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | cpm2_pic_init(np); | ||
41 | of_node_put(np); | ||
42 | |||
43 | /* Initialize stuff for the 82xx CPLD IC and install demux */ | ||
44 | pq2ads_pci_init_irq(); | ||
45 | } | ||
46 | |||
47 | struct cpm_pin { | ||
48 | int port, pin, flags; | ||
49 | }; | ||
50 | |||
51 | static struct cpm_pin pq2fads_pins[] = { | ||
52 | /* SCC1 */ | ||
53 | {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
54 | {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
55 | |||
56 | /* SCC2 */ | ||
57 | {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
58 | {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
59 | |||
60 | /* FCC2 */ | ||
61 | {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
62 | {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
63 | {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
64 | {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
65 | {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
66 | {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
67 | {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
68 | {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
69 | {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
70 | {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
71 | {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
72 | {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
73 | {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
74 | {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
75 | {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
76 | {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
77 | |||
78 | /* FCC3 */ | ||
79 | {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
80 | {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
81 | {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
82 | {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
83 | {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
84 | {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
85 | {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
86 | {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
87 | {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
88 | {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
89 | {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
90 | {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
91 | {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
92 | {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
93 | {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
94 | {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
95 | }; | ||
96 | |||
97 | static void __init init_ioports(void) | ||
98 | { | ||
99 | int i; | ||
100 | |||
101 | for (i = 0; i < ARRAY_SIZE(pq2fads_pins); i++) { | ||
102 | struct cpm_pin *pin = &pq2fads_pins[i]; | ||
103 | cpm2_set_pin(pin->port, pin->pin, pin->flags); | ||
104 | } | ||
105 | |||
106 | cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX); | ||
107 | cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX); | ||
108 | cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX); | ||
109 | cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX); | ||
110 | cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX); | ||
111 | cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX); | ||
112 | cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX); | ||
113 | cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX); | ||
114 | } | ||
115 | |||
116 | static void __init pq2fads_setup_arch(void) | ||
117 | { | ||
118 | struct device_node *np; | ||
119 | __be32 __iomem *bcsr; | ||
120 | |||
121 | if (ppc_md.progress) | ||
122 | ppc_md.progress("pq2fads_setup_arch()", 0); | ||
123 | |||
124 | cpm2_reset(); | ||
125 | |||
126 | np = of_find_compatible_node(NULL, NULL, "fsl,pq2fads-bcsr"); | ||
127 | if (!np) { | ||
128 | printk(KERN_ERR "No fsl,pq2fads-bcsr in device tree\n"); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | bcsr = of_iomap(np, 0); | ||
133 | if (!bcsr) { | ||
134 | printk(KERN_ERR "Cannot map BCSR registers\n"); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | of_node_put(np); | ||
139 | |||
140 | /* Enable the serial and ethernet ports */ | ||
141 | |||
142 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); | ||
143 | setbits32(&bcsr[1], BCSR1_FETH_RST); | ||
144 | |||
145 | clrbits32(&bcsr[3], BCSR3_FETHIEN2); | ||
146 | setbits32(&bcsr[3], BCSR3_FETH2_RST); | ||
147 | |||
148 | iounmap(bcsr); | ||
149 | |||
150 | init_ioports(); | ||
151 | |||
152 | /* Enable external IRQs */ | ||
153 | clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_siumcr, 0x0c000000); | ||
154 | |||
155 | pq2_init_pci(); | ||
156 | |||
157 | if (ppc_md.progress) | ||
158 | ppc_md.progress("pq2fads_setup_arch(), finish", 0); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Called very early, device-tree isn't unflattened | ||
163 | */ | ||
164 | static int __init pq2fads_probe(void) | ||
165 | { | ||
166 | unsigned long root = of_get_flat_dt_root(); | ||
167 | return of_flat_dt_is_compatible(root, "fsl,pq2fads"); | ||
168 | } | ||
169 | |||
170 | static struct of_device_id __initdata of_bus_ids[] = { | ||
171 | { .name = "soc", }, | ||
172 | { .name = "cpm", }, | ||
173 | { .name = "localbus", }, | ||
174 | {}, | ||
175 | }; | ||
176 | |||
177 | static int __init declare_of_platform_devices(void) | ||
178 | { | ||
179 | if (!machine_is(pq2fads)) | ||
180 | return 0; | ||
181 | |||
182 | /* Publish the QE devices */ | ||
183 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
184 | return 0; | ||
185 | } | ||
186 | device_initcall(declare_of_platform_devices); | ||
187 | |||
188 | define_machine(pq2fads) | ||
189 | { | ||
190 | .name = "Freescale PQ2FADS", | ||
191 | .probe = pq2fads_probe, | ||
192 | .setup_arch = pq2fads_setup_arch, | ||
193 | .init_IRQ = pq2fads_pic_init, | ||
194 | .get_irq = cpm2_get_irq, | ||
195 | .calibrate_decr = generic_calibrate_decr, | ||
196 | .restart = pq2_restart, | ||
197 | .progress = udbg_progress, | ||
198 | }; | ||
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 3edfe170a03b..33766b8f2594 100644 --- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c | |||
@@ -43,10 +43,8 @@ static void __init mpc8313_rdb_setup_arch(void) | |||
43 | ppc_md.progress("mpc8313_rdb_setup_arch()", 0); | 43 | ppc_md.progress("mpc8313_rdb_setup_arch()", 0); |
44 | 44 | ||
45 | #ifdef CONFIG_PCI | 45 | #ifdef CONFIG_PCI |
46 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 46 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
47 | mpc83xx_add_bridge(np); | 47 | mpc83xx_add_bridge(np); |
48 | |||
49 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
50 | #endif | 48 | #endif |
51 | mpc831x_usb_cfg(); | 49 | mpc831x_usb_cfg(); |
52 | } | 50 | } |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 2c8e641a739b..972fa8528a8c 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
33 | #include <asm/machdep.h> | 33 | #include <asm/machdep.h> |
34 | #include <asm/ipic.h> | 34 | #include <asm/ipic.h> |
35 | #include <asm/bootinfo.h> | ||
36 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
37 | #include <asm/prom.h> | 36 | #include <asm/prom.h> |
38 | #include <asm/udbg.h> | 37 | #include <asm/udbg.h> |
@@ -74,9 +73,8 @@ static void __init mpc832x_sys_setup_arch(void) | |||
74 | } | 73 | } |
75 | 74 | ||
76 | #ifdef CONFIG_PCI | 75 | #ifdef CONFIG_PCI |
77 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 76 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
78 | mpc83xx_add_bridge(np); | 77 | mpc83xx_add_bridge(np); |
79 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
80 | #endif | 78 | #endif |
81 | 79 | ||
82 | #ifdef CONFIG_QUICC_ENGINE | 80 | #ifdef CONFIG_QUICC_ENGINE |
@@ -142,7 +140,7 @@ static void __init mpc832x_sys_init_IRQ(void) | |||
142 | if (!np) | 140 | if (!np) |
143 | return; | 141 | return; |
144 | 142 | ||
145 | qe_ic_init(np, 0); | 143 | qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); |
146 | of_node_put(np); | 144 | of_node_put(np); |
147 | #endif /* CONFIG_QUICC_ENGINE */ | 145 | #endif /* CONFIG_QUICC_ENGINE */ |
148 | } | 146 | } |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 090906170a41..fbca336aa0ae 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/spi/spi.h> | ||
18 | 19 | ||
19 | #include <asm/of_platform.h> | 20 | #include <asm/of_platform.h> |
20 | #include <asm/time.h> | 21 | #include <asm/time.h> |
@@ -22,6 +23,7 @@ | |||
22 | #include <asm/udbg.h> | 23 | #include <asm/udbg.h> |
23 | #include <asm/qe.h> | 24 | #include <asm/qe.h> |
24 | #include <asm/qe_ic.h> | 25 | #include <asm/qe_ic.h> |
26 | #include <sysdev/fsl_soc.h> | ||
25 | 27 | ||
26 | #include "mpc83xx.h" | 28 | #include "mpc83xx.h" |
27 | 29 | ||
@@ -32,6 +34,50 @@ | |||
32 | #define DBG(fmt...) | 34 | #define DBG(fmt...) |
33 | #endif | 35 | #endif |
34 | 36 | ||
37 | static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity) | ||
38 | { | ||
39 | pr_debug("%s %d %d\n", __func__, cs, polarity); | ||
40 | par_io_data_set(3, 13, polarity); | ||
41 | } | ||
42 | |||
43 | static void mpc83xx_spi_deactivate_cs(u8 cs, u8 polarity) | ||
44 | { | ||
45 | pr_debug("%s %d %d\n", __func__, cs, polarity); | ||
46 | par_io_data_set(3, 13, !polarity); | ||
47 | } | ||
48 | |||
49 | static struct spi_board_info mpc832x_spi_boardinfo = { | ||
50 | .bus_num = 0x4c0, | ||
51 | .chip_select = 0, | ||
52 | .max_speed_hz = 50000000, | ||
53 | /* | ||
54 | * XXX: This is spidev (spi in userspace) stub, should | ||
55 | * be replaced by "mmc_spi" when mmc_spi will hit mainline. | ||
56 | */ | ||
57 | .modalias = "spidev", | ||
58 | }; | ||
59 | |||
60 | static int __init mpc832x_spi_init(void) | ||
61 | { | ||
62 | if (!machine_is(mpc832x_rdb)) | ||
63 | return 0; | ||
64 | |||
65 | par_io_config_pin(3, 0, 3, 0, 1, 0); /* SPI1 MOSI, I/O */ | ||
66 | par_io_config_pin(3, 1, 3, 0, 1, 0); /* SPI1 MISO, I/O */ | ||
67 | par_io_config_pin(3, 2, 3, 0, 1, 0); /* SPI1 CLK, I/O */ | ||
68 | par_io_config_pin(3, 3, 2, 0, 1, 0); /* SPI1 SEL, I */ | ||
69 | |||
70 | par_io_config_pin(3, 13, 1, 0, 0, 0); /* !SD_CS, O */ | ||
71 | par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */ | ||
72 | par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */ | ||
73 | |||
74 | return fsl_spi_init(&mpc832x_spi_boardinfo, 1, | ||
75 | mpc83xx_spi_activate_cs, | ||
76 | mpc83xx_spi_deactivate_cs); | ||
77 | } | ||
78 | |||
79 | device_initcall(mpc832x_spi_init); | ||
80 | |||
35 | /* ************************************************************************ | 81 | /* ************************************************************************ |
36 | * | 82 | * |
37 | * Setup the architecture | 83 | * Setup the architecture |
@@ -47,10 +93,8 @@ static void __init mpc832x_rdb_setup_arch(void) | |||
47 | ppc_md.progress("mpc832x_rdb_setup_arch()", 0); | 93 | ppc_md.progress("mpc832x_rdb_setup_arch()", 0); |
48 | 94 | ||
49 | #ifdef CONFIG_PCI | 95 | #ifdef CONFIG_PCI |
50 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 96 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
51 | mpc83xx_add_bridge(np); | 97 | mpc83xx_add_bridge(np); |
52 | |||
53 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
54 | #endif | 98 | #endif |
55 | 99 | ||
56 | #ifdef CONFIG_QUICC_ENGINE | 100 | #ifdef CONFIG_QUICC_ENGINE |
@@ -107,7 +151,7 @@ void __init mpc832x_rdb_init_IRQ(void) | |||
107 | if (!np) | 151 | if (!np) |
108 | return; | 152 | return; |
109 | 153 | ||
110 | qe_ic_init(np, 0); | 154 | qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); |
111 | of_node_put(np); | 155 | of_node_put(np); |
112 | #endif /* CONFIG_QUICC_ENGINE */ | 156 | #endif /* CONFIG_QUICC_ENGINE */ |
113 | } | 157 | } |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 47ba5446f63c..aa768199432d 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <asm/machdep.h> | 31 | #include <asm/machdep.h> |
32 | #include <asm/ipic.h> | 32 | #include <asm/ipic.h> |
33 | #include <asm/bootinfo.h> | ||
34 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
35 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
36 | #include <asm/udbg.h> | 35 | #include <asm/udbg.h> |
@@ -53,10 +52,8 @@ static void __init mpc834x_itx_setup_arch(void) | |||
53 | ppc_md.progress("mpc834x_itx_setup_arch()", 0); | 52 | ppc_md.progress("mpc834x_itx_setup_arch()", 0); |
54 | 53 | ||
55 | #ifdef CONFIG_PCI | 54 | #ifdef CONFIG_PCI |
56 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 55 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
57 | mpc83xx_add_bridge(np); | 56 | mpc83xx_add_bridge(np); |
58 | |||
59 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
60 | #endif | 57 | #endif |
61 | 58 | ||
62 | mpc834x_usb_cfg(); | 59 | mpc834x_usb_cfg(); |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 4c9ff9cadfe4..00aed7c2269e 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <asm/machdep.h> | 31 | #include <asm/machdep.h> |
32 | #include <asm/ipic.h> | 32 | #include <asm/ipic.h> |
33 | #include <asm/bootinfo.h> | ||
34 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
35 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
36 | #include <asm/udbg.h> | 35 | #include <asm/udbg.h> |
@@ -84,10 +83,8 @@ static void __init mpc834x_mds_setup_arch(void) | |||
84 | ppc_md.progress("mpc834x_mds_setup_arch()", 0); | 83 | ppc_md.progress("mpc834x_mds_setup_arch()", 0); |
85 | 84 | ||
86 | #ifdef CONFIG_PCI | 85 | #ifdef CONFIG_PCI |
87 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 86 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
88 | mpc83xx_add_bridge(np); | 87 | mpc83xx_add_bridge(np); |
89 | |||
90 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
91 | #endif | 88 | #endif |
92 | 89 | ||
93 | mpc834xemds_usb_cfg(); | 90 | mpc834xemds_usb_cfg(); |
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index 84b58934aafd..0f3855c95ff5 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | #include <asm/machdep.h> | 39 | #include <asm/machdep.h> |
40 | #include <asm/ipic.h> | 40 | #include <asm/ipic.h> |
41 | #include <asm/bootinfo.h> | ||
42 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
43 | #include <asm/prom.h> | 42 | #include <asm/prom.h> |
44 | #include <asm/udbg.h> | 43 | #include <asm/udbg.h> |
@@ -80,9 +79,8 @@ static void __init mpc836x_mds_setup_arch(void) | |||
80 | } | 79 | } |
81 | 80 | ||
82 | #ifdef CONFIG_PCI | 81 | #ifdef CONFIG_PCI |
83 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 82 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") |
84 | mpc83xx_add_bridge(np); | 83 | mpc83xx_add_bridge(np); |
85 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | ||
86 | #endif | 84 | #endif |
87 | 85 | ||
88 | #ifdef CONFIG_QUICC_ENGINE | 86 | #ifdef CONFIG_QUICC_ENGINE |
@@ -149,7 +147,7 @@ static void __init mpc836x_mds_init_IRQ(void) | |||
149 | if (!np) | 147 | if (!np) |
150 | return; | 148 | return; |
151 | 149 | ||
152 | qe_ic_init(np, 0); | 150 | qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); |
153 | of_node_put(np); | 151 | of_node_put(np); |
154 | #endif /* CONFIG_QUICC_ENGINE */ | 152 | #endif /* CONFIG_QUICC_ENGINE */ |
155 | } | 153 | } |
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 589ee55730f3..b778cb4f3fb5 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -49,8 +49,6 @@ | |||
49 | */ | 49 | */ |
50 | 50 | ||
51 | extern int mpc83xx_add_bridge(struct device_node *dev); | 51 | extern int mpc83xx_add_bridge(struct device_node *dev); |
52 | extern int mpc83xx_exclude_device(struct pci_controller *hose, | ||
53 | u_char bus, u_char devfn); | ||
54 | extern void mpc83xx_restart(char *cmd); | 52 | extern void mpc83xx_restart(char *cmd); |
55 | extern long mpc83xx_time_init(void); | 53 | extern long mpc83xx_time_init(void); |
56 | extern int mpc834x_usb_cfg(void); | 54 | extern int mpc834x_usb_cfg(void); |
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 92069469de20..80425d7b14f8 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c | |||
@@ -33,13 +33,6 @@ | |||
33 | #define DBG(x...) | 33 | #define DBG(x...) |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) | ||
37 | { | ||
38 | if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) | ||
39 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
40 | return PCIBIOS_SUCCESSFUL; | ||
41 | } | ||
42 | |||
43 | int __init mpc83xx_add_bridge(struct device_node *dev) | 36 | int __init mpc83xx_add_bridge(struct device_node *dev) |
44 | { | 37 | { |
45 | int len; | 38 | int len; |
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index f620171ad6b1..7748a3a426db 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -12,6 +12,7 @@ config MPC8540_ADS | |||
12 | config MPC8560_ADS | 12 | config MPC8560_ADS |
13 | bool "Freescale MPC8560 ADS" | 13 | bool "Freescale MPC8560 ADS" |
14 | select DEFAULT_UIMAGE | 14 | select DEFAULT_UIMAGE |
15 | select PPC_CPM_NEW_BINDING | ||
15 | help | 16 | help |
16 | This option enables support for the MPC 8560 ADS board | 17 | This option enables support for the MPC 8560 ADS board |
17 | 18 | ||
@@ -25,17 +26,17 @@ config MPC85xx_CDS | |||
25 | config MPC85xx_MDS | 26 | config MPC85xx_MDS |
26 | bool "Freescale MPC85xx MDS" | 27 | bool "Freescale MPC85xx MDS" |
27 | select DEFAULT_UIMAGE | 28 | select DEFAULT_UIMAGE |
28 | # select QUICC_ENGINE | 29 | select QUICC_ENGINE |
29 | help | 30 | help |
30 | This option enables support for the MPC85xx MDS board | 31 | This option enables support for the MPC85xx MDS board |
31 | 32 | ||
32 | config MPC8544_DS | 33 | config MPC85xx_DS |
33 | bool "Freescale MPC8544 DS" | 34 | bool "Freescale MPC85xx DS" |
34 | select PPC_I8259 | 35 | select PPC_I8259 |
35 | select DEFAULT_UIMAGE | 36 | select DEFAULT_UIMAGE |
36 | select FSL_ULI1575 | 37 | select FSL_ULI1575 |
37 | help | 38 | help |
38 | This option enables support for the MPC8544 DS board | 39 | This option enables support for the MPC85xx DS (MPC8544 DS) board |
39 | 40 | ||
40 | endchoice | 41 | endchoice |
41 | 42 | ||
@@ -58,4 +59,4 @@ config MPC85xx | |||
58 | select FSL_PCI if PCI | 59 | select FSL_PCI if PCI |
59 | select SERIAL_8250_SHARE_IRQ if SERIAL_8250 | 60 | select SERIAL_8250_SHARE_IRQ if SERIAL_8250 |
60 | default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \ | 61 | default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \ |
61 | || MPC85xx_MDS || MPC8544_DS | 62 | || MPC85xx_MDS || MPC85xx_DS |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index d70f2d0f9d36..5eca92023ec8 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -1,9 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 85xx linux kernel. | 2 | # Makefile for the PowerPC 85xx linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_PPC_85xx) += misc.o | ||
5 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o | 4 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o |
6 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o | 5 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o |
7 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o | 6 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o |
8 | obj-$(CONFIG_MPC8544_DS) += mpc8544_ds.o | 7 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o |
9 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o | 8 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o |
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c deleted file mode 100644 index 4fe376e9c3b6..000000000000 --- a/arch/powerpc/platforms/85xx/misc.c +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | * MPC85xx generic code. | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2005 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <asm/irq.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/prom.h> | ||
18 | #include <sysdev/fsl_soc.h> | ||
19 | |||
20 | static __be32 __iomem *rstcr; | ||
21 | |||
22 | extern void abort(void); | ||
23 | |||
24 | static int __init mpc85xx_rstcr(void) | ||
25 | { | ||
26 | struct device_node *np; | ||
27 | np = of_find_node_by_name(NULL, "global-utilities"); | ||
28 | if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) { | ||
29 | const u32 *prop = of_get_property(np, "reg", NULL); | ||
30 | if (prop) { | ||
31 | /* map reset control register | ||
32 | * 0xE00B0 is offset of reset control register | ||
33 | */ | ||
34 | rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff); | ||
35 | if (!rstcr) | ||
36 | printk (KERN_EMERG "Error: reset control " | ||
37 | "register not mapped!\n"); | ||
38 | } | ||
39 | } else | ||
40 | printk (KERN_INFO "rstcr compatible register does not exist!\n"); | ||
41 | if (np) | ||
42 | of_node_put(np); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | arch_initcall(mpc85xx_rstcr); | ||
47 | |||
48 | void mpc85xx_restart(char *cmd) | ||
49 | { | ||
50 | local_irq_disable(); | ||
51 | if (rstcr) | ||
52 | /* set reset control register */ | ||
53 | out_be32(rstcr, 0x2); /* HRESET_REQ */ | ||
54 | abort(); | ||
55 | } | ||
diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h deleted file mode 100644 index da82f4c0fdac..000000000000 --- a/arch/powerpc/platforms/85xx/mpc8540_ads.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* | ||
2 | * arch/powerpc/platforms/85xx/mpc8540_ads.h | ||
3 | * | ||
4 | * MPC8540ADS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor 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 | |||
17 | #ifndef __MACH_MPC8540ADS_H__ | ||
18 | #define __MACH_MPC8540ADS_H__ | ||
19 | |||
20 | #include <linux/initrd.h> | ||
21 | |||
22 | #define BOARD_CCSRBAR ((uint)0xe0000000) | ||
23 | #define BCSR_ADDR ((uint)0xf8000000) | ||
24 | #define BCSR_SIZE ((uint)(32 * 1024)) | ||
25 | |||
26 | /* PCI interrupt controller */ | ||
27 | #define PIRQA MPC85xx_IRQ_EXT1 | ||
28 | #define PIRQB MPC85xx_IRQ_EXT2 | ||
29 | #define PIRQC MPC85xx_IRQ_EXT3 | ||
30 | #define PIRQD MPC85xx_IRQ_EXT4 | ||
31 | |||
32 | /* Offset of CPM register space */ | ||
33 | #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) | ||
34 | |||
35 | #endif /* __MACH_MPC8540ADS_H__ */ | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h deleted file mode 100644 index 5b34deef12b5..000000000000 --- a/arch/powerpc/platforms/85xx/mpc85xx.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * arch/powerpc/platforms/85xx/mpc85xx.h | ||
3 | * | ||
4 | * MPC85xx soc definitions/function decls | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2005 Freescale Semiconductor 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 | |||
17 | extern void mpc85xx_restart(char *); | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 40a828675c7b..bccdc25f83a2 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
@@ -17,26 +17,22 @@ | |||
17 | #include <linux/kdev_t.h> | 17 | #include <linux/kdev_t.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/of_platform.h> | ||
20 | 21 | ||
21 | #include <asm/system.h> | 22 | #include <asm/system.h> |
22 | #include <asm/time.h> | 23 | #include <asm/time.h> |
23 | #include <asm/machdep.h> | 24 | #include <asm/machdep.h> |
24 | #include <asm/pci-bridge.h> | 25 | #include <asm/pci-bridge.h> |
25 | #include <asm/mpc85xx.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <asm/mpic.h> | 26 | #include <asm/mpic.h> |
28 | #include <mm/mmu_decl.h> | 27 | #include <mm/mmu_decl.h> |
29 | #include <asm/udbg.h> | 28 | #include <asm/udbg.h> |
30 | 29 | ||
31 | #include <sysdev/fsl_soc.h> | 30 | #include <sysdev/fsl_soc.h> |
32 | #include <sysdev/fsl_pci.h> | 31 | #include <sysdev/fsl_pci.h> |
33 | #include "mpc85xx.h" | ||
34 | 32 | ||
35 | #ifdef CONFIG_CPM2 | 33 | #ifdef CONFIG_CPM2 |
36 | #include <linux/fs_enet_pd.h> | ||
37 | #include <asm/cpm2.h> | 34 | #include <asm/cpm2.h> |
38 | #include <sysdev/cpm2_pic.h> | 35 | #include <sysdev/cpm2_pic.h> |
39 | #include <asm/fs_pd.h> | ||
40 | #endif | 36 | #endif |
41 | 37 | ||
42 | #ifdef CONFIG_PCI | 38 | #ifdef CONFIG_PCI |
@@ -96,10 +92,10 @@ static void __init mpc85xx_ads_pic_init(void) | |||
96 | 92 | ||
97 | #ifdef CONFIG_CPM2 | 93 | #ifdef CONFIG_CPM2 |
98 | /* Setup CPM2 PIC */ | 94 | /* Setup CPM2 PIC */ |
99 | np = of_find_node_by_type(NULL, "cpm-pic"); | 95 | np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic"); |
100 | if (np == NULL) { | 96 | if (np == NULL) { |
101 | printk(KERN_ERR "PIC init: can not find cpm-pic node\n"); | 97 | printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n"); |
102 | return; | 98 | return; |
103 | } | 99 | } |
104 | irq = irq_of_parse_and_map(np, 0); | 100 | irq = irq_of_parse_and_map(np, 0); |
105 | 101 | ||
@@ -112,87 +108,80 @@ static void __init mpc85xx_ads_pic_init(void) | |||
112 | * Setup the architecture | 108 | * Setup the architecture |
113 | */ | 109 | */ |
114 | #ifdef CONFIG_CPM2 | 110 | #ifdef CONFIG_CPM2 |
115 | void init_fcc_ioports(struct fs_platform_info *fpi) | 111 | struct cpm_pin { |
112 | int port, pin, flags; | ||
113 | }; | ||
114 | |||
115 | static struct cpm_pin mpc8560_ads_pins[] = { | ||
116 | /* SCC1 */ | ||
117 | {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
118 | {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
119 | {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
120 | |||
121 | /* SCC2 */ | ||
122 | {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
123 | {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
124 | {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
125 | |||
126 | /* FCC2 */ | ||
127 | {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
128 | {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
129 | {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
130 | {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
131 | {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
132 | {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
133 | {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
134 | {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
135 | {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
136 | {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
137 | {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
138 | {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
139 | {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
140 | {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
141 | {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK14 */ | ||
142 | {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK13 */ | ||
143 | |||
144 | /* FCC3 */ | ||
145 | {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
146 | {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
147 | {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
148 | {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
149 | {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
150 | {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
151 | {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
152 | {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
153 | {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
154 | {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
155 | {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
156 | {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
157 | {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
158 | {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
159 | {2, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK16 */ | ||
160 | {2, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK15 */ | ||
161 | }; | ||
162 | |||
163 | static void __init init_ioports(void) | ||
116 | { | 164 | { |
117 | struct io_port *io = cpm2_map(im_ioport); | 165 | int i; |
118 | int fcc_no = fs_get_fcc_index(fpi->fs_no); | 166 | |
119 | int target; | 167 | for (i = 0; i < ARRAY_SIZE(mpc8560_ads_pins); i++) { |
120 | u32 tempval; | 168 | struct cpm_pin *pin = &mpc8560_ads_pins[i]; |
121 | 169 | cpm2_set_pin(pin->port, pin->pin, pin->flags); | |
122 | switch(fcc_no) { | ||
123 | case 1: | ||
124 | tempval = in_be32(&io->iop_pdirb); | ||
125 | tempval &= ~PB2_DIRB0; | ||
126 | tempval |= PB2_DIRB1; | ||
127 | out_be32(&io->iop_pdirb, tempval); | ||
128 | |||
129 | tempval = in_be32(&io->iop_psorb); | ||
130 | tempval &= ~PB2_PSORB0; | ||
131 | tempval |= PB2_PSORB1; | ||
132 | out_be32(&io->iop_psorb, tempval); | ||
133 | |||
134 | tempval = in_be32(&io->iop_pparb); | ||
135 | tempval |= (PB2_DIRB0 | PB2_DIRB1); | ||
136 | out_be32(&io->iop_pparb, tempval); | ||
137 | |||
138 | target = CPM_CLK_FCC2; | ||
139 | break; | ||
140 | case 2: | ||
141 | tempval = in_be32(&io->iop_pdirb); | ||
142 | tempval &= ~PB3_DIRB0; | ||
143 | tempval |= PB3_DIRB1; | ||
144 | out_be32(&io->iop_pdirb, tempval); | ||
145 | |||
146 | tempval = in_be32(&io->iop_psorb); | ||
147 | tempval &= ~PB3_PSORB0; | ||
148 | tempval |= PB3_PSORB1; | ||
149 | out_be32(&io->iop_psorb, tempval); | ||
150 | |||
151 | tempval = in_be32(&io->iop_pparb); | ||
152 | tempval |= (PB3_DIRB0 | PB3_DIRB1); | ||
153 | out_be32(&io->iop_pparb, tempval); | ||
154 | |||
155 | tempval = in_be32(&io->iop_pdirc); | ||
156 | tempval |= PC3_DIRC1; | ||
157 | out_be32(&io->iop_pdirc, tempval); | ||
158 | |||
159 | tempval = in_be32(&io->iop_pparc); | ||
160 | tempval |= PC3_DIRC1; | ||
161 | out_be32(&io->iop_pparc, tempval); | ||
162 | |||
163 | target = CPM_CLK_FCC3; | ||
164 | break; | ||
165 | default: | ||
166 | printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n"); | ||
167 | return; | ||
168 | } | 170 | } |
169 | 171 | ||
170 | /* Port C has clocks...... */ | 172 | cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX); |
171 | tempval = in_be32(&io->iop_psorc); | 173 | cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX); |
172 | tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8)); | 174 | cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX); |
173 | out_be32(&io->iop_psorc, tempval); | 175 | cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX); |
174 | 176 | cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX); | |
175 | tempval = in_be32(&io->iop_pdirc); | 177 | cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX); |
176 | tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8)); | 178 | cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX); |
177 | out_be32(&io->iop_pdirc, tempval); | 179 | cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX); |
178 | tempval = in_be32(&io->iop_pparc); | ||
179 | tempval |= (PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8)); | ||
180 | out_be32(&io->iop_pparc, tempval); | ||
181 | |||
182 | cpm2_unmap(io); | ||
183 | |||
184 | /* Configure Serial Interface clock routing. | ||
185 | * First, clear FCC bits to zero, | ||
186 | * then set the ones we want. | ||
187 | */ | ||
188 | cpm2_clk_setup(target, fpi->clk_rx, CPM_CLK_RX); | ||
189 | cpm2_clk_setup(target, fpi->clk_tx, CPM_CLK_TX); | ||
190 | } | 180 | } |
191 | #endif | 181 | #endif |
192 | 182 | ||
193 | static void __init mpc85xx_ads_setup_arch(void) | 183 | static void __init mpc85xx_ads_setup_arch(void) |
194 | { | 184 | { |
195 | struct device_node *cpu; | ||
196 | #ifdef CONFIG_PCI | 185 | #ifdef CONFIG_PCI |
197 | struct device_node *np; | 186 | struct device_node *np; |
198 | #endif | 187 | #endif |
@@ -200,25 +189,15 @@ static void __init mpc85xx_ads_setup_arch(void) | |||
200 | if (ppc_md.progress) | 189 | if (ppc_md.progress) |
201 | ppc_md.progress("mpc85xx_ads_setup_arch()", 0); | 190 | ppc_md.progress("mpc85xx_ads_setup_arch()", 0); |
202 | 191 | ||
203 | cpu = of_find_node_by_type(NULL, "cpu"); | ||
204 | if (cpu != 0) { | ||
205 | const unsigned int *fp; | ||
206 | |||
207 | fp = of_get_property(cpu, "clock-frequency", NULL); | ||
208 | if (fp != 0) | ||
209 | loops_per_jiffy = *fp / HZ; | ||
210 | else | ||
211 | loops_per_jiffy = 50000000 / HZ; | ||
212 | of_node_put(cpu); | ||
213 | } | ||
214 | |||
215 | #ifdef CONFIG_CPM2 | 192 | #ifdef CONFIG_CPM2 |
216 | cpm2_reset(); | 193 | cpm2_reset(); |
194 | init_ioports(); | ||
217 | #endif | 195 | #endif |
218 | 196 | ||
219 | #ifdef CONFIG_PCI | 197 | #ifdef CONFIG_PCI |
220 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 198 | for_each_compatible_node(np, "pci", "fsl,mpc8540-pci") |
221 | fsl_add_bridge(np, 1); | 199 | fsl_add_bridge(np, 1); |
200 | |||
222 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 201 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
223 | #endif | 202 | #endif |
224 | } | 203 | } |
@@ -244,6 +223,24 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m) | |||
244 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | 223 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); |
245 | } | 224 | } |
246 | 225 | ||
226 | static struct of_device_id __initdata of_bus_ids[] = { | ||
227 | { .name = "soc", }, | ||
228 | { .type = "soc", }, | ||
229 | { .name = "cpm", }, | ||
230 | { .name = "localbus", }, | ||
231 | {}, | ||
232 | }; | ||
233 | |||
234 | static int __init declare_of_platform_devices(void) | ||
235 | { | ||
236 | if (!machine_is(mpc85xx_ads)) | ||
237 | return 0; | ||
238 | |||
239 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
240 | return 0; | ||
241 | } | ||
242 | device_initcall(declare_of_platform_devices); | ||
243 | |||
247 | /* | 244 | /* |
248 | * Called very early, device-tree isn't unflattened | 245 | * Called very early, device-tree isn't unflattened |
249 | */ | 246 | */ |
@@ -261,7 +258,7 @@ define_machine(mpc85xx_ads) { | |||
261 | .init_IRQ = mpc85xx_ads_pic_init, | 258 | .init_IRQ = mpc85xx_ads_pic_init, |
262 | .show_cpuinfo = mpc85xx_ads_show_cpuinfo, | 259 | .show_cpuinfo = mpc85xx_ads_show_cpuinfo, |
263 | .get_irq = mpic_get_irq, | 260 | .get_irq = mpic_get_irq, |
264 | .restart = mpc85xx_restart, | 261 | .restart = fsl_rstcr_restart, |
265 | .calibrate_decr = generic_calibrate_decr, | 262 | .calibrate_decr = generic_calibrate_decr, |
266 | .progress = udbg_progress, | 263 | .progress = udbg_progress, |
267 | }; | 264 | }; |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.h b/arch/powerpc/platforms/85xx/mpc85xx_ads.h deleted file mode 100644 index 46c3532992aa..000000000000 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.h +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /* | ||
2 | * MPC85xx ADS board definitions | ||
3 | * | ||
4 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
5 | * | ||
6 | * Copyright 2004 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * 2006 (c) MontaVista Software, Inc. | ||
9 | * Vitaly Bordug <vbordug@ru.mvista.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __MACH_MPC85XXADS_H | ||
19 | #define __MACH_MPC85XXADS_H | ||
20 | |||
21 | #include <linux/initrd.h> | ||
22 | #include <sysdev/fsl_soc.h> | ||
23 | |||
24 | #define BCSR_ADDR ((uint)0xf8000000) | ||
25 | #define BCSR_SIZE ((uint)(32 * 1024)) | ||
26 | |||
27 | #ifdef CONFIG_CPM2 | ||
28 | |||
29 | #define MPC85xx_CPM_OFFSET (0x80000) | ||
30 | |||
31 | #define CPM_MAP_ADDR (get_immrbase() + MPC85xx_CPM_OFFSET) | ||
32 | #define CPM_IRQ_OFFSET 60 | ||
33 | |||
34 | #define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET) | ||
35 | #define SIU_INT_SMC2 ((uint)0x05+CPM_IRQ_OFFSET) | ||
36 | #define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET) | ||
37 | #define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET) | ||
38 | #define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET) | ||
39 | #define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET) | ||
40 | |||
41 | /* FCC1 Clock Source Configuration. These can be | ||
42 | * redefined in the board specific file. | ||
43 | * Can only choose from CLK9-12 */ | ||
44 | #define F1_RXCLK 12 | ||
45 | #define F1_TXCLK 11 | ||
46 | |||
47 | /* FCC2 Clock Source Configuration. These can be | ||
48 | * redefined in the board specific file. | ||
49 | * Can only choose from CLK13-16 */ | ||
50 | #define F2_RXCLK 13 | ||
51 | #define F2_TXCLK 14 | ||
52 | |||
53 | /* FCC3 Clock Source Configuration. These can be | ||
54 | * redefined in the board specific file. | ||
55 | * Can only choose from CLK13-16 */ | ||
56 | #define F3_RXCLK 15 | ||
57 | #define F3_TXCLK 16 | ||
58 | |||
59 | #endif /* CONFIG_CPM2 */ | ||
60 | #endif /* __MACH_MPC85XXADS_H */ | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 2d4cb7847604..4d063eec6210 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c | |||
@@ -35,9 +35,7 @@ | |||
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | #include <asm/machdep.h> | 36 | #include <asm/machdep.h> |
37 | #include <asm/ipic.h> | 37 | #include <asm/ipic.h> |
38 | #include <asm/bootinfo.h> | ||
39 | #include <asm/pci-bridge.h> | 38 | #include <asm/pci-bridge.h> |
40 | #include <asm/mpc85xx.h> | ||
41 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
42 | #include <mm/mmu_decl.h> | 40 | #include <mm/mmu_decl.h> |
43 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
@@ -47,7 +45,15 @@ | |||
47 | 45 | ||
48 | #include <sysdev/fsl_soc.h> | 46 | #include <sysdev/fsl_soc.h> |
49 | #include <sysdev/fsl_pci.h> | 47 | #include <sysdev/fsl_pci.h> |
50 | #include "mpc85xx.h" | 48 | |
49 | /* CADMUS info */ | ||
50 | /* xxx - galak, move into device tree */ | ||
51 | #define CADMUS_BASE (0xf8004000) | ||
52 | #define CADMUS_SIZE (256) | ||
53 | #define CM_VER (0) | ||
54 | #define CM_CSR (1) | ||
55 | #define CM_RST (2) | ||
56 | |||
51 | 57 | ||
52 | static int cds_pci_slot = 2; | 58 | static int cds_pci_slot = 2; |
53 | static volatile u8 *cadmus; | 59 | static volatile u8 *cadmus; |
@@ -97,7 +103,7 @@ static void mpc85xx_cds_restart(char *cmd) | |||
97 | * If we can't find the VIA chip (maybe the P2P bridge is disabled) | 103 | * If we can't find the VIA chip (maybe the P2P bridge is disabled) |
98 | * or the VIA chip reset didn't work, just use the default reset. | 104 | * or the VIA chip reset didn't work, just use the default reset. |
99 | */ | 105 | */ |
100 | mpc85xx_restart(NULL); | 106 | fsl_rstcr_restart(NULL); |
101 | } | 107 | } |
102 | 108 | ||
103 | static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) | 109 | static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) |
@@ -266,7 +272,6 @@ device_initcall(mpc85xx_cds_8259_attach); | |||
266 | */ | 272 | */ |
267 | static void __init mpc85xx_cds_setup_arch(void) | 273 | static void __init mpc85xx_cds_setup_arch(void) |
268 | { | 274 | { |
269 | struct device_node *cpu; | ||
270 | #ifdef CONFIG_PCI | 275 | #ifdef CONFIG_PCI |
271 | struct device_node *np; | 276 | struct device_node *np; |
272 | #endif | 277 | #endif |
@@ -274,18 +279,6 @@ static void __init mpc85xx_cds_setup_arch(void) | |||
274 | if (ppc_md.progress) | 279 | if (ppc_md.progress) |
275 | ppc_md.progress("mpc85xx_cds_setup_arch()", 0); | 280 | ppc_md.progress("mpc85xx_cds_setup_arch()", 0); |
276 | 281 | ||
277 | cpu = of_find_node_by_type(NULL, "cpu"); | ||
278 | if (cpu != 0) { | ||
279 | const unsigned int *fp; | ||
280 | |||
281 | fp = of_get_property(cpu, "clock-frequency", NULL); | ||
282 | if (fp != 0) | ||
283 | loops_per_jiffy = *fp / HZ; | ||
284 | else | ||
285 | loops_per_jiffy = 500000000 / HZ; | ||
286 | of_node_put(cpu); | ||
287 | } | ||
288 | |||
289 | cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); | 282 | cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); |
290 | cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; | 283 | cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; |
291 | 284 | ||
@@ -297,14 +290,18 @@ static void __init mpc85xx_cds_setup_arch(void) | |||
297 | } | 290 | } |
298 | 291 | ||
299 | #ifdef CONFIG_PCI | 292 | #ifdef CONFIG_PCI |
300 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | 293 | for_each_node_by_type(np, "pci") { |
301 | struct resource rsrc; | 294 | if (of_device_is_compatible(np, "fsl,mpc8540-pci") || |
302 | of_address_to_resource(np, 0, &rsrc); | 295 | of_device_is_compatible(np, "fsl,mpc8548-pcie")) { |
303 | if ((rsrc.start & 0xfffff) == 0x8000) | 296 | struct resource rsrc; |
304 | fsl_add_bridge(np, 1); | 297 | of_address_to_resource(np, 0, &rsrc); |
305 | else | 298 | if ((rsrc.start & 0xfffff) == 0x8000) |
306 | fsl_add_bridge(np, 0); | 299 | fsl_add_bridge(np, 1); |
300 | else | ||
301 | fsl_add_bridge(np, 0); | ||
302 | } | ||
307 | } | 303 | } |
304 | |||
308 | ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; | 305 | ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; |
309 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 306 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
310 | #endif | 307 | #endif |
@@ -353,7 +350,7 @@ define_machine(mpc85xx_cds) { | |||
353 | .restart = mpc85xx_cds_restart, | 350 | .restart = mpc85xx_cds_restart, |
354 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | 351 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, |
355 | #else | 352 | #else |
356 | .restart = mpc85xx_restart, | 353 | .restart = fsl_rstcr_restart, |
357 | #endif | 354 | #endif |
358 | .calibrate_decr = generic_calibrate_decr, | 355 | .calibrate_decr = generic_calibrate_decr, |
359 | .progress = udbg_progress, | 356 | .progress = udbg_progress, |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h deleted file mode 100644 index b251c9feb3dc..000000000000 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.h +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /* | ||
2 | * arch/powerpc/platforms/85xx/mpc85xx_cds.h | ||
3 | * | ||
4 | * MPC85xx CDS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor, 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 | |||
17 | #ifndef __MACH_MPC85XX_CDS_H__ | ||
18 | #define __MACH_MPC85XX_CDS_H__ | ||
19 | |||
20 | /* CADMUS info */ | ||
21 | #define CADMUS_BASE (0xf8004000) | ||
22 | #define CADMUS_SIZE (256) | ||
23 | #define CM_VER (0) | ||
24 | #define CM_CSR (1) | ||
25 | #define CM_RST (2) | ||
26 | |||
27 | /* CDS NVRAM/RTC */ | ||
28 | #define CDS_RTC_ADDR (0xf8000000) | ||
29 | #define CDS_RTC_SIZE (8 * 1024) | ||
30 | |||
31 | /* PCI interrupt controller */ | ||
32 | #define PIRQ0A MPC85xx_IRQ_EXT0 | ||
33 | #define PIRQ0B MPC85xx_IRQ_EXT1 | ||
34 | #define PIRQ0C MPC85xx_IRQ_EXT2 | ||
35 | #define PIRQ0D MPC85xx_IRQ_EXT3 | ||
36 | #define PIRQ1A MPC85xx_IRQ_EXT11 | ||
37 | |||
38 | #define NR_8259_INTS 16 | ||
39 | #define CPM_IRQ_OFFSET NR_8259_INTS | ||
40 | |||
41 | #define MPC85xx_OPENPIC_IRQ_OFFSET 80 | ||
42 | |||
43 | #endif /* __MACH_MPC85XX_CDS_H__ */ | ||
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 48983bc56d46..59c121a97ac7 100644 --- a/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * MPC8544 DS Board Setup | 2 | * MPC85xx DS Board Setup |
3 | * | 3 | * |
4 | * Author Xianghua Xiao (x.xiao@freescale.com) | 4 | * Author Xianghua Xiao (x.xiao@freescale.com) |
5 | * Roy Zang <tie-fei.zang@freescale.com> | 5 | * Roy Zang <tie-fei.zang@freescale.com> |
@@ -24,7 +24,6 @@ | |||
24 | #include <asm/time.h> | 24 | #include <asm/time.h> |
25 | #include <asm/machdep.h> | 25 | #include <asm/machdep.h> |
26 | #include <asm/pci-bridge.h> | 26 | #include <asm/pci-bridge.h> |
27 | #include <asm/mpc85xx.h> | ||
28 | #include <mm/mmu_decl.h> | 27 | #include <mm/mmu_decl.h> |
29 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
30 | #include <asm/udbg.h> | 29 | #include <asm/udbg.h> |
@@ -33,7 +32,6 @@ | |||
33 | 32 | ||
34 | #include <sysdev/fsl_soc.h> | 33 | #include <sysdev/fsl_soc.h> |
35 | #include <sysdev/fsl_pci.h> | 34 | #include <sysdev/fsl_pci.h> |
36 | #include "mpc85xx.h" | ||
37 | 35 | ||
38 | #undef DEBUG | 36 | #undef DEBUG |
39 | 37 | ||
@@ -44,7 +42,7 @@ | |||
44 | #endif | 42 | #endif |
45 | 43 | ||
46 | #ifdef CONFIG_PPC_I8259 | 44 | #ifdef CONFIG_PPC_I8259 |
47 | static void mpc8544_8259_cascade(unsigned int irq, struct irq_desc *desc) | 45 | static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc) |
48 | { | 46 | { |
49 | unsigned int cascade_irq = i8259_irq(); | 47 | unsigned int cascade_irq = i8259_irq(); |
50 | 48 | ||
@@ -55,7 +53,7 @@ static void mpc8544_8259_cascade(unsigned int irq, struct irq_desc *desc) | |||
55 | } | 53 | } |
56 | #endif /* CONFIG_PPC_I8259 */ | 54 | #endif /* CONFIG_PPC_I8259 */ |
57 | 55 | ||
58 | void __init mpc8544_ds_pic_init(void) | 56 | void __init mpc85xx_ds_pic_init(void) |
59 | { | 57 | { |
60 | struct mpic *mpic; | 58 | struct mpic *mpic; |
61 | struct resource r; | 59 | struct resource r; |
@@ -104,16 +102,17 @@ void __init mpc8544_ds_pic_init(void) | |||
104 | return; | 102 | return; |
105 | } | 103 | } |
106 | 104 | ||
107 | DBG("mpc8544ds: cascade mapped to irq %d\n", cascade_irq); | 105 | DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq); |
108 | 106 | ||
109 | i8259_init(cascade_node, 0); | 107 | i8259_init(cascade_node, 0); |
110 | of_node_put(cascade_node); | 108 | of_node_put(cascade_node); |
111 | 109 | ||
112 | set_irq_chained_handler(cascade_irq, mpc8544_8259_cascade); | 110 | set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade); |
113 | #endif /* CONFIG_PPC_I8259 */ | 111 | #endif /* CONFIG_PPC_I8259 */ |
114 | } | 112 | } |
115 | 113 | ||
116 | #ifdef CONFIG_PCI | 114 | #ifdef CONFIG_PCI |
115 | static int primary_phb_addr; | ||
117 | extern int uses_fsl_uli_m1575; | 116 | extern int uses_fsl_uli_m1575; |
118 | extern int uli_exclude_device(struct pci_controller *hose, | 117 | extern int uli_exclude_device(struct pci_controller *hose, |
119 | u_char bus, u_char devfn); | 118 | u_char bus, u_char devfn); |
@@ -121,13 +120,13 @@ extern int uli_exclude_device(struct pci_controller *hose, | |||
121 | static int mpc85xx_exclude_device(struct pci_controller *hose, | 120 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
122 | u_char bus, u_char devfn) | 121 | u_char bus, u_char devfn) |
123 | { | 122 | { |
124 | struct device_node* node; | 123 | struct device_node* node; |
125 | struct resource rsrc; | 124 | struct resource rsrc; |
126 | 125 | ||
127 | node = (struct device_node *)hose->arch_data; | 126 | node = (struct device_node *)hose->arch_data; |
128 | of_address_to_resource(node, 0, &rsrc); | 127 | of_address_to_resource(node, 0, &rsrc); |
129 | 128 | ||
130 | if ((rsrc.start & 0xfffff) == 0xb000) { | 129 | if ((rsrc.start & 0xfffff) == primary_phb_addr) { |
131 | return uli_exclude_device(hose, bus, devfn); | 130 | return uli_exclude_device(hose, bus, devfn); |
132 | } | 131 | } |
133 | 132 | ||
@@ -138,29 +137,33 @@ static int mpc85xx_exclude_device(struct pci_controller *hose, | |||
138 | /* | 137 | /* |
139 | * Setup the architecture | 138 | * Setup the architecture |
140 | */ | 139 | */ |
141 | static void __init mpc8544_ds_setup_arch(void) | 140 | static void __init mpc85xx_ds_setup_arch(void) |
142 | { | 141 | { |
143 | #ifdef CONFIG_PCI | 142 | #ifdef CONFIG_PCI |
144 | struct device_node *np; | 143 | struct device_node *np; |
145 | #endif | 144 | #endif |
146 | 145 | ||
147 | if (ppc_md.progress) | 146 | if (ppc_md.progress) |
148 | ppc_md.progress("mpc8544_ds_setup_arch()", 0); | 147 | ppc_md.progress("mpc85xx_ds_setup_arch()", 0); |
149 | 148 | ||
150 | #ifdef CONFIG_PCI | 149 | #ifdef CONFIG_PCI |
151 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | 150 | for_each_node_by_type(np, "pci") { |
152 | struct resource rsrc; | 151 | if (of_device_is_compatible(np, "fsl,mpc8540-pci") || |
153 | of_address_to_resource(np, 0, &rsrc); | 152 | of_device_is_compatible(np, "fsl,mpc8548-pcie")) { |
154 | if ((rsrc.start & 0xfffff) == 0xb000) | 153 | struct resource rsrc; |
155 | fsl_add_bridge(np, 1); | 154 | of_address_to_resource(np, 0, &rsrc); |
156 | else | 155 | if ((rsrc.start & 0xfffff) == primary_phb_addr) |
157 | fsl_add_bridge(np, 0); | 156 | fsl_add_bridge(np, 1); |
157 | else | ||
158 | fsl_add_bridge(np, 0); | ||
159 | } | ||
158 | } | 160 | } |
161 | |||
159 | uses_fsl_uli_m1575 = 1; | 162 | uses_fsl_uli_m1575 = 1; |
160 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 163 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
161 | #endif | 164 | #endif |
162 | 165 | ||
163 | printk("MPC8544 DS board from Freescale Semiconductor\n"); | 166 | printk("MPC85xx DS board from Freescale Semiconductor\n"); |
164 | } | 167 | } |
165 | 168 | ||
166 | /* | 169 | /* |
@@ -170,19 +173,57 @@ static int __init mpc8544_ds_probe(void) | |||
170 | { | 173 | { |
171 | unsigned long root = of_get_flat_dt_root(); | 174 | unsigned long root = of_get_flat_dt_root(); |
172 | 175 | ||
173 | return of_flat_dt_is_compatible(root, "MPC8544DS"); | 176 | if (of_flat_dt_is_compatible(root, "MPC8544DS")) { |
177 | #ifdef CONFIG_PCI | ||
178 | primary_phb_addr = 0xb000; | ||
179 | #endif | ||
180 | return 1; | ||
181 | } else { | ||
182 | return 0; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Called very early, device-tree isn't unflattened | ||
188 | */ | ||
189 | static int __init mpc8572_ds_probe(void) | ||
190 | { | ||
191 | unsigned long root = of_get_flat_dt_root(); | ||
192 | |||
193 | if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS")) { | ||
194 | #ifdef CONFIG_PCI | ||
195 | primary_phb_addr = 0x8000; | ||
196 | #endif | ||
197 | return 1; | ||
198 | } else { | ||
199 | return 0; | ||
200 | } | ||
174 | } | 201 | } |
175 | 202 | ||
176 | define_machine(mpc8544_ds) { | 203 | define_machine(mpc8544_ds) { |
177 | .name = "MPC8544 DS", | 204 | .name = "MPC8544 DS", |
178 | .probe = mpc8544_ds_probe, | 205 | .probe = mpc8544_ds_probe, |
179 | .setup_arch = mpc8544_ds_setup_arch, | 206 | .setup_arch = mpc85xx_ds_setup_arch, |
180 | .init_IRQ = mpc8544_ds_pic_init, | 207 | .init_IRQ = mpc85xx_ds_pic_init, |
208 | #ifdef CONFIG_PCI | ||
209 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
210 | #endif | ||
211 | .get_irq = mpic_get_irq, | ||
212 | .restart = fsl_rstcr_restart, | ||
213 | .calibrate_decr = generic_calibrate_decr, | ||
214 | .progress = udbg_progress, | ||
215 | }; | ||
216 | |||
217 | define_machine(mpc8572_ds) { | ||
218 | .name = "MPC8572 DS", | ||
219 | .probe = mpc8572_ds_probe, | ||
220 | .setup_arch = mpc85xx_ds_setup_arch, | ||
221 | .init_IRQ = mpc85xx_ds_pic_init, | ||
181 | #ifdef CONFIG_PCI | 222 | #ifdef CONFIG_PCI |
182 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | 223 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, |
183 | #endif | 224 | #endif |
184 | .get_irq = mpic_get_irq, | 225 | .get_irq = mpic_get_irq, |
185 | .restart = mpc85xx_restart, | 226 | .restart = fsl_rstcr_restart, |
186 | .calibrate_decr = generic_calibrate_decr, | 227 | .calibrate_decr = generic_calibrate_decr, |
187 | .progress = udbg_progress, | 228 | .progress = udbg_progress, |
188 | }; | 229 | }; |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 7ca7e676f1c4..61b3eedf41b9 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
@@ -38,9 +38,7 @@ | |||
38 | #include <asm/time.h> | 38 | #include <asm/time.h> |
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | #include <asm/machdep.h> | 40 | #include <asm/machdep.h> |
41 | #include <asm/bootinfo.h> | ||
42 | #include <asm/pci-bridge.h> | 41 | #include <asm/pci-bridge.h> |
43 | #include <asm/mpc85xx.h> | ||
44 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
45 | #include <mm/mmu_decl.h> | 43 | #include <mm/mmu_decl.h> |
46 | #include <asm/prom.h> | 44 | #include <asm/prom.h> |
@@ -51,8 +49,6 @@ | |||
51 | #include <asm/qe_ic.h> | 49 | #include <asm/qe_ic.h> |
52 | #include <asm/mpic.h> | 50 | #include <asm/mpic.h> |
53 | 51 | ||
54 | #include "mpc85xx.h" | ||
55 | |||
56 | #undef DEBUG | 52 | #undef DEBUG |
57 | #ifdef DEBUG | 53 | #ifdef DEBUG |
58 | #define DBG(fmt...) udbg_printf(fmt) | 54 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -73,17 +69,6 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
73 | if (ppc_md.progress) | 69 | if (ppc_md.progress) |
74 | ppc_md.progress("mpc85xx_mds_setup_arch()", 0); | 70 | ppc_md.progress("mpc85xx_mds_setup_arch()", 0); |
75 | 71 | ||
76 | np = of_find_node_by_type(NULL, "cpu"); | ||
77 | if (np != NULL) { | ||
78 | const unsigned int *fp = | ||
79 | of_get_property(np, "clock-frequency", NULL); | ||
80 | if (fp != NULL) | ||
81 | loops_per_jiffy = *fp / HZ; | ||
82 | else | ||
83 | loops_per_jiffy = 50000000 / HZ; | ||
84 | of_node_put(np); | ||
85 | } | ||
86 | |||
87 | /* Map BCSR area */ | 72 | /* Map BCSR area */ |
88 | np = of_find_node_by_name(NULL, "bcsr"); | 73 | np = of_find_node_by_name(NULL, "bcsr"); |
89 | if (np != NULL) { | 74 | if (np != NULL) { |
@@ -95,9 +80,17 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
95 | } | 80 | } |
96 | 81 | ||
97 | #ifdef CONFIG_PCI | 82 | #ifdef CONFIG_PCI |
98 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 83 | for_each_node_by_type(np, "pci") { |
99 | fsl_add_bridge(np, 1); | 84 | if (of_device_is_compatible(np, "fsl,mpc8540-pci") || |
100 | of_node_put(np); | 85 | of_device_is_compatible(np, "fsl,mpc8548-pcie")) { |
86 | struct resource rsrc; | ||
87 | of_address_to_resource(np, 0, &rsrc); | ||
88 | if ((rsrc.start & 0xfffff) == 0x8000) | ||
89 | fsl_add_bridge(np, 1); | ||
90 | else | ||
91 | fsl_add_bridge(np, 0); | ||
92 | } | ||
93 | } | ||
101 | #endif | 94 | #endif |
102 | 95 | ||
103 | #ifdef CONFIG_QUICC_ENGINE | 96 | #ifdef CONFIG_QUICC_ENGINE |
@@ -119,18 +112,22 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
119 | } | 112 | } |
120 | 113 | ||
121 | if (bcsr_regs) { | 114 | if (bcsr_regs) { |
122 | u8 bcsr_phy; | 115 | #define BCSR_UCC1_GETH_EN (0x1 << 7) |
116 | #define BCSR_UCC2_GETH_EN (0x1 << 7) | ||
117 | #define BCSR_UCC1_MODE_MSK (0x3 << 4) | ||
118 | #define BCSR_UCC2_MODE_MSK (0x3 << 0) | ||
123 | 119 | ||
124 | /* Reset the Ethernet PHY */ | 120 | /* Turn off UCC1 & UCC2 */ |
125 | bcsr_phy = in_be8(&bcsr_regs[9]); | 121 | clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN); |
126 | bcsr_phy &= ~0x20; | 122 | clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN); |
127 | out_be8(&bcsr_regs[9], bcsr_phy); | ||
128 | 123 | ||
129 | udelay(1000); | 124 | /* Mode is RGMII, all bits clear */ |
125 | clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK | | ||
126 | BCSR_UCC2_MODE_MSK); | ||
130 | 127 | ||
131 | bcsr_phy = in_be8(&bcsr_regs[9]); | 128 | /* Turn UCC1 & UCC2 on */ |
132 | bcsr_phy |= 0x20; | 129 | setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN); |
133 | out_be8(&bcsr_regs[9], bcsr_phy); | 130 | setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN); |
134 | 131 | ||
135 | iounmap(bcsr_regs); | 132 | iounmap(bcsr_regs); |
136 | } | 133 | } |
@@ -186,7 +183,7 @@ static void __init mpc85xx_mds_pic_init(void) | |||
186 | if (!np) | 183 | if (!np) |
187 | return; | 184 | return; |
188 | 185 | ||
189 | qe_ic_init(np, 0); | 186 | qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL); |
190 | of_node_put(np); | 187 | of_node_put(np); |
191 | #endif /* CONFIG_QUICC_ENGINE */ | 188 | #endif /* CONFIG_QUICC_ENGINE */ |
192 | } | 189 | } |
@@ -204,7 +201,7 @@ define_machine(mpc85xx_mds) { | |||
204 | .setup_arch = mpc85xx_mds_setup_arch, | 201 | .setup_arch = mpc85xx_mds_setup_arch, |
205 | .init_IRQ = mpc85xx_mds_pic_init, | 202 | .init_IRQ = mpc85xx_mds_pic_init, |
206 | .get_irq = mpic_get_irq, | 203 | .get_irq = mpic_get_irq, |
207 | .restart = mpc85xx_restart, | 204 | .restart = fsl_rstcr_restart, |
208 | .calibrate_decr = generic_calibrate_decr, | 205 | .calibrate_decr = generic_calibrate_decr, |
209 | .progress = udbg_progress, | 206 | .progress = udbg_progress, |
210 | #ifdef CONFIG_PCI | 207 | #ifdef CONFIG_PCI |
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 685b2fbbbe00..21d113536b86 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
@@ -11,6 +11,12 @@ config MPC8641_HPCN | |||
11 | help | 11 | help |
12 | This option enables support for the MPC8641 HPCN board. | 12 | This option enables support for the MPC8641 HPCN board. |
13 | 13 | ||
14 | config MPC8610_HPCD | ||
15 | bool "Freescale MPC8610 HPCD" | ||
16 | select DEFAULT_UIMAGE | ||
17 | help | ||
18 | This option enables support for the MPC8610 HPCD board. | ||
19 | |||
14 | endchoice | 20 | endchoice |
15 | 21 | ||
16 | config MPC8641 | 22 | config MPC8641 |
@@ -19,3 +25,10 @@ config MPC8641 | |||
19 | select PPC_UDBG_16550 | 25 | select PPC_UDBG_16550 |
20 | select MPIC | 26 | select MPIC |
21 | default y if MPC8641_HPCN | 27 | default y if MPC8641_HPCN |
28 | |||
29 | config MPC8610 | ||
30 | bool | ||
31 | select FSL_PCI if PCI | ||
32 | select PPC_UDBG_16550 | ||
33 | select MPIC | ||
34 | default y if MPC8610_HPCD | ||
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 3376c7767f2d..c96706327eaa 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile | |||
@@ -4,3 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_SMP) += mpc86xx_smp.o | 5 | obj-$(CONFIG_SMP) += mpc86xx_smp.o |
6 | obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o | 6 | obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o |
7 | obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o | ||
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c new file mode 100644 index 000000000000..6390895e5e92 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * MPC8610 HPCD board specific routines | ||
3 | * | ||
4 | * Initial author: Xianghua Xiao <x.xiao@freescale.com> | ||
5 | * Recode: Jason Jin <jason.jin@freescale.com> | ||
6 | * | ||
7 | * Rewrite the interrupt routing. remove the 8259PIC support, | ||
8 | * All the integrated device in ULI use sideband interrupt. | ||
9 | * | ||
10 | * Copyright 2007 Freescale Semiconductor Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/kdev_t.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/seq_file.h> | ||
24 | #include <linux/of.h> | ||
25 | |||
26 | #include <asm/system.h> | ||
27 | #include <asm/time.h> | ||
28 | #include <asm/machdep.h> | ||
29 | #include <asm/pci-bridge.h> | ||
30 | #include <asm/mpc86xx.h> | ||
31 | #include <asm/prom.h> | ||
32 | #include <mm/mmu_decl.h> | ||
33 | #include <asm/udbg.h> | ||
34 | |||
35 | #include <asm/mpic.h> | ||
36 | |||
37 | #include <sysdev/fsl_pci.h> | ||
38 | #include <sysdev/fsl_soc.h> | ||
39 | |||
40 | void __init | ||
41 | mpc86xx_hpcd_init_irq(void) | ||
42 | { | ||
43 | struct mpic *mpic1; | ||
44 | struct device_node *np; | ||
45 | struct resource res; | ||
46 | |||
47 | /* Determine PIC address. */ | ||
48 | np = of_find_node_by_type(NULL, "open-pic"); | ||
49 | if (np == NULL) | ||
50 | return; | ||
51 | of_address_to_resource(np, 0, &res); | ||
52 | |||
53 | /* Alloc mpic structure and per isu has 16 INT entries. */ | ||
54 | mpic1 = mpic_alloc(np, res.start, | ||
55 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | ||
56 | 0, 256, " MPIC "); | ||
57 | BUG_ON(mpic1 == NULL); | ||
58 | |||
59 | mpic_init(mpic1); | ||
60 | } | ||
61 | |||
62 | #ifdef CONFIG_PCI | ||
63 | static void __devinit quirk_uli1575(struct pci_dev *dev) | ||
64 | { | ||
65 | u32 temp32; | ||
66 | |||
67 | /* Disable INTx */ | ||
68 | pci_read_config_dword(dev, 0x48, &temp32); | ||
69 | pci_write_config_dword(dev, 0x48, (temp32 | 1<<26)); | ||
70 | |||
71 | /* Enable sideband interrupt */ | ||
72 | pci_read_config_dword(dev, 0x90, &temp32); | ||
73 | pci_write_config_dword(dev, 0x90, (temp32 | 1<<22)); | ||
74 | } | ||
75 | |||
76 | static void __devinit quirk_uli5288(struct pci_dev *dev) | ||
77 | { | ||
78 | unsigned char c; | ||
79 | unsigned short temp; | ||
80 | |||
81 | /* Interrupt Disable, Needed when SATA disabled */ | ||
82 | pci_read_config_word(dev, PCI_COMMAND, &temp); | ||
83 | temp |= 1<<10; | ||
84 | pci_write_config_word(dev, PCI_COMMAND, temp); | ||
85 | |||
86 | pci_read_config_byte(dev, 0x83, &c); | ||
87 | c |= 0x80; | ||
88 | pci_write_config_byte(dev, 0x83, c); | ||
89 | |||
90 | pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01); | ||
91 | pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06); | ||
92 | |||
93 | pci_read_config_byte(dev, 0x83, &c); | ||
94 | c &= 0x7f; | ||
95 | pci_write_config_byte(dev, 0x83, c); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Since 8259PIC was disabled on the board, the IDE device can not | ||
100 | * use the legacy IRQ, we need to let the IDE device work under | ||
101 | * native mode and use the interrupt line like other PCI devices. | ||
102 | * IRQ14 is a sideband interrupt from IDE device to CPU and we use this | ||
103 | * as the interrupt for IDE device. | ||
104 | */ | ||
105 | static void __devinit quirk_uli5229(struct pci_dev *dev) | ||
106 | { | ||
107 | unsigned char c; | ||
108 | |||
109 | pci_read_config_byte(dev, 0x4b, &c); | ||
110 | c |= 0x10; | ||
111 | pci_write_config_byte(dev, 0x4b, c); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * SATA interrupt pin bug fix | ||
116 | * There's a chip bug for 5288, The interrupt pin should be 2, | ||
117 | * not the read only value 1, So it use INTB#, not INTA# which | ||
118 | * actually used by the IDE device 5229. | ||
119 | * As of this bug, during the PCI initialization, 5288 read the | ||
120 | * irq of IDE device from the device tree, this function fix this | ||
121 | * bug by re-assigning a correct irq to 5288. | ||
122 | * | ||
123 | */ | ||
124 | static void __devinit final_uli5288(struct pci_dev *dev) | ||
125 | { | ||
126 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
127 | struct device_node *hosenode = hose ? hose->arch_data : NULL; | ||
128 | struct of_irq oirq; | ||
129 | int virq, pin = 2; | ||
130 | u32 laddr[3]; | ||
131 | |||
132 | if (!hosenode) | ||
133 | return; | ||
134 | |||
135 | laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8); | ||
136 | laddr[1] = laddr[2] = 0; | ||
137 | of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq); | ||
138 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
139 | oirq.size); | ||
140 | dev->irq = virq; | ||
141 | } | ||
142 | |||
143 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575); | ||
144 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); | ||
145 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); | ||
146 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, final_uli5288); | ||
147 | #endif /* CONFIG_PCI */ | ||
148 | |||
149 | static void __init | ||
150 | mpc86xx_hpcd_setup_arch(void) | ||
151 | { | ||
152 | #ifdef CONFIG_PCI | ||
153 | struct device_node *np; | ||
154 | #endif | ||
155 | if (ppc_md.progress) | ||
156 | ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0); | ||
157 | |||
158 | #ifdef CONFIG_PCI | ||
159 | for_each_node_by_type(np, "pci") { | ||
160 | if (of_device_is_compatible(np, "fsl,mpc8610-pci") | ||
161 | || of_device_is_compatible(np, "fsl,mpc8641-pcie")) { | ||
162 | struct resource rsrc; | ||
163 | of_address_to_resource(np, 0, &rsrc); | ||
164 | if ((rsrc.start & 0xfffff) == 0xa000) | ||
165 | fsl_add_bridge(np, 1); | ||
166 | else | ||
167 | fsl_add_bridge(np, 0); | ||
168 | } | ||
169 | } | ||
170 | #endif | ||
171 | |||
172 | printk("MPC86xx HPCD board from Freescale Semiconductor\n"); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Called very early, device-tree isn't unflattened | ||
177 | */ | ||
178 | static int __init mpc86xx_hpcd_probe(void) | ||
179 | { | ||
180 | unsigned long root = of_get_flat_dt_root(); | ||
181 | |||
182 | if (of_flat_dt_is_compatible(root, "fsl,MPC8610HPCD")) | ||
183 | return 1; /* Looks good */ | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | long __init | ||
189 | mpc86xx_time_init(void) | ||
190 | { | ||
191 | unsigned int temp; | ||
192 | |||
193 | /* Set the time base to zero */ | ||
194 | mtspr(SPRN_TBWL, 0); | ||
195 | mtspr(SPRN_TBWU, 0); | ||
196 | |||
197 | temp = mfspr(SPRN_HID0); | ||
198 | temp |= HID0_TBEN; | ||
199 | mtspr(SPRN_HID0, temp); | ||
200 | asm volatile("isync"); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | define_machine(mpc86xx_hpcd) { | ||
206 | .name = "MPC86xx HPCD", | ||
207 | .probe = mpc86xx_hpcd_probe, | ||
208 | .setup_arch = mpc86xx_hpcd_setup_arch, | ||
209 | .init_IRQ = mpc86xx_hpcd_init_irq, | ||
210 | .get_irq = mpic_get_irq, | ||
211 | .restart = fsl_rstcr_restart, | ||
212 | .time_init = mpc86xx_time_init, | ||
213 | .calibrate_decr = generic_calibrate_decr, | ||
214 | .progress = udbg_progress, | ||
215 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
216 | }; | ||
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h deleted file mode 100644 index 41e554c4af94..000000000000 --- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* | ||
2 | * MPC8641 HPCN board definitions | ||
3 | * | ||
4 | * Copyright 2006 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * Author: Xianghua Xiao <x.xiao@freescale.com> | ||
12 | */ | ||
13 | |||
14 | #ifndef __MPC8641_HPCN_H__ | ||
15 | #define __MPC8641_HPCN_H__ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | |||
19 | #define MPC86XX_RSTCR_OFFSET (0xe00b0) /* Reset Control Register */ | ||
20 | |||
21 | #endif /* __MPC8641_HPCN_H__ */ | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 47aafa76c933..32a531aebcb7 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <sysdev/fsl_soc.h> | 35 | #include <sysdev/fsl_soc.h> |
36 | 36 | ||
37 | #include "mpc86xx.h" | 37 | #include "mpc86xx.h" |
38 | #include "mpc8641_hpcn.h" | ||
39 | 38 | ||
40 | #undef DEBUG | 39 | #undef DEBUG |
41 | 40 | ||
@@ -132,25 +131,15 @@ static int mpc86xx_exclude_device(struct pci_controller *hose, | |||
132 | static void __init | 131 | static void __init |
133 | mpc86xx_hpcn_setup_arch(void) | 132 | mpc86xx_hpcn_setup_arch(void) |
134 | { | 133 | { |
134 | #ifdef CONFIG_PCI | ||
135 | struct device_node *np; | 135 | struct device_node *np; |
136 | #endif | ||
136 | 137 | ||
137 | if (ppc_md.progress) | 138 | if (ppc_md.progress) |
138 | ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0); | 139 | ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0); |
139 | 140 | ||
140 | np = of_find_node_by_type(NULL, "cpu"); | ||
141 | if (np != 0) { | ||
142 | const unsigned int *fp; | ||
143 | |||
144 | fp = of_get_property(np, "clock-frequency", NULL); | ||
145 | if (fp != 0) | ||
146 | loops_per_jiffy = *fp / HZ; | ||
147 | else | ||
148 | loops_per_jiffy = 50000000 / HZ; | ||
149 | of_node_put(np); | ||
150 | } | ||
151 | |||
152 | #ifdef CONFIG_PCI | 141 | #ifdef CONFIG_PCI |
153 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | 142 | for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") { |
154 | struct resource rsrc; | 143 | struct resource rsrc; |
155 | of_address_to_resource(np, 0, &rsrc); | 144 | of_address_to_resource(np, 0, &rsrc); |
156 | if ((rsrc.start & 0xfffff) == 0x8000) | 145 | if ((rsrc.start & 0xfffff) == 0x8000) |
@@ -158,6 +147,7 @@ mpc86xx_hpcn_setup_arch(void) | |||
158 | else | 147 | else |
159 | fsl_add_bridge(np, 0); | 148 | fsl_add_bridge(np, 0); |
160 | } | 149 | } |
150 | |||
161 | uses_fsl_uli_m1575 = 1; | 151 | uses_fsl_uli_m1575 = 1; |
162 | ppc_md.pci_exclude_device = mpc86xx_exclude_device; | 152 | ppc_md.pci_exclude_device = mpc86xx_exclude_device; |
163 | 153 | ||
@@ -205,23 +195,6 @@ static int __init mpc86xx_hpcn_probe(void) | |||
205 | return 0; | 195 | return 0; |
206 | } | 196 | } |
207 | 197 | ||
208 | |||
209 | void | ||
210 | mpc86xx_restart(char *cmd) | ||
211 | { | ||
212 | void __iomem *rstcr; | ||
213 | |||
214 | rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100); | ||
215 | |||
216 | local_irq_disable(); | ||
217 | |||
218 | /* Assert reset request to Reset Control Register */ | ||
219 | out_be32(rstcr, 0x2); | ||
220 | |||
221 | /* not reached */ | ||
222 | } | ||
223 | |||
224 | |||
225 | long __init | 198 | long __init |
226 | mpc86xx_time_init(void) | 199 | mpc86xx_time_init(void) |
227 | { | 200 | { |
@@ -246,7 +219,7 @@ define_machine(mpc86xx_hpcn) { | |||
246 | .init_IRQ = mpc86xx_hpcn_init_irq, | 219 | .init_IRQ = mpc86xx_hpcn_init_irq, |
247 | .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, | 220 | .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, |
248 | .get_irq = mpic_get_irq, | 221 | .get_irq = mpic_get_irq, |
249 | .restart = mpc86xx_restart, | 222 | .restart = fsl_rstcr_restart, |
250 | .time_init = mpc86xx_time_init, | 223 | .time_init = mpc86xx_time_init, |
251 | .calibrate_decr = generic_calibrate_decr, | 224 | .calibrate_decr = generic_calibrate_decr, |
252 | .progress = udbg_progress, | 225 | .progress = udbg_progress, |
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index 39bb8c5ebe70..bd28655043a0 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig | |||
@@ -3,6 +3,7 @@ config FADS | |||
3 | 3 | ||
4 | config CPM1 | 4 | config CPM1 |
5 | bool | 5 | bool |
6 | select CPM | ||
6 | 7 | ||
7 | choice | 8 | choice |
8 | prompt "8xx Machine Type" | 9 | prompt "8xx Machine Type" |
@@ -25,12 +26,23 @@ config MPC86XADS | |||
25 | config MPC885ADS | 26 | config MPC885ADS |
26 | bool "MPC885ADS" | 27 | bool "MPC885ADS" |
27 | select CPM1 | 28 | select CPM1 |
29 | select PPC_CPM_NEW_BINDING | ||
28 | help | 30 | help |
29 | Freescale Semiconductor MPC885 Application Development System (ADS). | 31 | Freescale Semiconductor MPC885 Application Development System (ADS). |
30 | Also known as DUET. | 32 | Also known as DUET. |
31 | The MPC885ADS is meant to serve as a platform for s/w and h/w | 33 | The MPC885ADS is meant to serve as a platform for s/w and h/w |
32 | development around the MPC885 processor family. | 34 | development around the MPC885 processor family. |
33 | 35 | ||
36 | config PPC_EP88XC | ||
37 | bool "Embedded Planet EP88xC (a.k.a. CWH-PPC-885XN-VE)" | ||
38 | select CPM1 | ||
39 | select PPC_CPM_NEW_BINDING | ||
40 | help | ||
41 | This enables support for the Embedded Planet EP88xC board. | ||
42 | |||
43 | This board is also resold by Freescale as the QUICCStart | ||
44 | MPC885 Evaluation System and/or the CWH-PPC-885XN-VE. | ||
45 | |||
34 | endchoice | 46 | endchoice |
35 | 47 | ||
36 | menu "Freescale Ethernet driver platform-specific options" | 48 | menu "Freescale Ethernet driver platform-specific options" |
@@ -99,6 +111,22 @@ config 8xx_CPU6 | |||
99 | 111 | ||
100 | If in doubt, say N here. | 112 | If in doubt, say N here. |
101 | 113 | ||
114 | config 8xx_CPU15 | ||
115 | bool "CPU15 Silicon Errata" | ||
116 | default y | ||
117 | help | ||
118 | This enables a workaround for erratum CPU15 on MPC8xx chips. | ||
119 | This bug can cause incorrect code execution under certain | ||
120 | circumstances. This workaround adds some overhead (a TLB miss | ||
121 | every time execution crosses a page boundary), and you may wish | ||
122 | to disable it if you have worked around the bug in the compiler | ||
123 | (by not placing conditional branches or branches to LR or CTR | ||
124 | in the last word of a page, with a target of the last cache | ||
125 | line in the next page), or if you have used some other | ||
126 | workaround. | ||
127 | |||
128 | If in doubt, say Y here. | ||
129 | |||
102 | choice | 130 | choice |
103 | prompt "Microcode patch selection" | 131 | prompt "Microcode patch selection" |
104 | default NO_UCODE_PATCH | 132 | default NO_UCODE_PATCH |
diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile index 5e2dae3afd2f..8b7098018b59 100644 --- a/arch/powerpc/platforms/8xx/Makefile +++ b/arch/powerpc/platforms/8xx/Makefile | |||
@@ -4,3 +4,4 @@ | |||
4 | obj-$(CONFIG_PPC_8xx) += m8xx_setup.o | 4 | obj-$(CONFIG_PPC_8xx) += m8xx_setup.o |
5 | obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o | 5 | obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o |
6 | obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o | 6 | obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o |
7 | obj-$(CONFIG_PPC_EP88XC) += ep88xc.o | ||
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c new file mode 100644 index 000000000000..c518b6cc5fab --- /dev/null +++ b/arch/powerpc/platforms/8xx/ep88xc.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Platform setup for the Embedded Planet EP88xC board | ||
3 | * | ||
4 | * Author: Scott Wood <scottwood@freescale.com> | ||
5 | * Copyright 2007 Freescale Semiconductor, Inc. | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | ||
8 | * version 2. This program is licensed "as is" without any warranty of any | ||
9 | * kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/of_platform.h> | ||
14 | |||
15 | #include <asm/machdep.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/udbg.h> | ||
18 | #include <asm/commproc.h> | ||
19 | |||
20 | #include <sysdev/commproc.h> | ||
21 | |||
22 | struct cpm_pin { | ||
23 | int port, pin, flags; | ||
24 | }; | ||
25 | |||
26 | static struct cpm_pin ep88xc_pins[] = { | ||
27 | /* SMC1 */ | ||
28 | {1, 24, CPM_PIN_INPUT}, /* RX */ | ||
29 | {1, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */ | ||
30 | |||
31 | /* SCC2 */ | ||
32 | {0, 12, CPM_PIN_INPUT}, /* TX */ | ||
33 | {0, 13, CPM_PIN_INPUT}, /* RX */ | ||
34 | {2, 8, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* CD */ | ||
35 | {2, 9, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* CTS */ | ||
36 | {2, 14, CPM_PIN_INPUT}, /* RTS */ | ||
37 | |||
38 | /* MII1 */ | ||
39 | {0, 0, CPM_PIN_INPUT}, | ||
40 | {0, 1, CPM_PIN_INPUT}, | ||
41 | {0, 2, CPM_PIN_INPUT}, | ||
42 | {0, 3, CPM_PIN_INPUT}, | ||
43 | {0, 4, CPM_PIN_OUTPUT}, | ||
44 | {0, 10, CPM_PIN_OUTPUT}, | ||
45 | {0, 11, CPM_PIN_OUTPUT}, | ||
46 | {1, 19, CPM_PIN_INPUT}, | ||
47 | {1, 31, CPM_PIN_INPUT}, | ||
48 | {2, 12, CPM_PIN_INPUT}, | ||
49 | {2, 13, CPM_PIN_INPUT}, | ||
50 | {3, 8, CPM_PIN_INPUT}, | ||
51 | {4, 30, CPM_PIN_OUTPUT}, | ||
52 | {4, 31, CPM_PIN_OUTPUT}, | ||
53 | |||
54 | /* MII2 */ | ||
55 | {4, 14, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
56 | {4, 15, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
57 | {4, 16, CPM_PIN_OUTPUT}, | ||
58 | {4, 17, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
59 | {4, 18, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
60 | {4, 19, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
61 | {4, 20, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
62 | {4, 21, CPM_PIN_OUTPUT}, | ||
63 | {4, 22, CPM_PIN_OUTPUT}, | ||
64 | {4, 23, CPM_PIN_OUTPUT}, | ||
65 | {4, 24, CPM_PIN_OUTPUT}, | ||
66 | {4, 25, CPM_PIN_OUTPUT}, | ||
67 | {4, 26, CPM_PIN_OUTPUT}, | ||
68 | {4, 27, CPM_PIN_OUTPUT}, | ||
69 | {4, 28, CPM_PIN_OUTPUT}, | ||
70 | {4, 29, CPM_PIN_OUTPUT}, | ||
71 | |||
72 | /* USB */ | ||
73 | {0, 6, CPM_PIN_INPUT}, /* CLK2 */ | ||
74 | {0, 14, CPM_PIN_INPUT}, /* USBOE */ | ||
75 | {0, 15, CPM_PIN_INPUT}, /* USBRXD */ | ||
76 | {2, 6, CPM_PIN_OUTPUT}, /* USBTXN */ | ||
77 | {2, 7, CPM_PIN_OUTPUT}, /* USBTXP */ | ||
78 | {2, 10, CPM_PIN_INPUT}, /* USBRXN */ | ||
79 | {2, 11, CPM_PIN_INPUT}, /* USBRXP */ | ||
80 | |||
81 | /* Misc */ | ||
82 | {1, 26, CPM_PIN_INPUT}, /* BRGO2 */ | ||
83 | {1, 27, CPM_PIN_INPUT}, /* BRGO1 */ | ||
84 | }; | ||
85 | |||
86 | static void __init init_ioports(void) | ||
87 | { | ||
88 | int i; | ||
89 | |||
90 | for (i = 0; i < ARRAY_SIZE(ep88xc_pins); i++) { | ||
91 | struct cpm_pin *pin = &ep88xc_pins[i]; | ||
92 | cpm1_set_pin(pin->port, pin->pin, pin->flags); | ||
93 | } | ||
94 | |||
95 | cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX); | ||
96 | cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK2, CPM_CLK_TX); /* USB */ | ||
97 | cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK2, CPM_CLK_RX); | ||
98 | cpm1_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX); | ||
99 | cpm1_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX); | ||
100 | } | ||
101 | |||
102 | static u8 __iomem *ep88xc_bcsr; | ||
103 | |||
104 | #define BCSR7_SCC2_ENABLE 0x10 | ||
105 | |||
106 | #define BCSR8_PHY1_ENABLE 0x80 | ||
107 | #define BCSR8_PHY1_POWER 0x40 | ||
108 | #define BCSR8_PHY2_ENABLE 0x20 | ||
109 | #define BCSR8_PHY2_POWER 0x10 | ||
110 | |||
111 | #define BCSR9_USB_ENABLE 0x80 | ||
112 | #define BCSR9_USB_POWER 0x40 | ||
113 | #define BCSR9_USB_HOST 0x20 | ||
114 | #define BCSR9_USB_FULL_SPEED_TARGET 0x10 | ||
115 | |||
116 | static void __init ep88xc_setup_arch(void) | ||
117 | { | ||
118 | struct device_node *np; | ||
119 | |||
120 | cpm_reset(); | ||
121 | init_ioports(); | ||
122 | |||
123 | np = of_find_compatible_node(NULL, NULL, "fsl,ep88xc-bcsr"); | ||
124 | if (!np) { | ||
125 | printk(KERN_CRIT "Could not find fsl,ep88xc-bcsr node\n"); | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | ep88xc_bcsr = of_iomap(np, 0); | ||
130 | of_node_put(np); | ||
131 | |||
132 | if (!ep88xc_bcsr) { | ||
133 | printk(KERN_CRIT "Could not remap BCSR\n"); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | setbits8(&ep88xc_bcsr[7], BCSR7_SCC2_ENABLE); | ||
138 | setbits8(&ep88xc_bcsr[8], BCSR8_PHY1_ENABLE | BCSR8_PHY1_POWER | | ||
139 | BCSR8_PHY2_ENABLE | BCSR8_PHY2_POWER); | ||
140 | } | ||
141 | |||
142 | static int __init ep88xc_probe(void) | ||
143 | { | ||
144 | unsigned long root = of_get_flat_dt_root(); | ||
145 | return of_flat_dt_is_compatible(root, "fsl,ep88xc"); | ||
146 | } | ||
147 | |||
148 | static struct of_device_id __initdata of_bus_ids[] = { | ||
149 | { .name = "soc", }, | ||
150 | { .name = "cpm", }, | ||
151 | { .name = "localbus", }, | ||
152 | {}, | ||
153 | }; | ||
154 | |||
155 | static int __init declare_of_platform_devices(void) | ||
156 | { | ||
157 | /* Publish the QE devices */ | ||
158 | if (machine_is(ep88xc)) | ||
159 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | device_initcall(declare_of_platform_devices); | ||
164 | |||
165 | define_machine(ep88xc) { | ||
166 | .name = "Embedded Planet EP88xC", | ||
167 | .probe = ep88xc_probe, | ||
168 | .setup_arch = ep88xc_setup_arch, | ||
169 | .init_IRQ = m8xx_pic_init, | ||
170 | .get_irq = mpc8xx_get_irq, | ||
171 | .restart = mpc8xx_restart, | ||
172 | .calibrate_decr = mpc8xx_calibrate_decr, | ||
173 | .set_rtc_time = mpc8xx_set_rtc_time, | ||
174 | .get_rtc_time = mpc8xx_get_rtc_time, | ||
175 | .progress = udbg_progress, | ||
176 | }; | ||
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index f1693550c70c..d35eda80e9e6 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
@@ -10,57 +10,33 @@ | |||
10 | * bootup setup stuff.. | 10 | * bootup setup stuff.. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
16 | #include <linux/mm.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/unistd.h> | ||
19 | #include <linux/ptrace.h> | ||
20 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
21 | #include <linux/user.h> | ||
22 | #include <linux/a.out.h> | ||
23 | #include <linux/tty.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
26 | #include <linux/reboot.h> | ||
27 | #include <linux/init.h> | 16 | #include <linux/init.h> |
28 | #include <linux/initrd.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/bootmem.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/root_dev.h> | ||
33 | #include <linux/time.h> | 17 | #include <linux/time.h> |
34 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
35 | #include <linux/fsl_devices.h> | ||
36 | 19 | ||
37 | #include <asm/mmu.h> | ||
38 | #include <asm/reg.h> | ||
39 | #include <asm/residual.h> | ||
40 | #include <asm/io.h> | 20 | #include <asm/io.h> |
41 | #include <asm/pgtable.h> | ||
42 | #include <asm/mpc8xx.h> | 21 | #include <asm/mpc8xx.h> |
43 | #include <asm/8xx_immap.h> | 22 | #include <asm/8xx_immap.h> |
44 | #include <asm/machdep.h> | ||
45 | #include <asm/bootinfo.h> | ||
46 | #include <asm/time.h> | ||
47 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
48 | #include <asm/fs_pd.h> | 24 | #include <asm/fs_pd.h> |
49 | #include <mm/mmu_decl.h> | 25 | #include <mm/mmu_decl.h> |
50 | 26 | ||
51 | #include "sysdev/mpc8xx_pic.h" | 27 | #include <sysdev/mpc8xx_pic.h> |
28 | #include <sysdev/commproc.h> | ||
52 | 29 | ||
53 | #ifdef CONFIG_PCMCIA_M8XX | 30 | #ifdef CONFIG_PCMCIA_M8XX |
54 | struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | 31 | struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; |
55 | #endif | 32 | #endif |
56 | 33 | ||
57 | void m8xx_calibrate_decr(void); | 34 | void m8xx_calibrate_decr(void); |
58 | extern void m8xx_wdt_handler_install(bd_t *bp); | ||
59 | extern int cpm_pic_init(void); | 35 | extern int cpm_pic_init(void); |
60 | extern int cpm_get_irq(void); | 36 | extern int cpm_get_irq(void); |
61 | 37 | ||
62 | /* A place holder for time base interrupts, if they are ever enabled. */ | 38 | /* A place holder for time base interrupts, if they are ever enabled. */ |
63 | irqreturn_t timebase_interrupt(int irq, void * dev) | 39 | static irqreturn_t timebase_interrupt(int irq, void *dev) |
64 | { | 40 | { |
65 | printk ("timebase_interrupt()\n"); | 41 | printk ("timebase_interrupt()\n"); |
66 | 42 | ||
@@ -77,7 +53,7 @@ static struct irqaction tbint_irqaction = { | |||
77 | void __init __attribute__ ((weak)) | 53 | void __init __attribute__ ((weak)) |
78 | init_internal_rtc(void) | 54 | init_internal_rtc(void) |
79 | { | 55 | { |
80 | sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit); | 56 | sit8xx_t __iomem *sys_tmr = immr_map(im_sit); |
81 | 57 | ||
82 | /* Disable the RTC one second and alarm interrupts. */ | 58 | /* Disable the RTC one second and alarm interrupts. */ |
83 | clrbits16(&sys_tmr->sit_rtcsc, (RTCSC_SIE | RTCSC_ALE)); | 59 | clrbits16(&sys_tmr->sit_rtcsc, (RTCSC_SIE | RTCSC_ALE)); |
@@ -89,24 +65,24 @@ init_internal_rtc(void) | |||
89 | 65 | ||
90 | static int __init get_freq(char *name, unsigned long *val) | 66 | static int __init get_freq(char *name, unsigned long *val) |
91 | { | 67 | { |
92 | struct device_node *cpu; | 68 | struct device_node *cpu; |
93 | const unsigned int *fp; | 69 | const unsigned int *fp; |
94 | int found = 0; | 70 | int found = 0; |
95 | 71 | ||
96 | /* The cpu node should have timebase and clock frequency properties */ | 72 | /* The cpu node should have timebase and clock frequency properties */ |
97 | cpu = of_find_node_by_type(NULL, "cpu"); | 73 | cpu = of_find_node_by_type(NULL, "cpu"); |
98 | 74 | ||
99 | if (cpu) { | 75 | if (cpu) { |
100 | fp = of_get_property(cpu, name, NULL); | 76 | fp = of_get_property(cpu, name, NULL); |
101 | if (fp) { | 77 | if (fp) { |
102 | found = 1; | 78 | found = 1; |
103 | *val = *fp; | 79 | *val = *fp; |
104 | } | 80 | } |
105 | 81 | ||
106 | of_node_put(cpu); | 82 | of_node_put(cpu); |
107 | } | 83 | } |
108 | 84 | ||
109 | return found; | 85 | return found; |
110 | } | 86 | } |
111 | 87 | ||
112 | /* The decrementer counts at the system (internal) clock frequency divided by | 88 | /* The decrementer counts at the system (internal) clock frequency divided by |
@@ -116,13 +92,13 @@ static int __init get_freq(char *name, unsigned long *val) | |||
116 | void __init mpc8xx_calibrate_decr(void) | 92 | void __init mpc8xx_calibrate_decr(void) |
117 | { | 93 | { |
118 | struct device_node *cpu; | 94 | struct device_node *cpu; |
119 | cark8xx_t *clk_r1; | 95 | cark8xx_t __iomem *clk_r1; |
120 | car8xx_t *clk_r2; | 96 | car8xx_t __iomem *clk_r2; |
121 | sitk8xx_t *sys_tmr1; | 97 | sitk8xx_t __iomem *sys_tmr1; |
122 | sit8xx_t *sys_tmr2; | 98 | sit8xx_t __iomem *sys_tmr2; |
123 | int irq, virq; | 99 | int irq, virq; |
124 | 100 | ||
125 | clk_r1 = (cark8xx_t *) immr_map(im_clkrstk); | 101 | clk_r1 = immr_map(im_clkrstk); |
126 | 102 | ||
127 | /* Unlock the SCCR. */ | 103 | /* Unlock the SCCR. */ |
128 | out_be32(&clk_r1->cark_sccrk, ~KAPWR_KEY); | 104 | out_be32(&clk_r1->cark_sccrk, ~KAPWR_KEY); |
@@ -130,24 +106,24 @@ void __init mpc8xx_calibrate_decr(void) | |||
130 | immr_unmap(clk_r1); | 106 | immr_unmap(clk_r1); |
131 | 107 | ||
132 | /* Force all 8xx processors to use divide by 16 processor clock. */ | 108 | /* Force all 8xx processors to use divide by 16 processor clock. */ |
133 | clk_r2 = (car8xx_t *) immr_map(im_clkrst); | 109 | clk_r2 = immr_map(im_clkrst); |
134 | setbits32(&clk_r2->car_sccr, 0x02000000); | 110 | setbits32(&clk_r2->car_sccr, 0x02000000); |
135 | immr_unmap(clk_r2); | 111 | immr_unmap(clk_r2); |
136 | 112 | ||
137 | /* Processor frequency is MHz. | 113 | /* Processor frequency is MHz. |
138 | */ | 114 | */ |
139 | ppc_tb_freq = 50000000; | 115 | ppc_tb_freq = 50000000; |
140 | if (!get_freq("bus-frequency", &ppc_tb_freq)) { | 116 | if (!get_freq("bus-frequency", &ppc_tb_freq)) { |
141 | printk(KERN_ERR "WARNING: Estimating decrementer frequency " | 117 | printk(KERN_ERR "WARNING: Estimating decrementer frequency " |
142 | "(not found)\n"); | 118 | "(not found)\n"); |
143 | } | 119 | } |
144 | ppc_tb_freq /= 16; | 120 | ppc_tb_freq /= 16; |
145 | ppc_proc_freq = 50000000; | 121 | ppc_proc_freq = 50000000; |
146 | if (!get_freq("clock-frequency", &ppc_proc_freq)) | 122 | if (!get_freq("clock-frequency", &ppc_proc_freq)) |
147 | printk(KERN_ERR "WARNING: Estimating processor frequency" | 123 | printk(KERN_ERR "WARNING: Estimating processor frequency" |
148 | "(not found)\n"); | 124 | "(not found)\n"); |
149 | 125 | ||
150 | printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq); | 126 | printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq); |
151 | 127 | ||
152 | /* Perform some more timer/timebase initialization. This used | 128 | /* Perform some more timer/timebase initialization. This used |
153 | * to be done elsewhere, but other changes caused it to get | 129 | * to be done elsewhere, but other changes caused it to get |
@@ -164,7 +140,7 @@ void __init mpc8xx_calibrate_decr(void) | |||
164 | * we guarantee the registers are locked, then we unlock them | 140 | * we guarantee the registers are locked, then we unlock them |
165 | * for our use. | 141 | * for our use. |
166 | */ | 142 | */ |
167 | sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk); | 143 | sys_tmr1 = immr_map(im_sitk); |
168 | out_be32(&sys_tmr1->sitk_tbscrk, ~KAPWR_KEY); | 144 | out_be32(&sys_tmr1->sitk_tbscrk, ~KAPWR_KEY); |
169 | out_be32(&sys_tmr1->sitk_rtcsck, ~KAPWR_KEY); | 145 | out_be32(&sys_tmr1->sitk_rtcsck, ~KAPWR_KEY); |
170 | out_be32(&sys_tmr1->sitk_tbk, ~KAPWR_KEY); | 146 | out_be32(&sys_tmr1->sitk_tbk, ~KAPWR_KEY); |
@@ -180,24 +156,17 @@ void __init mpc8xx_calibrate_decr(void) | |||
180 | * we have to enable the timebase). The decrementer interrupt | 156 | * we have to enable the timebase). The decrementer interrupt |
181 | * is wired into the vector table, nothing to do here for that. | 157 | * is wired into the vector table, nothing to do here for that. |
182 | */ | 158 | */ |
183 | cpu = of_find_node_by_type(NULL, "cpu"); | 159 | cpu = of_find_node_by_type(NULL, "cpu"); |
184 | virq= irq_of_parse_and_map(cpu, 0); | 160 | virq= irq_of_parse_and_map(cpu, 0); |
185 | irq = irq_map[virq].hwirq; | 161 | irq = irq_map[virq].hwirq; |
186 | 162 | ||
187 | sys_tmr2 = (sit8xx_t *) immr_map(im_sit); | 163 | sys_tmr2 = immr_map(im_sit); |
188 | out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) | | 164 | out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) | |
189 | (TBSCR_TBF | TBSCR_TBE)); | 165 | (TBSCR_TBF | TBSCR_TBE)); |
190 | immr_unmap(sys_tmr2); | 166 | immr_unmap(sys_tmr2); |
191 | 167 | ||
192 | if (setup_irq(virq, &tbint_irqaction)) | 168 | if (setup_irq(virq, &tbint_irqaction)) |
193 | panic("Could not allocate timer IRQ!"); | 169 | panic("Could not allocate timer IRQ!"); |
194 | |||
195 | #ifdef CONFIG_8xx_WDT | ||
196 | /* Install watchdog timer handler early because it might be | ||
197 | * already enabled by the bootloader | ||
198 | */ | ||
199 | m8xx_wdt_handler_install(binfo); | ||
200 | #endif | ||
201 | } | 170 | } |
202 | 171 | ||
203 | /* The RTC on the MPC8xx is an internal register. | 172 | /* The RTC on the MPC8xx is an internal register. |
@@ -207,14 +176,14 @@ void __init mpc8xx_calibrate_decr(void) | |||
207 | 176 | ||
208 | int mpc8xx_set_rtc_time(struct rtc_time *tm) | 177 | int mpc8xx_set_rtc_time(struct rtc_time *tm) |
209 | { | 178 | { |
210 | sitk8xx_t *sys_tmr1; | 179 | sitk8xx_t __iomem *sys_tmr1; |
211 | sit8xx_t *sys_tmr2; | 180 | sit8xx_t __iomem *sys_tmr2; |
212 | int time; | 181 | int time; |
213 | 182 | ||
214 | sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk); | 183 | sys_tmr1 = immr_map(im_sitk); |
215 | sys_tmr2 = (sit8xx_t *) immr_map(im_sit); | 184 | sys_tmr2 = immr_map(im_sit); |
216 | time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, | 185 | time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, |
217 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 186 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
218 | 187 | ||
219 | out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY); | 188 | out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY); |
220 | out_be32(&sys_tmr2->sit_rtc, time); | 189 | out_be32(&sys_tmr2->sit_rtc, time); |
@@ -228,21 +197,20 @@ int mpc8xx_set_rtc_time(struct rtc_time *tm) | |||
228 | void mpc8xx_get_rtc_time(struct rtc_time *tm) | 197 | void mpc8xx_get_rtc_time(struct rtc_time *tm) |
229 | { | 198 | { |
230 | unsigned long data; | 199 | unsigned long data; |
231 | sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit); | 200 | sit8xx_t __iomem *sys_tmr = immr_map(im_sit); |
232 | 201 | ||
233 | /* Get time from the RTC. */ | 202 | /* Get time from the RTC. */ |
234 | data = in_be32(&sys_tmr->sit_rtc); | 203 | data = in_be32(&sys_tmr->sit_rtc); |
235 | to_tm(data, tm); | 204 | to_tm(data, tm); |
236 | tm->tm_year -= 1900; | 205 | tm->tm_year -= 1900; |
237 | tm->tm_mon -= 1; | 206 | tm->tm_mon -= 1; |
238 | immr_unmap(sys_tmr); | 207 | immr_unmap(sys_tmr); |
239 | return; | 208 | return; |
240 | } | 209 | } |
241 | 210 | ||
242 | void mpc8xx_restart(char *cmd) | 211 | void mpc8xx_restart(char *cmd) |
243 | { | 212 | { |
244 | __volatile__ unsigned char dummy; | 213 | car8xx_t __iomem *clk_r = immr_map(im_clkrst); |
245 | car8xx_t * clk_r = (car8xx_t *) immr_map(im_clkrst); | ||
246 | 214 | ||
247 | 215 | ||
248 | local_irq_disable(); | 216 | local_irq_disable(); |
@@ -252,26 +220,8 @@ void mpc8xx_restart(char *cmd) | |||
252 | */ | 220 | */ |
253 | mtmsr(mfmsr() & ~0x1000); | 221 | mtmsr(mfmsr() & ~0x1000); |
254 | 222 | ||
255 | dummy = in_8(&clk_r->res[0]); | 223 | in_8(&clk_r->res[0]); |
256 | printk("Restart failed\n"); | 224 | panic("Restart failed\n"); |
257 | while(1); | ||
258 | } | ||
259 | |||
260 | void mpc8xx_show_cpuinfo(struct seq_file *m) | ||
261 | { | ||
262 | struct device_node *root; | ||
263 | uint memsize = total_memory; | ||
264 | const char *model = ""; | ||
265 | |||
266 | seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); | ||
267 | |||
268 | root = of_find_node_by_path("/"); | ||
269 | if (root) | ||
270 | model = of_get_property(root, "model", NULL); | ||
271 | seq_printf(m, "Machine\t\t: %s\n", model); | ||
272 | of_node_put(root); | ||
273 | |||
274 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
275 | } | 225 | } |
276 | 226 | ||
277 | static void cpm_cascade(unsigned int irq, struct irq_desc *desc) | 227 | static void cpm_cascade(unsigned int irq, struct irq_desc *desc) |
@@ -298,7 +248,7 @@ void __init m8xx_pic_init(void) | |||
298 | int irq; | 248 | int irq; |
299 | 249 | ||
300 | if (mpc8xx_pic_init()) { | 250 | if (mpc8xx_pic_init()) { |
301 | printk(KERN_ERR "Failed interrupt 8xx controller initialization\n"); | 251 | printk(KERN_ERR "Failed interrupt 8xx controller initialization\n"); |
302 | return; | 252 | return; |
303 | } | 253 | } |
304 | 254 | ||
diff --git a/arch/powerpc/platforms/8xx/mpc86xads.h b/arch/powerpc/platforms/8xx/mpc86xads.h index 59bad2f9ae51..cffa194ccf1f 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads.h +++ b/arch/powerpc/platforms/8xx/mpc86xads.h | |||
@@ -15,7 +15,6 @@ | |||
15 | #ifndef __ASM_MPC86XADS_H__ | 15 | #ifndef __ASM_MPC86XADS_H__ |
16 | #define __ASM_MPC86XADS_H__ | 16 | #define __ASM_MPC86XADS_H__ |
17 | 17 | ||
18 | #include <asm/ppcboot.h> | ||
19 | #include <sysdev/fsl_soc.h> | 18 | #include <sysdev/fsl_soc.h> |
20 | 19 | ||
21 | /* U-Boot maps BCSR to 0xff080000 */ | 20 | /* U-Boot maps BCSR to 0xff080000 */ |
@@ -30,9 +29,6 @@ | |||
30 | #define CFG_PHYDEV_ADDR ((uint)0xff0a0000) | 29 | #define CFG_PHYDEV_ADDR ((uint)0xff0a0000) |
31 | #define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300)) | 30 | #define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300)) |
32 | 31 | ||
33 | #define IMAP_ADDR (get_immrbase()) | ||
34 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
35 | |||
36 | #define MPC8xx_CPM_OFFSET (0x9c0) | 32 | #define MPC8xx_CPM_OFFSET (0x9c0) |
37 | #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) | 33 | #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) |
38 | #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver | 34 | #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver |
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index cf0e7bc8c2e7..49012835f453 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c | |||
@@ -31,21 +31,13 @@ | |||
31 | #include <asm/processor.h> | 31 | #include <asm/processor.h> |
32 | #include <asm/system.h> | 32 | #include <asm/system.h> |
33 | #include <asm/time.h> | 33 | #include <asm/time.h> |
34 | #include <asm/ppcboot.h> | ||
35 | #include <asm/mpc8xx.h> | 34 | #include <asm/mpc8xx.h> |
36 | #include <asm/8xx_immap.h> | 35 | #include <asm/8xx_immap.h> |
37 | #include <asm/commproc.h> | 36 | #include <asm/commproc.h> |
38 | #include <asm/fs_pd.h> | 37 | #include <asm/fs_pd.h> |
39 | #include <asm/prom.h> | 38 | #include <asm/prom.h> |
40 | 39 | ||
41 | extern void cpm_reset(void); | 40 | #include <sysdev/commproc.h> |
42 | extern void mpc8xx_show_cpuinfo(struct seq_file*); | ||
43 | extern void mpc8xx_restart(char *cmd); | ||
44 | extern void mpc8xx_calibrate_decr(void); | ||
45 | extern int mpc8xx_set_rtc_time(struct rtc_time *tm); | ||
46 | extern void mpc8xx_get_rtc_time(struct rtc_time *tm); | ||
47 | extern void m8xx_pic_init(void); | ||
48 | extern unsigned int mpc8xx_get_irq(void); | ||
49 | 41 | ||
50 | static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); | 42 | static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); |
51 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); | 43 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); |
@@ -254,20 +246,6 @@ int platform_device_skip(const char *model, int id) | |||
254 | 246 | ||
255 | static void __init mpc86xads_setup_arch(void) | 247 | static void __init mpc86xads_setup_arch(void) |
256 | { | 248 | { |
257 | struct device_node *cpu; | ||
258 | |||
259 | cpu = of_find_node_by_type(NULL, "cpu"); | ||
260 | if (cpu != 0) { | ||
261 | const unsigned int *fp; | ||
262 | |||
263 | fp = of_get_property(cpu, "clock-frequency", NULL); | ||
264 | if (fp != 0) | ||
265 | loops_per_jiffy = *fp / HZ; | ||
266 | else | ||
267 | loops_per_jiffy = 50000000 / HZ; | ||
268 | of_node_put(cpu); | ||
269 | } | ||
270 | |||
271 | cpm_reset(); | 249 | cpm_reset(); |
272 | 250 | ||
273 | mpc86xads_board_setup(); | 251 | mpc86xads_board_setup(); |
@@ -292,7 +270,6 @@ define_machine(mpc86x_ads) { | |||
292 | .probe = mpc86xads_probe, | 270 | .probe = mpc86xads_probe, |
293 | .setup_arch = mpc86xads_setup_arch, | 271 | .setup_arch = mpc86xads_setup_arch, |
294 | .init_IRQ = m8xx_pic_init, | 272 | .init_IRQ = m8xx_pic_init, |
295 | .show_cpuinfo = mpc8xx_show_cpuinfo, | ||
296 | .get_irq = mpc8xx_get_irq, | 273 | .get_irq = mpc8xx_get_irq, |
297 | .restart = mpc8xx_restart, | 274 | .restart = mpc8xx_restart, |
298 | .calibrate_decr = mpc8xx_calibrate_decr, | 275 | .calibrate_decr = mpc8xx_calibrate_decr, |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads.h b/arch/powerpc/platforms/8xx/mpc885ads.h index 7c31aec284c2..a5076668bad6 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads.h +++ b/arch/powerpc/platforms/8xx/mpc885ads.h | |||
@@ -15,31 +15,12 @@ | |||
15 | #ifndef __ASM_MPC885ADS_H__ | 15 | #ifndef __ASM_MPC885ADS_H__ |
16 | #define __ASM_MPC885ADS_H__ | 16 | #define __ASM_MPC885ADS_H__ |
17 | 17 | ||
18 | #include <asm/ppcboot.h> | ||
19 | #include <sysdev/fsl_soc.h> | 18 | #include <sysdev/fsl_soc.h> |
20 | 19 | ||
21 | /* U-Boot maps BCSR to 0xff080000 */ | ||
22 | #define BCSR_ADDR ((uint)0xff080000) | ||
23 | #define BCSR_SIZE ((uint)32) | ||
24 | #define BCSR0 ((uint)(BCSR_ADDR + 0x00)) | ||
25 | #define BCSR1 ((uint)(BCSR_ADDR + 0x04)) | ||
26 | #define BCSR2 ((uint)(BCSR_ADDR + 0x08)) | ||
27 | #define BCSR3 ((uint)(BCSR_ADDR + 0x0c)) | ||
28 | #define BCSR4 ((uint)(BCSR_ADDR + 0x10)) | ||
29 | |||
30 | #define CFG_PHYDEV_ADDR ((uint)0xff0a0000) | ||
31 | #define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300)) | ||
32 | |||
33 | #define IMAP_ADDR (get_immrbase()) | ||
34 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
35 | |||
36 | #define MPC8xx_CPM_OFFSET (0x9c0) | 20 | #define MPC8xx_CPM_OFFSET (0x9c0) |
37 | #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) | 21 | #define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET) |
38 | #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver | 22 | #define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver |
39 | 23 | ||
40 | #define PCMCIA_MEM_ADDR ((uint)0xff020000) | ||
41 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
42 | |||
43 | /* Bits of interest in the BCSRs. | 24 | /* Bits of interest in the BCSRs. |
44 | */ | 25 | */ |
45 | #define BCSR1_ETHEN ((uint)0x20000000) | 26 | #define BCSR1_ETHEN ((uint)0x20000000) |
@@ -68,28 +49,5 @@ | |||
68 | #define BCSR5_MII1_EN 0x02 | 49 | #define BCSR5_MII1_EN 0x02 |
69 | #define BCSR5_MII1_RST 0x01 | 50 | #define BCSR5_MII1_RST 0x01 |
70 | 51 | ||
71 | /* Interrupt level assignments */ | ||
72 | #define PHY_INTERRUPT SIU_IRQ7 /* PHY link change interrupt */ | ||
73 | #define SIU_INT_FEC1 SIU_LEVEL1 /* FEC1 interrupt */ | ||
74 | #define SIU_INT_FEC2 SIU_LEVEL3 /* FEC2 interrupt */ | ||
75 | #define FEC_INTERRUPT SIU_INT_FEC1 /* FEC interrupt */ | ||
76 | |||
77 | /* We don't use the 8259 */ | ||
78 | #define NR_8259_INTS 0 | ||
79 | |||
80 | /* CPM Ethernet through SCC3 */ | ||
81 | #define PA_ENET_RXD ((ushort)0x0040) | ||
82 | #define PA_ENET_TXD ((ushort)0x0080) | ||
83 | #define PE_ENET_TCLK ((uint)0x00004000) | ||
84 | #define PE_ENET_RCLK ((uint)0x00008000) | ||
85 | #define PE_ENET_TENA ((uint)0x00000010) | ||
86 | #define PC_ENET_CLSN ((ushort)0x0400) | ||
87 | #define PC_ENET_RENA ((ushort)0x0800) | ||
88 | |||
89 | /* Control bits in the SICR to route TCLK (CLK5) and RCLK (CLK6) to | ||
90 | * SCC3. Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero */ | ||
91 | #define SICR_ENET_MASK ((uint)0x00ff0000) | ||
92 | #define SICR_ENET_CLKRT ((uint)0x002c0000) | ||
93 | |||
94 | #endif /* __ASM_MPC885ADS_H__ */ | 52 | #endif /* __ASM_MPC885ADS_H__ */ |
95 | #endif /* __KERNEL__ */ | 53 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index 5a808d611ae3..2cf1b6a75173 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
@@ -1,11 +1,13 @@ | |||
1 | /*arch/powerpc/platforms/8xx/mpc885ads_setup.c | 1 | /* |
2 | * | ||
3 | * Platform setup for the Freescale mpc885ads board | 2 | * Platform setup for the Freescale mpc885ads board |
4 | * | 3 | * |
5 | * Vitaly Bordug <vbordug@ru.mvista.com> | 4 | * Vitaly Bordug <vbordug@ru.mvista.com> |
6 | * | 5 | * |
7 | * Copyright 2005 MontaVista Software Inc. | 6 | * Copyright 2005 MontaVista Software Inc. |
8 | * | 7 | * |
8 | * Heavily modified by Scott Wood <scottwood@freescale.com> | ||
9 | * Copyright 2007 Freescale Semiconductor, Inc. | ||
10 | * | ||
9 | * This file is licensed under the terms of the GNU General Public License | 11 | * This file is licensed under the terms of the GNU General Public License |
10 | * version 2. This program is licensed "as is" without any warranty of any | 12 | * version 2. This program is licensed "as is" without any warranty of any |
11 | * kind, whether express or implied. | 13 | * kind, whether express or implied. |
@@ -18,12 +20,12 @@ | |||
18 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
19 | #include <linux/device.h> | 21 | #include <linux/device.h> |
20 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
21 | #include <linux/root_dev.h> | ||
22 | 23 | ||
23 | #include <linux/fs_enet_pd.h> | 24 | #include <linux/fs_enet_pd.h> |
24 | #include <linux/fs_uart_pd.h> | 25 | #include <linux/fs_uart_pd.h> |
25 | #include <linux/fsl_devices.h> | 26 | #include <linux/fsl_devices.h> |
26 | #include <linux/mii.h> | 27 | #include <linux/mii.h> |
28 | #include <linux/of_platform.h> | ||
27 | 29 | ||
28 | #include <asm/delay.h> | 30 | #include <asm/delay.h> |
29 | #include <asm/io.h> | 31 | #include <asm/io.h> |
@@ -32,46 +34,28 @@ | |||
32 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
33 | #include <asm/system.h> | 35 | #include <asm/system.h> |
34 | #include <asm/time.h> | 36 | #include <asm/time.h> |
35 | #include <asm/ppcboot.h> | ||
36 | #include <asm/mpc8xx.h> | 37 | #include <asm/mpc8xx.h> |
37 | #include <asm/8xx_immap.h> | 38 | #include <asm/8xx_immap.h> |
38 | #include <asm/commproc.h> | 39 | #include <asm/commproc.h> |
39 | #include <asm/fs_pd.h> | 40 | #include <asm/fs_pd.h> |
40 | #include <asm/prom.h> | 41 | #include <asm/udbg.h> |
41 | 42 | ||
42 | extern void cpm_reset(void); | 43 | #include <sysdev/commproc.h> |
43 | extern void mpc8xx_show_cpuinfo(struct seq_file *); | ||
44 | extern void mpc8xx_restart(char *cmd); | ||
45 | extern void mpc8xx_calibrate_decr(void); | ||
46 | extern int mpc8xx_set_rtc_time(struct rtc_time *tm); | ||
47 | extern void mpc8xx_get_rtc_time(struct rtc_time *tm); | ||
48 | extern void m8xx_pic_init(void); | ||
49 | extern unsigned int mpc8xx_get_irq(void); | ||
50 | 44 | ||
51 | static void init_smc1_uart_ioports(struct fs_uart_platform_info *fpi); | 45 | static u32 __iomem *bcsr, *bcsr5; |
52 | static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi); | ||
53 | static void init_scc3_ioports(struct fs_platform_info *ptr); | ||
54 | 46 | ||
55 | #ifdef CONFIG_PCMCIA_M8XX | 47 | #ifdef CONFIG_PCMCIA_M8XX |
56 | static void pcmcia_hw_setup(int slot, int enable) | 48 | static void pcmcia_hw_setup(int slot, int enable) |
57 | { | 49 | { |
58 | unsigned *bcsr_io; | ||
59 | |||
60 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
61 | if (enable) | 50 | if (enable) |
62 | clrbits32(bcsr_io, BCSR1_PCCEN); | 51 | clrbits32(&bcsr[1], BCSR1_PCCEN); |
63 | else | 52 | else |
64 | setbits32(bcsr_io, BCSR1_PCCEN); | 53 | setbits32(&bcsr[1], BCSR1_PCCEN); |
65 | |||
66 | iounmap(bcsr_io); | ||
67 | } | 54 | } |
68 | 55 | ||
69 | static int pcmcia_set_voltage(int slot, int vcc, int vpp) | 56 | static int pcmcia_set_voltage(int slot, int vcc, int vpp) |
70 | { | 57 | { |
71 | u32 reg = 0; | 58 | u32 reg = 0; |
72 | unsigned *bcsr_io; | ||
73 | |||
74 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
75 | 59 | ||
76 | switch (vcc) { | 60 | switch (vcc) { |
77 | case 0: | 61 | case 0: |
@@ -106,344 +90,196 @@ static int pcmcia_set_voltage(int slot, int vcc, int vpp) | |||
106 | } | 90 | } |
107 | 91 | ||
108 | /* first, turn off all power */ | 92 | /* first, turn off all power */ |
109 | clrbits32(bcsr_io, 0x00610000); | 93 | clrbits32(&bcsr[1], 0x00610000); |
110 | 94 | ||
111 | /* enable new powersettings */ | 95 | /* enable new powersettings */ |
112 | setbits32(bcsr_io, reg); | 96 | setbits32(&bcsr[1], reg); |
113 | 97 | ||
114 | iounmap(bcsr_io); | ||
115 | return 0; | 98 | return 0; |
116 | } | 99 | } |
117 | #endif | 100 | #endif |
118 | 101 | ||
119 | void __init mpc885ads_board_setup(void) | 102 | struct cpm_pin { |
120 | { | 103 | int port, pin, flags; |
121 | cpm8xx_t *cp; | 104 | }; |
122 | unsigned int *bcsr_io; | ||
123 | u8 tmpval8; | ||
124 | |||
125 | #ifdef CONFIG_FS_ENET | ||
126 | iop8xx_t *io_port; | ||
127 | #endif | ||
128 | |||
129 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
130 | cp = (cpm8xx_t *) immr_map(im_cpm); | ||
131 | |||
132 | if (bcsr_io == NULL) { | ||
133 | printk(KERN_CRIT "Could not remap BCSR\n"); | ||
134 | return; | ||
135 | } | ||
136 | #ifdef CONFIG_SERIAL_CPM_SMC1 | ||
137 | clrbits32(bcsr_io, BCSR1_RS232EN_1); | ||
138 | clrbits32(&cp->cp_simode, 0xe0000000 >> 17); /* brg1 */ | ||
139 | tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX); | ||
140 | out_8(&(cp->cp_smc[0].smc_smcm), tmpval8); | ||
141 | clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); /* brg1 */ | ||
142 | #else | ||
143 | setbits32(bcsr_io, BCSR1_RS232EN_1); | ||
144 | out_be16(&cp->cp_smc[0].smc_smcmr, 0); | ||
145 | out_8(&cp->cp_smc[0].smc_smce, 0); | ||
146 | #endif | ||
147 | |||
148 | #ifdef CONFIG_SERIAL_CPM_SMC2 | ||
149 | clrbits32(bcsr_io, BCSR1_RS232EN_2); | ||
150 | clrbits32(&cp->cp_simode, 0xe0000000 >> 1); | ||
151 | setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */ | ||
152 | tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX); | ||
153 | out_8(&(cp->cp_smc[1].smc_smcm), tmpval8); | ||
154 | clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN); | ||
155 | 105 | ||
156 | init_smc2_uart_ioports(0); | 106 | static struct cpm_pin mpc885ads_pins[] = { |
157 | #else | 107 | /* SMC1 */ |
158 | setbits32(bcsr_io, BCSR1_RS232EN_2); | 108 | {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */ |
159 | out_be16(&cp->cp_smc[1].smc_smcmr, 0); | 109 | {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */ |
160 | out_8(&cp->cp_smc[1].smc_smce, 0); | ||
161 | #endif | ||
162 | immr_unmap(cp); | ||
163 | iounmap(bcsr_io); | ||
164 | |||
165 | #ifdef CONFIG_FS_ENET | ||
166 | /* use MDC for MII (common) */ | ||
167 | io_port = (iop8xx_t *) immr_map(im_ioport); | ||
168 | setbits16(&io_port->iop_pdpar, 0x0080); | ||
169 | clrbits16(&io_port->iop_pddir, 0x0080); | ||
170 | |||
171 | bcsr_io = ioremap(BCSR5, sizeof(unsigned long)); | ||
172 | clrbits32(bcsr_io, BCSR5_MII1_EN); | ||
173 | clrbits32(bcsr_io, BCSR5_MII1_RST); | ||
174 | #ifndef CONFIG_FC_ENET_HAS_SCC | ||
175 | clrbits32(bcsr_io, BCSR5_MII2_EN); | ||
176 | clrbits32(bcsr_io, BCSR5_MII2_RST); | ||
177 | 110 | ||
111 | /* SMC2 */ | ||
112 | #ifndef CONFIG_MPC8xx_SECOND_ETH_FEC2 | ||
113 | {CPM_PORTE, 21, CPM_PIN_INPUT}, /* RX */ | ||
114 | {CPM_PORTE, 20, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */ | ||
178 | #endif | 115 | #endif |
179 | iounmap(bcsr_io); | ||
180 | immr_unmap(io_port); | ||
181 | 116 | ||
117 | /* SCC3 */ | ||
118 | {CPM_PORTA, 9, CPM_PIN_INPUT}, /* RX */ | ||
119 | {CPM_PORTA, 8, CPM_PIN_INPUT}, /* TX */ | ||
120 | {CPM_PORTC, 4, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* RENA */ | ||
121 | {CPM_PORTC, 5, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* CLSN */ | ||
122 | {CPM_PORTE, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TENA */ | ||
123 | {CPM_PORTE, 17, CPM_PIN_INPUT}, /* CLK5 */ | ||
124 | {CPM_PORTE, 16, CPM_PIN_INPUT}, /* CLK6 */ | ||
125 | |||
126 | /* MII1 */ | ||
127 | {CPM_PORTA, 0, CPM_PIN_INPUT}, | ||
128 | {CPM_PORTA, 1, CPM_PIN_INPUT}, | ||
129 | {CPM_PORTA, 2, CPM_PIN_INPUT}, | ||
130 | {CPM_PORTA, 3, CPM_PIN_INPUT}, | ||
131 | {CPM_PORTA, 4, CPM_PIN_OUTPUT}, | ||
132 | {CPM_PORTA, 10, CPM_PIN_OUTPUT}, | ||
133 | {CPM_PORTA, 11, CPM_PIN_OUTPUT}, | ||
134 | {CPM_PORTB, 19, CPM_PIN_INPUT}, | ||
135 | {CPM_PORTB, 31, CPM_PIN_INPUT}, | ||
136 | {CPM_PORTC, 12, CPM_PIN_INPUT}, | ||
137 | {CPM_PORTC, 13, CPM_PIN_INPUT}, | ||
138 | {CPM_PORTE, 30, CPM_PIN_OUTPUT}, | ||
139 | {CPM_PORTE, 31, CPM_PIN_OUTPUT}, | ||
140 | |||
141 | /* MII2 */ | ||
142 | #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2 | ||
143 | {CPM_PORTE, 14, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
144 | {CPM_PORTE, 15, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
145 | {CPM_PORTE, 16, CPM_PIN_OUTPUT}, | ||
146 | {CPM_PORTE, 17, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
147 | {CPM_PORTE, 18, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
148 | {CPM_PORTE, 19, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
149 | {CPM_PORTE, 20, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, | ||
150 | {CPM_PORTE, 21, CPM_PIN_OUTPUT}, | ||
151 | {CPM_PORTE, 22, CPM_PIN_OUTPUT}, | ||
152 | {CPM_PORTE, 23, CPM_PIN_OUTPUT}, | ||
153 | {CPM_PORTE, 24, CPM_PIN_OUTPUT}, | ||
154 | {CPM_PORTE, 25, CPM_PIN_OUTPUT}, | ||
155 | {CPM_PORTE, 26, CPM_PIN_OUTPUT}, | ||
156 | {CPM_PORTE, 27, CPM_PIN_OUTPUT}, | ||
157 | {CPM_PORTE, 28, CPM_PIN_OUTPUT}, | ||
158 | {CPM_PORTE, 29, CPM_PIN_OUTPUT}, | ||
182 | #endif | 159 | #endif |
160 | }; | ||
183 | 161 | ||
184 | #ifdef CONFIG_PCMCIA_M8XX | 162 | static void __init init_ioports(void) |
185 | /*Set up board specific hook-ups */ | ||
186 | m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; | ||
187 | m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; | ||
188 | #endif | ||
189 | } | ||
190 | |||
191 | static void init_fec1_ioports(struct fs_platform_info *ptr) | ||
192 | { | 163 | { |
193 | cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm); | 164 | int i; |
194 | iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport); | ||
195 | |||
196 | /* configure FEC1 pins */ | ||
197 | setbits16(&io_port->iop_papar, 0xf830); | ||
198 | setbits16(&io_port->iop_padir, 0x0830); | ||
199 | clrbits16(&io_port->iop_padir, 0xf000); | ||
200 | 165 | ||
201 | setbits32(&cp->cp_pbpar, 0x00001001); | 166 | for (i = 0; i < ARRAY_SIZE(mpc885ads_pins); i++) { |
202 | clrbits32(&cp->cp_pbdir, 0x00001001); | 167 | struct cpm_pin *pin = &mpc885ads_pins[i]; |
203 | 168 | cpm1_set_pin(pin->port, pin->pin, pin->flags); | |
204 | setbits16(&io_port->iop_pcpar, 0x000c); | 169 | } |
205 | clrbits16(&io_port->iop_pcdir, 0x000c); | ||
206 | 170 | ||
207 | setbits32(&cp->cp_pepar, 0x00000003); | 171 | cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX); |
208 | setbits32(&cp->cp_pedir, 0x00000003); | 172 | cpm1_clk_setup(CPM_CLK_SMC2, CPM_BRG2, CPM_CLK_RTX); |
209 | clrbits32(&cp->cp_peso, 0x00000003); | 173 | cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_TX); |
210 | clrbits32(&cp->cp_cptr, 0x00000100); | 174 | cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK6, CPM_CLK_RX); |
211 | 175 | ||
212 | immr_unmap(io_port); | 176 | /* Set FEC1 and FEC2 to MII mode */ |
213 | immr_unmap(cp); | 177 | clrbits32(&mpc8xx_immr->im_cpm.cp_cptr, 0x00000180); |
214 | } | 178 | } |
215 | 179 | ||
216 | static void init_fec2_ioports(struct fs_platform_info *ptr) | 180 | static void __init mpc885ads_setup_arch(void) |
217 | { | 181 | { |
218 | cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm); | 182 | struct device_node *np; |
219 | iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport); | ||
220 | |||
221 | /* configure FEC2 pins */ | ||
222 | setbits32(&cp->cp_pepar, 0x0003fffc); | ||
223 | setbits32(&cp->cp_pedir, 0x0003fffc); | ||
224 | clrbits32(&cp->cp_peso, 0x000087fc); | ||
225 | setbits32(&cp->cp_peso, 0x00037800); | ||
226 | clrbits32(&cp->cp_cptr, 0x00000080); | ||
227 | |||
228 | immr_unmap(io_port); | ||
229 | immr_unmap(cp); | ||
230 | } | ||
231 | 183 | ||
232 | void init_fec_ioports(struct fs_platform_info *fpi) | 184 | cpm_reset(); |
233 | { | 185 | init_ioports(); |
234 | int fec_no = fs_get_fec_index(fpi->fs_no); | ||
235 | 186 | ||
236 | switch (fec_no) { | 187 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc885ads-bcsr"); |
237 | case 0: | 188 | if (!np) { |
238 | init_fec1_ioports(fpi); | 189 | printk(KERN_CRIT "Could not find fsl,mpc885ads-bcsr node\n"); |
239 | break; | ||
240 | case 1: | ||
241 | init_fec2_ioports(fpi); | ||
242 | break; | ||
243 | default: | ||
244 | printk(KERN_ERR "init_fec_ioports: invalid FEC number\n"); | ||
245 | return; | 190 | return; |
246 | } | 191 | } |
247 | } | ||
248 | |||
249 | static void init_scc3_ioports(struct fs_platform_info *fpi) | ||
250 | { | ||
251 | unsigned *bcsr_io; | ||
252 | iop8xx_t *io_port; | ||
253 | cpm8xx_t *cp; | ||
254 | 192 | ||
255 | bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE); | 193 | bcsr = of_iomap(np, 0); |
256 | io_port = (iop8xx_t *) immr_map(im_ioport); | 194 | bcsr5 = of_iomap(np, 1); |
257 | cp = (cpm8xx_t *) immr_map(im_cpm); | 195 | of_node_put(np); |
258 | 196 | ||
259 | if (bcsr_io == NULL) { | 197 | if (!bcsr || !bcsr5) { |
260 | printk(KERN_CRIT "Could not remap BCSR\n"); | 198 | printk(KERN_CRIT "Could not remap BCSR\n"); |
261 | return; | 199 | return; |
262 | } | 200 | } |
263 | 201 | ||
264 | /* Enable the PHY. | 202 | clrbits32(&bcsr[1], BCSR1_RS232EN_1); |
265 | */ | 203 | #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2 |
266 | clrbits32(bcsr_io + 4, BCSR4_ETH10_RST); | 204 | setbits32(&bcsr[1], BCSR1_RS232EN_2); |
267 | udelay(1000); | 205 | #else |
268 | setbits32(bcsr_io + 4, BCSR4_ETH10_RST); | 206 | clrbits32(&bcsr[1], BCSR1_RS232EN_2); |
269 | /* Configure port A pins for Txd and Rxd. | 207 | #endif |
270 | */ | ||
271 | setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD); | ||
272 | clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD); | ||
273 | 208 | ||
274 | /* Configure port C pins to enable CLSN and RENA. | 209 | clrbits32(bcsr5, BCSR5_MII1_EN); |
275 | */ | 210 | setbits32(bcsr5, BCSR5_MII1_RST); |
276 | clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA); | 211 | udelay(1000); |
277 | clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA); | 212 | clrbits32(bcsr5, BCSR5_MII1_RST); |
278 | setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA); | ||
279 | 213 | ||
280 | /* Configure port E for TCLK and RCLK. | 214 | #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2 |
281 | */ | 215 | clrbits32(bcsr5, BCSR5_MII2_EN); |
282 | setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK); | 216 | setbits32(bcsr5, BCSR5_MII2_RST); |
283 | clrbits32(&cp->cp_pepar, PE_ENET_TENA); | 217 | udelay(1000); |
284 | clrbits32(&cp->cp_pedir, PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA); | 218 | clrbits32(bcsr5, BCSR5_MII2_RST); |
285 | clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK); | 219 | #else |
286 | setbits32(&cp->cp_peso, PE_ENET_TENA); | 220 | setbits32(bcsr5, BCSR5_MII2_EN); |
287 | 221 | #endif | |
288 | /* Configure Serial Interface clock routing. | ||
289 | * First, clear all SCC bits to zero, then set the ones we want. | ||
290 | */ | ||
291 | clrbits32(&cp->cp_sicr, SICR_ENET_MASK); | ||
292 | setbits32(&cp->cp_sicr, SICR_ENET_CLKRT); | ||
293 | 222 | ||
294 | /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used. | 223 | #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3 |
295 | */ | 224 | clrbits32(&bcsr[4], BCSR4_ETH10_RST); |
296 | clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); | 225 | udelay(1000); |
297 | /* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode | 226 | setbits32(&bcsr[4], BCSR4_ETH10_RST); |
298 | * by H/W setting after reset. SCC ethernet controller support only half duplex. | ||
299 | * This discrepancy of modes causes a lot of carrier lost errors. | ||
300 | */ | ||
301 | 227 | ||
302 | /* In the original SCC enet driver the following code is placed at | 228 | setbits32(&bcsr[1], BCSR1_ETHEN); |
303 | the end of the initialization */ | ||
304 | setbits32(&cp->cp_pepar, PE_ENET_TENA); | ||
305 | clrbits32(&cp->cp_pedir, PE_ENET_TENA); | ||
306 | setbits32(&cp->cp_peso, PE_ENET_TENA); | ||
307 | 229 | ||
308 | setbits32(bcsr_io + 4, BCSR1_ETHEN); | 230 | np = of_find_node_by_path("/soc@ff000000/cpm@9c0/serial@a80"); |
309 | iounmap(bcsr_io); | 231 | #else |
310 | immr_unmap(io_port); | 232 | np = of_find_node_by_path("/soc@ff000000/cpm@9c0/ethernet@a40"); |
311 | immr_unmap(cp); | 233 | #endif |
312 | } | ||
313 | 234 | ||
314 | void init_scc_ioports(struct fs_platform_info *fpi) | 235 | /* The SCC3 enet registers overlap the SMC1 registers, so |
315 | { | 236 | * one of the two must be removed from the device tree. |
316 | int scc_no = fs_get_scc_index(fpi->fs_no); | 237 | */ |
317 | 238 | ||
318 | switch (scc_no) { | 239 | if (np) { |
319 | case 2: | 240 | of_detach_node(np); |
320 | init_scc3_ioports(fpi); | 241 | of_node_put(np); |
321 | break; | ||
322 | default: | ||
323 | printk(KERN_ERR "init_scc_ioports: invalid SCC number\n"); | ||
324 | return; | ||
325 | } | 242 | } |
326 | } | ||
327 | 243 | ||
328 | static void init_smc1_uart_ioports(struct fs_uart_platform_info *ptr) | 244 | #ifdef CONFIG_PCMCIA_M8XX |
329 | { | 245 | /* Set up board specific hook-ups.*/ |
330 | unsigned *bcsr_io; | 246 | m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; |
331 | cpm8xx_t *cp; | 247 | m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; |
332 | 248 | #endif | |
333 | cp = (cpm8xx_t *) immr_map(im_cpm); | ||
334 | setbits32(&cp->cp_pepar, 0x000000c0); | ||
335 | clrbits32(&cp->cp_pedir, 0x000000c0); | ||
336 | clrbits32(&cp->cp_peso, 0x00000040); | ||
337 | setbits32(&cp->cp_peso, 0x00000080); | ||
338 | immr_unmap(cp); | ||
339 | |||
340 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
341 | |||
342 | if (bcsr_io == NULL) { | ||
343 | printk(KERN_CRIT "Could not remap BCSR1\n"); | ||
344 | return; | ||
345 | } | ||
346 | clrbits32(bcsr_io, BCSR1_RS232EN_1); | ||
347 | iounmap(bcsr_io); | ||
348 | } | 249 | } |
349 | 250 | ||
350 | static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi) | 251 | static int __init mpc885ads_probe(void) |
351 | { | 252 | { |
352 | unsigned *bcsr_io; | 253 | unsigned long root = of_get_flat_dt_root(); |
353 | cpm8xx_t *cp; | 254 | return of_flat_dt_is_compatible(root, "fsl,mpc885ads"); |
354 | |||
355 | cp = (cpm8xx_t *) immr_map(im_cpm); | ||
356 | setbits32(&cp->cp_pepar, 0x00000c00); | ||
357 | clrbits32(&cp->cp_pedir, 0x00000c00); | ||
358 | clrbits32(&cp->cp_peso, 0x00000400); | ||
359 | setbits32(&cp->cp_peso, 0x00000800); | ||
360 | immr_unmap(cp); | ||
361 | |||
362 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
363 | |||
364 | if (bcsr_io == NULL) { | ||
365 | printk(KERN_CRIT "Could not remap BCSR1\n"); | ||
366 | return; | ||
367 | } | ||
368 | clrbits32(bcsr_io, BCSR1_RS232EN_2); | ||
369 | iounmap(bcsr_io); | ||
370 | } | 255 | } |
371 | 256 | ||
372 | void init_smc_ioports(struct fs_uart_platform_info *data) | 257 | static struct of_device_id __initdata of_bus_ids[] = { |
373 | { | 258 | { .name = "soc", }, |
374 | int smc_no = fs_uart_id_fsid2smc(data->fs_no); | 259 | { .name = "cpm", }, |
260 | { .name = "localbus", }, | ||
261 | {}, | ||
262 | }; | ||
375 | 263 | ||
376 | switch (smc_no) { | 264 | static int __init declare_of_platform_devices(void) |
377 | case 0: | ||
378 | init_smc1_uart_ioports(data); | ||
379 | data->brg = data->clk_rx; | ||
380 | break; | ||
381 | case 1: | ||
382 | init_smc2_uart_ioports(data); | ||
383 | data->brg = data->clk_rx; | ||
384 | break; | ||
385 | default: | ||
386 | printk(KERN_ERR "init_scc_ioports: invalid SCC number\n"); | ||
387 | return; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | int platform_device_skip(const char *model, int id) | ||
392 | { | 265 | { |
393 | #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3 | 266 | /* Publish the QE devices */ |
394 | const char *dev = "FEC"; | 267 | if (machine_is(mpc885_ads)) |
395 | int n = 2; | 268 | of_platform_bus_probe(NULL, of_bus_ids, NULL); |
396 | #else | ||
397 | const char *dev = "SCC"; | ||
398 | int n = 3; | ||
399 | #endif | ||
400 | |||
401 | if (!strcmp(model, dev) && n == id) | ||
402 | return 1; | ||
403 | 269 | ||
404 | return 0; | 270 | return 0; |
405 | } | 271 | } |
406 | 272 | device_initcall(declare_of_platform_devices); | |
407 | static void __init mpc885ads_setup_arch(void) | 273 | |
408 | { | 274 | define_machine(mpc885_ads) { |
409 | struct device_node *cpu; | 275 | .name = "Freescale MPC885 ADS", |
410 | 276 | .probe = mpc885ads_probe, | |
411 | cpu = of_find_node_by_type(NULL, "cpu"); | 277 | .setup_arch = mpc885ads_setup_arch, |
412 | if (cpu != 0) { | 278 | .init_IRQ = m8xx_pic_init, |
413 | const unsigned int *fp; | 279 | .get_irq = mpc8xx_get_irq, |
414 | 280 | .restart = mpc8xx_restart, | |
415 | fp = of_get_property(cpu, "clock-frequency", NULL); | 281 | .calibrate_decr = mpc8xx_calibrate_decr, |
416 | if (fp != 0) | 282 | .set_rtc_time = mpc8xx_set_rtc_time, |
417 | loops_per_jiffy = *fp / HZ; | 283 | .get_rtc_time = mpc8xx_get_rtc_time, |
418 | else | 284 | .progress = udbg_progress, |
419 | loops_per_jiffy = 50000000 / HZ; | 285 | }; |
420 | of_node_put(cpu); | ||
421 | } | ||
422 | |||
423 | cpm_reset(); | ||
424 | |||
425 | mpc885ads_board_setup(); | ||
426 | |||
427 | ROOT_DEV = Root_NFS; | ||
428 | } | ||
429 | |||
430 | static int __init mpc885ads_probe(void) | ||
431 | { | ||
432 | char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), | ||
433 | "model", NULL); | ||
434 | if (model == NULL) | ||
435 | return 0; | ||
436 | if (strcmp(model, "MPC885ADS")) | ||
437 | return 0; | ||
438 | |||
439 | return 1; | ||
440 | } | ||
441 | |||
442 | define_machine(mpc885_ads) | ||
443 | { | ||
444 | .name = "MPC885 ADS",.probe = mpc885ads_probe,.setup_arch = | ||
445 | mpc885ads_setup_arch,.init_IRQ = | ||
446 | m8xx_pic_init,.show_cpuinfo = mpc8xx_show_cpuinfo,.get_irq = | ||
447 | mpc8xx_get_irq,.restart = mpc8xx_restart,.calibrate_decr = | ||
448 | mpc8xx_calibrate_decr,.set_rtc_time = | ||
449 | mpc8xx_set_rtc_time,.get_rtc_time = mpc8xx_get_rtc_time,}; | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 19d4628edf79..cc6013ffc29a 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -12,13 +12,10 @@ config PPC_MULTIPLATFORM | |||
12 | RS/6000 machine, an Apple machine, or a PReP, CHRP, | 12 | RS/6000 machine, an Apple machine, or a PReP, CHRP, |
13 | Maple or Cell-based machine. | 13 | Maple or Cell-based machine. |
14 | 14 | ||
15 | config EMBEDDED6xx | ||
16 | bool "Embedded 6xx/7xx/7xxx-based board" | ||
17 | depends on PPC32 && (BROKEN||BROKEN_ON_SMP) | ||
18 | |||
19 | config PPC_82xx | 15 | config PPC_82xx |
20 | bool "Freescale 82xx" | 16 | bool "Freescale 82xx" |
21 | depends on 6xx | 17 | depends on 6xx |
18 | select WANT_DEVICE_TREE | ||
22 | 19 | ||
23 | config PPC_83xx | 20 | config PPC_83xx |
24 | bool "Freescale 83xx" | 21 | bool "Freescale 83xx" |
@@ -58,7 +55,7 @@ source "arch/powerpc/platforms/85xx/Kconfig" | |||
58 | source "arch/powerpc/platforms/86xx/Kconfig" | 55 | source "arch/powerpc/platforms/86xx/Kconfig" |
59 | source "arch/powerpc/platforms/embedded6xx/Kconfig" | 56 | source "arch/powerpc/platforms/embedded6xx/Kconfig" |
60 | source "arch/powerpc/platforms/44x/Kconfig" | 57 | source "arch/powerpc/platforms/44x/Kconfig" |
61 | #source "arch/powerpc/platforms/4xx/Kconfig | 58 | source "arch/powerpc/platforms/40x/Kconfig" |
62 | 59 | ||
63 | config PPC_NATIVE | 60 | config PPC_NATIVE |
64 | bool | 61 | bool |
@@ -136,6 +133,16 @@ config MPIC_U3_HT_IRQS | |||
136 | depends on PPC_MAPLE | 133 | depends on PPC_MAPLE |
137 | default y | 134 | default y |
138 | 135 | ||
136 | config MPIC_BROKEN_REGREAD | ||
137 | bool | ||
138 | depends on MPIC | ||
139 | help | ||
140 | This option enables a MPIC driver workaround for some chips | ||
141 | that have a bug that causes some interrupt source information | ||
142 | to not read back properly. It is safe to use on other chips as | ||
143 | well, but enabling it uses about 8KB of memory to keep copies | ||
144 | of the register contents in software. | ||
145 | |||
139 | config IBMVIO | 146 | config IBMVIO |
140 | depends on PPC_PSERIES || PPC_ISERIES | 147 | depends on PPC_PSERIES || PPC_ISERIES |
141 | bool | 148 | bool |
@@ -266,12 +273,24 @@ config QUICC_ENGINE | |||
266 | config CPM2 | 273 | config CPM2 |
267 | bool | 274 | bool |
268 | default n | 275 | default n |
276 | select CPM | ||
269 | help | 277 | help |
270 | The CPM2 (Communications Processor Module) is a coprocessor on | 278 | The CPM2 (Communications Processor Module) is a coprocessor on |
271 | embedded CPUs made by Freescale. Selecting this option means that | 279 | embedded CPUs made by Freescale. Selecting this option means that |
272 | you wish to build a kernel for a machine with a CPM2 coprocessor | 280 | you wish to build a kernel for a machine with a CPM2 coprocessor |
273 | on it (826x, 827x, 8560). | 281 | on it (826x, 827x, 8560). |
274 | 282 | ||
283 | config PPC_CPM_NEW_BINDING | ||
284 | bool | ||
285 | depends on CPM1 || CPM2 | ||
286 | help | ||
287 | Select this if your board has been converted to use the new | ||
288 | device tree bindings for CPM, and no longer needs the | ||
289 | ioport callbacks or the platform device glue code. | ||
290 | |||
291 | The fs_enet and cpm_uart drivers will be built as | ||
292 | of_platform devices. | ||
293 | |||
275 | config AXON_RAM | 294 | config AXON_RAM |
276 | tristate "Axon DDR2 memory device driver" | 295 | tristate "Axon DDR2 memory device driver" |
277 | depends on PPC_IBM_CELL_BLADE | 296 | depends on PPC_IBM_CELL_BLADE |
@@ -291,4 +310,7 @@ config FSL_ULI1575 | |||
291 | Freescale reference boards. The boards all use the ULI in pretty | 310 | Freescale reference boards. The boards all use the ULI in pretty |
292 | much the same way. | 311 | much the same way. |
293 | 312 | ||
313 | config CPM | ||
314 | bool | ||
315 | |||
294 | endmenu | 316 | endmenu |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index e4b2aee53a73..4c315be25015 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -36,10 +36,12 @@ config PPC_8xx | |||
36 | bool "Freescale 8xx" | 36 | bool "Freescale 8xx" |
37 | select FSL_SOC | 37 | select FSL_SOC |
38 | select 8xx | 38 | select 8xx |
39 | select WANT_DEVICE_TREE | ||
39 | 40 | ||
40 | config 40x | 41 | config 40x |
41 | bool "AMCC 40x" | 42 | bool "AMCC 40x" |
42 | select PPC_DCR_NATIVE | 43 | select PPC_DCR_NATIVE |
44 | select WANT_DEVICE_TREE | ||
43 | 45 | ||
44 | config 44x | 46 | config 44x |
45 | bool "AMCC 44x" | 47 | bool "AMCC 44x" |
@@ -69,6 +71,18 @@ config POWER4 | |||
69 | depends on PPC64 | 71 | depends on PPC64 |
70 | def_bool y | 72 | def_bool y |
71 | 73 | ||
74 | config TUNE_CELL | ||
75 | bool "Optimize for Cell Broadband Engine" | ||
76 | depends on PPC64 | ||
77 | help | ||
78 | Cause the compiler to optimize for the PPE of the Cell Broadband | ||
79 | Engine. This will make the code run considerably faster on Cell | ||
80 | but somewhat slower on other machines. This option only changes | ||
81 | the scheduling of instructions, not the selection of instructions | ||
82 | itself, so the resulting kernel will keep running on all other | ||
83 | machines. When building a kernel that is supposed to run only | ||
84 | on Cell, you should also select the POWER4_ONLY option. | ||
85 | |||
72 | config 6xx | 86 | config 6xx |
73 | bool | 87 | bool |
74 | 88 | ||
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index d44e832b01f2..6d9079da5f5a 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -9,7 +9,7 @@ obj-$(CONFIG_PPC_PMAC) += powermac/ | |||
9 | endif | 9 | endif |
10 | endif | 10 | endif |
11 | obj-$(CONFIG_PPC_CHRP) += chrp/ | 11 | obj-$(CONFIG_PPC_CHRP) += chrp/ |
12 | #obj-$(CONFIG_4xx) += 4xx/ | 12 | obj-$(CONFIG_40x) += 40x/ |
13 | obj-$(CONFIG_44x) += 44x/ | 13 | obj-$(CONFIG_44x) += 44x/ |
14 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ | 14 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ |
15 | obj-$(CONFIG_PPC_8xx) += 8xx/ | 15 | obj-$(CONFIG_PPC_8xx) += 8xx/ |
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index f88a7c76f296..61d12f183036 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -13,15 +13,13 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o | |||
13 | endif | 13 | endif |
14 | 14 | ||
15 | # needed only when building loadable spufs.ko | 15 | # needed only when building loadable spufs.ko |
16 | spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o | ||
17 | spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o | 16 | spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o |
18 | 17 | ||
19 | spu-manage-$(CONFIG_PPC_CELLEB) += spu_manage.o | 18 | spu-manage-$(CONFIG_PPC_CELLEB) += spu_manage.o |
20 | spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o | 19 | spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o |
21 | 20 | ||
22 | obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ | 21 | obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ |
23 | spu_coredump.o \ | 22 | spu_syscalls.o \ |
24 | $(spufs-modular-m) \ | ||
25 | $(spu-priv1-y) \ | 23 | $(spu-priv1-y) \ |
26 | $(spu-manage-y) \ | 24 | $(spu-manage-y) \ |
27 | spufs/ | 25 | spufs/ |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 4c9ab5b70bae..1245b2f517bb 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
@@ -64,13 +64,11 @@ | |||
64 | 64 | ||
65 | 65 | ||
66 | struct axon_msic { | 66 | struct axon_msic { |
67 | struct device_node *dn; | ||
68 | struct irq_host *irq_host; | 67 | struct irq_host *irq_host; |
69 | __le32 *fifo; | 68 | __le32 *fifo; |
70 | dcr_host_t dcr_host; | 69 | dcr_host_t dcr_host; |
71 | struct list_head list; | 70 | struct list_head list; |
72 | u32 read_offset; | 71 | u32 read_offset; |
73 | u32 dcr_base; | ||
74 | }; | 72 | }; |
75 | 73 | ||
76 | static LIST_HEAD(axon_msic_list); | 74 | static LIST_HEAD(axon_msic_list); |
@@ -79,12 +77,12 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) | |||
79 | { | 77 | { |
80 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); | 78 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); |
81 | 79 | ||
82 | dcr_write(msic->dcr_host, msic->dcr_base + dcr_n, val); | 80 | dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val); |
83 | } | 81 | } |
84 | 82 | ||
85 | static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n) | 83 | static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n) |
86 | { | 84 | { |
87 | return dcr_read(msic->dcr_host, msic->dcr_base + dcr_n); | 85 | return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n); |
88 | } | 86 | } |
89 | 87 | ||
90 | static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) | 88 | static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) |
@@ -126,7 +124,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) | |||
126 | const phandle *ph; | 124 | const phandle *ph; |
127 | struct axon_msic *msic = NULL; | 125 | struct axon_msic *msic = NULL; |
128 | 126 | ||
129 | dn = pci_device_to_OF_node(dev); | 127 | dn = of_node_get(pci_device_to_OF_node(dev)); |
130 | if (!dn) { | 128 | if (!dn) { |
131 | dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); | 129 | dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); |
132 | return NULL; | 130 | return NULL; |
@@ -183,7 +181,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) | |||
183 | int len; | 181 | int len; |
184 | const u32 *prop; | 182 | const u32 *prop; |
185 | 183 | ||
186 | dn = pci_device_to_OF_node(dev); | 184 | dn = of_node_get(pci_device_to_OF_node(dev)); |
187 | if (!dn) { | 185 | if (!dn) { |
188 | dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); | 186 | dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); |
189 | return -ENODEV; | 187 | return -ENODEV; |
@@ -295,15 +293,7 @@ static int msic_host_map(struct irq_host *h, unsigned int virq, | |||
295 | return 0; | 293 | return 0; |
296 | } | 294 | } |
297 | 295 | ||
298 | static int msic_host_match(struct irq_host *host, struct device_node *dn) | ||
299 | { | ||
300 | struct axon_msic *msic = host->host_data; | ||
301 | |||
302 | return msic->dn == dn; | ||
303 | } | ||
304 | |||
305 | static struct irq_host_ops msic_host_ops = { | 296 | static struct irq_host_ops msic_host_ops = { |
306 | .match = msic_host_match, | ||
307 | .map = msic_host_map, | 297 | .map = msic_host_map, |
308 | }; | 298 | }; |
309 | 299 | ||
@@ -314,7 +304,8 @@ static int axon_msi_notify_reboot(struct notifier_block *nb, | |||
314 | u32 tmp; | 304 | u32 tmp; |
315 | 305 | ||
316 | list_for_each_entry(msic, &axon_msic_list, list) { | 306 | list_for_each_entry(msic, &axon_msic_list, list) { |
317 | pr_debug("axon_msi: disabling %s\n", msic->dn->full_name); | 307 | pr_debug("axon_msi: disabling %s\n", |
308 | msic->irq_host->of_node->full_name); | ||
318 | tmp = msic_dcr_read(msic, MSIC_CTRL_REG); | 309 | tmp = msic_dcr_read(msic, MSIC_CTRL_REG); |
319 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; | 310 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; |
320 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); | 311 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); |
@@ -332,7 +323,7 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
332 | struct page *page; | 323 | struct page *page; |
333 | struct axon_msic *msic; | 324 | struct axon_msic *msic; |
334 | unsigned int virq; | 325 | unsigned int virq; |
335 | int dcr_len; | 326 | int dcr_base, dcr_len; |
336 | 327 | ||
337 | pr_debug("axon_msi: setting up dn %s\n", dn->full_name); | 328 | pr_debug("axon_msi: setting up dn %s\n", dn->full_name); |
338 | 329 | ||
@@ -343,17 +334,17 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
343 | goto out; | 334 | goto out; |
344 | } | 335 | } |
345 | 336 | ||
346 | msic->dcr_base = dcr_resource_start(dn, 0); | 337 | dcr_base = dcr_resource_start(dn, 0); |
347 | dcr_len = dcr_resource_len(dn, 0); | 338 | dcr_len = dcr_resource_len(dn, 0); |
348 | 339 | ||
349 | if (msic->dcr_base == 0 || dcr_len == 0) { | 340 | if (dcr_base == 0 || dcr_len == 0) { |
350 | printk(KERN_ERR | 341 | printk(KERN_ERR |
351 | "axon_msi: couldn't parse dcr properties on %s\n", | 342 | "axon_msi: couldn't parse dcr properties on %s\n", |
352 | dn->full_name); | 343 | dn->full_name); |
353 | goto out; | 344 | goto out; |
354 | } | 345 | } |
355 | 346 | ||
356 | msic->dcr_host = dcr_map(dn, msic->dcr_base, dcr_len); | 347 | msic->dcr_host = dcr_map(dn, dcr_base, dcr_len); |
357 | if (!DCR_MAP_OK(msic->dcr_host)) { | 348 | if (!DCR_MAP_OK(msic->dcr_host)) { |
358 | printk(KERN_ERR "axon_msi: dcr_map failed for %s\n", | 349 | printk(KERN_ERR "axon_msi: dcr_map failed for %s\n", |
359 | dn->full_name); | 350 | dn->full_name); |
@@ -370,8 +361,8 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
370 | 361 | ||
371 | msic->fifo = page_address(page); | 362 | msic->fifo = page_address(page); |
372 | 363 | ||
373 | msic->irq_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, NR_IRQS, | 364 | msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, |
374 | &msic_host_ops, 0); | 365 | NR_IRQS, &msic_host_ops, 0); |
375 | if (!msic->irq_host) { | 366 | if (!msic->irq_host) { |
376 | printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", | 367 | printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", |
377 | dn->full_name); | 368 | dn->full_name); |
@@ -387,8 +378,6 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
387 | goto out_free_host; | 378 | goto out_free_host; |
388 | } | 379 | } |
389 | 380 | ||
390 | msic->dn = of_node_get(dn); | ||
391 | |||
392 | set_irq_data(virq, msic); | 381 | set_irq_data(virq, msic); |
393 | set_irq_chained_handler(virq, axon_msi_cascade); | 382 | set_irq_chained_handler(virq, axon_msi_cascade); |
394 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); | 383 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index 0b6e8ee85ab1..901236fa0f07 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <asm/machdep.h> | 24 | #include <asm/machdep.h> |
25 | #include <asm/of_platform.h> | 25 | #include <asm/of_platform.h> |
26 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
27 | #include "cbe_regs.h" | 27 | #include <asm/cell-regs.h> |
28 | #include "cbe_cpufreq.h" | 28 | #include "cbe_cpufreq.h" |
29 | 29 | ||
30 | static DEFINE_MUTEX(cbe_switch_mutex); | 30 | static DEFINE_MUTEX(cbe_switch_mutex); |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c index 163263b3e1cd..70fa7aef5edd 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c | |||
@@ -28,8 +28,8 @@ | |||
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
30 | #include <asm/hw_irq.h> | 30 | #include <asm/hw_irq.h> |
31 | #include <asm/cell-regs.h> | ||
31 | 32 | ||
32 | #include "cbe_regs.h" | ||
33 | #include "cbe_cpufreq.h" | 33 | #include "cbe_cpufreq.h" |
34 | 34 | ||
35 | /* to write to MIC register */ | 35 | /* to write to MIC register */ |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c index fc6f38982ff4..6a2c1b0a9a94 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c | |||
@@ -27,12 +27,12 @@ | |||
27 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
28 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
29 | #include <asm/pmi.h> | 29 | #include <asm/pmi.h> |
30 | #include <asm/cell-regs.h> | ||
30 | 31 | ||
31 | #ifdef DEBUG | 32 | #ifdef DEBUG |
32 | #include <asm/time.h> | 33 | #include <asm/time.h> |
33 | #endif | 34 | #endif |
34 | 35 | ||
35 | #include "cbe_regs.h" | ||
36 | #include "cbe_cpufreq.h" | 36 | #include "cbe_cpufreq.h" |
37 | 37 | ||
38 | static u8 pmi_slow_mode_limit[MAX_CBE]; | 38 | static u8 pmi_slow_mode_limit[MAX_CBE]; |
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index c8f7f0007422..16a9b07e7b0c 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c | |||
@@ -16,8 +16,7 @@ | |||
16 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
17 | #include <asm/of_device.h> | 17 | #include <asm/of_device.h> |
18 | #include <asm/of_platform.h> | 18 | #include <asm/of_platform.h> |
19 | 19 | #include <asm/cell-regs.h> | |
20 | #include "cbe_regs.h" | ||
21 | 20 | ||
22 | /* | 21 | /* |
23 | * Current implementation uses "cpu" nodes. We build our own mapping | 22 | * Current implementation uses "cpu" nodes. We build our own mapping |
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h deleted file mode 100644 index b24025f2ac7a..000000000000 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ /dev/null | |||
@@ -1,271 +0,0 @@ | |||
1 | /* | ||
2 | * cbe_regs.h | ||
3 | * | ||
4 | * This file is intended to hold the various register definitions for CBE | ||
5 | * on-chip system devices (memory controller, IO controller, etc...) | ||
6 | * | ||
7 | * (C) Copyright IBM Corporation 2001,2006 | ||
8 | * | ||
9 | * Authors: Maximino Aguilar (maguilar@us.ibm.com) | ||
10 | * David J. Erb (djerb@us.ibm.com) | ||
11 | * | ||
12 | * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. | ||
13 | */ | ||
14 | |||
15 | #ifndef CBE_REGS_H | ||
16 | #define CBE_REGS_H | ||
17 | |||
18 | #include <asm/cell-pmu.h> | ||
19 | |||
20 | /* | ||
21 | * | ||
22 | * Some HID register definitions | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | /* CBE specific HID0 bits */ | ||
27 | #define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul | ||
28 | #define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul | ||
29 | #define HID0_CBE_THERM_INT_EN 0x0000000400000000ul | ||
30 | #define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul | ||
31 | |||
32 | #define MAX_CBE 2 | ||
33 | |||
34 | /* | ||
35 | * | ||
36 | * Pervasive unit register definitions | ||
37 | * | ||
38 | */ | ||
39 | |||
40 | union spe_reg { | ||
41 | u64 val; | ||
42 | u8 spe[8]; | ||
43 | }; | ||
44 | |||
45 | union ppe_spe_reg { | ||
46 | u64 val; | ||
47 | struct { | ||
48 | u32 ppe; | ||
49 | u32 spe; | ||
50 | }; | ||
51 | }; | ||
52 | |||
53 | |||
54 | struct cbe_pmd_regs { | ||
55 | /* Debug Bus Control */ | ||
56 | u64 pad_0x0000; /* 0x0000 */ | ||
57 | |||
58 | u64 group_control; /* 0x0008 */ | ||
59 | |||
60 | u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */ | ||
61 | |||
62 | u64 debug_bus_control; /* 0x00a8 */ | ||
63 | |||
64 | u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */ | ||
65 | |||
66 | u64 trace_aux_data; /* 0x0100 */ | ||
67 | u64 trace_buffer_0_63; /* 0x0108 */ | ||
68 | u64 trace_buffer_64_127; /* 0x0110 */ | ||
69 | u64 trace_address; /* 0x0118 */ | ||
70 | u64 ext_tr_timer; /* 0x0120 */ | ||
71 | |||
72 | u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */ | ||
73 | |||
74 | /* Performance Monitor */ | ||
75 | u64 pm_status; /* 0x0400 */ | ||
76 | u64 pm_control; /* 0x0408 */ | ||
77 | u64 pm_interval; /* 0x0410 */ | ||
78 | u64 pm_ctr[4]; /* 0x0418 */ | ||
79 | u64 pm_start_stop; /* 0x0438 */ | ||
80 | u64 pm07_control[8]; /* 0x0440 */ | ||
81 | |||
82 | u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */ | ||
83 | |||
84 | /* Thermal Sensor Registers */ | ||
85 | union spe_reg ts_ctsr1; /* 0x0800 */ | ||
86 | u64 ts_ctsr2; /* 0x0808 */ | ||
87 | union spe_reg ts_mtsr1; /* 0x0810 */ | ||
88 | u64 ts_mtsr2; /* 0x0818 */ | ||
89 | union spe_reg ts_itr1; /* 0x0820 */ | ||
90 | u64 ts_itr2; /* 0x0828 */ | ||
91 | u64 ts_gitr; /* 0x0830 */ | ||
92 | u64 ts_isr; /* 0x0838 */ | ||
93 | u64 ts_imr; /* 0x0840 */ | ||
94 | union spe_reg tm_cr1; /* 0x0848 */ | ||
95 | u64 tm_cr2; /* 0x0850 */ | ||
96 | u64 tm_simr; /* 0x0858 */ | ||
97 | union ppe_spe_reg tm_tpr; /* 0x0860 */ | ||
98 | union spe_reg tm_str1; /* 0x0868 */ | ||
99 | u64 tm_str2; /* 0x0870 */ | ||
100 | union ppe_spe_reg tm_tsr; /* 0x0878 */ | ||
101 | |||
102 | /* Power Management */ | ||
103 | u64 pmcr; /* 0x0880 */ | ||
104 | #define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 | ||
105 | u64 pmsr; /* 0x0888 */ | ||
106 | |||
107 | /* Time Base Register */ | ||
108 | u64 tbr; /* 0x0890 */ | ||
109 | |||
110 | u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ | ||
111 | |||
112 | /* Fault Isolation Registers */ | ||
113 | u64 checkstop_fir; /* 0x0c00 */ | ||
114 | u64 recoverable_fir; /* 0x0c08 */ | ||
115 | u64 spec_att_mchk_fir; /* 0x0c10 */ | ||
116 | u32 fir_mode_reg; /* 0x0c18 */ | ||
117 | u8 pad_0x0c1c_0x0c20 [4]; /* 0x0c1c */ | ||
118 | #define CBE_PMD_FIR_MODE_M8 0x00800 | ||
119 | u64 fir_enable_mask; /* 0x0c20 */ | ||
120 | |||
121 | u8 pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28]; /* 0x0c28 */ | ||
122 | u64 ras_esc_0; /* 0x0ca8 */ | ||
123 | u8 pad_0x0cb0_0x1000 [0x1000 - 0x0cb0]; /* 0x0cb0 */ | ||
124 | }; | ||
125 | |||
126 | extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); | ||
127 | extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); | ||
128 | |||
129 | /* | ||
130 | * PMU shadow registers | ||
131 | * | ||
132 | * Many of the registers in the performance monitoring unit are write-only, | ||
133 | * so we need to save a copy of what we write to those registers. | ||
134 | * | ||
135 | * The actual data counters are read/write. However, writing to the counters | ||
136 | * only takes effect if the PMU is enabled. Otherwise the value is stored in | ||
137 | * a hardware latch until the next time the PMU is enabled. So we save a copy | ||
138 | * of the counter values if we need to read them back while the PMU is | ||
139 | * disabled. The counter_value_in_latch field is a bitmap indicating which | ||
140 | * counters currently have a value waiting to be written. | ||
141 | */ | ||
142 | |||
143 | struct cbe_pmd_shadow_regs { | ||
144 | u32 group_control; | ||
145 | u32 debug_bus_control; | ||
146 | u32 trace_address; | ||
147 | u32 ext_tr_timer; | ||
148 | u32 pm_status; | ||
149 | u32 pm_control; | ||
150 | u32 pm_interval; | ||
151 | u32 pm_start_stop; | ||
152 | u32 pm07_control[NR_CTRS]; | ||
153 | |||
154 | u32 pm_ctr[NR_PHYS_CTRS]; | ||
155 | u32 counter_value_in_latch; | ||
156 | }; | ||
157 | |||
158 | extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np); | ||
159 | extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu); | ||
160 | |||
161 | /* | ||
162 | * | ||
163 | * IIC unit register definitions | ||
164 | * | ||
165 | */ | ||
166 | |||
167 | struct cbe_iic_pending_bits { | ||
168 | u32 data; | ||
169 | u8 flags; | ||
170 | u8 class; | ||
171 | u8 source; | ||
172 | u8 prio; | ||
173 | }; | ||
174 | |||
175 | #define CBE_IIC_IRQ_VALID 0x80 | ||
176 | #define CBE_IIC_IRQ_IPI 0x40 | ||
177 | |||
178 | struct cbe_iic_thread_regs { | ||
179 | struct cbe_iic_pending_bits pending; | ||
180 | struct cbe_iic_pending_bits pending_destr; | ||
181 | u64 generate; | ||
182 | u64 prio; | ||
183 | }; | ||
184 | |||
185 | struct cbe_iic_regs { | ||
186 | u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */ | ||
187 | |||
188 | /* IIC interrupt registers */ | ||
189 | struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ | ||
190 | |||
191 | u64 iic_ir; /* 0x0440 */ | ||
192 | #define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12) | ||
193 | #define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4) | ||
194 | #define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf) | ||
195 | #define CBE_IIC_IR_IOC_0 0x0 | ||
196 | #define CBE_IIC_IR_IOC_1S 0xb | ||
197 | #define CBE_IIC_IR_PT_0 0xe | ||
198 | #define CBE_IIC_IR_PT_1 0xf | ||
199 | |||
200 | u64 iic_is; /* 0x0448 */ | ||
201 | #define CBE_IIC_IS_PMI 0x2 | ||
202 | |||
203 | u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ | ||
204 | |||
205 | /* IOC FIR */ | ||
206 | u64 ioc_fir_reset; /* 0x0500 */ | ||
207 | u64 ioc_fir_set; /* 0x0508 */ | ||
208 | u64 ioc_checkstop_enable; /* 0x0510 */ | ||
209 | u64 ioc_fir_error_mask; /* 0x0518 */ | ||
210 | u64 ioc_syserr_enable; /* 0x0520 */ | ||
211 | u64 ioc_fir; /* 0x0528 */ | ||
212 | |||
213 | u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ | ||
214 | }; | ||
215 | |||
216 | extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); | ||
217 | extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); | ||
218 | |||
219 | |||
220 | struct cbe_mic_tm_regs { | ||
221 | u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */ | ||
222 | |||
223 | u64 mic_ctl_cnfg2; /* 0x0040 */ | ||
224 | #define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL | ||
225 | #define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL | ||
226 | #define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL | ||
227 | #define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL | ||
228 | |||
229 | u64 pad_0x0048; /* 0x0048 */ | ||
230 | |||
231 | u64 mic_aux_trc_base; /* 0x0050 */ | ||
232 | u64 mic_aux_trc_max_addr; /* 0x0058 */ | ||
233 | u64 mic_aux_trc_cur_addr; /* 0x0060 */ | ||
234 | u64 mic_aux_trc_grf_addr; /* 0x0068 */ | ||
235 | u64 mic_aux_trc_grf_data; /* 0x0070 */ | ||
236 | |||
237 | u64 pad_0x0078; /* 0x0078 */ | ||
238 | |||
239 | u64 mic_ctl_cnfg_0; /* 0x0080 */ | ||
240 | #define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL | ||
241 | |||
242 | u64 pad_0x0088; /* 0x0088 */ | ||
243 | |||
244 | u64 slow_fast_timer_0; /* 0x0090 */ | ||
245 | u64 slow_next_timer_0; /* 0x0098 */ | ||
246 | |||
247 | u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */ | ||
248 | |||
249 | u64 mic_ctl_cnfg_1; /* 0x01c0 */ | ||
250 | #define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL | ||
251 | u64 pad_0x01c8; /* 0x01c8 */ | ||
252 | |||
253 | u64 slow_fast_timer_1; /* 0x01d0 */ | ||
254 | u64 slow_next_timer_1; /* 0x01d8 */ | ||
255 | |||
256 | u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */ | ||
257 | }; | ||
258 | |||
259 | extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); | ||
260 | extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); | ||
261 | |||
262 | /* some utility functions to deal with SMT */ | ||
263 | extern u32 cbe_get_hw_thread_id(int cpu); | ||
264 | extern u32 cbe_cpu_to_node(int cpu); | ||
265 | extern u32 cbe_node_to_cpu(int node); | ||
266 | |||
267 | /* Init this module early */ | ||
268 | extern void cbe_regs_init(void); | ||
269 | |||
270 | |||
271 | #endif /* CBE_REGS_H */ | ||
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index fb5eda48467d..4852bf312d83 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #include <asm/spu.h> | 52 | #include <asm/spu.h> |
53 | #include <asm/io.h> | 53 | #include <asm/io.h> |
54 | #include <asm/prom.h> | 54 | #include <asm/prom.h> |
55 | #include <asm/cell-regs.h> | ||
55 | 56 | ||
56 | #include "cbe_regs.h" | ||
57 | #include "spu_priv1_mmio.h" | 57 | #include "spu_priv1_mmio.h" |
58 | 58 | ||
59 | #define TEMP_MIN 65 | 59 | #define TEMP_MIN 65 |
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 47264e722029..151fd8b82d63 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
@@ -41,9 +41,9 @@ | |||
41 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
42 | #include <asm/ptrace.h> | 42 | #include <asm/ptrace.h> |
43 | #include <asm/machdep.h> | 43 | #include <asm/machdep.h> |
44 | #include <asm/cell-regs.h> | ||
44 | 45 | ||
45 | #include "interrupt.h" | 46 | #include "interrupt.h" |
46 | #include "cbe_regs.h" | ||
47 | 47 | ||
48 | struct iic { | 48 | struct iic { |
49 | struct cbe_iic_thread_regs __iomem *regs; | 49 | struct cbe_iic_thread_regs __iomem *regs; |
@@ -381,7 +381,7 @@ static int __init setup_iic(void) | |||
381 | void __init iic_init_IRQ(void) | 381 | void __init iic_init_IRQ(void) |
382 | { | 382 | { |
383 | /* Setup an irq host data structure */ | 383 | /* Setup an irq host data structure */ |
384 | iic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT, | 384 | iic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT, |
385 | &iic_host_ops, IIC_IRQ_INVALID); | 385 | &iic_host_ops, IIC_IRQ_INVALID); |
386 | BUG_ON(iic_host == NULL); | 386 | BUG_ON(iic_host == NULL); |
387 | irq_set_default_host(iic_host); | 387 | irq_set_default_host(iic_host); |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 760caa76841a..faabc3fdc130 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -34,8 +34,8 @@ | |||
34 | #include <asm/udbg.h> | 34 | #include <asm/udbg.h> |
35 | #include <asm/of_platform.h> | 35 | #include <asm/of_platform.h> |
36 | #include <asm/lmb.h> | 36 | #include <asm/lmb.h> |
37 | #include <asm/cell-regs.h> | ||
37 | 38 | ||
38 | #include "cbe_regs.h" | ||
39 | #include "interrupt.h" | 39 | #include "interrupt.h" |
40 | 40 | ||
41 | /* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages | 41 | /* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages |
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 4ede22d363fa..0304589c0a80 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c | |||
@@ -34,9 +34,9 @@ | |||
34 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/reg.h> | 36 | #include <asm/reg.h> |
37 | #include <asm/cell-regs.h> | ||
37 | 38 | ||
38 | #include "pervasive.h" | 39 | #include "pervasive.h" |
39 | #include "cbe_regs.h" | ||
40 | 40 | ||
41 | static int sysreset_hack; | 41 | static int sysreset_hack; |
42 | 42 | ||
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index 66ca4b5a1dbc..1ed303678887 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c | |||
@@ -30,8 +30,8 @@ | |||
30 | #include <asm/pmc.h> | 30 | #include <asm/pmc.h> |
31 | #include <asm/reg.h> | 31 | #include <asm/reg.h> |
32 | #include <asm/spu.h> | 32 | #include <asm/spu.h> |
33 | #include <asm/cell-regs.h> | ||
33 | 34 | ||
34 | #include "cbe_regs.h" | ||
35 | #include "interrupt.h" | 35 | #include "interrupt.h" |
36 | 36 | ||
37 | /* | 37 | /* |
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 3961a085b432..b2494ebcdbe9 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c | |||
@@ -10,9 +10,9 @@ | |||
10 | #include <asm/prom.h> | 10 | #include <asm/prom.h> |
11 | #include <asm/machdep.h> | 11 | #include <asm/machdep.h> |
12 | #include <asm/rtas.h> | 12 | #include <asm/rtas.h> |
13 | #include <asm/cell-regs.h> | ||
13 | 14 | ||
14 | #include "ras.h" | 15 | #include "ras.h" |
15 | #include "cbe_regs.h" | ||
16 | 16 | ||
17 | 17 | ||
18 | static void dump_fir(int cpu) | 18 | static void dump_fir(int cpu) |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index db6654272e13..98e7ef8e6fc6 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -52,9 +52,9 @@ | |||
52 | #include <asm/udbg.h> | 52 | #include <asm/udbg.h> |
53 | #include <asm/mpic.h> | 53 | #include <asm/mpic.h> |
54 | #include <asm/of_platform.h> | 54 | #include <asm/of_platform.h> |
55 | #include <asm/cell-regs.h> | ||
55 | 56 | ||
56 | #include "interrupt.h" | 57 | #include "interrupt.h" |
57 | #include "cbe_regs.h" | ||
58 | #include "pervasive.h" | 58 | #include "pervasive.h" |
59 | #include "ras.h" | 59 | #include "ras.h" |
60 | 60 | ||
@@ -83,12 +83,22 @@ static void cell_progress(char *s, unsigned short hex) | |||
83 | 83 | ||
84 | static int __init cell_publish_devices(void) | 84 | static int __init cell_publish_devices(void) |
85 | { | 85 | { |
86 | int node; | ||
87 | |||
86 | if (!machine_is(cell)) | 88 | if (!machine_is(cell)) |
87 | return 0; | 89 | return 0; |
88 | 90 | ||
89 | /* Publish OF platform devices for southbridge IOs */ | 91 | /* Publish OF platform devices for southbridge IOs */ |
90 | of_platform_bus_probe(NULL, NULL, NULL); | 92 | of_platform_bus_probe(NULL, NULL, NULL); |
91 | 93 | ||
94 | /* There is no device for the MIC memory controller, thus we create | ||
95 | * a platform device for it to attach the EDAC driver to. | ||
96 | */ | ||
97 | for_each_online_node(node) { | ||
98 | if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL) | ||
99 | continue; | ||
100 | platform_device_register_simple("cbe-mic", node, NULL, 0); | ||
101 | } | ||
92 | return 0; | 102 | return 0; |
93 | } | 103 | } |
94 | device_initcall(cell_publish_devices); | 104 | device_initcall(cell_publish_devices); |
@@ -161,11 +171,6 @@ static void __init cell_setup_arch(void) | |||
161 | /* init to some ~sane value until calibrate_delay() runs */ | 171 | /* init to some ~sane value until calibrate_delay() runs */ |
162 | loops_per_jiffy = 50000000; | 172 | loops_per_jiffy = 50000000; |
163 | 173 | ||
164 | if (ROOT_DEV == 0) { | ||
165 | printk("No ramdisk, default root is /dev/hda2\n"); | ||
166 | ROOT_DEV = Root_HDA2; | ||
167 | } | ||
168 | |||
169 | /* Find and initialize PCI host bridges */ | 174 | /* Find and initialize PCI host bridges */ |
170 | init_pci_config_tokens(); | 175 | init_pci_config_tokens(); |
171 | find_and_init_phbs(); | 176 | find_and_init_phbs(); |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 05f4b3d3d756..3f4b4aef756d 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -63,7 +63,6 @@ enum { | |||
63 | 63 | ||
64 | struct spider_pic { | 64 | struct spider_pic { |
65 | struct irq_host *host; | 65 | struct irq_host *host; |
66 | struct device_node *of_node; | ||
67 | void __iomem *regs; | 66 | void __iomem *regs; |
68 | unsigned int node_id; | 67 | unsigned int node_id; |
69 | }; | 68 | }; |
@@ -176,12 +175,6 @@ static struct irq_chip spider_pic = { | |||
176 | .set_type = spider_set_irq_type, | 175 | .set_type = spider_set_irq_type, |
177 | }; | 176 | }; |
178 | 177 | ||
179 | static int spider_host_match(struct irq_host *h, struct device_node *node) | ||
180 | { | ||
181 | struct spider_pic *pic = h->host_data; | ||
182 | return node == pic->of_node; | ||
183 | } | ||
184 | |||
185 | static int spider_host_map(struct irq_host *h, unsigned int virq, | 178 | static int spider_host_map(struct irq_host *h, unsigned int virq, |
186 | irq_hw_number_t hw) | 179 | irq_hw_number_t hw) |
187 | { | 180 | { |
@@ -208,7 +201,6 @@ static int spider_host_xlate(struct irq_host *h, struct device_node *ct, | |||
208 | } | 201 | } |
209 | 202 | ||
210 | static struct irq_host_ops spider_host_ops = { | 203 | static struct irq_host_ops spider_host_ops = { |
211 | .match = spider_host_match, | ||
212 | .map = spider_host_map, | 204 | .map = spider_host_map, |
213 | .xlate = spider_host_xlate, | 205 | .xlate = spider_host_xlate, |
214 | }; | 206 | }; |
@@ -247,18 +239,18 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) | |||
247 | * tree in case the device-tree is ever fixed | 239 | * tree in case the device-tree is ever fixed |
248 | */ | 240 | */ |
249 | struct of_irq oirq; | 241 | struct of_irq oirq; |
250 | if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) { | 242 | if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) { |
251 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | 243 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, |
252 | oirq.size); | 244 | oirq.size); |
253 | return virq; | 245 | return virq; |
254 | } | 246 | } |
255 | 247 | ||
256 | /* Now do the horrible hacks */ | 248 | /* Now do the horrible hacks */ |
257 | tmp = of_get_property(pic->of_node, "#interrupt-cells", NULL); | 249 | tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL); |
258 | if (tmp == NULL) | 250 | if (tmp == NULL) |
259 | return NO_IRQ; | 251 | return NO_IRQ; |
260 | intsize = *tmp; | 252 | intsize = *tmp; |
261 | imap = of_get_property(pic->of_node, "interrupt-map", &imaplen); | 253 | imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen); |
262 | if (imap == NULL || imaplen < (intsize + 1)) | 254 | if (imap == NULL || imaplen < (intsize + 1)) |
263 | return NO_IRQ; | 255 | return NO_IRQ; |
264 | iic = of_find_node_by_phandle(imap[intsize]); | 256 | iic = of_find_node_by_phandle(imap[intsize]); |
@@ -308,15 +300,13 @@ static void __init spider_init_one(struct device_node *of_node, int chip, | |||
308 | panic("spider_pic: can't map registers !"); | 300 | panic("spider_pic: can't map registers !"); |
309 | 301 | ||
310 | /* Allocate a host */ | 302 | /* Allocate a host */ |
311 | pic->host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, SPIDER_SRC_COUNT, | 303 | pic->host = irq_alloc_host(of_node_get(of_node), IRQ_HOST_MAP_LINEAR, |
312 | &spider_host_ops, SPIDER_IRQ_INVALID); | 304 | SPIDER_SRC_COUNT, &spider_host_ops, |
305 | SPIDER_IRQ_INVALID); | ||
313 | if (pic->host == NULL) | 306 | if (pic->host == NULL) |
314 | panic("spider_pic: can't allocate irq host !"); | 307 | panic("spider_pic: can't allocate irq host !"); |
315 | pic->host->host_data = pic; | 308 | pic->host->host_data = pic; |
316 | 309 | ||
317 | /* Fill out other bits */ | ||
318 | pic->of_node = of_node_get(of_node); | ||
319 | |||
320 | /* Go through all sources and disable them */ | 310 | /* Go through all sources and disable them */ |
321 | for (i = 0; i < SPIDER_SRC_COUNT; i++) { | 311 | for (i = 0; i < SPIDER_SRC_COUNT; i++) { |
322 | void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i; | 312 | void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i; |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 106d2921e2d9..c83c3e3f5178 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -168,7 +168,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
168 | #else | 168 | #else |
169 | psize = mm->context.user_psize; | 169 | psize = mm->context.user_psize; |
170 | #endif | 170 | #endif |
171 | vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | | 171 | vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | |
172 | SLB_VSID_USER; | 172 | SLB_VSID_USER; |
173 | break; | 173 | break; |
174 | case VMALLOC_REGION_ID: | 174 | case VMALLOC_REGION_ID: |
@@ -176,12 +176,12 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
176 | psize = mmu_vmalloc_psize; | 176 | psize = mmu_vmalloc_psize; |
177 | else | 177 | else |
178 | psize = mmu_io_psize; | 178 | psize = mmu_io_psize; |
179 | vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | | 179 | vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | |
180 | SLB_VSID_KERNEL; | 180 | SLB_VSID_KERNEL; |
181 | break; | 181 | break; |
182 | case KERNEL_REGION_ID: | 182 | case KERNEL_REGION_ID: |
183 | psize = mmu_linear_psize; | 183 | psize = mmu_linear_psize; |
184 | vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | | 184 | vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | |
185 | SLB_VSID_KERNEL; | 185 | SLB_VSID_KERNEL; |
186 | break; | 186 | break; |
187 | default: | 187 | default: |
@@ -458,7 +458,7 @@ static int spu_shutdown(struct sys_device *sysdev) | |||
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
460 | 460 | ||
461 | struct sysdev_class spu_sysdev_class = { | 461 | static struct sysdev_class spu_sysdev_class = { |
462 | set_kset_name("spu"), | 462 | set_kset_name("spu"), |
463 | .shutdown = spu_shutdown, | 463 | .shutdown = spu_shutdown, |
464 | }; | 464 | }; |
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index 47ec3be3edcd..dceb8b6a9382 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * System call callback functions for SPUs | 2 | * System call callback functions for SPUs |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #define DEBUG | 5 | #undef DEBUG |
6 | 6 | ||
7 | #include <linux/kallsyms.h> | 7 | #include <linux/kallsyms.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
@@ -33,7 +33,7 @@ | |||
33 | * mbind, mq_open, ipc, ... | 33 | * mbind, mq_open, ipc, ... |
34 | */ | 34 | */ |
35 | 35 | ||
36 | void *spu_syscall_table[] = { | 36 | static void *spu_syscall_table[] = { |
37 | #define SYSCALL(func) sys_ni_syscall, | 37 | #define SYSCALL(func) sys_ni_syscall, |
38 | #define COMPAT_SYS(func) sys_ni_syscall, | 38 | #define COMPAT_SYS(func) sys_ni_syscall, |
39 | #define PPC_SYS(func) sys_ni_syscall, | 39 | #define PPC_SYS(func) sys_ni_syscall, |
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c deleted file mode 100644 index 4fd37ff1e210..000000000000 --- a/arch/powerpc/platforms/cell/spu_coredump.c +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | /* | ||
2 | * SPU core dump code | ||
3 | * | ||
4 | * (C) Copyright 2006 IBM Corp. | ||
5 | * | ||
6 | * Author: Dwayne Grant McConnell <decimal@us.ibm.com> | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/file.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/syscalls.h> | ||
26 | |||
27 | #include <asm/spu.h> | ||
28 | |||
29 | static struct spu_coredump_calls *spu_coredump_calls; | ||
30 | static DEFINE_MUTEX(spu_coredump_mutex); | ||
31 | |||
32 | int arch_notes_size(void) | ||
33 | { | ||
34 | long ret; | ||
35 | |||
36 | ret = -ENOSYS; | ||
37 | mutex_lock(&spu_coredump_mutex); | ||
38 | if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { | ||
39 | ret = spu_coredump_calls->arch_notes_size(); | ||
40 | module_put(spu_coredump_calls->owner); | ||
41 | } | ||
42 | mutex_unlock(&spu_coredump_mutex); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | void arch_write_notes(struct file *file) | ||
47 | { | ||
48 | mutex_lock(&spu_coredump_mutex); | ||
49 | if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) { | ||
50 | spu_coredump_calls->arch_write_notes(file); | ||
51 | module_put(spu_coredump_calls->owner); | ||
52 | } | ||
53 | mutex_unlock(&spu_coredump_mutex); | ||
54 | } | ||
55 | |||
56 | int register_arch_coredump_calls(struct spu_coredump_calls *calls) | ||
57 | { | ||
58 | int ret = 0; | ||
59 | |||
60 | |||
61 | mutex_lock(&spu_coredump_mutex); | ||
62 | if (spu_coredump_calls) | ||
63 | ret = -EBUSY; | ||
64 | else | ||
65 | spu_coredump_calls = calls; | ||
66 | mutex_unlock(&spu_coredump_mutex); | ||
67 | return ret; | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(register_arch_coredump_calls); | ||
70 | |||
71 | void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) | ||
72 | { | ||
73 | BUG_ON(spu_coredump_calls != calls); | ||
74 | |||
75 | mutex_lock(&spu_coredump_mutex); | ||
76 | spu_coredump_calls = NULL; | ||
77 | mutex_unlock(&spu_coredump_mutex); | ||
78 | } | ||
79 | EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); | ||
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 0e14f532500e..1b010707488d 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c | |||
@@ -377,10 +377,10 @@ static int qs20_reg_memory[QS20_SPES_PER_BE] = { 1, 1, 0, 0, 0, 0, 0, 0 }; | |||
377 | static struct spu *spu_lookup_reg(int node, u32 reg) | 377 | static struct spu *spu_lookup_reg(int node, u32 reg) |
378 | { | 378 | { |
379 | struct spu *spu; | 379 | struct spu *spu; |
380 | u32 *spu_reg; | 380 | const u32 *spu_reg; |
381 | 381 | ||
382 | list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { | 382 | list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { |
383 | spu_reg = (u32*)of_get_property(spu_devnode(spu), "reg", NULL); | 383 | spu_reg = of_get_property(spu_devnode(spu), "reg", NULL); |
384 | if (*spu_reg == reg) | 384 | if (*spu_reg == reg) |
385 | return spu; | 385 | return spu; |
386 | } | 386 | } |
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c index 027ac32cc636..a9438b719fe8 100644 --- a/arch/powerpc/platforms/cell/spu_syscalls.c +++ b/arch/powerpc/platforms/cell/spu_syscalls.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * SPU file system -- system call stubs | 2 | * SPU file system -- system call stubs |
3 | * | 3 | * |
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | 4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 |
5 | * (C) Copyright 2006-2007, IBM Corporation | ||
5 | * | 6 | * |
6 | * Author: Arnd Bergmann <arndb@de.ibm.com> | 7 | * Author: Arnd Bergmann <arndb@de.ibm.com> |
7 | * | 8 | * |
@@ -20,44 +21,73 @@ | |||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | */ | 22 | */ |
22 | #include <linux/file.h> | 23 | #include <linux/file.h> |
24 | #include <linux/fs.h> | ||
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
27 | #include <linux/rcupdate.h> | ||
25 | 28 | ||
26 | #include <asm/spu.h> | 29 | #include <asm/spu.h> |
27 | 30 | ||
28 | struct spufs_calls spufs_calls = { | 31 | /* protected by rcu */ |
29 | .owner = NULL, | 32 | static struct spufs_calls *spufs_calls; |
30 | }; | ||
31 | 33 | ||
32 | /* These stub syscalls are needed to have the actual implementation | 34 | #ifdef CONFIG_SPU_FS_MODULE |
33 | * within a loadable module. When spufs is built into the kernel, | 35 | |
34 | * this file is not used and the syscalls directly enter the fs code */ | 36 | static inline struct spufs_calls *spufs_calls_get(void) |
37 | { | ||
38 | struct spufs_calls *calls = NULL; | ||
39 | |||
40 | rcu_read_lock(); | ||
41 | calls = rcu_dereference(spufs_calls); | ||
42 | if (calls && !try_module_get(calls->owner)) | ||
43 | calls = NULL; | ||
44 | rcu_read_unlock(); | ||
45 | |||
46 | return calls; | ||
47 | } | ||
48 | |||
49 | static inline void spufs_calls_put(struct spufs_calls *calls) | ||
50 | { | ||
51 | BUG_ON(calls != spufs_calls); | ||
52 | |||
53 | /* we don't need to rcu this, as we hold a reference to the module */ | ||
54 | module_put(spufs_calls->owner); | ||
55 | } | ||
56 | |||
57 | #else /* !defined CONFIG_SPU_FS_MODULE */ | ||
58 | |||
59 | static inline struct spufs_calls *spufs_calls_get(void) | ||
60 | { | ||
61 | return spufs_calls; | ||
62 | } | ||
63 | |||
64 | static inline void spufs_calls_put(struct spufs_calls *calls) { } | ||
65 | |||
66 | #endif /* CONFIG_SPU_FS_MODULE */ | ||
35 | 67 | ||
36 | asmlinkage long sys_spu_create(const char __user *name, | 68 | asmlinkage long sys_spu_create(const char __user *name, |
37 | unsigned int flags, mode_t mode, int neighbor_fd) | 69 | unsigned int flags, mode_t mode, int neighbor_fd) |
38 | { | 70 | { |
39 | long ret; | 71 | long ret; |
40 | struct module *owner = spufs_calls.owner; | ||
41 | struct file *neighbor; | 72 | struct file *neighbor; |
42 | int fput_needed; | 73 | int fput_needed; |
74 | struct spufs_calls *calls; | ||
43 | 75 | ||
44 | ret = -ENOSYS; | 76 | calls = spufs_calls_get(); |
45 | if (owner && try_module_get(owner)) { | 77 | if (!calls) |
46 | if (flags & SPU_CREATE_AFFINITY_SPU) { | 78 | return -ENOSYS; |
47 | neighbor = fget_light(neighbor_fd, &fput_needed); | 79 | |
48 | ret = -EBADF; | 80 | if (flags & SPU_CREATE_AFFINITY_SPU) { |
49 | if (neighbor) { | 81 | ret = -EBADF; |
50 | ret = spufs_calls.create_thread(name, flags, | 82 | neighbor = fget_light(neighbor_fd, &fput_needed); |
51 | mode, neighbor); | 83 | if (neighbor) { |
52 | fput_light(neighbor, fput_needed); | 84 | ret = calls->create_thread(name, flags, mode, neighbor); |
53 | } | 85 | fput_light(neighbor, fput_needed); |
54 | } | ||
55 | else { | ||
56 | ret = spufs_calls.create_thread(name, flags, | ||
57 | mode, NULL); | ||
58 | } | 86 | } |
59 | module_put(owner); | 87 | } else |
60 | } | 88 | ret = calls->create_thread(name, flags, mode, NULL); |
89 | |||
90 | spufs_calls_put(calls); | ||
61 | return ret; | 91 | return ret; |
62 | } | 92 | } |
63 | 93 | ||
@@ -66,37 +96,69 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) | |||
66 | long ret; | 96 | long ret; |
67 | struct file *filp; | 97 | struct file *filp; |
68 | int fput_needed; | 98 | int fput_needed; |
69 | struct module *owner = spufs_calls.owner; | 99 | struct spufs_calls *calls; |
70 | 100 | ||
71 | ret = -ENOSYS; | 101 | calls = spufs_calls_get(); |
72 | if (owner && try_module_get(owner)) { | 102 | if (!calls) |
73 | ret = -EBADF; | 103 | return -ENOSYS; |
74 | filp = fget_light(fd, &fput_needed); | 104 | |
75 | if (filp) { | 105 | ret = -EBADF; |
76 | ret = spufs_calls.spu_run(filp, unpc, ustatus); | 106 | filp = fget_light(fd, &fput_needed); |
77 | fput_light(filp, fput_needed); | 107 | if (filp) { |
78 | } | 108 | ret = calls->spu_run(filp, unpc, ustatus); |
79 | module_put(owner); | 109 | fput_light(filp, fput_needed); |
80 | } | 110 | } |
111 | |||
112 | spufs_calls_put(calls); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | int elf_coredump_extra_notes_size(void) | ||
117 | { | ||
118 | struct spufs_calls *calls; | ||
119 | int ret; | ||
120 | |||
121 | calls = spufs_calls_get(); | ||
122 | if (!calls) | ||
123 | return 0; | ||
124 | |||
125 | ret = calls->coredump_extra_notes_size(); | ||
126 | |||
127 | spufs_calls_put(calls); | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset) | ||
133 | { | ||
134 | struct spufs_calls *calls; | ||
135 | int ret; | ||
136 | |||
137 | calls = spufs_calls_get(); | ||
138 | if (!calls) | ||
139 | return 0; | ||
140 | |||
141 | ret = calls->coredump_extra_notes_write(file, foffset); | ||
142 | |||
143 | spufs_calls_put(calls); | ||
144 | |||
81 | return ret; | 145 | return ret; |
82 | } | 146 | } |
83 | 147 | ||
84 | int register_spu_syscalls(struct spufs_calls *calls) | 148 | int register_spu_syscalls(struct spufs_calls *calls) |
85 | { | 149 | { |
86 | if (spufs_calls.owner) | 150 | if (spufs_calls) |
87 | return -EBUSY; | 151 | return -EBUSY; |
88 | 152 | ||
89 | spufs_calls.create_thread = calls->create_thread; | 153 | rcu_assign_pointer(spufs_calls, calls); |
90 | spufs_calls.spu_run = calls->spu_run; | ||
91 | smp_mb(); | ||
92 | spufs_calls.owner = calls->owner; | ||
93 | return 0; | 154 | return 0; |
94 | } | 155 | } |
95 | EXPORT_SYMBOL_GPL(register_spu_syscalls); | 156 | EXPORT_SYMBOL_GPL(register_spu_syscalls); |
96 | 157 | ||
97 | void unregister_spu_syscalls(struct spufs_calls *calls) | 158 | void unregister_spu_syscalls(struct spufs_calls *calls) |
98 | { | 159 | { |
99 | BUG_ON(spufs_calls.owner != calls->owner); | 160 | BUG_ON(spufs_calls->owner != calls->owner); |
100 | spufs_calls.owner = NULL; | 161 | rcu_assign_pointer(spufs_calls, NULL); |
162 | synchronize_rcu(); | ||
101 | } | 163 | } |
102 | EXPORT_SYMBOL_GPL(unregister_spu_syscalls); | 164 | EXPORT_SYMBOL_GPL(unregister_spu_syscalls); |
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 5e31799b1e3f..80f62363e1ce 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c | |||
@@ -31,16 +31,7 @@ | |||
31 | 31 | ||
32 | #include "spufs.h" | 32 | #include "spufs.h" |
33 | 33 | ||
34 | struct spufs_ctx_info { | 34 | static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer, |
35 | struct list_head list; | ||
36 | int dfd; | ||
37 | int memsize; /* in bytes */ | ||
38 | struct spu_context *ctx; | ||
39 | }; | ||
40 | |||
41 | static LIST_HEAD(ctx_info_list); | ||
42 | |||
43 | static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer, | ||
44 | size_t size, loff_t *off) | 35 | size_t size, loff_t *off) |
45 | { | 36 | { |
46 | u64 data; | 37 | u64 data; |
@@ -50,49 +41,57 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *b | |||
50 | return spufs_coredump_read[num].read(ctx, buffer, size, off); | 41 | return spufs_coredump_read[num].read(ctx, buffer, size, off); |
51 | 42 | ||
52 | data = spufs_coredump_read[num].get(ctx); | 43 | data = spufs_coredump_read[num].get(ctx); |
53 | ret = copy_to_user(buffer, &data, 8); | 44 | ret = snprintf(buffer, size, "0x%.16lx", data); |
54 | return ret ? -EFAULT : 8; | 45 | if (ret >= size) |
46 | return size; | ||
47 | return ++ret; /* count trailing NULL */ | ||
55 | } | 48 | } |
56 | 49 | ||
57 | /* | 50 | /* |
58 | * These are the only things you should do on a core-file: use only these | 51 | * These are the only things you should do on a core-file: use only these |
59 | * functions to write out all the necessary info. | 52 | * functions to write out all the necessary info. |
60 | */ | 53 | */ |
61 | static int spufs_dump_write(struct file *file, const void *addr, int nr) | 54 | static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset) |
62 | { | 55 | { |
63 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | 56 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
64 | } | 57 | ssize_t written; |
65 | 58 | ||
66 | static int spufs_dump_seek(struct file *file, loff_t off) | 59 | if (*foffset + nr > limit) |
67 | { | 60 | return -EIO; |
68 | if (file->f_op->llseek) { | 61 | |
69 | if (file->f_op->llseek(file, off, 0) != off) | 62 | written = file->f_op->write(file, addr, nr, &file->f_pos); |
70 | return 0; | 63 | *foffset += written; |
71 | } else | 64 | |
72 | file->f_pos = off; | 65 | if (written != nr) |
73 | return 1; | 66 | return -EIO; |
67 | |||
68 | return 0; | ||
74 | } | 69 | } |
75 | 70 | ||
76 | static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info) | 71 | static int spufs_dump_align(struct file *file, char *buf, loff_t new_off, |
72 | loff_t *foffset) | ||
77 | { | 73 | { |
78 | struct spu_context *ctx; | 74 | int rc, size; |
79 | unsigned long long lslr; | 75 | |
76 | size = min((loff_t)PAGE_SIZE, new_off - *foffset); | ||
77 | memset(buf, 0, size); | ||
78 | |||
79 | rc = 0; | ||
80 | while (rc == 0 && new_off > *foffset) { | ||
81 | size = min((loff_t)PAGE_SIZE, new_off - *foffset); | ||
82 | rc = spufs_dump_write(file, buf, size, foffset); | ||
83 | } | ||
80 | 84 | ||
81 | ctx = ctx_info->ctx; | 85 | return rc; |
82 | lslr = ctx->csa.priv2.spu_lslr_RW; | ||
83 | ctx_info->memsize = lslr + 1; | ||
84 | } | 86 | } |
85 | 87 | ||
86 | static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) | 88 | static int spufs_ctx_note_size(struct spu_context *ctx, int dfd) |
87 | { | 89 | { |
88 | int dfd, memsize, i, sz, total = 0; | 90 | int i, sz, total = 0; |
89 | char *name; | 91 | char *name; |
90 | char fullname[80]; | 92 | char fullname[80]; |
91 | 93 | ||
92 | dfd = ctx_info->dfd; | 94 | for (i = 0; spufs_coredump_read[i].name != NULL; i++) { |
93 | memsize = ctx_info->memsize; | ||
94 | |||
95 | for (i = 0; spufs_coredump_read[i].name; i++) { | ||
96 | name = spufs_coredump_read[i].name; | 95 | name = spufs_coredump_read[i].name; |
97 | sz = spufs_coredump_read[i].size; | 96 | sz = spufs_coredump_read[i].size; |
98 | 97 | ||
@@ -100,39 +99,12 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) | |||
100 | 99 | ||
101 | total += sizeof(struct elf_note); | 100 | total += sizeof(struct elf_note); |
102 | total += roundup(strlen(fullname) + 1, 4); | 101 | total += roundup(strlen(fullname) + 1, 4); |
103 | if (!strcmp(name, "mem")) | 102 | total += roundup(sz, 4); |
104 | total += roundup(memsize, 4); | ||
105 | else | ||
106 | total += roundup(sz, 4); | ||
107 | } | 103 | } |
108 | 104 | ||
109 | return total; | 105 | return total; |
110 | } | 106 | } |
111 | 107 | ||
112 | static int spufs_add_one_context(struct file *file, int dfd) | ||
113 | { | ||
114 | struct spu_context *ctx; | ||
115 | struct spufs_ctx_info *ctx_info; | ||
116 | int size; | ||
117 | |||
118 | ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; | ||
119 | if (ctx->flags & SPU_CREATE_NOSCHED) | ||
120 | return 0; | ||
121 | |||
122 | ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL); | ||
123 | if (unlikely(!ctx_info)) | ||
124 | return -ENOMEM; | ||
125 | |||
126 | ctx_info->dfd = dfd; | ||
127 | ctx_info->ctx = ctx; | ||
128 | |||
129 | spufs_fill_memsize(ctx_info); | ||
130 | |||
131 | size = spufs_ctx_note_size(ctx_info); | ||
132 | list_add(&ctx_info->list, &ctx_info_list); | ||
133 | return size; | ||
134 | } | ||
135 | |||
136 | /* | 108 | /* |
137 | * The additional architecture-specific notes for Cell are various | 109 | * The additional architecture-specific notes for Cell are various |
138 | * context files in the spu context. | 110 | * context files in the spu context. |
@@ -142,33 +114,57 @@ static int spufs_add_one_context(struct file *file, int dfd) | |||
142 | * internal functionality to dump them without needing to actually | 114 | * internal functionality to dump them without needing to actually |
143 | * open the files. | 115 | * open the files. |
144 | */ | 116 | */ |
145 | static int spufs_arch_notes_size(void) | 117 | static struct spu_context *coredump_next_context(int *fd) |
146 | { | 118 | { |
147 | struct fdtable *fdt = files_fdtable(current->files); | 119 | struct fdtable *fdt = files_fdtable(current->files); |
148 | int size = 0, fd; | 120 | struct file *file; |
121 | struct spu_context *ctx = NULL; | ||
149 | 122 | ||
150 | for (fd = 0; fd < fdt->max_fds; fd++) { | 123 | for (; *fd < fdt->max_fds; (*fd)++) { |
151 | if (FD_ISSET(fd, fdt->open_fds)) { | 124 | if (!FD_ISSET(*fd, fdt->open_fds)) |
152 | struct file *file = fcheck(fd); | 125 | continue; |
153 | 126 | ||
154 | if (file && file->f_op == &spufs_context_fops) { | 127 | file = fcheck(*fd); |
155 | int rval = spufs_add_one_context(file, fd); | 128 | |
156 | if (rval < 0) | 129 | if (!file || file->f_op != &spufs_context_fops) |
157 | break; | 130 | continue; |
158 | size += rval; | 131 | |
159 | } | 132 | ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; |
160 | } | 133 | if (ctx->flags & SPU_CREATE_NOSCHED) |
134 | continue; | ||
135 | |||
136 | /* start searching the next fd next time we're called */ | ||
137 | (*fd)++; | ||
138 | break; | ||
161 | } | 139 | } |
162 | 140 | ||
163 | return size; | 141 | return ctx; |
164 | } | 142 | } |
165 | 143 | ||
166 | static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, | 144 | int spufs_coredump_extra_notes_size(void) |
167 | struct file *file) | ||
168 | { | 145 | { |
169 | struct spu_context *ctx; | 146 | struct spu_context *ctx; |
147 | int size = 0, rc, fd; | ||
148 | |||
149 | fd = 0; | ||
150 | while ((ctx = coredump_next_context(&fd)) != NULL) { | ||
151 | spu_acquire_saved(ctx); | ||
152 | rc = spufs_ctx_note_size(ctx, fd); | ||
153 | spu_release_saved(ctx); | ||
154 | if (rc < 0) | ||
155 | break; | ||
156 | |||
157 | size += rc; | ||
158 | } | ||
159 | |||
160 | return size; | ||
161 | } | ||
162 | |||
163 | static int spufs_arch_write_note(struct spu_context *ctx, int i, | ||
164 | struct file *file, int dfd, loff_t *foffset) | ||
165 | { | ||
170 | loff_t pos = 0; | 166 | loff_t pos = 0; |
171 | int sz, dfd, rc, total = 0; | 167 | int sz, rc, nread, total = 0; |
172 | const int bufsz = PAGE_SIZE; | 168 | const int bufsz = PAGE_SIZE; |
173 | char *name; | 169 | char *name; |
174 | char fullname[80], *buf; | 170 | char fullname[80], *buf; |
@@ -176,64 +172,70 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, | |||
176 | 172 | ||
177 | buf = (void *)get_zeroed_page(GFP_KERNEL); | 173 | buf = (void *)get_zeroed_page(GFP_KERNEL); |
178 | if (!buf) | 174 | if (!buf) |
179 | return; | 175 | return -ENOMEM; |
180 | 176 | ||
181 | dfd = ctx_info->dfd; | ||
182 | name = spufs_coredump_read[i].name; | 177 | name = spufs_coredump_read[i].name; |
183 | 178 | sz = spufs_coredump_read[i].size; | |
184 | if (!strcmp(name, "mem")) | ||
185 | sz = ctx_info->memsize; | ||
186 | else | ||
187 | sz = spufs_coredump_read[i].size; | ||
188 | |||
189 | ctx = ctx_info->ctx; | ||
190 | if (!ctx) | ||
191 | goto out; | ||
192 | 179 | ||
193 | sprintf(fullname, "SPU/%d/%s", dfd, name); | 180 | sprintf(fullname, "SPU/%d/%s", dfd, name); |
194 | en.n_namesz = strlen(fullname) + 1; | 181 | en.n_namesz = strlen(fullname) + 1; |
195 | en.n_descsz = sz; | 182 | en.n_descsz = sz; |
196 | en.n_type = NT_SPU; | 183 | en.n_type = NT_SPU; |
197 | 184 | ||
198 | if (!spufs_dump_write(file, &en, sizeof(en))) | 185 | rc = spufs_dump_write(file, &en, sizeof(en), foffset); |
186 | if (rc) | ||
199 | goto out; | 187 | goto out; |
200 | if (!spufs_dump_write(file, fullname, en.n_namesz)) | 188 | |
189 | rc = spufs_dump_write(file, fullname, en.n_namesz, foffset); | ||
190 | if (rc) | ||
201 | goto out; | 191 | goto out; |
202 | if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) | 192 | |
193 | rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset); | ||
194 | if (rc) | ||
203 | goto out; | 195 | goto out; |
204 | 196 | ||
205 | do { | 197 | do { |
206 | rc = do_coredump_read(i, ctx, buf, bufsz, &pos); | 198 | nread = do_coredump_read(i, ctx, buf, bufsz, &pos); |
207 | if (rc > 0) { | 199 | if (nread > 0) { |
208 | if (!spufs_dump_write(file, buf, rc)) | 200 | rc = spufs_dump_write(file, buf, nread, foffset); |
201 | if (rc) | ||
209 | goto out; | 202 | goto out; |
210 | total += rc; | 203 | total += nread; |
211 | } | 204 | } |
212 | } while (rc == bufsz && total < sz); | 205 | } while (nread == bufsz && total < sz); |
206 | |||
207 | if (nread < 0) { | ||
208 | rc = nread; | ||
209 | goto out; | ||
210 | } | ||
211 | |||
212 | rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4), | ||
213 | foffset); | ||
213 | 214 | ||
214 | spufs_dump_seek(file, roundup((unsigned long)file->f_pos | ||
215 | - total + sz, 4)); | ||
216 | out: | 215 | out: |
217 | free_page((unsigned long)buf); | 216 | free_page((unsigned long)buf); |
217 | return rc; | ||
218 | } | 218 | } |
219 | 219 | ||
220 | static void spufs_arch_write_notes(struct file *file) | 220 | int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset) |
221 | { | 221 | { |
222 | int j; | 222 | struct spu_context *ctx; |
223 | struct spufs_ctx_info *ctx_info, *next; | 223 | int fd, j, rc; |
224 | 224 | ||
225 | list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) { | 225 | fd = 0; |
226 | spu_acquire_saved(ctx_info->ctx); | 226 | while ((ctx = coredump_next_context(&fd)) != NULL) { |
227 | for (j = 0; j < spufs_coredump_num_notes; j++) | 227 | spu_acquire_saved(ctx); |
228 | spufs_arch_write_note(ctx_info, j, file); | 228 | |
229 | spu_release_saved(ctx_info->ctx); | 229 | for (j = 0; spufs_coredump_read[j].name != NULL; j++) { |
230 | list_del(&ctx_info->list); | 230 | rc = spufs_arch_write_note(ctx, j, file, fd, foffset); |
231 | kfree(ctx_info); | 231 | if (rc) { |
232 | spu_release_saved(ctx); | ||
233 | return rc; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | spu_release_saved(ctx); | ||
232 | } | 238 | } |
233 | } | ||
234 | 239 | ||
235 | struct spu_coredump_calls spufs_coredump_calls = { | 240 | return 0; |
236 | .arch_notes_size = spufs_arch_notes_size, | 241 | } |
237 | .arch_write_notes = spufs_arch_write_notes, | ||
238 | .owner = THIS_MODULE, | ||
239 | }; | ||
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 7de4e919687b..d72b16d6816e 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -199,9 +199,9 @@ static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | #ifdef CONFIG_SPU_FS_64K_LS | 201 | #ifdef CONFIG_SPU_FS_64K_LS |
202 | unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, | 202 | static unsigned long spufs_get_unmapped_area(struct file *file, |
203 | unsigned long len, unsigned long pgoff, | 203 | unsigned long addr, unsigned long len, unsigned long pgoff, |
204 | unsigned long flags) | 204 | unsigned long flags) |
205 | { | 205 | { |
206 | struct spu_context *ctx = file->private_data; | 206 | struct spu_context *ctx = file->private_data; |
207 | struct spu_state *csa = &ctx->csa; | 207 | struct spu_state *csa = &ctx->csa; |
@@ -1076,6 +1076,36 @@ static const struct file_operations spufs_signal2_nosched_fops = { | |||
1076 | .mmap = spufs_signal2_mmap, | 1076 | .mmap = spufs_signal2_mmap, |
1077 | }; | 1077 | }; |
1078 | 1078 | ||
1079 | /* | ||
1080 | * This is a wrapper around DEFINE_SIMPLE_ATTRIBUTE which does the | ||
1081 | * work of acquiring (or not) the SPU context before calling through | ||
1082 | * to the actual get routine. The set routine is called directly. | ||
1083 | */ | ||
1084 | #define SPU_ATTR_NOACQUIRE 0 | ||
1085 | #define SPU_ATTR_ACQUIRE 1 | ||
1086 | #define SPU_ATTR_ACQUIRE_SAVED 2 | ||
1087 | |||
1088 | #define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \ | ||
1089 | static u64 __##__get(void *data) \ | ||
1090 | { \ | ||
1091 | struct spu_context *ctx = data; \ | ||
1092 | u64 ret; \ | ||
1093 | \ | ||
1094 | if (__acquire == SPU_ATTR_ACQUIRE) { \ | ||
1095 | spu_acquire(ctx); \ | ||
1096 | ret = __get(ctx); \ | ||
1097 | spu_release(ctx); \ | ||
1098 | } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \ | ||
1099 | spu_acquire_saved(ctx); \ | ||
1100 | ret = __get(ctx); \ | ||
1101 | spu_release_saved(ctx); \ | ||
1102 | } else \ | ||
1103 | ret = __get(ctx); \ | ||
1104 | \ | ||
1105 | return ret; \ | ||
1106 | } \ | ||
1107 | DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt); | ||
1108 | |||
1079 | static void spufs_signal1_type_set(void *data, u64 val) | 1109 | static void spufs_signal1_type_set(void *data, u64 val) |
1080 | { | 1110 | { |
1081 | struct spu_context *ctx = data; | 1111 | struct spu_context *ctx = data; |
@@ -1085,25 +1115,13 @@ static void spufs_signal1_type_set(void *data, u64 val) | |||
1085 | spu_release(ctx); | 1115 | spu_release(ctx); |
1086 | } | 1116 | } |
1087 | 1117 | ||
1088 | static u64 __spufs_signal1_type_get(void *data) | 1118 | static u64 spufs_signal1_type_get(struct spu_context *ctx) |
1089 | { | 1119 | { |
1090 | struct spu_context *ctx = data; | ||
1091 | return ctx->ops->signal1_type_get(ctx); | 1120 | return ctx->ops->signal1_type_get(ctx); |
1092 | } | 1121 | } |
1122 | DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get, | ||
1123 | spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE); | ||
1093 | 1124 | ||
1094 | static u64 spufs_signal1_type_get(void *data) | ||
1095 | { | ||
1096 | struct spu_context *ctx = data; | ||
1097 | u64 ret; | ||
1098 | |||
1099 | spu_acquire(ctx); | ||
1100 | ret = __spufs_signal1_type_get(data); | ||
1101 | spu_release(ctx); | ||
1102 | |||
1103 | return ret; | ||
1104 | } | ||
1105 | DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get, | ||
1106 | spufs_signal1_type_set, "%llu"); | ||
1107 | 1125 | ||
1108 | static void spufs_signal2_type_set(void *data, u64 val) | 1126 | static void spufs_signal2_type_set(void *data, u64 val) |
1109 | { | 1127 | { |
@@ -1114,25 +1132,12 @@ static void spufs_signal2_type_set(void *data, u64 val) | |||
1114 | spu_release(ctx); | 1132 | spu_release(ctx); |
1115 | } | 1133 | } |
1116 | 1134 | ||
1117 | static u64 __spufs_signal2_type_get(void *data) | 1135 | static u64 spufs_signal2_type_get(struct spu_context *ctx) |
1118 | { | 1136 | { |
1119 | struct spu_context *ctx = data; | ||
1120 | return ctx->ops->signal2_type_get(ctx); | 1137 | return ctx->ops->signal2_type_get(ctx); |
1121 | } | 1138 | } |
1122 | 1139 | DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, | |
1123 | static u64 spufs_signal2_type_get(void *data) | 1140 | spufs_signal2_type_set, "%llu", SPU_ATTR_ACQUIRE); |
1124 | { | ||
1125 | struct spu_context *ctx = data; | ||
1126 | u64 ret; | ||
1127 | |||
1128 | spu_acquire(ctx); | ||
1129 | ret = __spufs_signal2_type_get(data); | ||
1130 | spu_release(ctx); | ||
1131 | |||
1132 | return ret; | ||
1133 | } | ||
1134 | DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, | ||
1135 | spufs_signal2_type_set, "%llu"); | ||
1136 | 1141 | ||
1137 | #if SPUFS_MMAP_4K | 1142 | #if SPUFS_MMAP_4K |
1138 | static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma, | 1143 | static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma, |
@@ -1608,17 +1613,12 @@ static void spufs_npc_set(void *data, u64 val) | |||
1608 | spu_release(ctx); | 1613 | spu_release(ctx); |
1609 | } | 1614 | } |
1610 | 1615 | ||
1611 | static u64 spufs_npc_get(void *data) | 1616 | static u64 spufs_npc_get(struct spu_context *ctx) |
1612 | { | 1617 | { |
1613 | struct spu_context *ctx = data; | 1618 | return ctx->ops->npc_read(ctx); |
1614 | u64 ret; | ||
1615 | spu_acquire(ctx); | ||
1616 | ret = ctx->ops->npc_read(ctx); | ||
1617 | spu_release(ctx); | ||
1618 | return ret; | ||
1619 | } | 1619 | } |
1620 | DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, | 1620 | DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, |
1621 | "0x%llx\n") | 1621 | "0x%llx\n", SPU_ATTR_ACQUIRE); |
1622 | 1622 | ||
1623 | static void spufs_decr_set(void *data, u64 val) | 1623 | static void spufs_decr_set(void *data, u64 val) |
1624 | { | 1624 | { |
@@ -1629,24 +1629,13 @@ static void spufs_decr_set(void *data, u64 val) | |||
1629 | spu_release_saved(ctx); | 1629 | spu_release_saved(ctx); |
1630 | } | 1630 | } |
1631 | 1631 | ||
1632 | static u64 __spufs_decr_get(void *data) | 1632 | static u64 spufs_decr_get(struct spu_context *ctx) |
1633 | { | 1633 | { |
1634 | struct spu_context *ctx = data; | ||
1635 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1634 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1636 | return lscsa->decr.slot[0]; | 1635 | return lscsa->decr.slot[0]; |
1637 | } | 1636 | } |
1638 | 1637 | DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, | |
1639 | static u64 spufs_decr_get(void *data) | 1638 | "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED); |
1640 | { | ||
1641 | struct spu_context *ctx = data; | ||
1642 | u64 ret; | ||
1643 | spu_acquire_saved(ctx); | ||
1644 | ret = __spufs_decr_get(data); | ||
1645 | spu_release_saved(ctx); | ||
1646 | return ret; | ||
1647 | } | ||
1648 | DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, | ||
1649 | "0x%llx\n") | ||
1650 | 1639 | ||
1651 | static void spufs_decr_status_set(void *data, u64 val) | 1640 | static void spufs_decr_status_set(void *data, u64 val) |
1652 | { | 1641 | { |
@@ -1659,26 +1648,16 @@ static void spufs_decr_status_set(void *data, u64 val) | |||
1659 | spu_release_saved(ctx); | 1648 | spu_release_saved(ctx); |
1660 | } | 1649 | } |
1661 | 1650 | ||
1662 | static u64 __spufs_decr_status_get(void *data) | 1651 | static u64 spufs_decr_status_get(struct spu_context *ctx) |
1663 | { | 1652 | { |
1664 | struct spu_context *ctx = data; | ||
1665 | if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING) | 1653 | if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING) |
1666 | return SPU_DECR_STATUS_RUNNING; | 1654 | return SPU_DECR_STATUS_RUNNING; |
1667 | else | 1655 | else |
1668 | return 0; | 1656 | return 0; |
1669 | } | 1657 | } |
1670 | 1658 | DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, | |
1671 | static u64 spufs_decr_status_get(void *data) | 1659 | spufs_decr_status_set, "0x%llx\n", |
1672 | { | 1660 | SPU_ATTR_ACQUIRE_SAVED); |
1673 | struct spu_context *ctx = data; | ||
1674 | u64 ret; | ||
1675 | spu_acquire_saved(ctx); | ||
1676 | ret = __spufs_decr_status_get(data); | ||
1677 | spu_release_saved(ctx); | ||
1678 | return ret; | ||
1679 | } | ||
1680 | DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, | ||
1681 | spufs_decr_status_set, "0x%llx\n") | ||
1682 | 1661 | ||
1683 | static void spufs_event_mask_set(void *data, u64 val) | 1662 | static void spufs_event_mask_set(void *data, u64 val) |
1684 | { | 1663 | { |
@@ -1689,28 +1668,18 @@ static void spufs_event_mask_set(void *data, u64 val) | |||
1689 | spu_release_saved(ctx); | 1668 | spu_release_saved(ctx); |
1690 | } | 1669 | } |
1691 | 1670 | ||
1692 | static u64 __spufs_event_mask_get(void *data) | 1671 | static u64 spufs_event_mask_get(struct spu_context *ctx) |
1693 | { | 1672 | { |
1694 | struct spu_context *ctx = data; | ||
1695 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1673 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1696 | return lscsa->event_mask.slot[0]; | 1674 | return lscsa->event_mask.slot[0]; |
1697 | } | 1675 | } |
1698 | 1676 | ||
1699 | static u64 spufs_event_mask_get(void *data) | 1677 | DEFINE_SPUFS_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, |
1700 | { | 1678 | spufs_event_mask_set, "0x%llx\n", |
1701 | struct spu_context *ctx = data; | 1679 | SPU_ATTR_ACQUIRE_SAVED); |
1702 | u64 ret; | ||
1703 | spu_acquire_saved(ctx); | ||
1704 | ret = __spufs_event_mask_get(data); | ||
1705 | spu_release_saved(ctx); | ||
1706 | return ret; | ||
1707 | } | ||
1708 | DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, | ||
1709 | spufs_event_mask_set, "0x%llx\n") | ||
1710 | 1680 | ||
1711 | static u64 __spufs_event_status_get(void *data) | 1681 | static u64 spufs_event_status_get(struct spu_context *ctx) |
1712 | { | 1682 | { |
1713 | struct spu_context *ctx = data; | ||
1714 | struct spu_state *state = &ctx->csa; | 1683 | struct spu_state *state = &ctx->csa; |
1715 | u64 stat; | 1684 | u64 stat; |
1716 | stat = state->spu_chnlcnt_RW[0]; | 1685 | stat = state->spu_chnlcnt_RW[0]; |
@@ -1718,19 +1687,8 @@ static u64 __spufs_event_status_get(void *data) | |||
1718 | return state->spu_chnldata_RW[0]; | 1687 | return state->spu_chnldata_RW[0]; |
1719 | return 0; | 1688 | return 0; |
1720 | } | 1689 | } |
1721 | 1690 | DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, | |
1722 | static u64 spufs_event_status_get(void *data) | 1691 | NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED) |
1723 | { | ||
1724 | struct spu_context *ctx = data; | ||
1725 | u64 ret = 0; | ||
1726 | |||
1727 | spu_acquire_saved(ctx); | ||
1728 | ret = __spufs_event_status_get(data); | ||
1729 | spu_release_saved(ctx); | ||
1730 | return ret; | ||
1731 | } | ||
1732 | DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, | ||
1733 | NULL, "0x%llx\n") | ||
1734 | 1692 | ||
1735 | static void spufs_srr0_set(void *data, u64 val) | 1693 | static void spufs_srr0_set(void *data, u64 val) |
1736 | { | 1694 | { |
@@ -1741,45 +1699,32 @@ static void spufs_srr0_set(void *data, u64 val) | |||
1741 | spu_release_saved(ctx); | 1699 | spu_release_saved(ctx); |
1742 | } | 1700 | } |
1743 | 1701 | ||
1744 | static u64 spufs_srr0_get(void *data) | 1702 | static u64 spufs_srr0_get(struct spu_context *ctx) |
1745 | { | 1703 | { |
1746 | struct spu_context *ctx = data; | ||
1747 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1704 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1748 | u64 ret; | 1705 | return lscsa->srr0.slot[0]; |
1749 | spu_acquire_saved(ctx); | ||
1750 | ret = lscsa->srr0.slot[0]; | ||
1751 | spu_release_saved(ctx); | ||
1752 | return ret; | ||
1753 | } | 1706 | } |
1754 | DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, | 1707 | DEFINE_SPUFS_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, |
1755 | "0x%llx\n") | 1708 | "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED) |
1756 | 1709 | ||
1757 | static u64 spufs_id_get(void *data) | 1710 | static u64 spufs_id_get(struct spu_context *ctx) |
1758 | { | 1711 | { |
1759 | struct spu_context *ctx = data; | ||
1760 | u64 num; | 1712 | u64 num; |
1761 | 1713 | ||
1762 | spu_acquire(ctx); | ||
1763 | if (ctx->state == SPU_STATE_RUNNABLE) | 1714 | if (ctx->state == SPU_STATE_RUNNABLE) |
1764 | num = ctx->spu->number; | 1715 | num = ctx->spu->number; |
1765 | else | 1716 | else |
1766 | num = (unsigned int)-1; | 1717 | num = (unsigned int)-1; |
1767 | spu_release(ctx); | ||
1768 | 1718 | ||
1769 | return num; | 1719 | return num; |
1770 | } | 1720 | } |
1771 | DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") | 1721 | DEFINE_SPUFS_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n", |
1772 | 1722 | SPU_ATTR_ACQUIRE) | |
1773 | static u64 __spufs_object_id_get(void *data) | ||
1774 | { | ||
1775 | struct spu_context *ctx = data; | ||
1776 | return ctx->object_id; | ||
1777 | } | ||
1778 | 1723 | ||
1779 | static u64 spufs_object_id_get(void *data) | 1724 | static u64 spufs_object_id_get(struct spu_context *ctx) |
1780 | { | 1725 | { |
1781 | /* FIXME: Should there really be no locking here? */ | 1726 | /* FIXME: Should there really be no locking here? */ |
1782 | return __spufs_object_id_get(data); | 1727 | return ctx->object_id; |
1783 | } | 1728 | } |
1784 | 1729 | ||
1785 | static void spufs_object_id_set(void *data, u64 id) | 1730 | static void spufs_object_id_set(void *data, u64 id) |
@@ -1788,27 +1733,15 @@ static void spufs_object_id_set(void *data, u64 id) | |||
1788 | ctx->object_id = id; | 1733 | ctx->object_id = id; |
1789 | } | 1734 | } |
1790 | 1735 | ||
1791 | DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, | 1736 | DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, |
1792 | spufs_object_id_set, "0x%llx\n"); | 1737 | spufs_object_id_set, "0x%llx\n", SPU_ATTR_NOACQUIRE); |
1793 | 1738 | ||
1794 | static u64 __spufs_lslr_get(void *data) | 1739 | static u64 spufs_lslr_get(struct spu_context *ctx) |
1795 | { | 1740 | { |
1796 | struct spu_context *ctx = data; | ||
1797 | return ctx->csa.priv2.spu_lslr_RW; | 1741 | return ctx->csa.priv2.spu_lslr_RW; |
1798 | } | 1742 | } |
1799 | 1743 | DEFINE_SPUFS_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n", | |
1800 | static u64 spufs_lslr_get(void *data) | 1744 | SPU_ATTR_ACQUIRE_SAVED); |
1801 | { | ||
1802 | struct spu_context *ctx = data; | ||
1803 | u64 ret; | ||
1804 | |||
1805 | spu_acquire_saved(ctx); | ||
1806 | ret = __spufs_lslr_get(data); | ||
1807 | spu_release_saved(ctx); | ||
1808 | |||
1809 | return ret; | ||
1810 | } | ||
1811 | DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n") | ||
1812 | 1745 | ||
1813 | static int spufs_info_open(struct inode *inode, struct file *file) | 1746 | static int spufs_info_open(struct inode *inode, struct file *file) |
1814 | { | 1747 | { |
@@ -2231,25 +2164,25 @@ struct tree_descr spufs_dir_nosched_contents[] = { | |||
2231 | }; | 2164 | }; |
2232 | 2165 | ||
2233 | struct spufs_coredump_reader spufs_coredump_read[] = { | 2166 | struct spufs_coredump_reader spufs_coredump_read[] = { |
2234 | { "regs", __spufs_regs_read, NULL, 128 * 16 }, | 2167 | { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])}, |
2235 | { "fpcr", __spufs_fpcr_read, NULL, 16 }, | 2168 | { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) }, |
2236 | { "lslr", NULL, __spufs_lslr_get, 11 }, | 2169 | { "lslr", NULL, spufs_lslr_get, 19 }, |
2237 | { "decr", NULL, __spufs_decr_get, 11 }, | 2170 | { "decr", NULL, spufs_decr_get, 19 }, |
2238 | { "decr_status", NULL, __spufs_decr_status_get, 11 }, | 2171 | { "decr_status", NULL, spufs_decr_status_get, 19 }, |
2239 | { "mem", __spufs_mem_read, NULL, 256 * 1024, }, | 2172 | { "mem", __spufs_mem_read, NULL, LS_SIZE, }, |
2240 | { "signal1", __spufs_signal1_read, NULL, 4 }, | 2173 | { "signal1", __spufs_signal1_read, NULL, sizeof(u32) }, |
2241 | { "signal1_type", NULL, __spufs_signal1_type_get, 2 }, | 2174 | { "signal1_type", NULL, spufs_signal1_type_get, 19 }, |
2242 | { "signal2", __spufs_signal2_read, NULL, 4 }, | 2175 | { "signal2", __spufs_signal2_read, NULL, sizeof(u32) }, |
2243 | { "signal2_type", NULL, __spufs_signal2_type_get, 2 }, | 2176 | { "signal2_type", NULL, spufs_signal2_type_get, 19 }, |
2244 | { "event_mask", NULL, __spufs_event_mask_get, 8 }, | 2177 | { "event_mask", NULL, spufs_event_mask_get, 19 }, |
2245 | { "event_status", NULL, __spufs_event_status_get, 8 }, | 2178 | { "event_status", NULL, spufs_event_status_get, 19 }, |
2246 | { "mbox_info", __spufs_mbox_info_read, NULL, 4 }, | 2179 | { "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) }, |
2247 | { "ibox_info", __spufs_ibox_info_read, NULL, 4 }, | 2180 | { "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) }, |
2248 | { "wbox_info", __spufs_wbox_info_read, NULL, 16 }, | 2181 | { "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)}, |
2249 | { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 }, | 2182 | { "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)}, |
2250 | { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 }, | 2183 | { "proxydma_info", __spufs_proxydma_info_read, |
2251 | { "object-id", NULL, __spufs_object_id_get, 19 }, | 2184 | NULL, sizeof(struct spu_proxydma_info)}, |
2252 | { }, | 2185 | { "object-id", NULL, spufs_object_id_get, 19 }, |
2186 | { "npc", NULL, spufs_npc_get, 19 }, | ||
2187 | { NULL }, | ||
2253 | }; | 2188 | }; |
2254 | int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1; | ||
2255 | |||
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3d0dd118dd0..11098747d09b 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -43,6 +43,7 @@ | |||
43 | 43 | ||
44 | static struct kmem_cache *spufs_inode_cache; | 44 | static struct kmem_cache *spufs_inode_cache; |
45 | char *isolated_loader; | 45 | char *isolated_loader; |
46 | static int isolated_loader_size; | ||
46 | 47 | ||
47 | static struct inode * | 48 | static struct inode * |
48 | spufs_alloc_inode(struct super_block *sb) | 49 | spufs_alloc_inode(struct super_block *sb) |
@@ -667,7 +668,8 @@ spufs_parse_options(char *options, struct inode *root) | |||
667 | 668 | ||
668 | static void spufs_exit_isolated_loader(void) | 669 | static void spufs_exit_isolated_loader(void) |
669 | { | 670 | { |
670 | kfree(isolated_loader); | 671 | free_pages((unsigned long) isolated_loader, |
672 | get_order(isolated_loader_size)); | ||
671 | } | 673 | } |
672 | 674 | ||
673 | static void | 675 | static void |
@@ -685,11 +687,12 @@ spufs_init_isolated_loader(void) | |||
685 | if (!loader) | 687 | if (!loader) |
686 | return; | 688 | return; |
687 | 689 | ||
688 | /* kmalloc should align on a 16 byte boundary..* */ | 690 | /* the loader must be align on a 16 byte boundary */ |
689 | isolated_loader = kmalloc(size, GFP_KERNEL); | 691 | isolated_loader = (char *)__get_free_pages(GFP_KERNEL, get_order(size)); |
690 | if (!isolated_loader) | 692 | if (!isolated_loader) |
691 | return; | 693 | return; |
692 | 694 | ||
695 | isolated_loader_size = size; | ||
693 | memcpy(isolated_loader, loader, size); | 696 | memcpy(isolated_loader, loader, size); |
694 | printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); | 697 | printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); |
695 | } | 698 | } |
@@ -787,16 +790,11 @@ static int __init spufs_init(void) | |||
787 | ret = register_spu_syscalls(&spufs_calls); | 790 | ret = register_spu_syscalls(&spufs_calls); |
788 | if (ret) | 791 | if (ret) |
789 | goto out_fs; | 792 | goto out_fs; |
790 | ret = register_arch_coredump_calls(&spufs_coredump_calls); | ||
791 | if (ret) | ||
792 | goto out_syscalls; | ||
793 | 793 | ||
794 | spufs_init_isolated_loader(); | 794 | spufs_init_isolated_loader(); |
795 | 795 | ||
796 | return 0; | 796 | return 0; |
797 | 797 | ||
798 | out_syscalls: | ||
799 | unregister_spu_syscalls(&spufs_calls); | ||
800 | out_fs: | 798 | out_fs: |
801 | unregister_filesystem(&spufs_type); | 799 | unregister_filesystem(&spufs_type); |
802 | out_sched: | 800 | out_sched: |
@@ -812,7 +810,6 @@ static void __exit spufs_exit(void) | |||
812 | { | 810 | { |
813 | spu_sched_exit(); | 811 | spu_sched_exit(); |
814 | spufs_exit_isolated_loader(); | 812 | spufs_exit_isolated_loader(); |
815 | unregister_arch_coredump_calls(&spufs_coredump_calls); | ||
816 | unregister_spu_syscalls(&spufs_calls); | 813 | unregister_spu_syscalls(&spufs_calls); |
817 | unregister_filesystem(&spufs_type); | 814 | unregister_filesystem(&spufs_type); |
818 | kmem_cache_destroy(spufs_inode_cache); | 815 | kmem_cache_destroy(spufs_inode_cache); |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 958f10e90fdd..1ce5e22ea5f4 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -205,7 +205,7 @@ static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, | |||
205 | * This means we can only do a very rough approximation of POSIX | 205 | * This means we can only do a very rough approximation of POSIX |
206 | * signal semantics. | 206 | * signal semantics. |
207 | */ | 207 | */ |
208 | int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, | 208 | static int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, |
209 | unsigned int *npc) | 209 | unsigned int *npc) |
210 | { | 210 | { |
211 | int ret; | 211 | int ret; |
@@ -241,7 +241,7 @@ int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, | |||
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | 243 | ||
244 | int spu_process_callback(struct spu_context *ctx) | 244 | static int spu_process_callback(struct spu_context *ctx) |
245 | { | 245 | { |
246 | struct spu_syscall_block s; | 246 | struct spu_syscall_block s; |
247 | u32 ls_pointer, npc; | 247 | u32 ls_pointer, npc; |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 5bebe7fbe056..4d257b3f9336 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -230,8 +230,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
230 | 230 | ||
231 | if (ctx->flags & SPU_CREATE_NOSCHED) | 231 | if (ctx->flags & SPU_CREATE_NOSCHED) |
232 | atomic_inc(&cbe_spu_info[spu->node].reserved_spus); | 232 | atomic_inc(&cbe_spu_info[spu->node].reserved_spus); |
233 | if (!list_empty(&ctx->aff_list)) | ||
234 | atomic_inc(&ctx->gang->aff_sched_count); | ||
235 | 233 | ||
236 | ctx->stats.slb_flt_base = spu->stats.slb_flt; | 234 | ctx->stats.slb_flt_base = spu->stats.slb_flt; |
237 | ctx->stats.class2_intr_base = spu->stats.class2_intr; | 235 | ctx->stats.class2_intr_base = spu->stats.class2_intr; |
@@ -392,7 +390,6 @@ static int has_affinity(struct spu_context *ctx) | |||
392 | if (list_empty(&ctx->aff_list)) | 390 | if (list_empty(&ctx->aff_list)) |
393 | return 0; | 391 | return 0; |
394 | 392 | ||
395 | mutex_lock(&gang->aff_mutex); | ||
396 | if (!gang->aff_ref_spu) { | 393 | if (!gang->aff_ref_spu) { |
397 | if (!(gang->aff_flags & AFF_MERGED)) | 394 | if (!(gang->aff_flags & AFF_MERGED)) |
398 | aff_merge_remaining_ctxs(gang); | 395 | aff_merge_remaining_ctxs(gang); |
@@ -400,7 +397,6 @@ static int has_affinity(struct spu_context *ctx) | |||
400 | aff_set_offsets(gang); | 397 | aff_set_offsets(gang); |
401 | aff_set_ref_point_location(gang); | 398 | aff_set_ref_point_location(gang); |
402 | } | 399 | } |
403 | mutex_unlock(&gang->aff_mutex); | ||
404 | 400 | ||
405 | return gang->aff_ref_spu != NULL; | 401 | return gang->aff_ref_spu != NULL; |
406 | } | 402 | } |
@@ -418,9 +414,16 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
418 | 414 | ||
419 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) | 415 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) |
420 | atomic_dec(&cbe_spu_info[spu->node].reserved_spus); | 416 | atomic_dec(&cbe_spu_info[spu->node].reserved_spus); |
421 | if (!list_empty(&ctx->aff_list)) | 417 | |
422 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | 418 | if (ctx->gang){ |
423 | ctx->gang->aff_ref_spu = NULL; | 419 | mutex_lock(&ctx->gang->aff_mutex); |
420 | if (has_affinity(ctx)) { | ||
421 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | ||
422 | ctx->gang->aff_ref_spu = NULL; | ||
423 | } | ||
424 | mutex_unlock(&ctx->gang->aff_mutex); | ||
425 | } | ||
426 | |||
424 | spu_switch_notify(spu, NULL); | 427 | spu_switch_notify(spu, NULL); |
425 | spu_unmap_mappings(ctx); | 428 | spu_unmap_mappings(ctx); |
426 | spu_save(&ctx->csa, spu); | 429 | spu_save(&ctx->csa, spu); |
@@ -511,20 +514,32 @@ static void spu_prio_wait(struct spu_context *ctx) | |||
511 | 514 | ||
512 | static struct spu *spu_get_idle(struct spu_context *ctx) | 515 | static struct spu *spu_get_idle(struct spu_context *ctx) |
513 | { | 516 | { |
514 | struct spu *spu; | 517 | struct spu *spu, *aff_ref_spu; |
515 | int node, n; | 518 | int node, n; |
516 | 519 | ||
517 | if (has_affinity(ctx)) { | 520 | if (ctx->gang) { |
518 | node = ctx->gang->aff_ref_spu->node; | 521 | mutex_lock(&ctx->gang->aff_mutex); |
522 | if (has_affinity(ctx)) { | ||
523 | aff_ref_spu = ctx->gang->aff_ref_spu; | ||
524 | atomic_inc(&ctx->gang->aff_sched_count); | ||
525 | mutex_unlock(&ctx->gang->aff_mutex); | ||
526 | node = aff_ref_spu->node; | ||
519 | 527 | ||
520 | mutex_lock(&cbe_spu_info[node].list_mutex); | 528 | mutex_lock(&cbe_spu_info[node].list_mutex); |
521 | spu = ctx_location(ctx->gang->aff_ref_spu, ctx->aff_offset, node); | 529 | spu = ctx_location(aff_ref_spu, ctx->aff_offset, node); |
522 | if (spu && spu->alloc_state == SPU_FREE) | 530 | if (spu && spu->alloc_state == SPU_FREE) |
523 | goto found; | 531 | goto found; |
524 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 532 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
525 | return NULL; | ||
526 | } | ||
527 | 533 | ||
534 | mutex_lock(&ctx->gang->aff_mutex); | ||
535 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | ||
536 | ctx->gang->aff_ref_spu = NULL; | ||
537 | mutex_unlock(&ctx->gang->aff_mutex); | ||
538 | |||
539 | return NULL; | ||
540 | } | ||
541 | mutex_unlock(&ctx->gang->aff_mutex); | ||
542 | } | ||
528 | node = cpu_to_node(raw_smp_processor_id()); | 543 | node = cpu_to_node(raw_smp_processor_id()); |
529 | for (n = 0; n < MAX_NUMNODES; n++, node++) { | 544 | for (n = 0; n < MAX_NUMNODES; n++, node++) { |
530 | node = (node < MAX_NUMNODES) ? node : 0; | 545 | node = (node < MAX_NUMNODES) ? node : 0; |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 2bfdeb8ea8bd..ca47b991bda5 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -200,9 +200,14 @@ extern struct tree_descr spufs_dir_contents[]; | |||
200 | extern struct tree_descr spufs_dir_nosched_contents[]; | 200 | extern struct tree_descr spufs_dir_nosched_contents[]; |
201 | 201 | ||
202 | /* system call implementation */ | 202 | /* system call implementation */ |
203 | extern struct spufs_calls spufs_calls; | ||
203 | long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); | 204 | long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); |
204 | long spufs_create(struct nameidata *nd, unsigned int flags, | 205 | long spufs_create(struct nameidata *nd, unsigned int flags, |
205 | mode_t mode, struct file *filp); | 206 | mode_t mode, struct file *filp); |
207 | /* ELF coredump callbacks for writing SPU ELF notes */ | ||
208 | extern int spufs_coredump_extra_notes_size(void); | ||
209 | extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset); | ||
210 | |||
206 | extern const struct file_operations spufs_context_fops; | 211 | extern const struct file_operations spufs_context_fops; |
207 | 212 | ||
208 | /* gang management */ | 213 | /* gang management */ |
@@ -295,7 +300,7 @@ struct spufs_coredump_reader { | |||
295 | char *name; | 300 | char *name; |
296 | ssize_t (*read)(struct spu_context *ctx, | 301 | ssize_t (*read)(struct spu_context *ctx, |
297 | char __user *buffer, size_t size, loff_t *pos); | 302 | char __user *buffer, size_t size, loff_t *pos); |
298 | u64 (*get)(void *data); | 303 | u64 (*get)(struct spu_context *ctx); |
299 | size_t size; | 304 | size_t size; |
300 | }; | 305 | }; |
301 | extern struct spufs_coredump_reader spufs_coredump_read[]; | 306 | extern struct spufs_coredump_reader spufs_coredump_read[]; |
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 27ffdae98e5a..3d64c81cc6e2 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -699,7 +699,7 @@ static inline void get_kernel_slb(u64 ea, u64 slb[2]) | |||
699 | llp = mmu_psize_defs[mmu_linear_psize].sllp; | 699 | llp = mmu_psize_defs[mmu_linear_psize].sllp; |
700 | else | 700 | else |
701 | llp = mmu_psize_defs[mmu_virtual_psize].sllp; | 701 | llp = mmu_psize_defs[mmu_virtual_psize].sllp; |
702 | slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | | 702 | slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | |
703 | SLB_VSID_KERNEL | llp; | 703 | SLB_VSID_KERNEL | llp; |
704 | slb[1] = (ea & ESID_MASK) | SLB_ESID_V; | 704 | slb[1] = (ea & ESID_MASK) | SLB_ESID_V; |
705 | } | 705 | } |
@@ -1559,15 +1559,15 @@ static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu) | |||
1559 | * "wrapped" flag is set, OR in a '1' to | 1559 | * "wrapped" flag is set, OR in a '1' to |
1560 | * CSA.SPU_Event_Status[Tm]. | 1560 | * CSA.SPU_Event_Status[Tm]. |
1561 | */ | 1561 | */ |
1562 | if (csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED) { | 1562 | if (!(csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED)) |
1563 | csa->spu_chnldata_RW[0] |= 0x20; | 1563 | return; |
1564 | } | 1564 | |
1565 | if ((csa->lscsa->decr_status.slot[0] & SPU_DECR_STATUS_WRAPPED) && | 1565 | if ((csa->spu_chnlcnt_RW[0] == 0) && |
1566 | (csa->spu_chnlcnt_RW[0] == 0 && | 1566 | (csa->spu_chnldata_RW[1] & 0x20) && |
1567 | ((csa->spu_chnldata_RW[2] & 0x20) == 0x0) && | 1567 | !(csa->spu_chnldata_RW[0] & 0x20)) |
1568 | ((csa->spu_chnldata_RW[0] & 0x20) != 0x1))) { | ||
1569 | csa->spu_chnlcnt_RW[0] = 1; | 1568 | csa->spu_chnlcnt_RW[0] = 1; |
1570 | } | 1569 | |
1570 | csa->spu_chnldata_RW[0] |= 0x20; | ||
1571 | } | 1571 | } |
1572 | 1572 | ||
1573 | static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu) | 1573 | static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu) |
@@ -2146,19 +2146,6 @@ int spu_restore(struct spu_state *new, struct spu *spu) | |||
2146 | } | 2146 | } |
2147 | EXPORT_SYMBOL_GPL(spu_restore); | 2147 | EXPORT_SYMBOL_GPL(spu_restore); |
2148 | 2148 | ||
2149 | /** | ||
2150 | * spu_harvest - SPU harvest (reset) operation | ||
2151 | * @spu: pointer to SPU iomem structure. | ||
2152 | * | ||
2153 | * Perform SPU harvest (reset) operation. | ||
2154 | */ | ||
2155 | void spu_harvest(struct spu *spu) | ||
2156 | { | ||
2157 | acquire_spu_lock(spu); | ||
2158 | harvest(NULL, spu); | ||
2159 | release_spu_lock(spu); | ||
2160 | } | ||
2161 | |||
2162 | static void init_prob(struct spu_state *csa) | 2149 | static void init_prob(struct spu_state *csa) |
2163 | { | 2150 | { |
2164 | csa->spu_chnlcnt_RW[9] = 1; | 2151 | csa->spu_chnlcnt_RW[9] = 1; |
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index 43f0fb88abbc..2c34f7170190 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c | |||
@@ -58,26 +58,8 @@ out: | |||
58 | return ret; | 58 | return ret; |
59 | } | 59 | } |
60 | 60 | ||
61 | #ifndef MODULE | 61 | static long do_spu_create(const char __user *pathname, unsigned int flags, |
62 | asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) | 62 | mode_t mode, struct file *neighbor) |
63 | { | ||
64 | int fput_needed; | ||
65 | struct file *filp; | ||
66 | long ret; | ||
67 | |||
68 | ret = -EBADF; | ||
69 | filp = fget_light(fd, &fput_needed); | ||
70 | if (filp) { | ||
71 | ret = do_spu_run(filp, unpc, ustatus); | ||
72 | fput_light(filp, fput_needed); | ||
73 | } | ||
74 | |||
75 | return ret; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | asmlinkage long do_spu_create(const char __user *pathname, unsigned int flags, | ||
80 | mode_t mode, struct file *neighbor) | ||
81 | { | 63 | { |
82 | char *tmp; | 64 | char *tmp; |
83 | int ret; | 65 | int ret; |
@@ -99,32 +81,10 @@ asmlinkage long do_spu_create(const char __user *pathname, unsigned int flags, | |||
99 | return ret; | 81 | return ret; |
100 | } | 82 | } |
101 | 83 | ||
102 | #ifndef MODULE | ||
103 | asmlinkage long sys_spu_create(const char __user *pathname, unsigned int flags, | ||
104 | mode_t mode, int neighbor_fd) | ||
105 | { | ||
106 | int fput_needed; | ||
107 | struct file *neighbor; | ||
108 | long ret; | ||
109 | |||
110 | if (flags & SPU_CREATE_AFFINITY_SPU) { | ||
111 | ret = -EBADF; | ||
112 | neighbor = fget_light(neighbor_fd, &fput_needed); | ||
113 | if (neighbor) { | ||
114 | ret = do_spu_create(pathname, flags, mode, neighbor); | ||
115 | fput_light(neighbor, fput_needed); | ||
116 | } | ||
117 | } | ||
118 | else { | ||
119 | ret = do_spu_create(pathname, flags, mode, NULL); | ||
120 | } | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | #endif | ||
125 | |||
126 | struct spufs_calls spufs_calls = { | 84 | struct spufs_calls spufs_calls = { |
127 | .create_thread = do_spu_create, | 85 | .create_thread = do_spu_create, |
128 | .spu_run = do_spu_run, | 86 | .spu_run = do_spu_run, |
87 | .coredump_extra_notes_size = spufs_coredump_extra_notes_size, | ||
88 | .coredump_extra_notes_write = spufs_coredump_extra_notes_write, | ||
129 | .owner = THIS_MODULE, | 89 | .owner = THIS_MODULE, |
130 | }; | 90 | }; |
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig index 2db1e293433e..04748d410fc9 100644 --- a/arch/powerpc/platforms/celleb/Kconfig +++ b/arch/powerpc/platforms/celleb/Kconfig | |||
@@ -2,6 +2,7 @@ config PPC_CELLEB | |||
2 | bool "Toshiba's Cell Reference Set 'Celleb' Architecture" | 2 | bool "Toshiba's Cell Reference Set 'Celleb' Architecture" |
3 | depends on PPC_MULTIPLATFORM && PPC64 | 3 | depends on PPC_MULTIPLATFORM && PPC64 |
4 | select PPC_CELL | 4 | select PPC_CELL |
5 | select PPC_INDIRECT_IO | ||
5 | select PPC_OF_PLATFORM_PCI | 6 | select PPC_OF_PLATFORM_PCI |
6 | select HAS_TXX9_SERIAL | 7 | select HAS_TXX9_SERIAL |
7 | select PPC_UDBG_BEAT | 8 | select PPC_UDBG_BEAT |
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile index 5240046d8671..889d43f715ea 100644 --- a/arch/powerpc/platforms/celleb/Makefile +++ b/arch/powerpc/platforms/celleb/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-y += interrupt.o iommu.o setup.o \ | 1 | obj-y += interrupt.o iommu.o setup.o \ |
2 | htab.o beat.o pci.o \ | 2 | htab.o beat.o hvCall.o pci.o \ |
3 | scc_epci.o scc_uhc.o hvCall.o | 3 | scc_epci.o scc_uhc.o \ |
4 | io-workarounds.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_SMP) += smp.o | 6 | obj-$(CONFIG_SMP) += smp.o |
6 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o | 7 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o |
diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/celleb/beat.c index 99341ce8a697..93ebb7d85120 100644 --- a/arch/powerpc/platforms/celleb/beat.c +++ b/arch/powerpc/platforms/celleb/beat.c | |||
@@ -22,16 +22,24 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/rtc.h> | 24 | #include <linux/rtc.h> |
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/irqreturn.h> | ||
27 | #include <linux/reboot.h> | ||
25 | 28 | ||
26 | #include <asm/hvconsole.h> | 29 | #include <asm/hvconsole.h> |
27 | #include <asm/time.h> | 30 | #include <asm/time.h> |
31 | #include <asm/machdep.h> | ||
32 | #include <asm/firmware.h> | ||
28 | 33 | ||
29 | #include "beat_wrapper.h" | 34 | #include "beat_wrapper.h" |
30 | #include "beat.h" | 35 | #include "beat.h" |
36 | #include "interrupt.h" | ||
37 | |||
38 | static int beat_pm_poweroff_flag; | ||
31 | 39 | ||
32 | void beat_restart(char *cmd) | 40 | void beat_restart(char *cmd) |
33 | { | 41 | { |
34 | beat_shutdown_logical_partition(1); | 42 | beat_shutdown_logical_partition(!beat_pm_poweroff_flag); |
35 | } | 43 | } |
36 | 44 | ||
37 | void beat_power_off(void) | 45 | void beat_power_off(void) |
@@ -158,6 +166,102 @@ int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2) | |||
158 | return beat_put_characters_to_console(vterm, len, (u8*)db); | 166 | return beat_put_characters_to_console(vterm, len, (u8*)db); |
159 | } | 167 | } |
160 | 168 | ||
169 | void beat_power_save(void) | ||
170 | { | ||
171 | beat_pause(0); | ||
172 | } | ||
173 | |||
174 | #ifdef CONFIG_KEXEC | ||
175 | void beat_kexec_cpu_down(int crash, int secondary) | ||
176 | { | ||
177 | beatic_deinit_IRQ(); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | static irqreturn_t beat_power_event(int virq, void *arg) | ||
182 | { | ||
183 | printk(KERN_DEBUG "Beat: power button pressed\n"); | ||
184 | beat_pm_poweroff_flag = 1; | ||
185 | ctrl_alt_del(); | ||
186 | return IRQ_HANDLED; | ||
187 | } | ||
188 | |||
189 | static irqreturn_t beat_reset_event(int virq, void *arg) | ||
190 | { | ||
191 | printk(KERN_DEBUG "Beat: reset button pressed\n"); | ||
192 | beat_pm_poweroff_flag = 0; | ||
193 | ctrl_alt_del(); | ||
194 | return IRQ_HANDLED; | ||
195 | } | ||
196 | |||
197 | static struct beat_event_list { | ||
198 | const char *typecode; | ||
199 | irq_handler_t handler; | ||
200 | unsigned int virq; | ||
201 | } beat_event_list[] = { | ||
202 | { "power", beat_power_event, 0 }, | ||
203 | { "reset", beat_reset_event, 0 }, | ||
204 | }; | ||
205 | |||
206 | static int __init beat_register_event(void) | ||
207 | { | ||
208 | u64 path[4], data[2]; | ||
209 | int rc, i; | ||
210 | unsigned int virq; | ||
211 | |||
212 | for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) { | ||
213 | struct beat_event_list *ev = &beat_event_list[i]; | ||
214 | |||
215 | if (beat_construct_event_receive_port(data) != 0) { | ||
216 | printk(KERN_ERR "Beat: " | ||
217 | "cannot construct event receive port for %s\n", | ||
218 | ev->typecode); | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | virq = irq_create_mapping(NULL, data[0]); | ||
223 | if (virq == NO_IRQ) { | ||
224 | printk(KERN_ERR "Beat: failed to get virtual IRQ" | ||
225 | " for event receive port for %s\n", | ||
226 | ev->typecode); | ||
227 | beat_destruct_event_receive_port(data[0]); | ||
228 | return -EIO; | ||
229 | } | ||
230 | ev->virq = virq; | ||
231 | |||
232 | rc = request_irq(virq, ev->handler, IRQF_DISABLED, | ||
233 | ev->typecode, NULL); | ||
234 | if (rc != 0) { | ||
235 | printk(KERN_ERR "Beat: failed to request virtual IRQ" | ||
236 | " for event receive port for %s\n", | ||
237 | ev->typecode); | ||
238 | beat_destruct_event_receive_port(data[0]); | ||
239 | return rc; | ||
240 | } | ||
241 | |||
242 | path[0] = 0x1000000065780000ul; /* 1,ex */ | ||
243 | path[1] = 0x627574746f6e0000ul; /* button */ | ||
244 | path[2] = 0; | ||
245 | strncpy((char *)&path[2], ev->typecode, 8); | ||
246 | path[3] = 0; | ||
247 | data[1] = 0; | ||
248 | |||
249 | beat_create_repository_node(path, data); | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int __init beat_event_init(void) | ||
255 | { | ||
256 | if (!firmware_has_feature(FW_FEATURE_BEAT)) | ||
257 | return -EINVAL; | ||
258 | |||
259 | beat_pm_poweroff_flag = 0; | ||
260 | return beat_register_event(); | ||
261 | } | ||
262 | |||
263 | device_initcall(beat_event_init); | ||
264 | |||
161 | EXPORT_SYMBOL(beat_get_term_char); | 265 | EXPORT_SYMBOL(beat_get_term_char); |
162 | EXPORT_SYMBOL(beat_put_term_char); | 266 | EXPORT_SYMBOL(beat_put_term_char); |
163 | EXPORT_SYMBOL(beat_halt_code); | 267 | EXPORT_SYMBOL(beat_halt_code); |
diff --git a/arch/powerpc/platforms/celleb/beat.h b/arch/powerpc/platforms/celleb/beat.h index 2b16bf3bee89..b2e292df13ca 100644 --- a/arch/powerpc/platforms/celleb/beat.h +++ b/arch/powerpc/platforms/celleb/beat.h | |||
@@ -36,5 +36,7 @@ ssize_t beat_nvram_get_size(void); | |||
36 | ssize_t beat_nvram_read(char *, size_t, loff_t *); | 36 | ssize_t beat_nvram_read(char *, size_t, loff_t *); |
37 | ssize_t beat_nvram_write(char *, size_t, loff_t *); | 37 | ssize_t beat_nvram_write(char *, size_t, loff_t *); |
38 | int beat_set_xdabr(unsigned long); | 38 | int beat_set_xdabr(unsigned long); |
39 | void beat_power_save(void); | ||
40 | void beat_kexec_cpu_down(int, int); | ||
39 | 41 | ||
40 | #endif /* _CELLEB_BEAT_H */ | 42 | #endif /* _CELLEB_BEAT_H */ |
diff --git a/arch/powerpc/platforms/celleb/beat_syscall.h b/arch/powerpc/platforms/celleb/beat_syscall.h index 14e16974773f..8580dc7e1798 100644 --- a/arch/powerpc/platforms/celleb/beat_syscall.h +++ b/arch/powerpc/platforms/celleb/beat_syscall.h | |||
@@ -157,4 +157,8 @@ | |||
157 | #define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1) | 157 | #define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1) |
158 | #define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1) | 158 | #define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1) |
159 | #define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1) | 159 | #define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1) |
160 | #define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1) | ||
161 | #define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1) | ||
162 | #define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1) | ||
163 | #define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1) | ||
160 | #endif | 164 | #endif |
diff --git a/arch/powerpc/platforms/celleb/beat_wrapper.h b/arch/powerpc/platforms/celleb/beat_wrapper.h index 76ea0a6a9011..cbc1487df7de 100644 --- a/arch/powerpc/platforms/celleb/beat_wrapper.h +++ b/arch/powerpc/platforms/celleb/beat_wrapper.h | |||
@@ -98,6 +98,37 @@ static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot, | |||
98 | return ret; | 98 | return ret; |
99 | } | 99 | } |
100 | 100 | ||
101 | static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group, | ||
102 | u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot) | ||
103 | { | ||
104 | u64 dummy[1]; | ||
105 | s64 ret; | ||
106 | |||
107 | ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group, | ||
108 | hpte_v, hpte_r, mask_v, value_v); | ||
109 | *slot = dummy[0]; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group, | ||
114 | u64 va, u64 pss) | ||
115 | { | ||
116 | return beat_hcall_norets(HV_invalidate_htab_entry3, | ||
117 | htab_id, group, va, pss); | ||
118 | } | ||
119 | |||
120 | static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group, | ||
121 | u64 va, u64 pss, u64 ptel_mask, u64 ptel_value) | ||
122 | { | ||
123 | return beat_hcall_norets(HV_update_htab_permission3, | ||
124 | htab_id, group, va, pss, ptel_mask, ptel_value); | ||
125 | } | ||
126 | |||
127 | static inline s64 beat_clear_htab3(u64 htab_id) | ||
128 | { | ||
129 | return beat_hcall_norets(HV_clear_htab3, htab_id); | ||
130 | } | ||
131 | |||
101 | static inline void beat_shutdown_logical_partition(u64 code) | 132 | static inline void beat_shutdown_logical_partition(u64 code) |
102 | { | 133 | { |
103 | (void)beat_hcall_norets(HV_shutdown_logical_partition, code); | 134 | (void)beat_hcall_norets(HV_shutdown_logical_partition, code); |
@@ -217,4 +248,41 @@ static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr, | |||
217 | ioid, flags); | 248 | ioid, flags); |
218 | } | 249 | } |
219 | 250 | ||
251 | static inline s64 beat_construct_event_receive_port(u64 *port) | ||
252 | { | ||
253 | u64 dummy[1]; | ||
254 | s64 ret; | ||
255 | |||
256 | ret = beat_hcall1(HV_construct_event_receive_port, dummy); | ||
257 | *port = dummy[0]; | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static inline s64 beat_destruct_event_receive_port(u64 port) | ||
262 | { | ||
263 | s64 ret; | ||
264 | |||
265 | ret = beat_hcall_norets(HV_destruct_event_receive_port, port); | ||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static inline s64 beat_create_repository_node(u64 path[4], u64 data[2]) | ||
270 | { | ||
271 | s64 ret; | ||
272 | |||
273 | ret = beat_hcall_norets(HV_create_repository_node2, | ||
274 | path[0], path[1], path[2], path[3], data[0], data[1]); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4], | ||
279 | u64 data[2]) | ||
280 | { | ||
281 | s64 ret; | ||
282 | |||
283 | ret = beat_hcall2(HV_get_repository_node_value2, data, | ||
284 | lpid, path[0], path[1], path[2], path[3]); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
220 | #endif | 288 | #endif |
diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c index 279d7339e170..fbf27c74ebda 100644 --- a/arch/powerpc/platforms/celleb/htab.c +++ b/arch/powerpc/platforms/celleb/htab.c | |||
@@ -90,7 +90,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group) | |||
90 | static long beat_lpar_hpte_insert(unsigned long hpte_group, | 90 | static long beat_lpar_hpte_insert(unsigned long hpte_group, |
91 | unsigned long va, unsigned long pa, | 91 | unsigned long va, unsigned long pa, |
92 | unsigned long rflags, unsigned long vflags, | 92 | unsigned long rflags, unsigned long vflags, |
93 | int psize) | 93 | int psize, int ssize) |
94 | { | 94 | { |
95 | unsigned long lpar_rc; | 95 | unsigned long lpar_rc; |
96 | unsigned long slot; | 96 | unsigned long slot; |
@@ -105,7 +105,8 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group, | |||
105 | "rflags=%lx, vflags=%lx, psize=%d)\n", | 105 | "rflags=%lx, vflags=%lx, psize=%d)\n", |
106 | hpte_group, va, pa, rflags, vflags, psize); | 106 | hpte_group, va, pa, rflags, vflags, psize); |
107 | 107 | ||
108 | hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; | 108 | hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) | |
109 | vflags | HPTE_V_VALID; | ||
109 | hpte_r = hpte_encode_r(pa, psize) | rflags; | 110 | hpte_r = hpte_encode_r(pa, psize) | rflags; |
110 | 111 | ||
111 | if (!(vflags & HPTE_V_BOLTED)) | 112 | if (!(vflags & HPTE_V_BOLTED)) |
@@ -184,12 +185,12 @@ static void beat_lpar_hptab_clear(void) | |||
184 | static long beat_lpar_hpte_updatepp(unsigned long slot, | 185 | static long beat_lpar_hpte_updatepp(unsigned long slot, |
185 | unsigned long newpp, | 186 | unsigned long newpp, |
186 | unsigned long va, | 187 | unsigned long va, |
187 | int psize, int local) | 188 | int psize, int ssize, int local) |
188 | { | 189 | { |
189 | unsigned long lpar_rc; | 190 | unsigned long lpar_rc; |
190 | unsigned long dummy0, dummy1, want_v; | 191 | unsigned long dummy0, dummy1, want_v; |
191 | 192 | ||
192 | want_v = hpte_encode_v(va, psize); | 193 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
193 | 194 | ||
194 | DBG_LOW(" update: " | 195 | DBG_LOW(" update: " |
195 | "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", | 196 | "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", |
@@ -225,8 +226,8 @@ static long beat_lpar_hpte_find(unsigned long va, int psize) | |||
225 | long slot; | 226 | long slot; |
226 | unsigned long want_v, hpte_v; | 227 | unsigned long want_v, hpte_v; |
227 | 228 | ||
228 | hash = hpt_hash(va, mmu_psize_defs[psize].shift); | 229 | hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M); |
229 | want_v = hpte_encode_v(va, psize); | 230 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
230 | 231 | ||
231 | for (j = 0; j < 2; j++) { | 232 | for (j = 0; j < 2; j++) { |
232 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 233 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
@@ -251,11 +252,11 @@ static long beat_lpar_hpte_find(unsigned long va, int psize) | |||
251 | 252 | ||
252 | static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, | 253 | static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, |
253 | unsigned long ea, | 254 | unsigned long ea, |
254 | int psize) | 255 | int psize, int ssize) |
255 | { | 256 | { |
256 | unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1; | 257 | unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1; |
257 | 258 | ||
258 | vsid = get_kernel_vsid(ea); | 259 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); |
259 | va = (vsid << 28) | (ea & 0x0fffffff); | 260 | va = (vsid << 28) | (ea & 0x0fffffff); |
260 | 261 | ||
261 | spin_lock(&beat_htab_lock); | 262 | spin_lock(&beat_htab_lock); |
@@ -270,7 +271,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, | |||
270 | } | 271 | } |
271 | 272 | ||
272 | static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | 273 | static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, |
273 | int psize, int local) | 274 | int psize, int ssize, int local) |
274 | { | 275 | { |
275 | unsigned long want_v; | 276 | unsigned long want_v; |
276 | unsigned long lpar_rc; | 277 | unsigned long lpar_rc; |
@@ -279,7 +280,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
279 | 280 | ||
280 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", | 281 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", |
281 | slot, va, psize, local); | 282 | slot, va, psize, local); |
282 | want_v = hpte_encode_v(va, psize); | 283 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
283 | 284 | ||
284 | spin_lock_irqsave(&beat_htab_lock, flags); | 285 | spin_lock_irqsave(&beat_htab_lock, flags); |
285 | dummy1 = beat_lpar_hpte_getword0(slot); | 286 | dummy1 = beat_lpar_hpte_getword0(slot); |
@@ -306,3 +307,134 @@ void __init hpte_init_beat(void) | |||
306 | ppc_md.hpte_remove = beat_lpar_hpte_remove; | 307 | ppc_md.hpte_remove = beat_lpar_hpte_remove; |
307 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear; | 308 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear; |
308 | } | 309 | } |
310 | |||
311 | static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, | ||
312 | unsigned long va, unsigned long pa, | ||
313 | unsigned long rflags, unsigned long vflags, | ||
314 | int psize, int ssize) | ||
315 | { | ||
316 | unsigned long lpar_rc; | ||
317 | unsigned long slot; | ||
318 | unsigned long hpte_v, hpte_r; | ||
319 | |||
320 | /* same as iseries */ | ||
321 | if (vflags & HPTE_V_SECONDARY) | ||
322 | return -1; | ||
323 | |||
324 | if (!(vflags & HPTE_V_BOLTED)) | ||
325 | DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " | ||
326 | "rflags=%lx, vflags=%lx, psize=%d)\n", | ||
327 | hpte_group, va, pa, rflags, vflags, psize); | ||
328 | |||
329 | hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) | | ||
330 | vflags | HPTE_V_VALID; | ||
331 | hpte_r = hpte_encode_r(pa, psize) | rflags; | ||
332 | |||
333 | if (!(vflags & HPTE_V_BOLTED)) | ||
334 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); | ||
335 | |||
336 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) | ||
337 | hpte_r &= ~_PAGE_COHERENT; | ||
338 | |||
339 | /* insert into not-volted entry */ | ||
340 | lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r, | ||
341 | HPTE_V_BOLTED, 0, &slot); | ||
342 | /* | ||
343 | * Since we try and ioremap PHBs we don't own, the pte insert | ||
344 | * will fail. However we must catch the failure in hash_page | ||
345 | * or we will loop forever, so return -2 in this case. | ||
346 | */ | ||
347 | if (unlikely(lpar_rc != 0)) { | ||
348 | if (!(vflags & HPTE_V_BOLTED)) | ||
349 | DBG_LOW(" lpar err %lx\n", lpar_rc); | ||
350 | return -2; | ||
351 | } | ||
352 | if (!(vflags & HPTE_V_BOLTED)) | ||
353 | DBG_LOW(" -> slot: %lx\n", slot); | ||
354 | |||
355 | /* We have to pass down the secondary bucket bit here as well */ | ||
356 | return (slot ^ hpte_group) & 15; | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and | ||
361 | * the low 3 bits of flags happen to line up. So no transform is needed. | ||
362 | * We can probably optimize here and assume the high bits of newpp are | ||
363 | * already zero. For now I am paranoid. | ||
364 | */ | ||
365 | static long beat_lpar_hpte_updatepp_v3(unsigned long slot, | ||
366 | unsigned long newpp, | ||
367 | unsigned long va, | ||
368 | int psize, int ssize, int local) | ||
369 | { | ||
370 | unsigned long lpar_rc; | ||
371 | unsigned long want_v; | ||
372 | unsigned long pss; | ||
373 | |||
374 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); | ||
375 | pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc; | ||
376 | |||
377 | DBG_LOW(" update: " | ||
378 | "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", | ||
379 | want_v & HPTE_V_AVPN, slot, psize, newpp); | ||
380 | |||
381 | lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp); | ||
382 | |||
383 | if (lpar_rc == 0xfffffff7) { | ||
384 | DBG_LOW("not found !\n"); | ||
385 | return -1; | ||
386 | } | ||
387 | |||
388 | DBG_LOW("ok\n"); | ||
389 | |||
390 | BUG_ON(lpar_rc != 0); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va, | ||
396 | int psize, int ssize, int local) | ||
397 | { | ||
398 | unsigned long want_v; | ||
399 | unsigned long lpar_rc; | ||
400 | unsigned long pss; | ||
401 | |||
402 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", | ||
403 | slot, va, psize, local); | ||
404 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); | ||
405 | pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc; | ||
406 | |||
407 | lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss); | ||
408 | |||
409 | /* E_busy can be valid output: page may be already replaced */ | ||
410 | BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7); | ||
411 | } | ||
412 | |||
413 | static int64_t _beat_lpar_hptab_clear_v3(void) | ||
414 | { | ||
415 | return beat_clear_htab3(0); | ||
416 | } | ||
417 | |||
418 | static void beat_lpar_hptab_clear_v3(void) | ||
419 | { | ||
420 | _beat_lpar_hptab_clear_v3(); | ||
421 | } | ||
422 | |||
423 | void __init hpte_init_beat_v3(void) | ||
424 | { | ||
425 | if (_beat_lpar_hptab_clear_v3() == 0) { | ||
426 | ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate_v3; | ||
427 | ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp_v3; | ||
428 | ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; | ||
429 | ppc_md.hpte_insert = beat_lpar_hpte_insert_v3; | ||
430 | ppc_md.hpte_remove = beat_lpar_hpte_remove; | ||
431 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear_v3; | ||
432 | } else { | ||
433 | ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate; | ||
434 | ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp; | ||
435 | ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; | ||
436 | ppc_md.hpte_insert = beat_lpar_hpte_insert; | ||
437 | ppc_md.hpte_remove = beat_lpar_hpte_remove; | ||
438 | ppc_md.hpte_clear_all = beat_lpar_hptab_clear; | ||
439 | } | ||
440 | } | ||
diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/celleb/interrupt.c index 98e6665681d3..c7c68ca70c82 100644 --- a/arch/powerpc/platforms/celleb/interrupt.c +++ b/arch/powerpc/platforms/celleb/interrupt.c | |||
@@ -175,11 +175,18 @@ static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct, | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static int beatic_pic_host_match(struct irq_host *h, struct device_node *np) | ||
179 | { | ||
180 | /* Match all */ | ||
181 | return 1; | ||
182 | } | ||
183 | |||
178 | static struct irq_host_ops beatic_pic_host_ops = { | 184 | static struct irq_host_ops beatic_pic_host_ops = { |
179 | .map = beatic_pic_host_map, | 185 | .map = beatic_pic_host_map, |
180 | .remap = beatic_pic_host_remap, | 186 | .remap = beatic_pic_host_remap, |
181 | .unmap = beatic_pic_host_unmap, | 187 | .unmap = beatic_pic_host_unmap, |
182 | .xlate = beatic_pic_host_xlate, | 188 | .xlate = beatic_pic_host_xlate, |
189 | .match = beatic_pic_host_match, | ||
183 | }; | 190 | }; |
184 | 191 | ||
185 | /* | 192 | /* |
@@ -242,7 +249,7 @@ void __init beatic_init_IRQ(void) | |||
242 | ppc_md.get_irq = beatic_get_irq; | 249 | ppc_md.get_irq = beatic_get_irq; |
243 | 250 | ||
244 | /* Allocate an irq host */ | 251 | /* Allocate an irq host */ |
245 | beatic_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, | 252 | beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, |
246 | &beatic_pic_host_ops, | 253 | &beatic_pic_host_ops, |
247 | 0); | 254 | 0); |
248 | BUG_ON(beatic_host == NULL); | 255 | BUG_ON(beatic_host == NULL); |
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c new file mode 100644 index 000000000000..2b912140bcbb --- /dev/null +++ b/arch/powerpc/platforms/celleb/io-workarounds.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * Support for Celleb io workarounds | ||
3 | * | ||
4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION | ||
5 | * | ||
6 | * This file is based to arch/powerpc/platform/cell/io-workarounds.c | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | */ | ||
22 | |||
23 | #undef DEBUG | ||
24 | |||
25 | #include <linux/of_device.h> | ||
26 | #include <linux/irq.h> | ||
27 | |||
28 | #include <asm/io.h> | ||
29 | #include <asm/prom.h> | ||
30 | #include <asm/machdep.h> | ||
31 | #include <asm/pci-bridge.h> | ||
32 | #include <asm/ppc-pci.h> | ||
33 | |||
34 | #include "pci.h" | ||
35 | |||
36 | #define MAX_CELLEB_PCI_BUS 4 | ||
37 | |||
38 | void *celleb_dummy_page_va; | ||
39 | |||
40 | static struct celleb_pci_bus { | ||
41 | struct pci_controller *phb; | ||
42 | void (*dummy_read)(struct pci_controller *); | ||
43 | } celleb_pci_busses[MAX_CELLEB_PCI_BUS]; | ||
44 | |||
45 | static int celleb_pci_count = 0; | ||
46 | |||
47 | static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr, | ||
48 | unsigned long paddr) | ||
49 | { | ||
50 | int i, j; | ||
51 | struct resource *res; | ||
52 | |||
53 | for (i = 0; i < celleb_pci_count; i++) { | ||
54 | struct celleb_pci_bus *bus = &celleb_pci_busses[i]; | ||
55 | struct pci_controller *phb = bus->phb; | ||
56 | if (paddr) | ||
57 | for (j = 0; j < 3; j++) { | ||
58 | res = &phb->mem_resources[j]; | ||
59 | if (paddr >= res->start && paddr <= res->end) | ||
60 | return bus; | ||
61 | } | ||
62 | res = &phb->io_resource; | ||
63 | if (vaddr && vaddr >= res->start && vaddr <= res->end) | ||
64 | return bus; | ||
65 | } | ||
66 | return NULL; | ||
67 | } | ||
68 | |||
69 | static void celleb_io_flush(const PCI_IO_ADDR addr) | ||
70 | { | ||
71 | struct celleb_pci_bus *bus; | ||
72 | int token; | ||
73 | |||
74 | token = PCI_GET_ADDR_TOKEN(addr); | ||
75 | |||
76 | if (token && token <= celleb_pci_count) | ||
77 | bus = &celleb_pci_busses[token - 1]; | ||
78 | else { | ||
79 | unsigned long vaddr, paddr; | ||
80 | pte_t *ptep; | ||
81 | |||
82 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | ||
83 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) | ||
84 | return; | ||
85 | |||
86 | ptep = find_linux_pte(init_mm.pgd, vaddr); | ||
87 | if (ptep == NULL) | ||
88 | paddr = 0; | ||
89 | else | ||
90 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | ||
91 | bus = celleb_pci_find(vaddr, paddr); | ||
92 | |||
93 | if (bus == NULL) | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | if (bus->dummy_read) | ||
98 | bus->dummy_read(bus->phb); | ||
99 | } | ||
100 | |||
101 | static u8 celleb_readb(const PCI_IO_ADDR addr) | ||
102 | { | ||
103 | u8 val; | ||
104 | val = __do_readb(addr); | ||
105 | celleb_io_flush(addr); | ||
106 | return val; | ||
107 | } | ||
108 | |||
109 | static u16 celleb_readw(const PCI_IO_ADDR addr) | ||
110 | { | ||
111 | u16 val; | ||
112 | val = __do_readw(addr); | ||
113 | celleb_io_flush(addr); | ||
114 | return val; | ||
115 | } | ||
116 | |||
117 | static u32 celleb_readl(const PCI_IO_ADDR addr) | ||
118 | { | ||
119 | u32 val; | ||
120 | val = __do_readl(addr); | ||
121 | celleb_io_flush(addr); | ||
122 | return val; | ||
123 | } | ||
124 | |||
125 | static u64 celleb_readq(const PCI_IO_ADDR addr) | ||
126 | { | ||
127 | u64 val; | ||
128 | val = __do_readq(addr); | ||
129 | celleb_io_flush(addr); | ||
130 | return val; | ||
131 | } | ||
132 | |||
133 | static u16 celleb_readw_be(const PCI_IO_ADDR addr) | ||
134 | { | ||
135 | u16 val; | ||
136 | val = __do_readw_be(addr); | ||
137 | celleb_io_flush(addr); | ||
138 | return val; | ||
139 | } | ||
140 | |||
141 | static u32 celleb_readl_be(const PCI_IO_ADDR addr) | ||
142 | { | ||
143 | u32 val; | ||
144 | val = __do_readl_be(addr); | ||
145 | celleb_io_flush(addr); | ||
146 | return val; | ||
147 | } | ||
148 | |||
149 | static u64 celleb_readq_be(const PCI_IO_ADDR addr) | ||
150 | { | ||
151 | u64 val; | ||
152 | val = __do_readq_be(addr); | ||
153 | celleb_io_flush(addr); | ||
154 | return val; | ||
155 | } | ||
156 | |||
157 | static void celleb_readsb(const PCI_IO_ADDR addr, | ||
158 | void *buf, unsigned long count) | ||
159 | { | ||
160 | __do_readsb(addr, buf, count); | ||
161 | celleb_io_flush(addr); | ||
162 | } | ||
163 | |||
164 | static void celleb_readsw(const PCI_IO_ADDR addr, | ||
165 | void *buf, unsigned long count) | ||
166 | { | ||
167 | __do_readsw(addr, buf, count); | ||
168 | celleb_io_flush(addr); | ||
169 | } | ||
170 | |||
171 | static void celleb_readsl(const PCI_IO_ADDR addr, | ||
172 | void *buf, unsigned long count) | ||
173 | { | ||
174 | __do_readsl(addr, buf, count); | ||
175 | celleb_io_flush(addr); | ||
176 | } | ||
177 | |||
178 | static void celleb_memcpy_fromio(void *dest, | ||
179 | const PCI_IO_ADDR src, | ||
180 | unsigned long n) | ||
181 | { | ||
182 | __do_memcpy_fromio(dest, src, n); | ||
183 | celleb_io_flush(src); | ||
184 | } | ||
185 | |||
186 | static void __iomem *celleb_ioremap(unsigned long addr, | ||
187 | unsigned long size, | ||
188 | unsigned long flags) | ||
189 | { | ||
190 | struct celleb_pci_bus *bus; | ||
191 | void __iomem *res = __ioremap(addr, size, flags); | ||
192 | int busno; | ||
193 | |||
194 | bus = celleb_pci_find(0, addr); | ||
195 | if (bus != NULL) { | ||
196 | busno = bus - celleb_pci_busses; | ||
197 | PCI_SET_ADDR_TOKEN(res, busno + 1); | ||
198 | } | ||
199 | return res; | ||
200 | } | ||
201 | |||
202 | static void celleb_iounmap(volatile void __iomem *addr) | ||
203 | { | ||
204 | return __iounmap(PCI_FIX_ADDR(addr)); | ||
205 | } | ||
206 | |||
207 | static struct ppc_pci_io celleb_pci_io __initdata = { | ||
208 | .readb = celleb_readb, | ||
209 | .readw = celleb_readw, | ||
210 | .readl = celleb_readl, | ||
211 | .readq = celleb_readq, | ||
212 | .readw_be = celleb_readw_be, | ||
213 | .readl_be = celleb_readl_be, | ||
214 | .readq_be = celleb_readq_be, | ||
215 | .readsb = celleb_readsb, | ||
216 | .readsw = celleb_readsw, | ||
217 | .readsl = celleb_readsl, | ||
218 | .memcpy_fromio = celleb_memcpy_fromio, | ||
219 | }; | ||
220 | |||
221 | void __init celleb_pci_add_one(struct pci_controller *phb, | ||
222 | void (*dummy_read)(struct pci_controller *)) | ||
223 | { | ||
224 | struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count]; | ||
225 | struct device_node *np = phb->arch_data; | ||
226 | |||
227 | if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) { | ||
228 | printk(KERN_ERR "Too many pci bridges, workarounds" | ||
229 | " disabled for %s\n", np->full_name); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | celleb_pci_count++; | ||
234 | |||
235 | bus->phb = phb; | ||
236 | bus->dummy_read = dummy_read; | ||
237 | } | ||
238 | |||
239 | static struct of_device_id celleb_pci_workaround_match[] __initdata = { | ||
240 | { | ||
241 | .name = "pci-pseudo", | ||
242 | .data = fake_pci_workaround_init, | ||
243 | }, { | ||
244 | .name = "epci", | ||
245 | .data = epci_workaround_init, | ||
246 | }, { | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | int __init celleb_pci_workaround_init(void) | ||
251 | { | ||
252 | struct pci_controller *phb; | ||
253 | struct device_node *node; | ||
254 | const struct of_device_id *match; | ||
255 | void (*init_func)(struct pci_controller *); | ||
256 | |||
257 | celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
258 | if (!celleb_dummy_page_va) { | ||
259 | printk(KERN_ERR "Celleb: dummy read disabled." | ||
260 | "Alloc celleb_dummy_page_va failed\n"); | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | list_for_each_entry(phb, &hose_list, list_node) { | ||
265 | node = phb->arch_data; | ||
266 | match = of_match_node(celleb_pci_workaround_match, node); | ||
267 | |||
268 | if (match) { | ||
269 | init_func = match->data; | ||
270 | (*init_func)(phb); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | ppc_pci_io = celleb_pci_io; | ||
275 | ppc_md.ioremap = celleb_ioremap; | ||
276 | ppc_md.iounmap = celleb_iounmap; | ||
277 | |||
278 | return 0; | ||
279 | } | ||
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c index e9ac19c4bba4..6bc32fda7a6b 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/celleb/pci.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/bootmem.h> | 32 | #include <linux/bootmem.h> |
33 | #include <linux/pci_regs.h> | 33 | #include <linux/pci_regs.h> |
34 | #include <linux/of_device.h> | ||
34 | 35 | ||
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -242,8 +243,8 @@ static int celleb_fake_pci_write_config(struct pci_bus *bus, | |||
242 | } | 243 | } |
243 | 244 | ||
244 | static struct pci_ops celleb_fake_pci_ops = { | 245 | static struct pci_ops celleb_fake_pci_ops = { |
245 | celleb_fake_pci_read_config, | 246 | .read = celleb_fake_pci_read_config, |
246 | celleb_fake_pci_write_config | 247 | .write = celleb_fake_pci_write_config, |
247 | }; | 248 | }; |
248 | 249 | ||
249 | static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, | 250 | static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, |
@@ -288,8 +289,8 @@ static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, | |||
288 | celleb_config_write_fake(config, PCI_COMMAND, 2, val); | 289 | celleb_config_write_fake(config, PCI_COMMAND, 2, val); |
289 | } | 290 | } |
290 | 291 | ||
291 | static int __devinit celleb_setup_fake_pci_device(struct device_node *node, | 292 | static int __init celleb_setup_fake_pci_device(struct device_node *node, |
292 | struct pci_controller *hose) | 293 | struct pci_controller *hose) |
293 | { | 294 | { |
294 | unsigned int rlen; | 295 | unsigned int rlen; |
295 | int num_base_addr = 0; | 296 | int num_base_addr = 0; |
@@ -327,10 +328,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, | |||
327 | 328 | ||
328 | size = 256; | 329 | size = 256; |
329 | config = &private->fake_config[devno][fn]; | 330 | config = &private->fake_config[devno][fn]; |
330 | if (mem_init_done) | 331 | *config = alloc_maybe_bootmem(size, GFP_KERNEL); |
331 | *config = kzalloc(size, GFP_KERNEL); | ||
332 | else | ||
333 | *config = alloc_bootmem(size); | ||
334 | if (*config == NULL) { | 332 | if (*config == NULL) { |
335 | printk(KERN_ERR "PCI: " | 333 | printk(KERN_ERR "PCI: " |
336 | "not enough memory for fake configuration space\n"); | 334 | "not enough memory for fake configuration space\n"); |
@@ -341,10 +339,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node, | |||
341 | 339 | ||
342 | size = sizeof(struct celleb_pci_resource); | 340 | size = sizeof(struct celleb_pci_resource); |
343 | res = &private->res[devno][fn]; | 341 | res = &private->res[devno][fn]; |
344 | if (mem_init_done) | 342 | *res = alloc_maybe_bootmem(size, GFP_KERNEL); |
345 | *res = kzalloc(size, GFP_KERNEL); | ||
346 | else | ||
347 | *res = alloc_bootmem(size); | ||
348 | if (*res == NULL) { | 343 | if (*res == NULL) { |
349 | printk(KERN_ERR | 344 | printk(KERN_ERR |
350 | "PCI: not enough memory for resource data space\n"); | 345 | "PCI: not enough memory for resource data space\n"); |
@@ -418,8 +413,8 @@ error: | |||
418 | return 1; | 413 | return 1; |
419 | } | 414 | } |
420 | 415 | ||
421 | static int __devinit phb_set_bus_ranges(struct device_node *dev, | 416 | static int __init phb_set_bus_ranges(struct device_node *dev, |
422 | struct pci_controller *phb) | 417 | struct pci_controller *phb) |
423 | { | 418 | { |
424 | const int *bus_range; | 419 | const int *bus_range; |
425 | unsigned int len; | 420 | unsigned int len; |
@@ -434,46 +429,65 @@ static int __devinit phb_set_bus_ranges(struct device_node *dev, | |||
434 | return 0; | 429 | return 0; |
435 | } | 430 | } |
436 | 431 | ||
437 | static void __devinit celleb_alloc_private_mem(struct pci_controller *hose) | 432 | static void __init celleb_alloc_private_mem(struct pci_controller *hose) |
438 | { | 433 | { |
439 | if (mem_init_done) | 434 | hose->private_data = |
440 | hose->private_data = | 435 | alloc_maybe_bootmem(sizeof(struct celleb_pci_private), |
441 | kzalloc(sizeof(struct celleb_pci_private), GFP_KERNEL); | 436 | GFP_KERNEL); |
442 | else | ||
443 | hose->private_data = | ||
444 | alloc_bootmem(sizeof(struct celleb_pci_private)); | ||
445 | } | 437 | } |
446 | 438 | ||
447 | int __devinit celleb_setup_phb(struct pci_controller *phb) | 439 | static int __init celleb_setup_fake_pci(struct device_node *dev, |
440 | struct pci_controller *phb) | ||
448 | { | 441 | { |
449 | const char *name; | ||
450 | struct device_node *dev = phb->arch_data; | ||
451 | struct device_node *node; | 442 | struct device_node *node; |
452 | unsigned int rlen; | ||
453 | 443 | ||
454 | name = of_get_property(dev, "name", &rlen); | 444 | phb->ops = &celleb_fake_pci_ops; |
455 | if (!name) | 445 | celleb_alloc_private_mem(phb); |
456 | return 1; | ||
457 | 446 | ||
458 | pr_debug("PCI: celleb_setup_phb() %s\n", name); | 447 | for (node = of_get_next_child(dev, NULL); |
459 | phb_set_bus_ranges(dev, phb); | 448 | node != NULL; node = of_get_next_child(dev, node)) |
460 | phb->buid = 1; | 449 | celleb_setup_fake_pci_device(node, phb); |
450 | |||
451 | return 0; | ||
452 | } | ||
461 | 453 | ||
462 | if (strcmp(name, "epci") == 0) { | 454 | void __init fake_pci_workaround_init(struct pci_controller *phb) |
463 | phb->ops = &celleb_epci_ops; | 455 | { |
464 | return celleb_setup_epci(dev, phb); | 456 | /** |
457 | * We will add fake pci bus to scc_pci_bus for the purpose to improve | ||
458 | * I/O Macro performance. But device-tree and device drivers | ||
459 | * are not ready to use address with a token. | ||
460 | */ | ||
461 | |||
462 | /* celleb_pci_add_one(phb, NULL); */ | ||
463 | } | ||
465 | 464 | ||
466 | } else if (strcmp(name, "pci-pseudo") == 0) { | 465 | static struct of_device_id celleb_phb_match[] __initdata = { |
467 | phb->ops = &celleb_fake_pci_ops; | 466 | { |
468 | celleb_alloc_private_mem(phb); | 467 | .name = "pci-pseudo", |
469 | for (node = of_get_next_child(dev, NULL); | 468 | .data = celleb_setup_fake_pci, |
470 | node != NULL; node = of_get_next_child(dev, node)) | 469 | }, { |
471 | celleb_setup_fake_pci_device(node, phb); | 470 | .name = "epci", |
471 | .data = celleb_setup_epci, | ||
472 | }, { | ||
473 | }, | ||
474 | }; | ||
472 | 475 | ||
473 | } else | 476 | int __init celleb_setup_phb(struct pci_controller *phb) |
477 | { | ||
478 | struct device_node *dev = phb->arch_data; | ||
479 | const struct of_device_id *match; | ||
480 | int (*setup_func)(struct device_node *, struct pci_controller *); | ||
481 | |||
482 | match = of_match_node(celleb_phb_match, dev); | ||
483 | if (!match) | ||
474 | return 1; | 484 | return 1; |
475 | 485 | ||
476 | return 0; | 486 | phb_set_bus_ranges(dev, phb); |
487 | phb->buid = 1; | ||
488 | |||
489 | setup_func = match->data; | ||
490 | return (*setup_func)(dev, phb); | ||
477 | } | 491 | } |
478 | 492 | ||
479 | int celleb_pci_probe_mode(struct pci_bus *bus) | 493 | int celleb_pci_probe_mode(struct pci_bus *bus) |
diff --git a/arch/powerpc/platforms/celleb/pci.h b/arch/powerpc/platforms/celleb/pci.h index 5340e348e297..5d5544ffeddb 100644 --- a/arch/powerpc/platforms/celleb/pci.h +++ b/arch/powerpc/platforms/celleb/pci.h | |||
@@ -25,11 +25,18 @@ | |||
25 | 25 | ||
26 | #include <asm/pci-bridge.h> | 26 | #include <asm/pci-bridge.h> |
27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
28 | #include <asm/ppc-pci.h> | ||
28 | 29 | ||
29 | extern int celleb_setup_phb(struct pci_controller *); | 30 | extern int celleb_setup_phb(struct pci_controller *); |
30 | extern int celleb_pci_probe_mode(struct pci_bus *); | 31 | extern int celleb_pci_probe_mode(struct pci_bus *); |
31 | 32 | ||
32 | extern struct pci_ops celleb_epci_ops; | ||
33 | extern int celleb_setup_epci(struct device_node *, struct pci_controller *); | 33 | extern int celleb_setup_epci(struct device_node *, struct pci_controller *); |
34 | 34 | ||
35 | extern void *celleb_dummy_page_va; | ||
36 | extern int __init celleb_pci_workaround_init(void); | ||
37 | extern void __init celleb_pci_add_one(struct pci_controller *, | ||
38 | void (*)(struct pci_controller *)); | ||
39 | extern void fake_pci_workaround_init(struct pci_controller *); | ||
40 | extern void epci_workaround_init(struct pci_controller *); | ||
41 | |||
35 | #endif /* _CELLEB_PCI_H */ | 42 | #endif /* _CELLEB_PCI_H */ |
diff --git a/arch/powerpc/platforms/celleb/scc.h b/arch/powerpc/platforms/celleb/scc.h index e9ce8a7c1882..6be1542a6e66 100644 --- a/arch/powerpc/platforms/celleb/scc.h +++ b/arch/powerpc/platforms/celleb/scc.h | |||
@@ -53,7 +53,7 @@ | |||
53 | #define SCC_EPCI_STATUS 0x808 | 53 | #define SCC_EPCI_STATUS 0x808 |
54 | #define SCC_EPCI_ABTSET 0x80c | 54 | #define SCC_EPCI_ABTSET 0x80c |
55 | #define SCC_EPCI_WATRP 0x810 | 55 | #define SCC_EPCI_WATRP 0x810 |
56 | #define SCC_EPCI_DUMMYRADR 0x814 | 56 | #define SCC_EPCI_DUMYRADR 0x814 |
57 | #define SCC_EPCI_SWRESP 0x818 | 57 | #define SCC_EPCI_SWRESP 0x818 |
58 | #define SCC_EPCI_CNTOPT 0x81c | 58 | #define SCC_EPCI_CNTOPT 0x81c |
59 | #define SCC_EPCI_ECMODE 0xf00 | 59 | #define SCC_EPCI_ECMODE 0xf00 |
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c index c4b011094bd6..9d076426676c 100644 --- a/arch/powerpc/platforms/celleb/scc_epci.c +++ b/arch/powerpc/platforms/celleb/scc_epci.c | |||
@@ -43,7 +43,11 @@ | |||
43 | 43 | ||
44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") | 44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") |
45 | 45 | ||
46 | static inline volatile void __iomem *celleb_epci_get_epci_base( | 46 | struct epci_private { |
47 | dma_addr_t dummy_page_da; | ||
48 | }; | ||
49 | |||
50 | static inline PCI_IO_ADDR celleb_epci_get_epci_base( | ||
47 | struct pci_controller *hose) | 51 | struct pci_controller *hose) |
48 | { | 52 | { |
49 | /* | 53 | /* |
@@ -55,7 +59,7 @@ static inline volatile void __iomem *celleb_epci_get_epci_base( | |||
55 | return hose->cfg_addr; | 59 | return hose->cfg_addr; |
56 | } | 60 | } |
57 | 61 | ||
58 | static inline volatile void __iomem *celleb_epci_get_epci_cfg( | 62 | static inline PCI_IO_ADDR celleb_epci_get_epci_cfg( |
59 | struct pci_controller *hose) | 63 | struct pci_controller *hose) |
60 | { | 64 | { |
61 | /* | 65 | /* |
@@ -67,20 +71,11 @@ static inline volatile void __iomem *celleb_epci_get_epci_cfg( | |||
67 | return hose->cfg_data; | 71 | return hose->cfg_data; |
68 | } | 72 | } |
69 | 73 | ||
70 | #if 0 /* test code for epci dummy read */ | 74 | static void scc_epci_dummy_read(struct pci_controller *hose) |
71 | static void celleb_epci_dummy_read(struct pci_dev *dev) | ||
72 | { | 75 | { |
73 | volatile void __iomem *epci_base; | 76 | PCI_IO_ADDR epci_base; |
74 | struct device_node *node; | ||
75 | struct pci_controller *hose; | ||
76 | u32 val; | 77 | u32 val; |
77 | 78 | ||
78 | node = (struct device_node *)dev->bus->sysdata; | ||
79 | hose = pci_find_hose_for_OF_device(node); | ||
80 | |||
81 | if (!hose) | ||
82 | return; | ||
83 | |||
84 | epci_base = celleb_epci_get_epci_base(hose); | 79 | epci_base = celleb_epci_get_epci_base(hose); |
85 | 80 | ||
86 | val = in_be32(epci_base + SCC_EPCI_WATRP); | 81 | val = in_be32(epci_base + SCC_EPCI_WATRP); |
@@ -88,21 +83,45 @@ static void celleb_epci_dummy_read(struct pci_dev *dev) | |||
88 | 83 | ||
89 | return; | 84 | return; |
90 | } | 85 | } |
91 | #endif | 86 | |
87 | void __init epci_workaround_init(struct pci_controller *hose) | ||
88 | { | ||
89 | PCI_IO_ADDR epci_base; | ||
90 | PCI_IO_ADDR reg; | ||
91 | struct epci_private *private = hose->private_data; | ||
92 | |||
93 | BUG_ON(!private); | ||
94 | |||
95 | private->dummy_page_da = dma_map_single(hose->parent, | ||
96 | celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); | ||
97 | if (private->dummy_page_da == DMA_ERROR_CODE) { | ||
98 | printk(KERN_ERR "EPCI: dummy read disabled." | ||
99 | "Map dummy page failed.\n"); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | celleb_pci_add_one(hose, scc_epci_dummy_read); | ||
104 | epci_base = celleb_epci_get_epci_base(hose); | ||
105 | |||
106 | reg = epci_base + SCC_EPCI_DUMYRADR; | ||
107 | out_be32(reg, private->dummy_page_da); | ||
108 | } | ||
92 | 109 | ||
93 | static inline void clear_and_disable_master_abort_interrupt( | 110 | static inline void clear_and_disable_master_abort_interrupt( |
94 | struct pci_controller *hose) | 111 | struct pci_controller *hose) |
95 | { | 112 | { |
96 | volatile void __iomem *epci_base, *reg; | 113 | PCI_IO_ADDR epci_base; |
114 | PCI_IO_ADDR reg; | ||
97 | epci_base = celleb_epci_get_epci_base(hose); | 115 | epci_base = celleb_epci_get_epci_base(hose); |
98 | reg = epci_base + PCI_COMMAND; | 116 | reg = epci_base + PCI_COMMAND; |
99 | out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16)); | 117 | out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16)); |
100 | } | 118 | } |
101 | 119 | ||
102 | static int celleb_epci_check_abort(struct pci_controller *hose, | 120 | static int celleb_epci_check_abort(struct pci_controller *hose, |
103 | volatile void __iomem *addr) | 121 | PCI_IO_ADDR addr) |
104 | { | 122 | { |
105 | volatile void __iomem *reg, *epci_base; | 123 | PCI_IO_ADDR reg; |
124 | PCI_IO_ADDR epci_base; | ||
106 | u32 val; | 125 | u32 val; |
107 | 126 | ||
108 | iob(); | 127 | iob(); |
@@ -132,12 +151,12 @@ static int celleb_epci_check_abort(struct pci_controller *hose, | |||
132 | return PCIBIOS_SUCCESSFUL; | 151 | return PCIBIOS_SUCCESSFUL; |
133 | } | 152 | } |
134 | 153 | ||
135 | static volatile void __iomem *celleb_epci_make_config_addr( | 154 | static PCI_IO_ADDR celleb_epci_make_config_addr( |
136 | struct pci_bus *bus, | 155 | struct pci_bus *bus, |
137 | struct pci_controller *hose, | 156 | struct pci_controller *hose, |
138 | unsigned int devfn, int where) | 157 | unsigned int devfn, int where) |
139 | { | 158 | { |
140 | volatile void __iomem *addr; | 159 | PCI_IO_ADDR addr; |
141 | 160 | ||
142 | if (bus != hose->bus) | 161 | if (bus != hose->bus) |
143 | addr = celleb_epci_get_epci_cfg(hose) + | 162 | addr = celleb_epci_get_epci_cfg(hose) + |
@@ -157,7 +176,8 @@ static volatile void __iomem *celleb_epci_make_config_addr( | |||
157 | static int celleb_epci_read_config(struct pci_bus *bus, | 176 | static int celleb_epci_read_config(struct pci_bus *bus, |
158 | unsigned int devfn, int where, int size, u32 * val) | 177 | unsigned int devfn, int where, int size, u32 * val) |
159 | { | 178 | { |
160 | volatile void __iomem *epci_base, *addr; | 179 | PCI_IO_ADDR epci_base; |
180 | PCI_IO_ADDR addr; | ||
161 | struct device_node *node; | 181 | struct device_node *node; |
162 | struct pci_controller *hose; | 182 | struct pci_controller *hose; |
163 | 183 | ||
@@ -220,7 +240,8 @@ static int celleb_epci_read_config(struct pci_bus *bus, | |||
220 | static int celleb_epci_write_config(struct pci_bus *bus, | 240 | static int celleb_epci_write_config(struct pci_bus *bus, |
221 | unsigned int devfn, int where, int size, u32 val) | 241 | unsigned int devfn, int where, int size, u32 val) |
222 | { | 242 | { |
223 | volatile void __iomem *epci_base, *addr; | 243 | PCI_IO_ADDR epci_base; |
244 | PCI_IO_ADDR addr; | ||
224 | struct device_node *node; | 245 | struct device_node *node; |
225 | struct pci_controller *hose; | 246 | struct pci_controller *hose; |
226 | 247 | ||
@@ -278,15 +299,16 @@ static int celleb_epci_write_config(struct pci_bus *bus, | |||
278 | } | 299 | } |
279 | 300 | ||
280 | struct pci_ops celleb_epci_ops = { | 301 | struct pci_ops celleb_epci_ops = { |
281 | celleb_epci_read_config, | 302 | .read = celleb_epci_read_config, |
282 | celleb_epci_write_config, | 303 | .write = celleb_epci_write_config, |
283 | }; | 304 | }; |
284 | 305 | ||
285 | /* to be moved in FW */ | 306 | /* to be moved in FW */ |
286 | static int __devinit celleb_epci_init(struct pci_controller *hose) | 307 | static int __init celleb_epci_init(struct pci_controller *hose) |
287 | { | 308 | { |
288 | u32 val; | 309 | u32 val; |
289 | volatile void __iomem *reg, *epci_base; | 310 | PCI_IO_ADDR reg; |
311 | PCI_IO_ADDR epci_base; | ||
290 | int hwres = 0; | 312 | int hwres = 0; |
291 | 313 | ||
292 | epci_base = celleb_epci_get_epci_base(hose); | 314 | epci_base = celleb_epci_get_epci_base(hose); |
@@ -403,7 +425,7 @@ static int __devinit celleb_epci_init(struct pci_controller *hose) | |||
403 | return 0; | 425 | return 0; |
404 | } | 426 | } |
405 | 427 | ||
406 | int __devinit celleb_setup_epci(struct device_node *node, | 428 | int __init celleb_setup_epci(struct device_node *node, |
407 | struct pci_controller *hose) | 429 | struct pci_controller *hose) |
408 | { | 430 | { |
409 | struct resource r; | 431 | struct resource r; |
@@ -440,10 +462,24 @@ int __devinit celleb_setup_epci(struct device_node *node, | |||
440 | r.start, (unsigned long)hose->cfg_data, | 462 | r.start, (unsigned long)hose->cfg_data, |
441 | (r.end - r.start + 1)); | 463 | (r.end - r.start + 1)); |
442 | 464 | ||
465 | hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL); | ||
466 | if (hose->private_data == NULL) { | ||
467 | printk(KERN_ERR "EPCI: no memory for private data.\n"); | ||
468 | goto error; | ||
469 | } | ||
470 | |||
471 | hose->ops = &celleb_epci_ops; | ||
443 | celleb_epci_init(hose); | 472 | celleb_epci_init(hose); |
444 | 473 | ||
445 | return 0; | 474 | return 0; |
446 | 475 | ||
447 | error: | 476 | error: |
477 | kfree(hose->private_data); | ||
478 | |||
479 | if (hose->cfg_addr) | ||
480 | iounmap(hose->cfg_addr); | ||
481 | |||
482 | if (hose->cfg_data) | ||
483 | iounmap(hose->cfg_data); | ||
448 | return 1; | 484 | return 1; |
449 | } | 485 | } |
diff --git a/arch/powerpc/platforms/celleb/scc_sio.c b/arch/powerpc/platforms/celleb/scc_sio.c index bcd25f54d986..610008211ca1 100644 --- a/arch/powerpc/platforms/celleb/scc_sio.c +++ b/arch/powerpc/platforms/celleb/scc_sio.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * setup serial port in SCC | 2 | * setup serial port in SCC |
3 | * | 3 | * |
4 | * (C) Copyright 2006 TOSHIBA CORPORATION | 4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -28,58 +28,58 @@ | |||
28 | 28 | ||
29 | /* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024 | 29 | /* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024 |
30 | mmio=0xfff000-0x1000,0xff2000-0x1000 */ | 30 | mmio=0xfff000-0x1000,0xff2000-0x1000 */ |
31 | static int txx9_serial_bitmap = 0; | 31 | static int txx9_serial_bitmap __initdata = 0; |
32 | 32 | ||
33 | static struct { | 33 | static struct { |
34 | uint32_t offset; | 34 | uint32_t offset; |
35 | uint32_t index; | 35 | uint32_t index; |
36 | } txx9_scc_tab[3] = { | 36 | } txx9_scc_tab[3] __initdata = { |
37 | { 0x300, 0 }, /* 0xFFF300 */ | 37 | { 0x300, 0 }, /* 0xFFF300 */ |
38 | { 0x400, 0 }, /* 0xFFF400 */ | 38 | { 0x400, 0 }, /* 0xFFF400 */ |
39 | { 0x800, 1 } /* 0xFF2800 */ | 39 | { 0x800, 1 } /* 0xFF2800 */ |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static int txx9_serial_init(void) | 42 | static int __init txx9_serial_init(void) |
43 | { | 43 | { |
44 | extern int early_serial_txx9_setup(struct uart_port *port); | 44 | extern int early_serial_txx9_setup(struct uart_port *port); |
45 | struct device_node *node; | 45 | struct device_node *node = NULL; |
46 | int i; | 46 | int i; |
47 | struct uart_port req; | 47 | struct uart_port req; |
48 | struct of_irq irq; | 48 | struct of_irq irq; |
49 | struct resource res; | 49 | struct resource res; |
50 | 50 | ||
51 | node = of_find_node_by_path("/ioif1/sio"); | 51 | while ((node = of_find_compatible_node(node, |
52 | if (!node) | 52 | "serial", "toshiba,sio-scc")) != NULL) { |
53 | return 0; | 53 | for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) { |
54 | if (!(txx9_serial_bitmap & (1<<i))) | ||
55 | continue; | ||
54 | 56 | ||
55 | for(i = 0; i < sizeof(txx9_scc_tab)/sizeof(txx9_scc_tab[0]); i++) { | 57 | if (of_irq_map_one(node, i, &irq)) |
56 | if (!(txx9_serial_bitmap & (1<<i))) | 58 | continue; |
57 | continue; | 59 | if (of_address_to_resource(node, |
60 | txx9_scc_tab[i].index, &res)) | ||
61 | continue; | ||
58 | 62 | ||
59 | if (of_irq_map_one(node, i, &irq)) | 63 | memset(&req, 0, sizeof(req)); |
60 | continue; | 64 | req.line = i; |
61 | if (of_address_to_resource(node, txx9_scc_tab[i].index, &res)) | 65 | req.iotype = UPIO_MEM; |
62 | continue; | 66 | req.mapbase = res.start + txx9_scc_tab[i].offset; |
63 | |||
64 | memset(&req, 0, sizeof(req)); | ||
65 | req.line = i; | ||
66 | req.iotype = UPIO_MEM; | ||
67 | req.mapbase = res.start + txx9_scc_tab[i].offset; | ||
68 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE | 67 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE |
69 | req.membase = ioremap(req.mapbase, 0x24); | 68 | req.membase = ioremap(req.mapbase, 0x24); |
70 | #endif | 69 | #endif |
71 | req.irq = irq_create_of_mapping(irq.controller, | 70 | req.irq = irq_create_of_mapping(irq.controller, |
72 | irq.specifier, irq.size); | 71 | irq.specifier, irq.size); |
73 | req.flags |= UPF_IOREMAP | UPF_BUGGY_UART /*HAVE_CTS_LINE*/; | 72 | req.flags |= UPF_IOREMAP | UPF_BUGGY_UART |
74 | req.uartclk = 83300000; | 73 | /*HAVE_CTS_LINE*/; |
75 | early_serial_txx9_setup(&req); | 74 | req.uartclk = 83300000; |
75 | early_serial_txx9_setup(&req); | ||
76 | } | ||
76 | } | 77 | } |
77 | 78 | ||
78 | of_node_put(node); | ||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int txx9_serial_config(char *ptr) | 82 | static int __init txx9_serial_config(char *ptr) |
83 | { | 83 | { |
84 | int i; | 84 | int i; |
85 | 85 | ||
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index 5e9f7f163571..1769d755eff3 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c | |||
@@ -73,7 +73,7 @@ static void celleb_show_cpuinfo(struct seq_file *m) | |||
73 | of_node_put(root); | 73 | of_node_put(root); |
74 | } | 74 | } |
75 | 75 | ||
76 | static int celleb_machine_type_hack(char *ptr) | 76 | static int __init celleb_machine_type_hack(char *ptr) |
77 | { | 77 | { |
78 | strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type)); | 78 | strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type)); |
79 | celleb_machine_type[sizeof(celleb_machine_type)-1] = 0; | 79 | celleb_machine_type[sizeof(celleb_machine_type)-1] = 0; |
@@ -101,21 +101,11 @@ static void __init celleb_setup_arch(void) | |||
101 | /* init to some ~sane value until calibrate_delay() runs */ | 101 | /* init to some ~sane value until calibrate_delay() runs */ |
102 | loops_per_jiffy = 50000000; | 102 | loops_per_jiffy = 50000000; |
103 | 103 | ||
104 | if (ROOT_DEV == 0) { | ||
105 | printk("No ramdisk, default root is /dev/hda2\n"); | ||
106 | ROOT_DEV = Root_HDA2; | ||
107 | } | ||
108 | |||
109 | #ifdef CONFIG_DUMMY_CONSOLE | 104 | #ifdef CONFIG_DUMMY_CONSOLE |
110 | conswitchp = &dummy_con; | 105 | conswitchp = &dummy_con; |
111 | #endif | 106 | #endif |
112 | } | 107 | } |
113 | 108 | ||
114 | static void beat_power_save(void) | ||
115 | { | ||
116 | beat_pause(0); | ||
117 | } | ||
118 | |||
119 | static int __init celleb_probe(void) | 109 | static int __init celleb_probe(void) |
120 | { | 110 | { |
121 | unsigned long root = of_get_flat_dt_root(); | 111 | unsigned long root = of_get_flat_dt_root(); |
@@ -124,18 +114,11 @@ static int __init celleb_probe(void) | |||
124 | return 0; | 114 | return 0; |
125 | 115 | ||
126 | powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; | 116 | powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; |
127 | hpte_init_beat(); | 117 | hpte_init_beat_v3(); |
128 | return 1; | 118 | return 1; |
129 | } | 119 | } |
130 | 120 | ||
131 | #ifdef CONFIG_KEXEC | 121 | static struct of_device_id celleb_bus_ids[] __initdata = { |
132 | static void celleb_kexec_cpu_down(int crash, int secondary) | ||
133 | { | ||
134 | beatic_deinit_IRQ(); | ||
135 | } | ||
136 | #endif | ||
137 | |||
138 | static struct of_device_id celleb_bus_ids[] = { | ||
139 | { .type = "scc", }, | 122 | { .type = "scc", }, |
140 | { .type = "ioif", }, /* old style */ | 123 | { .type = "ioif", }, /* old style */ |
141 | {}, | 124 | {}, |
@@ -149,6 +132,8 @@ static int __init celleb_publish_devices(void) | |||
149 | /* Publish OF platform devices for southbridge IOs */ | 132 | /* Publish OF platform devices for southbridge IOs */ |
150 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); | 133 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); |
151 | 134 | ||
135 | celleb_pci_workaround_init(); | ||
136 | |||
152 | return 0; | 137 | return 0; |
153 | } | 138 | } |
154 | device_initcall(celleb_publish_devices); | 139 | device_initcall(celleb_publish_devices); |
@@ -175,7 +160,7 @@ define_machine(celleb) { | |||
175 | .pci_probe_mode = celleb_pci_probe_mode, | 160 | .pci_probe_mode = celleb_pci_probe_mode, |
176 | .pci_setup_phb = celleb_setup_phb, | 161 | .pci_setup_phb = celleb_setup_phb, |
177 | #ifdef CONFIG_KEXEC | 162 | #ifdef CONFIG_KEXEC |
178 | .kexec_cpu_down = celleb_kexec_cpu_down, | 163 | .kexec_cpu_down = beat_kexec_cpu_down, |
179 | .machine_kexec = default_machine_kexec, | 164 | .machine_kexec = default_machine_kexec, |
180 | .machine_kexec_prepare = default_machine_kexec_prepare, | 165 | .machine_kexec_prepare = default_machine_kexec_prepare, |
181 | .machine_crash_shutdown = default_machine_crash_shutdown, | 166 | .machine_crash_shutdown = default_machine_crash_shutdown, |
diff --git a/arch/powerpc/platforms/chrp/gg2.h b/arch/powerpc/platforms/chrp/gg2.h new file mode 100644 index 000000000000..341ae55b99fb --- /dev/null +++ b/arch/powerpc/platforms/chrp/gg2.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/gg2.h -- VLSI VAS96011/12 `Golden Gate 2' register definitions | ||
3 | * | ||
4 | * Copyright (C) 1997 Geert Uytterhoeven | ||
5 | * | ||
6 | * This file is based on the following documentation: | ||
7 | * | ||
8 | * The VAS96011/12 Chipset, Data Book, Edition 1.0 | ||
9 | * VLSI Technology, Inc. | ||
10 | * | ||
11 | * This file is subject to the terms and conditions of the GNU General Public | ||
12 | * License. See the file COPYING in the main directory of this archive | ||
13 | * for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef _ASMPPC_GG2_H | ||
17 | #define _ASMPPC_GG2_H | ||
18 | |||
19 | /* | ||
20 | * Memory Map (CHRP mode) | ||
21 | */ | ||
22 | |||
23 | #define GG2_PCI_MEM_BASE 0xc0000000 /* Peripheral memory space */ | ||
24 | #define GG2_ISA_MEM_BASE 0xf7000000 /* Peripheral memory alias */ | ||
25 | #define GG2_ISA_IO_BASE 0xf8000000 /* Peripheral I/O space */ | ||
26 | #define GG2_PCI_CONFIG_BASE 0xfec00000 /* PCI configuration space */ | ||
27 | #define GG2_INT_ACK_SPECIAL 0xfec80000 /* Interrupt acknowledge and */ | ||
28 | /* special PCI cycles */ | ||
29 | #define GG2_ROM_BASE0 0xff000000 /* ROM bank 0 */ | ||
30 | #define GG2_ROM_BASE1 0xff800000 /* ROM bank 1 */ | ||
31 | |||
32 | |||
33 | /* | ||
34 | * GG2 specific PCI Registers | ||
35 | */ | ||
36 | |||
37 | extern void __iomem *gg2_pci_config_base; /* kernel virtual address */ | ||
38 | |||
39 | #define GG2_PCI_BUSNO 0x40 /* Bus number */ | ||
40 | #define GG2_PCI_SUBBUSNO 0x41 /* Subordinate bus number */ | ||
41 | #define GG2_PCI_DISCCTR 0x42 /* Disconnect counter */ | ||
42 | #define GG2_PCI_PPC_CTRL 0x50 /* PowerPC interface control register */ | ||
43 | #define GG2_PCI_ADDR_MAP 0x5c /* Address map */ | ||
44 | #define GG2_PCI_PCI_CTRL 0x60 /* PCI interface control register */ | ||
45 | #define GG2_PCI_ROM_CTRL 0x70 /* ROM interface control register */ | ||
46 | #define GG2_PCI_ROM_TIME 0x74 /* ROM timing */ | ||
47 | #define GG2_PCI_CC_CTRL 0x80 /* Cache controller control register */ | ||
48 | #define GG2_PCI_DRAM_BANK0 0x90 /* Control register for DRAM bank #0 */ | ||
49 | #define GG2_PCI_DRAM_BANK1 0x94 /* Control register for DRAM bank #1 */ | ||
50 | #define GG2_PCI_DRAM_BANK2 0x98 /* Control register for DRAM bank #2 */ | ||
51 | #define GG2_PCI_DRAM_BANK3 0x9c /* Control register for DRAM bank #3 */ | ||
52 | #define GG2_PCI_DRAM_BANK4 0xa0 /* Control register for DRAM bank #4 */ | ||
53 | #define GG2_PCI_DRAM_BANK5 0xa4 /* Control register for DRAM bank #5 */ | ||
54 | #define GG2_PCI_DRAM_TIME0 0xb0 /* Timing parameters set #0 */ | ||
55 | #define GG2_PCI_DRAM_TIME1 0xb4 /* Timing parameters set #1 */ | ||
56 | #define GG2_PCI_DRAM_CTRL 0xc0 /* DRAM control */ | ||
57 | #define GG2_PCI_ERR_CTRL 0xd0 /* Error control register */ | ||
58 | #define GG2_PCI_ERR_STATUS 0xd4 /* Error status register */ | ||
59 | /* Cleared when read */ | ||
60 | |||
61 | #endif /* _ASMPPC_GG2_H */ | ||
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 28d1647b204e..e43465d34d29 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/irq.h> | 13 | #include <asm/irq.h> |
14 | #include <asm/hydra.h> | 14 | #include <asm/hydra.h> |
15 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
16 | #include <asm/gg2.h> | ||
17 | #include <asm/machdep.h> | 16 | #include <asm/machdep.h> |
18 | #include <asm/sections.h> | 17 | #include <asm/sections.h> |
19 | #include <asm/pci-bridge.h> | 18 | #include <asm/pci-bridge.h> |
@@ -21,6 +20,7 @@ | |||
21 | #include <asm/rtas.h> | 20 | #include <asm/rtas.h> |
22 | 21 | ||
23 | #include "chrp.h" | 22 | #include "chrp.h" |
23 | #include "gg2.h" | ||
24 | 24 | ||
25 | /* LongTrail */ | 25 | /* LongTrail */ |
26 | void __iomem *gg2_pci_config_base; | 26 | void __iomem *gg2_pci_config_base; |
@@ -86,8 +86,8 @@ int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, | |||
86 | 86 | ||
87 | static struct pci_ops gg2_pci_ops = | 87 | static struct pci_ops gg2_pci_ops = |
88 | { | 88 | { |
89 | gg2_read_config, | 89 | .read = gg2_read_config, |
90 | gg2_write_config | 90 | .write = gg2_write_config, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* | 93 | /* |
@@ -124,8 +124,8 @@ int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
124 | 124 | ||
125 | static struct pci_ops rtas_pci_ops = | 125 | static struct pci_ops rtas_pci_ops = |
126 | { | 126 | { |
127 | rtas_read_config, | 127 | .read = rtas_read_config, |
128 | rtas_write_config | 128 | .write = rtas_write_config, |
129 | }; | 129 | }; |
130 | 130 | ||
131 | volatile struct Hydra __iomem *Hydra = NULL; | 131 | volatile struct Hydra __iomem *Hydra = NULL; |
@@ -338,3 +338,32 @@ void chrp_pci_fixup_winbond_ata(struct pci_dev *sl82c105) | |||
338 | } | 338 | } |
339 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, | 339 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, |
340 | chrp_pci_fixup_winbond_ata); | 340 | chrp_pci_fixup_winbond_ata); |
341 | |||
342 | /* Pegasos2 firmware version 20040810 configures the built-in IDE controller | ||
343 | * in legacy mode, but sets the PCI registers to PCI native mode. | ||
344 | * The chip can only operate in legacy mode, so force the PCI class into legacy | ||
345 | * mode as well. The same fixup must be done to the class-code property in | ||
346 | * the IDE node /pci@80000000/ide@C,1 | ||
347 | */ | ||
348 | static void chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide) | ||
349 | { | ||
350 | u8 progif; | ||
351 | struct pci_dev *viaisa; | ||
352 | |||
353 | if (!machine_is(chrp) || _chrp_type != _CHRP_Pegasos) | ||
354 | return; | ||
355 | if (viaide->irq != 14) | ||
356 | return; | ||
357 | |||
358 | viaisa = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL); | ||
359 | if (!viaisa) | ||
360 | return; | ||
361 | printk("Fixing VIA IDE, force legacy mode on '%s'\n", viaide->dev.bus_id); | ||
362 | |||
363 | pci_read_config_byte(viaide, PCI_CLASS_PROG, &progif); | ||
364 | pci_write_config_byte(viaide, PCI_CLASS_PROG, progif & ~0x5); | ||
365 | viaide->class &= ~0x5; | ||
366 | |||
367 | pci_dev_put(viaisa); | ||
368 | } | ||
369 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata); | ||
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 373de4c063db..59306261f5b2 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -32,13 +32,11 @@ | |||
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include <linux/root_dev.h> | 33 | #include <linux/root_dev.h> |
34 | #include <linux/initrd.h> | 34 | #include <linux/initrd.h> |
35 | #include <linux/module.h> | ||
36 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
37 | 36 | ||
38 | #include <asm/io.h> | 37 | #include <asm/io.h> |
39 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
40 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
41 | #include <asm/gg2.h> | ||
42 | #include <asm/pci-bridge.h> | 40 | #include <asm/pci-bridge.h> |
43 | #include <asm/dma.h> | 41 | #include <asm/dma.h> |
44 | #include <asm/machdep.h> | 42 | #include <asm/machdep.h> |
@@ -52,6 +50,7 @@ | |||
52 | #include <asm/xmon.h> | 50 | #include <asm/xmon.h> |
53 | 51 | ||
54 | #include "chrp.h" | 52 | #include "chrp.h" |
53 | #include "gg2.h" | ||
55 | 54 | ||
56 | void rtas_indicator_progress(char *, unsigned short); | 55 | void rtas_indicator_progress(char *, unsigned short); |
57 | 56 | ||
@@ -291,16 +290,6 @@ void __init chrp_setup_arch(void) | |||
291 | ppc_md.set_rtc_time = rtas_set_rtc_time; | 290 | ppc_md.set_rtc_time = rtas_set_rtc_time; |
292 | } | 291 | } |
293 | 292 | ||
294 | #ifdef CONFIG_BLK_DEV_INITRD | ||
295 | /* this is fine for chrp */ | ||
296 | initrd_below_start_ok = 1; | ||
297 | |||
298 | if (initrd_start) | ||
299 | ROOT_DEV = Root_RAM0; | ||
300 | else | ||
301 | #endif | ||
302 | ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ | ||
303 | |||
304 | /* On pegasos, enable the L2 cache if not already done by OF */ | 293 | /* On pegasos, enable the L2 cache if not already done by OF */ |
305 | pegasos_set_l2cr(); | 294 | pegasos_set_l2cr(); |
306 | 295 | ||
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index 3ea0eb78568e..10a4a4d063b6 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c | |||
@@ -26,10 +26,8 @@ | |||
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
28 | #include <asm/smp.h> | 28 | #include <asm/smp.h> |
29 | #include <asm/residual.h> | ||
30 | #include <asm/time.h> | 29 | #include <asm/time.h> |
31 | #include <asm/machdep.h> | 30 | #include <asm/machdep.h> |
32 | #include <asm/smp.h> | ||
33 | #include <asm/mpic.h> | 31 | #include <asm/mpic.h> |
34 | #include <asm/rtas.h> | 32 | #include <asm/rtas.h> |
35 | 33 | ||
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 2d12f77e46bc..8924095a7928 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
@@ -1,9 +1,10 @@ | |||
1 | choice | 1 | config EMBEDDED6xx |
2 | prompt "Machine Type" | 2 | bool "Embedded 6xx/7xx/7xxx-based boards" |
3 | depends on EMBEDDED6xx | 3 | depends on PPC32 && BROKEN_ON_SMP && PPC_MULTIPLATFORM |
4 | 4 | ||
5 | config LINKSTATION | 5 | config LINKSTATION |
6 | bool "Linkstation / Kurobox(HG) from Buffalo" | 6 | bool "Linkstation / Kurobox(HG) from Buffalo" |
7 | depends on EMBEDDED6xx | ||
7 | select MPIC | 8 | select MPIC |
8 | select FSL_SOC | 9 | select FSL_SOC |
9 | select PPC_UDBG_16550 if SERIAL_8250 | 10 | select PPC_UDBG_16550 if SERIAL_8250 |
@@ -17,15 +18,18 @@ config LINKSTATION | |||
17 | 18 | ||
18 | config MPC7448HPC2 | 19 | config MPC7448HPC2 |
19 | bool "Freescale MPC7448HPC2(Taiga)" | 20 | bool "Freescale MPC7448HPC2(Taiga)" |
21 | depends on EMBEDDED6xx | ||
20 | select TSI108_BRIDGE | 22 | select TSI108_BRIDGE |
21 | select DEFAULT_UIMAGE | 23 | select DEFAULT_UIMAGE |
22 | select PPC_UDBG_16550 | 24 | select PPC_UDBG_16550 |
25 | select WANT_DEVICE_TREE | ||
23 | help | 26 | help |
24 | Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) | 27 | Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) |
25 | platform | 28 | platform |
26 | 29 | ||
27 | config PPC_HOLLY | 30 | config PPC_HOLLY |
28 | bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" | 31 | bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" |
32 | depends on EMBEDDED6xx | ||
29 | select TSI108_BRIDGE | 33 | select TSI108_BRIDGE |
30 | select PPC_UDBG_16550 | 34 | select PPC_UDBG_16550 |
31 | select WANT_DEVICE_TREE | 35 | select WANT_DEVICE_TREE |
@@ -35,12 +39,12 @@ config PPC_HOLLY | |||
35 | 39 | ||
36 | config PPC_PRPMC2800 | 40 | config PPC_PRPMC2800 |
37 | bool "Motorola-PrPMC2800" | 41 | bool "Motorola-PrPMC2800" |
42 | depends on EMBEDDED6xx | ||
38 | select MV64X60 | 43 | select MV64X60 |
39 | select NOT_COHERENT_CACHE | 44 | select NOT_COHERENT_CACHE |
40 | select WANT_DEVICE_TREE | 45 | select WANT_DEVICE_TREE |
41 | help | 46 | help |
42 | This option enables support for the Motorola PrPMC2800 board | 47 | This option enables support for the Motorola PrPMC2800 board |
43 | endchoice | ||
44 | 48 | ||
45 | config TSI108_BRIDGE | 49 | config TSI108_BRIDGE |
46 | bool | 50 | bool |
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 6292e36dc577..b6de2b5223dd 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c | |||
@@ -113,23 +113,11 @@ static void holly_remap_bridge(void) | |||
113 | 113 | ||
114 | static void __init holly_setup_arch(void) | 114 | static void __init holly_setup_arch(void) |
115 | { | 115 | { |
116 | struct device_node *cpu; | ||
117 | struct device_node *np; | 116 | struct device_node *np; |
118 | 117 | ||
119 | if (ppc_md.progress) | 118 | if (ppc_md.progress) |
120 | ppc_md.progress("holly_setup_arch():set_bridge", 0); | 119 | ppc_md.progress("holly_setup_arch():set_bridge", 0); |
121 | 120 | ||
122 | cpu = of_find_node_by_type(NULL, "cpu"); | ||
123 | if (cpu) { | ||
124 | const unsigned int *fp; | ||
125 | |||
126 | fp = of_get_property(cpu, "clock-frequency", NULL); | ||
127 | if (fp) | ||
128 | loops_per_jiffy = *fp / HZ; | ||
129 | else | ||
130 | loops_per_jiffy = 50000000 / HZ; | ||
131 | of_node_put(cpu); | ||
132 | } | ||
133 | tsi108_csr_vir_base = get_vir_csrbase(); | 121 | tsi108_csr_vir_base = get_vir_csrbase(); |
134 | 122 | ||
135 | /* setup PCI host bridge */ | 123 | /* setup PCI host bridge */ |
@@ -147,7 +135,7 @@ static void __init holly_setup_arch(void) | |||
147 | } | 135 | } |
148 | 136 | ||
149 | /* | 137 | /* |
150 | * Interrupt setup and service. Interrrupts on the holly come | 138 | * Interrupt setup and service. Interrupts on the holly come |
151 | * from the four external INT pins, PCI interrupts are routed via | 139 | * from the four external INT pins, PCI interrupts are routed via |
152 | * PCI interrupt control registers, it generates internal IRQ23 | 140 | * PCI interrupt control registers, it generates internal IRQ23 |
153 | * | 141 | * |
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index bd5ca58345a1..eb5d74e26fe9 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
@@ -11,16 +11,16 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/pci.h> | ||
15 | #include <linux/initrd.h> | 14 | #include <linux/initrd.h> |
16 | #include <linux/mtd/physmap.h> | 15 | #include <linux/mtd/physmap.h> |
17 | 16 | ||
18 | #include <asm/time.h> | 17 | #include <asm/time.h> |
19 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
20 | #include <asm/mpic.h> | 19 | #include <asm/mpic.h> |
21 | #include <asm/mpc10x.h> | ||
22 | #include <asm/pci-bridge.h> | 20 | #include <asm/pci-bridge.h> |
23 | 21 | ||
22 | #include "mpc10x.h" | ||
23 | |||
24 | static struct mtd_partition linkstation_physmap_partitions[] = { | 24 | static struct mtd_partition linkstation_physmap_partitions[] = { |
25 | { | 25 | { |
26 | .name = "mtd_firmimg", | 26 | .name = "mtd_firmimg", |
@@ -91,7 +91,7 @@ static void __init linkstation_setup_arch(void) | |||
91 | #endif | 91 | #endif |
92 | 92 | ||
93 | /* Lookup PCI host bridges */ | 93 | /* Lookup PCI host bridges */ |
94 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 94 | for_each_compatible_node(np, "pci", "mpc10x-pci") |
95 | linkstation_add_bridge(np); | 95 | linkstation_add_bridge(np); |
96 | 96 | ||
97 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); | 97 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); |
@@ -99,7 +99,7 @@ static void __init linkstation_setup_arch(void) | |||
99 | } | 99 | } |
100 | 100 | ||
101 | /* | 101 | /* |
102 | * Interrupt setup and service. Interrrupts on the linkstation come | 102 | * Interrupt setup and service. Interrupts on the linkstation come |
103 | * from the four PCI slots plus onboard 8241 devices: I2C, DUART. | 103 | * from the four PCI slots plus onboard 8241 devices: I2C, DUART. |
104 | */ | 104 | */ |
105 | static void __init linkstation_init_IRQ(void) | 105 | static void __init linkstation_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c index d0bee9f19e4e..c99264cedda5 100644 --- a/arch/powerpc/platforms/embedded6xx/ls_uart.c +++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c | |||
@@ -1,14 +1,25 @@ | |||
1 | /* | ||
2 | * AVR power-management chip interface for the Buffalo Linkstation / | ||
3 | * Kurobox Platform. | ||
4 | * | ||
5 | * Author: 2006 (c) G. Liakhovetski | ||
6 | * g.liakhovetski@gmx.de | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of | ||
10 | * any kind, whether express or implied. | ||
11 | */ | ||
1 | #include <linux/workqueue.h> | 12 | #include <linux/workqueue.h> |
2 | #include <linux/string.h> | 13 | #include <linux/string.h> |
3 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
4 | #include <linux/serial_reg.h> | 15 | #include <linux/serial_reg.h> |
5 | #include <linux/serial_8250.h> | 16 | #include <linux/serial_8250.h> |
6 | #include <asm/io.h> | 17 | #include <asm/io.h> |
7 | #include <asm/mpc10x.h> | ||
8 | #include <asm/ppc_sys.h> | ||
9 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
10 | #include <asm/termbits.h> | 19 | #include <asm/termbits.h> |
11 | 20 | ||
21 | #include "mpc10x.h" | ||
22 | |||
12 | static void __iomem *avr_addr; | 23 | static void __iomem *avr_addr; |
13 | static unsigned long avr_clock; | 24 | static unsigned long avr_clock; |
14 | 25 | ||
@@ -106,6 +117,9 @@ static int __init ls_uarts_init(void) | |||
106 | phys_addr_t phys_addr; | 117 | phys_addr_t phys_addr; |
107 | int len; | 118 | int len; |
108 | 119 | ||
120 | if (!machine_is(linkstation)) | ||
121 | return 0; | ||
122 | |||
109 | avr = of_find_node_by_path("/soc10x/serial@80004500"); | 123 | avr = of_find_node_by_path("/soc10x/serial@80004500"); |
110 | if (!avr) | 124 | if (!avr) |
111 | return -EINVAL; | 125 | return -EINVAL; |
diff --git a/arch/powerpc/platforms/embedded6xx/mpc10x.h b/arch/powerpc/platforms/embedded6xx/mpc10x.h new file mode 100644 index 000000000000..b30a6a3b5bd2 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/mpc10x.h | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Common routines for the Motorola SPS MPC106/8240/107 Host bridge/Mem | ||
3 | * ctlr/EPIC/etc. | ||
4 | * | ||
5 | * Author: Mark A. Greer | ||
6 | * mgreer@mvista.com | ||
7 | * | ||
8 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | #ifndef __PPC_KERNEL_MPC10X_H | ||
14 | #define __PPC_KERNEL_MPC10X_H | ||
15 | |||
16 | #include <linux/pci_ids.h> | ||
17 | #include <asm/pci-bridge.h> | ||
18 | |||
19 | /* | ||
20 | * The values here don't completely map everything but should work in most | ||
21 | * cases. | ||
22 | * | ||
23 | * MAP A (PReP Map) | ||
24 | * Processor: 0x80000000 - 0x807fffff -> PCI I/O: 0x00000000 - 0x007fffff | ||
25 | * Processor: 0xc0000000 - 0xdfffffff -> PCI MEM: 0x00000000 - 0x1fffffff | ||
26 | * PCI MEM: 0x80000000 -> Processor System Memory: 0x00000000 | ||
27 | * EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB) | ||
28 | * | ||
29 | * MAP B (CHRP Map) | ||
30 | * Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff | ||
31 | * Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff | ||
32 | * PCI MEM: 0x00000000 -> Processor System Memory: 0x00000000 | ||
33 | * EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB) | ||
34 | */ | ||
35 | |||
36 | /* | ||
37 | * Define the vendor/device IDs for the various bridges--should be added to | ||
38 | * <linux/pci_ids.h> | ||
39 | */ | ||
40 | #define MPC10X_BRIDGE_106 ((PCI_DEVICE_ID_MOTOROLA_MPC106 << 16) | \ | ||
41 | PCI_VENDOR_ID_MOTOROLA) | ||
42 | #define MPC10X_BRIDGE_8240 ((0x0003 << 16) | PCI_VENDOR_ID_MOTOROLA) | ||
43 | #define MPC10X_BRIDGE_107 ((0x0004 << 16) | PCI_VENDOR_ID_MOTOROLA) | ||
44 | #define MPC10X_BRIDGE_8245 ((0x0006 << 16) | PCI_VENDOR_ID_MOTOROLA) | ||
45 | |||
46 | /* Define the type of map to use */ | ||
47 | #define MPC10X_MEM_MAP_A 1 | ||
48 | #define MPC10X_MEM_MAP_B 2 | ||
49 | |||
50 | /* Map A (PReP Map) Defines */ | ||
51 | #define MPC10X_MAPA_CNFG_ADDR 0x80000cf8 | ||
52 | #define MPC10X_MAPA_CNFG_DATA 0x80000cfc | ||
53 | |||
54 | #define MPC10X_MAPA_ISA_IO_BASE 0x80000000 | ||
55 | #define MPC10X_MAPA_ISA_MEM_BASE 0xc0000000 | ||
56 | #define MPC10X_MAPA_DRAM_OFFSET 0x80000000 | ||
57 | |||
58 | #define MPC10X_MAPA_PCI_INTACK_ADDR 0xbffffff0 | ||
59 | #define MPC10X_MAPA_PCI_IO_START 0x00000000 | ||
60 | #define MPC10X_MAPA_PCI_IO_END (0x00800000 - 1) | ||
61 | #define MPC10X_MAPA_PCI_MEM_START 0x00000000 | ||
62 | #define MPC10X_MAPA_PCI_MEM_END (0x20000000 - 1) | ||
63 | |||
64 | #define MPC10X_MAPA_PCI_MEM_OFFSET (MPC10X_MAPA_ISA_MEM_BASE - \ | ||
65 | MPC10X_MAPA_PCI_MEM_START) | ||
66 | |||
67 | /* Map B (CHRP Map) Defines */ | ||
68 | #define MPC10X_MAPB_CNFG_ADDR 0xfec00000 | ||
69 | #define MPC10X_MAPB_CNFG_DATA 0xfee00000 | ||
70 | |||
71 | #define MPC10X_MAPB_ISA_IO_BASE 0xfe000000 | ||
72 | #define MPC10X_MAPB_ISA_MEM_BASE 0x80000000 | ||
73 | #define MPC10X_MAPB_DRAM_OFFSET 0x00000000 | ||
74 | |||
75 | #define MPC10X_MAPB_PCI_INTACK_ADDR 0xfef00000 | ||
76 | #define MPC10X_MAPB_PCI_IO_START 0x00000000 | ||
77 | #define MPC10X_MAPB_PCI_IO_END (0x00c00000 - 1) | ||
78 | #define MPC10X_MAPB_PCI_MEM_START 0x80000000 | ||
79 | #define MPC10X_MAPB_PCI_MEM_END (0xc0000000 - 1) | ||
80 | |||
81 | #define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \ | ||
82 | MPC10X_MAPB_PCI_MEM_START) | ||
83 | |||
84 | /* Set hose members to values appropriate for the mem map used */ | ||
85 | #define MPC10X_SETUP_HOSE(hose, map) { \ | ||
86 | (hose)->pci_mem_offset = MPC10X_MAP##map##_PCI_MEM_OFFSET; \ | ||
87 | (hose)->io_space.start = MPC10X_MAP##map##_PCI_IO_START; \ | ||
88 | (hose)->io_space.end = MPC10X_MAP##map##_PCI_IO_END; \ | ||
89 | (hose)->mem_space.start = MPC10X_MAP##map##_PCI_MEM_START; \ | ||
90 | (hose)->mem_space.end = MPC10X_MAP##map##_PCI_MEM_END; \ | ||
91 | (hose)->io_base_virt = (void *)MPC10X_MAP##map##_ISA_IO_BASE; \ | ||
92 | } | ||
93 | |||
94 | |||
95 | /* Miscellaneous Configuration register offsets */ | ||
96 | #define MPC10X_CFG_PIR_REG 0x09 | ||
97 | #define MPC10X_CFG_PIR_HOST_BRIDGE 0x00 | ||
98 | #define MPC10X_CFG_PIR_AGENT 0x01 | ||
99 | |||
100 | #define MPC10X_CFG_EUMBBAR 0x78 | ||
101 | |||
102 | #define MPC10X_CFG_PICR1_REG 0xa8 | ||
103 | #define MPC10X_CFG_PICR1_ADDR_MAP_MASK 0x00010000 | ||
104 | #define MPC10X_CFG_PICR1_ADDR_MAP_A 0x00010000 | ||
105 | #define MPC10X_CFG_PICR1_ADDR_MAP_B 0x00000000 | ||
106 | #define MPC10X_CFG_PICR1_SPEC_PCI_RD 0x00000004 | ||
107 | #define MPC10X_CFG_PICR1_ST_GATH_EN 0x00000040 | ||
108 | |||
109 | #define MPC10X_CFG_PICR2_REG 0xac | ||
110 | #define MPC10X_CFG_PICR2_COPYBACK_OPT 0x00000001 | ||
111 | |||
112 | #define MPC10X_CFG_MAPB_OPTIONS_REG 0xe0 | ||
113 | #define MPC10X_CFG_MAPB_OPTIONS_CFAE 0x80 /* CPU_FD_ALIAS_EN */ | ||
114 | #define MPC10X_CFG_MAPB_OPTIONS_PFAE 0x40 /* PCI_FD_ALIAS_EN */ | ||
115 | #define MPC10X_CFG_MAPB_OPTIONS_DR 0x20 /* DLL_RESET */ | ||
116 | #define MPC10X_CFG_MAPB_OPTIONS_PCICH 0x08 /* PCI_COMPATIBILITY_HOLE */ | ||
117 | #define MPC10X_CFG_MAPB_OPTIONS_PROCCH 0x04 /* PROC_COMPATIBILITY_HOLE */ | ||
118 | |||
119 | /* Define offsets for the memory controller registers in the config space */ | ||
120 | #define MPC10X_MCTLR_MEM_START_1 0x80 /* Banks 0-3 */ | ||
121 | #define MPC10X_MCTLR_MEM_START_2 0x84 /* Banks 4-7 */ | ||
122 | #define MPC10X_MCTLR_EXT_MEM_START_1 0x88 /* Banks 0-3 */ | ||
123 | #define MPC10X_MCTLR_EXT_MEM_START_2 0x8c /* Banks 4-7 */ | ||
124 | |||
125 | #define MPC10X_MCTLR_MEM_END_1 0x90 /* Banks 0-3 */ | ||
126 | #define MPC10X_MCTLR_MEM_END_2 0x94 /* Banks 4-7 */ | ||
127 | #define MPC10X_MCTLR_EXT_MEM_END_1 0x98 /* Banks 0-3 */ | ||
128 | #define MPC10X_MCTLR_EXT_MEM_END_2 0x9c /* Banks 4-7 */ | ||
129 | |||
130 | #define MPC10X_MCTLR_MEM_BANK_ENABLES 0xa0 | ||
131 | |||
132 | /* Define some offset in the EUMB */ | ||
133 | #define MPC10X_EUMB_SIZE 0x00100000 /* Total EUMB size (1MB) */ | ||
134 | |||
135 | #define MPC10X_EUMB_MU_OFFSET 0x00000000 /* Msg Unit reg offset */ | ||
136 | #define MPC10X_EUMB_MU_SIZE 0x00001000 /* Msg Unit reg size */ | ||
137 | #define MPC10X_EUMB_DMA_OFFSET 0x00001000 /* DMA Unit reg offset */ | ||
138 | #define MPC10X_EUMB_DMA_SIZE 0x00001000 /* DMA Unit reg size */ | ||
139 | #define MPC10X_EUMB_ATU_OFFSET 0x00002000 /* Addr xlate reg offset */ | ||
140 | #define MPC10X_EUMB_ATU_SIZE 0x00001000 /* Addr xlate reg size */ | ||
141 | #define MPC10X_EUMB_I2C_OFFSET 0x00003000 /* I2C Unit reg offset */ | ||
142 | #define MPC10X_EUMB_I2C_SIZE 0x00001000 /* I2C Unit reg size */ | ||
143 | #define MPC10X_EUMB_DUART_OFFSET 0x00004000 /* DUART Unit reg offset (8245) */ | ||
144 | #define MPC10X_EUMB_DUART_SIZE 0x00001000 /* DUART Unit reg size (8245) */ | ||
145 | #define MPC10X_EUMB_EPIC_OFFSET 0x00040000 /* EPIC offset in EUMB */ | ||
146 | #define MPC10X_EUMB_EPIC_SIZE 0x00030000 /* EPIC size */ | ||
147 | #define MPC10X_EUMB_PM_OFFSET 0x000fe000 /* Performance Monitor reg offset (8245) */ | ||
148 | #define MPC10X_EUMB_PM_SIZE 0x00001000 /* Performance Monitor reg size (8245) */ | ||
149 | #define MPC10X_EUMB_WP_OFFSET 0x000ff000 /* Data path diagnostic, watchpoint reg offset */ | ||
150 | #define MPC10X_EUMB_WP_SIZE 0x00001000 /* Data path diagnostic, watchpoint reg size */ | ||
151 | |||
152 | /* | ||
153 | * Define some recommended places to put the EUMB regs. | ||
154 | * For both maps, recommend putting the EUMB from 0xeff00000 to 0xefffffff. | ||
155 | */ | ||
156 | extern unsigned long ioremap_base; | ||
157 | #define MPC10X_MAPA_EUMB_BASE (ioremap_base - MPC10X_EUMB_SIZE) | ||
158 | #define MPC10X_MAPB_EUMB_BASE MPC10X_MAPA_EUMB_BASE | ||
159 | |||
160 | enum ppc_sys_devices { | ||
161 | MPC10X_IIC1, | ||
162 | MPC10X_DMA0, | ||
163 | MPC10X_DMA1, | ||
164 | MPC10X_UART0, | ||
165 | MPC10X_UART1, | ||
166 | NUM_PPC_SYS_DEVS, | ||
167 | }; | ||
168 | |||
169 | int mpc10x_bridge_init(struct pci_controller *hose, | ||
170 | uint current_map, | ||
171 | uint new_map, | ||
172 | uint phys_eumb_base); | ||
173 | unsigned long mpc10x_get_mem_size(uint mem_map); | ||
174 | int mpc10x_enable_store_gathering(struct pci_controller *hose); | ||
175 | int mpc10x_disable_store_gathering(struct pci_controller *hose); | ||
176 | |||
177 | /* For MPC107 boards that use the built-in openpic */ | ||
178 | void mpc10x_set_openpic(void); | ||
179 | |||
180 | #endif /* __PPC_KERNEL_MPC10X_H */ | ||
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 1e3cc69487b5..a2c04b9d42b1 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <asm/pci-bridge.h> | 40 | #include <asm/pci-bridge.h> |
41 | #include <asm/reg.h> | 41 | #include <asm/reg.h> |
42 | #include <mm/mmu_decl.h> | 42 | #include <mm/mmu_decl.h> |
43 | #include "mpc7448_hpc2.h" | ||
44 | #include <asm/tsi108_pci.h> | 43 | #include <asm/tsi108_pci.h> |
45 | #include <asm/tsi108_irq.h> | 44 | #include <asm/tsi108_irq.h> |
46 | #include <asm/mpic.h> | 45 | #include <asm/mpic.h> |
@@ -75,7 +74,7 @@ static void __init mpc7448_hpc2_setup_arch(void) | |||
75 | 74 | ||
76 | /* setup PCI host bridge */ | 75 | /* setup PCI host bridge */ |
77 | #ifdef CONFIG_PCI | 76 | #ifdef CONFIG_PCI |
78 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 77 | for_each_compatible_node(np, "pci", "tsi108-pci") |
79 | tsi108_setup_pci(np, MPC7448HPC2_PCI_CFG_PHYS, 0); | 78 | tsi108_setup_pci(np, MPC7448HPC2_PCI_CFG_PHYS, 0); |
80 | 79 | ||
81 | ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device; | 80 | ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device; |
@@ -91,7 +90,7 @@ static void __init mpc7448_hpc2_setup_arch(void) | |||
91 | } | 90 | } |
92 | 91 | ||
93 | /* | 92 | /* |
94 | * Interrupt setup and service. Interrrupts on the mpc7448_hpc2 come | 93 | * Interrupt setup and service. Interrupts on the mpc7448_hpc2 come |
95 | * from the four external INT pins, PCI interrupts are routed via | 94 | * from the four external INT pins, PCI interrupts are routed via |
96 | * PCI interrupt control registers, it generates internal IRQ23 | 95 | * PCI interrupt control registers, it generates internal IRQ23 |
97 | * | 96 | * |
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h deleted file mode 100644 index f7e0e0c7f8d8..000000000000 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* | ||
2 | * mpc7448_hpc2.h | ||
3 | * | ||
4 | * Definitions for Freescale MPC7448_HPC2 platform | ||
5 | * | ||
6 | * Author: Jacob Pan | ||
7 | * jacob.pan@freescale.com | ||
8 | * Maintainer: Roy Zang <roy.zang@freescale.com> | ||
9 | * | ||
10 | * 2006 (c) Freescale Semiconductor, Inc. This file is licensed under | ||
11 | * the terms of the GNU General Public License version 2. This program | ||
12 | * is licensed "as is" without any warranty of any kind, whether express | ||
13 | * or implied. | ||
14 | */ | ||
15 | |||
16 | #ifndef __PPC_PLATFORMS_MPC7448_HPC2_H | ||
17 | #define __PPC_PLATFORMS_MPC7448_HPC2_H | ||
18 | |||
19 | #include <asm/ppcboot.h> | ||
20 | |||
21 | #endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ | ||
diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c index 53420951dc53..e484cac75095 100644 --- a/arch/powerpc/platforms/embedded6xx/prpmc2800.c +++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c | |||
@@ -44,7 +44,6 @@ static void __init prpmc2800_setup_arch(void) | |||
44 | struct device_node *np; | 44 | struct device_node *np; |
45 | phys_addr_t paddr; | 45 | phys_addr_t paddr; |
46 | const unsigned int *reg; | 46 | const unsigned int *reg; |
47 | const unsigned int *prop; | ||
48 | 47 | ||
49 | /* | 48 | /* |
50 | * ioremap mpp and gpp registers in case they are later | 49 | * ioremap mpp and gpp registers in case they are later |
@@ -62,12 +61,6 @@ static void __init prpmc2800_setup_arch(void) | |||
62 | of_node_put(np); | 61 | of_node_put(np); |
63 | mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); | 62 | mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); |
64 | 63 | ||
65 | np = of_find_node_by_type(NULL, "cpu"); | ||
66 | prop = of_get_property(np, "clock-frequency", NULL); | ||
67 | if (prop) | ||
68 | loops_per_jiffy = *prop / HZ; | ||
69 | of_node_put(np); | ||
70 | |||
71 | #ifdef CONFIG_PCI | 64 | #ifdef CONFIG_PCI |
72 | mv64x60_pci_init(); | 65 | mv64x60_pci_init(); |
73 | #endif | 66 | #endif |
@@ -158,6 +151,7 @@ define_machine(prpmc2800){ | |||
158 | .name = prpmc2800_platform_name, | 151 | .name = prpmc2800_platform_name, |
159 | .probe = prpmc2800_probe, | 152 | .probe = prpmc2800_probe, |
160 | .setup_arch = prpmc2800_setup_arch, | 153 | .setup_arch = prpmc2800_setup_arch, |
154 | .init_early = mv64x60_init_early, | ||
161 | .show_cpuinfo = prpmc2800_show_cpuinfo, | 155 | .show_cpuinfo = prpmc2800_show_cpuinfo, |
162 | .init_IRQ = mv64x60_init_irq, | 156 | .init_IRQ = mv64x60_init_irq, |
163 | .get_irq = mv64x60_get_irq, | 157 | .get_irq = mv64x60_get_irq, |
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 13ac3015d91c..a65f1b44abf8 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile | |||
@@ -2,11 +2,12 @@ EXTRA_CFLAGS += -mno-minimal-toc | |||
2 | 2 | ||
3 | extra-y += dt.o | 3 | extra-y += dt.o |
4 | 4 | ||
5 | obj-y += exception.o | ||
5 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ | 6 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ |
6 | hvcall.o proc.o htab.o iommu.o misc.o irq.o | 7 | hvcall.o proc.o htab.o iommu.o misc.o irq.o |
7 | obj-$(CONFIG_PCI) += pci.o vpdinfo.o | 8 | obj-$(CONFIG_PCI) += pci.o vpdinfo.o |
8 | obj-$(CONFIG_SMP) += smp.o | 9 | obj-$(CONFIG_SMP) += smp.o |
9 | obj-$(CONFIG_VIOPATH) += viopath.o | 10 | obj-$(CONFIG_VIOPATH) += viopath.o vio.o |
10 | obj-$(CONFIG_MODULES) += ksyms.o | 11 | obj-$(CONFIG_MODULES) += ksyms.o |
11 | 12 | ||
12 | quiet_cmd_dt_strings = DT_STR $@ | 13 | quiet_cmd_dt_strings = DT_STR $@ |
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 9e8a334a518a..4543c4bc3a56 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c | |||
@@ -72,8 +72,6 @@ static char __initdata device_type_cpu[] = "cpu"; | |||
72 | static char __initdata device_type_memory[] = "memory"; | 72 | static char __initdata device_type_memory[] = "memory"; |
73 | static char __initdata device_type_serial[] = "serial"; | 73 | static char __initdata device_type_serial[] = "serial"; |
74 | static char __initdata device_type_network[] = "network"; | 74 | static char __initdata device_type_network[] = "network"; |
75 | static char __initdata device_type_block[] = "block"; | ||
76 | static char __initdata device_type_byte[] = "byte"; | ||
77 | static char __initdata device_type_pci[] = "pci"; | 75 | static char __initdata device_type_pci[] = "pci"; |
78 | static char __initdata device_type_vdevice[] = "vdevice"; | 76 | static char __initdata device_type_vdevice[] = "vdevice"; |
79 | static char __initdata device_type_vscsi[] = "vscsi"; | 77 | static char __initdata device_type_vscsi[] = "vscsi"; |
@@ -375,21 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) | |||
375 | 373 | ||
376 | dt_end_node(dt); | 374 | dt_end_node(dt); |
377 | } | 375 | } |
378 | reg += HVMAXARCHITECTEDVIRTUALLANS; | ||
379 | |||
380 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) | ||
381 | dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, | ||
382 | "IBM,iSeries-viodasd", 1); | ||
383 | reg += HVMAXARCHITECTEDVIRTUALDISKS; | ||
384 | |||
385 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) | ||
386 | dt_do_vdevice(dt, "viocd", reg, i, device_type_block, | ||
387 | "IBM,iSeries-viocd", 1); | ||
388 | reg += HVMAXARCHITECTEDVIRTUALCDROMS; | ||
389 | |||
390 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) | ||
391 | dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, | ||
392 | "IBM,iSeries-viotape", 1); | ||
393 | 376 | ||
394 | dt_end_node(dt); | 377 | dt_end_node(dt); |
395 | } | 378 | } |
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S new file mode 100644 index 000000000000..5381038f0881 --- /dev/null +++ b/arch/powerpc/platforms/iseries/exception.S | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Low level routines for legacy iSeries support. | ||
3 | * | ||
4 | * Extracted from head_64.S | ||
5 | * | ||
6 | * PowerPC version | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * | ||
9 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | ||
10 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> | ||
11 | * Adapted for Power Macintosh by Paul Mackerras. | ||
12 | * Low-level exception handlers and MMU support | ||
13 | * rewritten by Paul Mackerras. | ||
14 | * Copyright (C) 1996 Paul Mackerras. | ||
15 | * | ||
16 | * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and | ||
17 | * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com | ||
18 | * | ||
19 | * This file contains the low-level support and setup for the | ||
20 | * PowerPC-64 platform, including trap and interrupt dispatch. | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or | ||
23 | * modify it under the terms of the GNU General Public License | ||
24 | * as published by the Free Software Foundation; either version | ||
25 | * 2 of the License, or (at your option) any later version. | ||
26 | */ | ||
27 | |||
28 | #include <asm/reg.h> | ||
29 | #include <asm/ppc_asm.h> | ||
30 | #include <asm/asm-offsets.h> | ||
31 | #include <asm/thread_info.h> | ||
32 | #include <asm/ptrace.h> | ||
33 | #include <asm/cputable.h> | ||
34 | |||
35 | #include "exception.h" | ||
36 | |||
37 | .text | ||
38 | |||
39 | .globl system_reset_iSeries | ||
40 | system_reset_iSeries: | ||
41 | mfspr r13,SPRN_SPRG3 /* Get paca address */ | ||
42 | mfmsr r24 | ||
43 | ori r24,r24,MSR_RI | ||
44 | mtmsrd r24 /* RI on */ | ||
45 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | ||
46 | cmpwi 0,r24,0 /* Are we processor 0? */ | ||
47 | bne 1f | ||
48 | b .__start_initialization_iSeries /* Start up the first processor */ | ||
49 | 1: mfspr r4,SPRN_CTRLF | ||
50 | li r5,CTRL_RUNLATCH /* Turn off the run light */ | ||
51 | andc r4,r4,r5 | ||
52 | mtspr SPRN_CTRLT,r4 | ||
53 | |||
54 | 1: | ||
55 | HMT_LOW | ||
56 | #ifdef CONFIG_SMP | ||
57 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | ||
58 | * should start */ | ||
59 | sync | ||
60 | LOAD_REG_IMMEDIATE(r3,current_set) | ||
61 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
62 | ldx r3,r3,r28 | ||
63 | addi r1,r3,THREAD_SIZE | ||
64 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
65 | |||
66 | cmpwi 0,r23,0 | ||
67 | beq iSeries_secondary_smp_loop /* Loop until told to go */ | ||
68 | b __secondary_start /* Loop until told to go */ | ||
69 | iSeries_secondary_smp_loop: | ||
70 | /* Let the Hypervisor know we are alive */ | ||
71 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | ||
72 | lis r3,0x8002 | ||
73 | rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ | ||
74 | #else /* CONFIG_SMP */ | ||
75 | /* Yield the processor. This is required for non-SMP kernels | ||
76 | which are running on multi-threaded machines. */ | ||
77 | lis r3,0x8000 | ||
78 | rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ | ||
79 | addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ | ||
80 | li r4,0 /* "yield timed" */ | ||
81 | li r5,-1 /* "yield forever" */ | ||
82 | #endif /* CONFIG_SMP */ | ||
83 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | ||
84 | sc /* Invoke the hypervisor via a system call */ | ||
85 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ | ||
86 | b 1b /* If SMP not configured, secondaries | ||
87 | * loop forever */ | ||
88 | |||
89 | /*** ISeries-LPAR interrupt handlers ***/ | ||
90 | |||
91 | STD_EXCEPTION_ISERIES(machine_check, PACA_EXMC) | ||
92 | |||
93 | .globl data_access_iSeries | ||
94 | data_access_iSeries: | ||
95 | mtspr SPRN_SPRG1,r13 | ||
96 | BEGIN_FTR_SECTION | ||
97 | mtspr SPRN_SPRG2,r12 | ||
98 | mfspr r13,SPRN_DAR | ||
99 | mfspr r12,SPRN_DSISR | ||
100 | srdi r13,r13,60 | ||
101 | rlwimi r13,r12,16,0x20 | ||
102 | mfcr r12 | ||
103 | cmpwi r13,0x2c | ||
104 | beq .do_stab_bolted_iSeries | ||
105 | mtcrf 0x80,r12 | ||
106 | mfspr r12,SPRN_SPRG2 | ||
107 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
108 | EXCEPTION_PROLOG_1(PACA_EXGEN) | ||
109 | EXCEPTION_PROLOG_ISERIES_1 | ||
110 | b data_access_common | ||
111 | |||
112 | .do_stab_bolted_iSeries: | ||
113 | mtcrf 0x80,r12 | ||
114 | mfspr r12,SPRN_SPRG2 | ||
115 | EXCEPTION_PROLOG_1(PACA_EXSLB) | ||
116 | EXCEPTION_PROLOG_ISERIES_1 | ||
117 | b .do_stab_bolted | ||
118 | |||
119 | .globl data_access_slb_iSeries | ||
120 | data_access_slb_iSeries: | ||
121 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
122 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
123 | std r3,PACA_EXSLB+EX_R3(r13) | ||
124 | mfspr r3,SPRN_DAR | ||
125 | std r9,PACA_EXSLB+EX_R9(r13) | ||
126 | mfcr r9 | ||
127 | #ifdef __DISABLED__ | ||
128 | cmpdi r3,0 | ||
129 | bge slb_miss_user_iseries | ||
130 | #endif | ||
131 | std r10,PACA_EXSLB+EX_R10(r13) | ||
132 | std r11,PACA_EXSLB+EX_R11(r13) | ||
133 | std r12,PACA_EXSLB+EX_R12(r13) | ||
134 | mfspr r10,SPRN_SPRG1 | ||
135 | std r10,PACA_EXSLB+EX_R13(r13) | ||
136 | ld r12,PACALPPACAPTR(r13) | ||
137 | ld r12,LPPACASRR1(r12) | ||
138 | b .slb_miss_realmode | ||
139 | |||
140 | STD_EXCEPTION_ISERIES(instruction_access, PACA_EXGEN) | ||
141 | |||
142 | .globl instruction_access_slb_iSeries | ||
143 | instruction_access_slb_iSeries: | ||
144 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
145 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
146 | std r3,PACA_EXSLB+EX_R3(r13) | ||
147 | ld r3,PACALPPACAPTR(r13) | ||
148 | ld r3,LPPACASRR0(r3) /* get SRR0 value */ | ||
149 | std r9,PACA_EXSLB+EX_R9(r13) | ||
150 | mfcr r9 | ||
151 | #ifdef __DISABLED__ | ||
152 | cmpdi r3,0 | ||
153 | bge slb_miss_user_iseries | ||
154 | #endif | ||
155 | std r10,PACA_EXSLB+EX_R10(r13) | ||
156 | std r11,PACA_EXSLB+EX_R11(r13) | ||
157 | std r12,PACA_EXSLB+EX_R12(r13) | ||
158 | mfspr r10,SPRN_SPRG1 | ||
159 | std r10,PACA_EXSLB+EX_R13(r13) | ||
160 | ld r12,PACALPPACAPTR(r13) | ||
161 | ld r12,LPPACASRR1(r12) | ||
162 | b .slb_miss_realmode | ||
163 | |||
164 | #ifdef __DISABLED__ | ||
165 | slb_miss_user_iseries: | ||
166 | std r10,PACA_EXGEN+EX_R10(r13) | ||
167 | std r11,PACA_EXGEN+EX_R11(r13) | ||
168 | std r12,PACA_EXGEN+EX_R12(r13) | ||
169 | mfspr r10,SPRG1 | ||
170 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
171 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
172 | std r10,PACA_EXGEN+EX_R13(r13) | ||
173 | std r11,PACA_EXGEN+EX_R9(r13) | ||
174 | std r12,PACA_EXGEN+EX_R3(r13) | ||
175 | EXCEPTION_PROLOG_ISERIES_1 | ||
176 | b slb_miss_user_common | ||
177 | #endif | ||
178 | |||
179 | MASKABLE_EXCEPTION_ISERIES(hardware_interrupt) | ||
180 | STD_EXCEPTION_ISERIES(alignment, PACA_EXGEN) | ||
181 | STD_EXCEPTION_ISERIES(program_check, PACA_EXGEN) | ||
182 | STD_EXCEPTION_ISERIES(fp_unavailable, PACA_EXGEN) | ||
183 | MASKABLE_EXCEPTION_ISERIES(decrementer) | ||
184 | STD_EXCEPTION_ISERIES(trap_0a, PACA_EXGEN) | ||
185 | STD_EXCEPTION_ISERIES(trap_0b, PACA_EXGEN) | ||
186 | |||
187 | .globl system_call_iSeries | ||
188 | system_call_iSeries: | ||
189 | mr r9,r13 | ||
190 | mfspr r13,SPRN_SPRG3 | ||
191 | EXCEPTION_PROLOG_ISERIES_1 | ||
192 | b system_call_common | ||
193 | |||
194 | STD_EXCEPTION_ISERIES(single_step, PACA_EXGEN) | ||
195 | STD_EXCEPTION_ISERIES(trap_0e, PACA_EXGEN) | ||
196 | STD_EXCEPTION_ISERIES(performance_monitor, PACA_EXGEN) | ||
197 | |||
198 | decrementer_iSeries_masked: | ||
199 | /* We may not have a valid TOC pointer in here. */ | ||
200 | li r11,1 | ||
201 | ld r12,PACALPPACAPTR(r13) | ||
202 | stb r11,LPPACADECRINT(r12) | ||
203 | LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy) | ||
204 | lwz r12,0(r12) | ||
205 | mtspr SPRN_DEC,r12 | ||
206 | /* fall through */ | ||
207 | |||
208 | hardware_interrupt_iSeries_masked: | ||
209 | mtcrf 0x80,r9 /* Restore regs */ | ||
210 | ld r12,PACALPPACAPTR(r13) | ||
211 | ld r11,LPPACASRR0(r12) | ||
212 | ld r12,LPPACASRR1(r12) | ||
213 | mtspr SPRN_SRR0,r11 | ||
214 | mtspr SPRN_SRR1,r12 | ||
215 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
216 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
217 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
218 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
219 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
220 | rfid | ||
221 | b . /* prevent speculative execution */ | ||
222 | |||
223 | _INIT_STATIC(__start_initialization_iSeries) | ||
224 | /* Clear out the BSS */ | ||
225 | LOAD_REG_IMMEDIATE(r11,__bss_stop) | ||
226 | LOAD_REG_IMMEDIATE(r8,__bss_start) | ||
227 | sub r11,r11,r8 /* bss size */ | ||
228 | addi r11,r11,7 /* round up to an even double word */ | ||
229 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
230 | beq 4f | ||
231 | addi r8,r8,-8 | ||
232 | li r0,0 | ||
233 | mtctr r11 /* zero this many doublewords */ | ||
234 | 3: stdu r0,8(r8) | ||
235 | bdnz 3b | ||
236 | 4: | ||
237 | LOAD_REG_IMMEDIATE(r1,init_thread_union) | ||
238 | addi r1,r1,THREAD_SIZE | ||
239 | li r0,0 | ||
240 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
241 | |||
242 | LOAD_REG_IMMEDIATE(r2,__toc_start) | ||
243 | addi r2,r2,0x4000 | ||
244 | addi r2,r2,0x4000 | ||
245 | |||
246 | bl .iSeries_early_setup | ||
247 | bl .early_setup | ||
248 | |||
249 | /* relocation is on at this point */ | ||
250 | |||
251 | b .start_here_common | ||
diff --git a/arch/powerpc/platforms/iseries/exception.h b/arch/powerpc/platforms/iseries/exception.h new file mode 100644 index 000000000000..ced45a8fa1aa --- /dev/null +++ b/arch/powerpc/platforms/iseries/exception.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef _ASM_POWERPC_ISERIES_EXCEPTION_H | ||
2 | #define _ASM_POWERPC_ISERIES_EXCEPTION_H | ||
3 | /* | ||
4 | * Extracted from head_64.S | ||
5 | * | ||
6 | * PowerPC version | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * | ||
9 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | ||
10 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> | ||
11 | * Adapted for Power Macintosh by Paul Mackerras. | ||
12 | * Low-level exception handlers and MMU support | ||
13 | * rewritten by Paul Mackerras. | ||
14 | * Copyright (C) 1996 Paul Mackerras. | ||
15 | * | ||
16 | * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and | ||
17 | * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com | ||
18 | * | ||
19 | * This file contains the low-level support and setup for the | ||
20 | * PowerPC-64 platform, including trap and interrupt dispatch. | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or | ||
23 | * modify it under the terms of the GNU General Public License | ||
24 | * as published by the Free Software Foundation; either version | ||
25 | * 2 of the License, or (at your option) any later version. | ||
26 | */ | ||
27 | #include <asm/exception.h> | ||
28 | |||
29 | #define EXCEPTION_PROLOG_ISERIES_1 \ | ||
30 | mfmsr r10; \ | ||
31 | ld r12,PACALPPACAPTR(r13); \ | ||
32 | ld r11,LPPACASRR0(r12); \ | ||
33 | ld r12,LPPACASRR1(r12); \ | ||
34 | ori r10,r10,MSR_RI; \ | ||
35 | mtmsrd r10,1 | ||
36 | |||
37 | #define STD_EXCEPTION_ISERIES(label, area) \ | ||
38 | .globl label##_iSeries; \ | ||
39 | label##_iSeries: \ | ||
40 | HMT_MEDIUM; \ | ||
41 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
42 | EXCEPTION_PROLOG_1(area); \ | ||
43 | EXCEPTION_PROLOG_ISERIES_1; \ | ||
44 | b label##_common | ||
45 | |||
46 | #define MASKABLE_EXCEPTION_ISERIES(label) \ | ||
47 | .globl label##_iSeries; \ | ||
48 | label##_iSeries: \ | ||
49 | HMT_MEDIUM; \ | ||
50 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
51 | EXCEPTION_PROLOG_1(PACA_EXGEN); \ | ||
52 | lbz r10,PACASOFTIRQEN(r13); \ | ||
53 | cmpwi 0,r10,0; \ | ||
54 | beq- label##_iSeries_masked; \ | ||
55 | EXCEPTION_PROLOG_ISERIES_1; \ | ||
56 | b label##_common; \ | ||
57 | |||
58 | #endif /* _ASM_POWERPC_ISERIES_EXCEPTION_H */ | ||
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index b4e2c7a038e1..15a7097e5dd7 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c | |||
@@ -86,7 +86,8 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
86 | } | 86 | } |
87 | 87 | ||
88 | 88 | ||
89 | lhpte.v = hpte_encode_v(va, MMU_PAGE_4K) | vflags | HPTE_V_VALID; | 89 | lhpte.v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M) | |
90 | vflags | HPTE_V_VALID; | ||
90 | lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags; | 91 | lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags; |
91 | 92 | ||
92 | /* Now fill in the actual HPTE */ | 93 | /* Now fill in the actual HPTE */ |
@@ -142,7 +143,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group) | |||
142 | * bits 61..63 : PP2,PP1,PP0 | 143 | * bits 61..63 : PP2,PP1,PP0 |
143 | */ | 144 | */ |
144 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | 145 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, |
145 | unsigned long va, int psize, int local) | 146 | unsigned long va, int psize, int ssize, int local) |
146 | { | 147 | { |
147 | struct hash_pte hpte; | 148 | struct hash_pte hpte; |
148 | unsigned long want_v; | 149 | unsigned long want_v; |
@@ -150,7 +151,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
150 | iSeries_hlock(slot); | 151 | iSeries_hlock(slot); |
151 | 152 | ||
152 | HvCallHpt_get(&hpte, slot); | 153 | HvCallHpt_get(&hpte, slot); |
153 | want_v = hpte_encode_v(va, MMU_PAGE_4K); | 154 | want_v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M); |
154 | 155 | ||
155 | if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) { | 156 | if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) { |
156 | /* | 157 | /* |
@@ -205,14 +206,14 @@ static long iSeries_hpte_find(unsigned long vpn) | |||
205 | * No need to lock here because we should be the only user. | 206 | * No need to lock here because we should be the only user. |
206 | */ | 207 | */ |
207 | static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | 208 | static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, |
208 | int psize) | 209 | int psize, int ssize) |
209 | { | 210 | { |
210 | unsigned long vsid,va,vpn; | 211 | unsigned long vsid,va,vpn; |
211 | long slot; | 212 | long slot; |
212 | 213 | ||
213 | BUG_ON(psize != MMU_PAGE_4K); | 214 | BUG_ON(psize != MMU_PAGE_4K); |
214 | 215 | ||
215 | vsid = get_kernel_vsid(ea); | 216 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); |
216 | va = (vsid << 28) | (ea & 0x0fffffff); | 217 | va = (vsid << 28) | (ea & 0x0fffffff); |
217 | vpn = va >> HW_PAGE_SHIFT; | 218 | vpn = va >> HW_PAGE_SHIFT; |
218 | slot = iSeries_hpte_find(vpn); | 219 | slot = iSeries_hpte_find(vpn); |
@@ -222,7 +223,7 @@ static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
222 | } | 223 | } |
223 | 224 | ||
224 | static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, | 225 | static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, |
225 | int psize, int local) | 226 | int psize, int ssize, int local) |
226 | { | 227 | { |
227 | unsigned long hpte_v; | 228 | unsigned long hpte_v; |
228 | unsigned long avpn = va >> 23; | 229 | unsigned long avpn = va >> 23; |
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 3b6a9666c2c0..49e9c664ea89 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
@@ -28,14 +28,17 @@ | |||
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/module.h> | ||
31 | 32 | ||
32 | #include <asm/iommu.h> | 33 | #include <asm/iommu.h> |
34 | #include <asm/vio.h> | ||
33 | #include <asm/tce.h> | 35 | #include <asm/tce.h> |
34 | #include <asm/machdep.h> | 36 | #include <asm/machdep.h> |
35 | #include <asm/abs_addr.h> | 37 | #include <asm/abs_addr.h> |
36 | #include <asm/prom.h> | 38 | #include <asm/prom.h> |
37 | #include <asm/pci-bridge.h> | 39 | #include <asm/pci-bridge.h> |
38 | #include <asm/iseries/hv_call_xm.h> | 40 | #include <asm/iseries/hv_call_xm.h> |
41 | #include <asm/iseries/hv_call_event.h> | ||
39 | #include <asm/iseries/iommu.h> | 42 | #include <asm/iseries/iommu.h> |
40 | 43 | ||
41 | static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, | 44 | static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, |
@@ -189,6 +192,55 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) | |||
189 | } | 192 | } |
190 | #endif | 193 | #endif |
191 | 194 | ||
195 | static struct iommu_table veth_iommu_table; | ||
196 | static struct iommu_table vio_iommu_table; | ||
197 | |||
198 | void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag) | ||
199 | { | ||
200 | return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle, | ||
201 | DMA_32BIT_MASK, flag, -1); | ||
202 | } | ||
203 | EXPORT_SYMBOL_GPL(iseries_hv_alloc); | ||
204 | |||
205 | void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle) | ||
206 | { | ||
207 | iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle); | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(iseries_hv_free); | ||
210 | |||
211 | dma_addr_t iseries_hv_map(void *vaddr, size_t size, | ||
212 | enum dma_data_direction direction) | ||
213 | { | ||
214 | return iommu_map_single(&vio_iommu_table, vaddr, size, | ||
215 | DMA_32BIT_MASK, direction); | ||
216 | } | ||
217 | |||
218 | void iseries_hv_unmap(dma_addr_t dma_handle, size_t size, | ||
219 | enum dma_data_direction direction) | ||
220 | { | ||
221 | iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction); | ||
222 | } | ||
223 | |||
224 | void __init iommu_vio_init(void) | ||
225 | { | ||
226 | iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); | ||
227 | veth_iommu_table.it_size /= 2; | ||
228 | vio_iommu_table = veth_iommu_table; | ||
229 | vio_iommu_table.it_offset += veth_iommu_table.it_size; | ||
230 | |||
231 | if (!iommu_init_table(&veth_iommu_table, -1)) | ||
232 | printk("Virtual Bus VETH TCE table failed.\n"); | ||
233 | if (!iommu_init_table(&vio_iommu_table, -1)) | ||
234 | printk("Virtual Bus VIO TCE table failed.\n"); | ||
235 | } | ||
236 | |||
237 | struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev) | ||
238 | { | ||
239 | if (strcmp(dev->type, "network") == 0) | ||
240 | return &veth_iommu_table; | ||
241 | return &vio_iommu_table; | ||
242 | } | ||
243 | |||
192 | void iommu_init_early_iSeries(void) | 244 | void iommu_init_early_iSeries(void) |
193 | { | 245 | { |
194 | ppc_md.tce_build = tce_build_iSeries; | 246 | ppc_md.tce_build = tce_build_iSeries; |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 63b33675848b..701d9297c207 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -346,8 +346,15 @@ static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | static int iseries_irq_host_match(struct irq_host *h, struct device_node *np) | ||
350 | { | ||
351 | /* Match all */ | ||
352 | return 1; | ||
353 | } | ||
354 | |||
349 | static struct irq_host_ops iseries_irq_host_ops = { | 355 | static struct irq_host_ops iseries_irq_host_ops = { |
350 | .map = iseries_irq_host_map, | 356 | .map = iseries_irq_host_map, |
357 | .match = iseries_irq_host_match, | ||
351 | }; | 358 | }; |
352 | 359 | ||
353 | /* | 360 | /* |
@@ -369,7 +376,8 @@ void __init iSeries_init_IRQ(void) | |||
369 | /* Create irq host. No need for a revmap since HV will give us | 376 | /* Create irq host. No need for a revmap since HV will give us |
370 | * back our virtual irq number | 377 | * back our virtual irq number |
371 | */ | 378 | */ |
372 | host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0); | 379 | host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, |
380 | &iseries_irq_host_ops, 0); | ||
373 | BUG_ON(host == NULL); | 381 | BUG_ON(host == NULL); |
374 | irq_set_default_host(host); | 382 | irq_set_default_host(host); |
375 | 383 | ||
diff --git a/arch/powerpc/platforms/iseries/it_lp_naca.h b/arch/powerpc/platforms/iseries/it_lp_naca.h index 9bbf58986819..cf6dcf6ef07b 100644 --- a/arch/powerpc/platforms/iseries/it_lp_naca.h +++ b/arch/powerpc/platforms/iseries/it_lp_naca.h | |||
@@ -60,7 +60,7 @@ struct ItLpNaca { | |||
60 | u8 xRsvd2_0[128]; // Reserved x00-x7F | 60 | u8 xRsvd2_0[128]; // Reserved x00-x7F |
61 | 61 | ||
62 | // CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators | 62 | // CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators |
63 | // NB: Padding required to keep xInterrruptHdlr at x300 which is required | 63 | // NB: Padding required to keep xInterruptHdlr at x300 which is required |
64 | // for v4r4 PLIC. | 64 | // for v4r4 PLIC. |
65 | u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F | 65 | u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F |
66 | u8 xRsvd3_0[384]; // Reserved 180-2FF | 66 | u8 xRsvd3_0[384]; // Reserved 180-2FF |
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index b1187d95e3b2..c0f2433bc16e 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
@@ -39,9 +39,9 @@ | |||
39 | #include <asm/paca.h> | 39 | #include <asm/paca.h> |
40 | #include <asm/abs_addr.h> | 40 | #include <asm/abs_addr.h> |
41 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
42 | #include <asm/iseries/vio.h> | ||
43 | #include <asm/iseries/mf.h> | 42 | #include <asm/iseries/mf.h> |
44 | #include <asm/iseries/hv_lp_config.h> | 43 | #include <asm/iseries/hv_lp_config.h> |
44 | #include <asm/iseries/hv_lp_event.h> | ||
45 | #include <asm/iseries/it_lp_queue.h> | 45 | #include <asm/iseries/it_lp_queue.h> |
46 | 46 | ||
47 | #include "setup.h" | 47 | #include "setup.h" |
@@ -870,8 +870,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off, | |||
870 | if ((off + count) > 256) | 870 | if ((off + count) > 256) |
871 | count = 256 - off; | 871 | count = 256 - off; |
872 | 872 | ||
873 | dma_addr = dma_map_single(iSeries_vio_dev, page, off + count, | 873 | dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE); |
874 | DMA_FROM_DEVICE); | ||
875 | if (dma_mapping_error(dma_addr)) | 874 | if (dma_mapping_error(dma_addr)) |
876 | return -ENOMEM; | 875 | return -ENOMEM; |
877 | memset(page, 0, off + count); | 876 | memset(page, 0, off + count); |
@@ -883,8 +882,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off, | |||
883 | vsp_cmd.sub_data.kern.length = off + count; | 882 | vsp_cmd.sub_data.kern.length = off + count; |
884 | mb(); | 883 | mb(); |
885 | rc = signal_vsp_instruction(&vsp_cmd); | 884 | rc = signal_vsp_instruction(&vsp_cmd); |
886 | dma_unmap_single(iSeries_vio_dev, dma_addr, off + count, | 885 | iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE); |
887 | DMA_FROM_DEVICE); | ||
888 | if (rc) | 886 | if (rc) |
889 | return rc; | 887 | return rc; |
890 | if (vsp_cmd.result_code != 0) | 888 | if (vsp_cmd.result_code != 0) |
@@ -919,8 +917,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) | |||
919 | int len = *size; | 917 | int len = *size; |
920 | dma_addr_t dma_addr; | 918 | dma_addr_t dma_addr; |
921 | 919 | ||
922 | dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, | 920 | dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE); |
923 | DMA_FROM_DEVICE); | ||
924 | memset(buffer, 0, len); | 921 | memset(buffer, 0, len); |
925 | memset(&vsp_cmd, 0, sizeof(vsp_cmd)); | 922 | memset(&vsp_cmd, 0, sizeof(vsp_cmd)); |
926 | vsp_cmd.cmd = 32; | 923 | vsp_cmd.cmd = 32; |
@@ -938,7 +935,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) | |||
938 | rc = -ENOMEM; | 935 | rc = -ENOMEM; |
939 | } | 936 | } |
940 | 937 | ||
941 | dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); | 938 | iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE); |
942 | 939 | ||
943 | return rc; | 940 | return rc; |
944 | } | 941 | } |
@@ -1149,8 +1146,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, | |||
1149 | goto out; | 1146 | goto out; |
1150 | 1147 | ||
1151 | dma_addr = 0; | 1148 | dma_addr = 0; |
1152 | page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, | 1149 | page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC); |
1153 | GFP_ATOMIC); | ||
1154 | ret = -ENOMEM; | 1150 | ret = -ENOMEM; |
1155 | if (page == NULL) | 1151 | if (page == NULL) |
1156 | goto out; | 1152 | goto out; |
@@ -1170,7 +1166,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, | |||
1170 | ret = count; | 1166 | ret = count; |
1171 | 1167 | ||
1172 | out_free: | 1168 | out_free: |
1173 | dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); | 1169 | iseries_hv_free(count, page, dma_addr); |
1174 | out: | 1170 | out: |
1175 | return ret; | 1171 | return ret; |
1176 | } | 1172 | } |
@@ -1190,8 +1186,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file, | |||
1190 | goto out; | 1186 | goto out; |
1191 | 1187 | ||
1192 | dma_addr = 0; | 1188 | dma_addr = 0; |
1193 | page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, | 1189 | page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC); |
1194 | GFP_ATOMIC); | ||
1195 | rc = -ENOMEM; | 1190 | rc = -ENOMEM; |
1196 | if (page == NULL) { | 1191 | if (page == NULL) { |
1197 | printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); | 1192 | printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); |
@@ -1219,7 +1214,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file, | |||
1219 | *ppos += count; | 1214 | *ppos += count; |
1220 | rc = count; | 1215 | rc = count; |
1221 | out_free: | 1216 | out_free: |
1222 | dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); | 1217 | iseries_hv_free(count, page, dma_addr); |
1223 | out: | 1218 | out: |
1224 | return rc; | 1219 | return rc; |
1225 | } | 1220 | } |
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 13a8b1908ded..37ae07ee54a9 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/major.h> | 26 | #include <linux/major.h> |
27 | #include <linux/root_dev.h> | 27 | #include <linux/root_dev.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/hrtimer.h> | ||
30 | #include <linux/tick.h> | ||
29 | 31 | ||
30 | #include <asm/processor.h> | 32 | #include <asm/processor.h> |
31 | #include <asm/machdep.h> | 33 | #include <asm/machdep.h> |
@@ -41,7 +43,6 @@ | |||
41 | #include <asm/time.h> | 43 | #include <asm/time.h> |
42 | #include <asm/paca.h> | 44 | #include <asm/paca.h> |
43 | #include <asm/cache.h> | 45 | #include <asm/cache.h> |
44 | #include <asm/sections.h> | ||
45 | #include <asm/abs_addr.h> | 46 | #include <asm/abs_addr.h> |
46 | #include <asm/iseries/hv_lp_config.h> | 47 | #include <asm/iseries/hv_lp_config.h> |
47 | #include <asm/iseries/hv_call_event.h> | 48 | #include <asm/iseries/hv_call_event.h> |
@@ -562,6 +563,7 @@ static void yield_shared_processor(void) | |||
562 | static void iseries_shared_idle(void) | 563 | static void iseries_shared_idle(void) |
563 | { | 564 | { |
564 | while (1) { | 565 | while (1) { |
566 | tick_nohz_stop_sched_tick(); | ||
565 | while (!need_resched() && !hvlpevent_is_pending()) { | 567 | while (!need_resched() && !hvlpevent_is_pending()) { |
566 | local_irq_disable(); | 568 | local_irq_disable(); |
567 | ppc64_runlatch_off(); | 569 | ppc64_runlatch_off(); |
@@ -575,6 +577,7 @@ static void iseries_shared_idle(void) | |||
575 | } | 577 | } |
576 | 578 | ||
577 | ppc64_runlatch_on(); | 579 | ppc64_runlatch_on(); |
580 | tick_nohz_restart_sched_tick(); | ||
578 | 581 | ||
579 | if (hvlpevent_is_pending()) | 582 | if (hvlpevent_is_pending()) |
580 | process_iSeries_events(); | 583 | process_iSeries_events(); |
@@ -590,6 +593,7 @@ static void iseries_dedicated_idle(void) | |||
590 | set_thread_flag(TIF_POLLING_NRFLAG); | 593 | set_thread_flag(TIF_POLLING_NRFLAG); |
591 | 594 | ||
592 | while (1) { | 595 | while (1) { |
596 | tick_nohz_stop_sched_tick(); | ||
593 | if (!need_resched()) { | 597 | if (!need_resched()) { |
594 | while (!need_resched()) { | 598 | while (!need_resched()) { |
595 | ppc64_runlatch_off(); | 599 | ppc64_runlatch_off(); |
@@ -606,6 +610,7 @@ static void iseries_dedicated_idle(void) | |||
606 | } | 610 | } |
607 | 611 | ||
608 | ppc64_runlatch_on(); | 612 | ppc64_runlatch_on(); |
613 | tick_nohz_restart_sched_tick(); | ||
609 | preempt_enable_no_resched(); | 614 | preempt_enable_no_resched(); |
610 | schedule(); | 615 | schedule(); |
611 | preempt_disable(); | 616 | preempt_disable(); |
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c new file mode 100644 index 000000000000..910b00b4703e --- /dev/null +++ b/arch/powerpc/platforms/iseries/vio.c | |||
@@ -0,0 +1,553 @@ | |||
1 | /* | ||
2 | * Legacy iSeries specific vio initialisation | ||
3 | * that needs to be built in (not a module). | ||
4 | * | ||
5 | * © Copyright 2007 IBM Corporation | ||
6 | * Author: Stephen Rothwell | ||
7 | * Some parts collected from various other files | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License as | ||
11 | * published by the Free Software Foundation; either version 2 of the | ||
12 | * License, or (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software Foundation, | ||
21 | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/gfp.h> | ||
26 | #include <linux/completion.h> | ||
27 | #include <linux/proc_fs.h> | ||
28 | #include <linux/module.h> | ||
29 | |||
30 | #include <asm/firmware.h> | ||
31 | #include <asm/vio.h> | ||
32 | #include <asm/iseries/vio.h> | ||
33 | #include <asm/iseries/iommu.h> | ||
34 | #include <asm/iseries/hv_types.h> | ||
35 | #include <asm/iseries/hv_lp_event.h> | ||
36 | |||
37 | #define FIRST_VTY 0 | ||
38 | #define NUM_VTYS 1 | ||
39 | #define FIRST_VSCSI (FIRST_VTY + NUM_VTYS) | ||
40 | #define NUM_VSCSIS 1 | ||
41 | #define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS) | ||
42 | #define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS | ||
43 | #define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS) | ||
44 | #define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS | ||
45 | #define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS) | ||
46 | #define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS | ||
47 | #define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS) | ||
48 | #define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES | ||
49 | |||
50 | struct vio_waitevent { | ||
51 | struct completion com; | ||
52 | int rc; | ||
53 | u16 sub_result; | ||
54 | }; | ||
55 | |||
56 | struct vio_resource { | ||
57 | char rsrcname[10]; | ||
58 | char type[4]; | ||
59 | char model[3]; | ||
60 | }; | ||
61 | |||
62 | static struct property *new_property(const char *name, int length, | ||
63 | const void *value) | ||
64 | { | ||
65 | struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length, | ||
66 | GFP_KERNEL); | ||
67 | |||
68 | if (!np) | ||
69 | return NULL; | ||
70 | np->name = (char *)(np + 1); | ||
71 | np->value = np->name + strlen(name) + 1; | ||
72 | strcpy(np->name, name); | ||
73 | memcpy(np->value, value, length); | ||
74 | np->length = length; | ||
75 | return np; | ||
76 | } | ||
77 | |||
78 | static void __init free_property(struct property *np) | ||
79 | { | ||
80 | kfree(np); | ||
81 | } | ||
82 | |||
83 | static struct device_node *new_node(const char *path, | ||
84 | struct device_node *parent) | ||
85 | { | ||
86 | struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL); | ||
87 | |||
88 | if (!np) | ||
89 | return NULL; | ||
90 | np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL); | ||
91 | if (!np->full_name) { | ||
92 | kfree(np); | ||
93 | return NULL; | ||
94 | } | ||
95 | strcpy(np->full_name, path); | ||
96 | of_node_set_flag(np, OF_DYNAMIC); | ||
97 | kref_init(&np->kref); | ||
98 | np->parent = of_node_get(parent); | ||
99 | return np; | ||
100 | } | ||
101 | |||
102 | static void free_node(struct device_node *np) | ||
103 | { | ||
104 | struct property *next; | ||
105 | struct property *prop; | ||
106 | |||
107 | next = np->properties; | ||
108 | while (next) { | ||
109 | prop = next; | ||
110 | next = prop->next; | ||
111 | free_property(prop); | ||
112 | } | ||
113 | of_node_put(np->parent); | ||
114 | kfree(np->full_name); | ||
115 | kfree(np); | ||
116 | } | ||
117 | |||
118 | static int add_string_property(struct device_node *np, const char *name, | ||
119 | const char *value) | ||
120 | { | ||
121 | struct property *nprop = new_property(name, strlen(value) + 1, value); | ||
122 | |||
123 | if (!nprop) | ||
124 | return 0; | ||
125 | prom_add_property(np, nprop); | ||
126 | return 1; | ||
127 | } | ||
128 | |||
129 | static int add_raw_property(struct device_node *np, const char *name, | ||
130 | int length, const void *value) | ||
131 | { | ||
132 | struct property *nprop = new_property(name, length, value); | ||
133 | |||
134 | if (!nprop) | ||
135 | return 0; | ||
136 | prom_add_property(np, nprop); | ||
137 | return 1; | ||
138 | } | ||
139 | |||
140 | static struct device_node *do_device_node(struct device_node *parent, | ||
141 | const char *name, u32 reg, u32 unit, const char *type, | ||
142 | const char *compat, struct vio_resource *res) | ||
143 | { | ||
144 | struct device_node *np; | ||
145 | char path[32]; | ||
146 | |||
147 | snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg); | ||
148 | np = new_node(path, parent); | ||
149 | if (!np) | ||
150 | return NULL; | ||
151 | if (!add_string_property(np, "name", name) || | ||
152 | !add_string_property(np, "device_type", type) || | ||
153 | !add_string_property(np, "compatible", compat) || | ||
154 | !add_raw_property(np, "reg", sizeof(reg), ®) || | ||
155 | !add_raw_property(np, "linux,unit_address", | ||
156 | sizeof(unit), &unit)) { | ||
157 | goto node_free; | ||
158 | } | ||
159 | if (res) { | ||
160 | if (!add_raw_property(np, "linux,vio_rsrcname", | ||
161 | sizeof(res->rsrcname), res->rsrcname) || | ||
162 | !add_raw_property(np, "linux,vio_type", | ||
163 | sizeof(res->type), res->type) || | ||
164 | !add_raw_property(np, "linux,vio_model", | ||
165 | sizeof(res->model), res->model)) | ||
166 | goto node_free; | ||
167 | } | ||
168 | np->name = of_get_property(np, "name", NULL); | ||
169 | np->type = of_get_property(np, "device_type", NULL); | ||
170 | of_attach_node(np); | ||
171 | #ifdef CONFIG_PROC_DEVICETREE | ||
172 | if (parent->pde) { | ||
173 | struct proc_dir_entry *ent; | ||
174 | |||
175 | ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde); | ||
176 | if (ent) | ||
177 | proc_device_tree_add_node(np, ent); | ||
178 | } | ||
179 | #endif | ||
180 | return np; | ||
181 | |||
182 | node_free: | ||
183 | free_node(np); | ||
184 | return NULL; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * This is here so that we can dynamically add viodasd | ||
189 | * devices without exposing all the above infrastructure. | ||
190 | */ | ||
191 | struct vio_dev *vio_create_viodasd(u32 unit) | ||
192 | { | ||
193 | struct device_node *vio_root; | ||
194 | struct device_node *np; | ||
195 | struct vio_dev *vdev = NULL; | ||
196 | |||
197 | vio_root = of_find_node_by_path("/vdevice"); | ||
198 | if (!vio_root) | ||
199 | return NULL; | ||
200 | np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit, | ||
201 | "block", "IBM,iSeries-viodasd", NULL); | ||
202 | of_node_put(vio_root); | ||
203 | if (np) { | ||
204 | vdev = vio_register_device_node(np); | ||
205 | if (!vdev) | ||
206 | free_node(np); | ||
207 | } | ||
208 | return vdev; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(vio_create_viodasd); | ||
211 | |||
212 | static void __init handle_block_event(struct HvLpEvent *event) | ||
213 | { | ||
214 | struct vioblocklpevent *bevent = (struct vioblocklpevent *)event; | ||
215 | struct vio_waitevent *pwe; | ||
216 | |||
217 | if (event == NULL) | ||
218 | /* Notification that a partition went away! */ | ||
219 | return; | ||
220 | /* First, we should NEVER get an int here...only acks */ | ||
221 | if (hvlpevent_is_int(event)) { | ||
222 | printk(KERN_WARNING "handle_viod_request: " | ||
223 | "Yikes! got an int in viodasd event handler!\n"); | ||
224 | if (hvlpevent_need_ack(event)) { | ||
225 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | ||
226 | HvCallEvent_ackLpEvent(event); | ||
227 | } | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { | ||
232 | case vioblockopen: | ||
233 | /* | ||
234 | * Handle a response to an open request. We get all the | ||
235 | * disk information in the response, so update it. The | ||
236 | * correlation token contains a pointer to a waitevent | ||
237 | * structure that has a completion in it. update the | ||
238 | * return code in the waitevent structure and post the | ||
239 | * completion to wake up the guy who sent the request | ||
240 | */ | ||
241 | pwe = (struct vio_waitevent *)event->xCorrelationToken; | ||
242 | pwe->rc = event->xRc; | ||
243 | pwe->sub_result = bevent->sub_result; | ||
244 | complete(&pwe->com); | ||
245 | break; | ||
246 | case vioblockclose: | ||
247 | break; | ||
248 | default: | ||
249 | printk(KERN_WARNING "handle_viod_request: unexpected subtype!"); | ||
250 | if (hvlpevent_need_ack(event)) { | ||
251 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | ||
252 | HvCallEvent_ackLpEvent(event); | ||
253 | } | ||
254 | } | ||
255 | } | ||
256 | |||
257 | static void __init probe_disk(struct device_node *vio_root, u32 unit) | ||
258 | { | ||
259 | HvLpEvent_Rc hvrc; | ||
260 | struct vio_waitevent we; | ||
261 | u16 flags = 0; | ||
262 | |||
263 | retry: | ||
264 | init_completion(&we.com); | ||
265 | |||
266 | /* Send the open event to OS/400 */ | ||
267 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
268 | HvLpEvent_Type_VirtualIo, | ||
269 | viomajorsubtype_blockio | vioblockopen, | ||
270 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
271 | viopath_sourceinst(viopath_hostLp), | ||
272 | viopath_targetinst(viopath_hostLp), | ||
273 | (u64)(unsigned long)&we, VIOVERSION << 16, | ||
274 | ((u64)unit << 48) | ((u64)flags<< 32), | ||
275 | 0, 0, 0); | ||
276 | if (hvrc != 0) { | ||
277 | printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n", | ||
278 | (int)hvrc); | ||
279 | return; | ||
280 | } | ||
281 | |||
282 | wait_for_completion(&we.com); | ||
283 | |||
284 | if (we.rc != 0) { | ||
285 | if (flags != 0) | ||
286 | return; | ||
287 | /* try again with read only flag set */ | ||
288 | flags = vioblockflags_ro; | ||
289 | goto retry; | ||
290 | } | ||
291 | |||
292 | /* Send the close event to OS/400. We DON'T expect a response */ | ||
293 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
294 | HvLpEvent_Type_VirtualIo, | ||
295 | viomajorsubtype_blockio | vioblockclose, | ||
296 | HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck, | ||
297 | viopath_sourceinst(viopath_hostLp), | ||
298 | viopath_targetinst(viopath_hostLp), | ||
299 | 0, VIOVERSION << 16, | ||
300 | ((u64)unit << 48) | ((u64)flags << 32), | ||
301 | 0, 0, 0); | ||
302 | if (hvrc != 0) { | ||
303 | printk(KERN_WARNING "probe_disk: " | ||
304 | "bad rc sending event to OS/400 %d\n", (int)hvrc); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit, | ||
309 | "block", "IBM,iSeries-viodasd", NULL); | ||
310 | } | ||
311 | |||
312 | static void __init get_viodasd_info(struct device_node *vio_root) | ||
313 | { | ||
314 | int rc; | ||
315 | u32 unit; | ||
316 | |||
317 | rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2); | ||
318 | if (rc) { | ||
319 | printk(KERN_WARNING "get_viodasd_info: " | ||
320 | "error opening path to host partition %d\n", | ||
321 | viopath_hostLp); | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | /* Initialize our request handler */ | ||
326 | vio_setHandler(viomajorsubtype_blockio, handle_block_event); | ||
327 | |||
328 | for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++) | ||
329 | probe_disk(vio_root, unit); | ||
330 | |||
331 | vio_clearHandler(viomajorsubtype_blockio); | ||
332 | viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2); | ||
333 | } | ||
334 | |||
335 | static void __init handle_cd_event(struct HvLpEvent *event) | ||
336 | { | ||
337 | struct viocdlpevent *bevent; | ||
338 | struct vio_waitevent *pwe; | ||
339 | |||
340 | if (!event) | ||
341 | /* Notification that a partition went away! */ | ||
342 | return; | ||
343 | |||
344 | /* First, we should NEVER get an int here...only acks */ | ||
345 | if (hvlpevent_is_int(event)) { | ||
346 | printk(KERN_WARNING "handle_cd_event: got an unexpected int\n"); | ||
347 | if (hvlpevent_need_ack(event)) { | ||
348 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | ||
349 | HvCallEvent_ackLpEvent(event); | ||
350 | } | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | bevent = (struct viocdlpevent *)event; | ||
355 | |||
356 | switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { | ||
357 | case viocdgetinfo: | ||
358 | pwe = (struct vio_waitevent *)event->xCorrelationToken; | ||
359 | pwe->rc = event->xRc; | ||
360 | pwe->sub_result = bevent->sub_result; | ||
361 | complete(&pwe->com); | ||
362 | break; | ||
363 | |||
364 | default: | ||
365 | printk(KERN_WARNING "handle_cd_event: " | ||
366 | "message with unexpected subtype %0x04X!\n", | ||
367 | event->xSubtype & VIOMINOR_SUBTYPE_MASK); | ||
368 | if (hvlpevent_need_ack(event)) { | ||
369 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | ||
370 | HvCallEvent_ackLpEvent(event); | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | static void __init get_viocd_info(struct device_node *vio_root) | ||
376 | { | ||
377 | HvLpEvent_Rc hvrc; | ||
378 | u32 unit; | ||
379 | struct vio_waitevent we; | ||
380 | struct vio_resource *unitinfo; | ||
381 | dma_addr_t unitinfo_dmaaddr; | ||
382 | int ret; | ||
383 | |||
384 | ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2); | ||
385 | if (ret) { | ||
386 | printk(KERN_WARNING | ||
387 | "get_viocd_info: error opening path to host partition %d\n", | ||
388 | viopath_hostLp); | ||
389 | return; | ||
390 | } | ||
391 | |||
392 | /* Initialize our request handler */ | ||
393 | vio_setHandler(viomajorsubtype_cdio, handle_cd_event); | ||
394 | |||
395 | unitinfo = iseries_hv_alloc( | ||
396 | sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, | ||
397 | &unitinfo_dmaaddr, GFP_ATOMIC); | ||
398 | if (!unitinfo) { | ||
399 | printk(KERN_WARNING | ||
400 | "get_viocd_info: error allocating unitinfo\n"); | ||
401 | goto clear_handler; | ||
402 | } | ||
403 | |||
404 | memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS); | ||
405 | |||
406 | init_completion(&we.com); | ||
407 | |||
408 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
409 | HvLpEvent_Type_VirtualIo, | ||
410 | viomajorsubtype_cdio | viocdgetinfo, | ||
411 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
412 | viopath_sourceinst(viopath_hostLp), | ||
413 | viopath_targetinst(viopath_hostLp), | ||
414 | (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, | ||
415 | sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0); | ||
416 | if (hvrc != HvLpEvent_Rc_Good) { | ||
417 | printk(KERN_WARNING | ||
418 | "get_viocd_info: cdrom error sending event. rc %d\n", | ||
419 | (int)hvrc); | ||
420 | goto hv_free; | ||
421 | } | ||
422 | |||
423 | wait_for_completion(&we.com); | ||
424 | |||
425 | if (we.rc) { | ||
426 | printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n", | ||
427 | we.rc, we.sub_result); | ||
428 | goto hv_free; | ||
429 | } | ||
430 | |||
431 | for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) && | ||
432 | unitinfo[unit].rsrcname[0]; unit++) { | ||
433 | if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit, | ||
434 | "block", "IBM,iSeries-viocd", &unitinfo[unit])) | ||
435 | break; | ||
436 | } | ||
437 | |||
438 | hv_free: | ||
439 | iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, | ||
440 | unitinfo, unitinfo_dmaaddr); | ||
441 | clear_handler: | ||
442 | vio_clearHandler(viomajorsubtype_cdio); | ||
443 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2); | ||
444 | } | ||
445 | |||
446 | /* Handle interrupt events for tape */ | ||
447 | static void __init handle_tape_event(struct HvLpEvent *event) | ||
448 | { | ||
449 | struct vio_waitevent *we; | ||
450 | struct viotapelpevent *tevent = (struct viotapelpevent *)event; | ||
451 | |||
452 | if (event == NULL) | ||
453 | /* Notification that a partition went away! */ | ||
454 | return; | ||
455 | |||
456 | we = (struct vio_waitevent *)event->xCorrelationToken; | ||
457 | switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { | ||
458 | case viotapegetinfo: | ||
459 | we->rc = tevent->sub_type_result; | ||
460 | complete(&we->com); | ||
461 | break; | ||
462 | default: | ||
463 | printk(KERN_WARNING "handle_tape_event: weird ack\n"); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static void __init get_viotape_info(struct device_node *vio_root) | ||
468 | { | ||
469 | HvLpEvent_Rc hvrc; | ||
470 | u32 unit; | ||
471 | struct vio_resource *unitinfo; | ||
472 | dma_addr_t unitinfo_dmaaddr; | ||
473 | size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES; | ||
474 | struct vio_waitevent we; | ||
475 | int ret; | ||
476 | |||
477 | ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2); | ||
478 | if (ret) { | ||
479 | printk(KERN_WARNING "get_viotape_info: " | ||
480 | "error on viopath_open to hostlp %d\n", ret); | ||
481 | return; | ||
482 | } | ||
483 | |||
484 | vio_setHandler(viomajorsubtype_tape, handle_tape_event); | ||
485 | |||
486 | unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC); | ||
487 | if (!unitinfo) | ||
488 | goto clear_handler; | ||
489 | |||
490 | memset(unitinfo, 0, len); | ||
491 | |||
492 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
493 | HvLpEvent_Type_VirtualIo, | ||
494 | viomajorsubtype_tape | viotapegetinfo, | ||
495 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
496 | viopath_sourceinst(viopath_hostLp), | ||
497 | viopath_targetinst(viopath_hostLp), | ||
498 | (u64)(unsigned long)&we, VIOVERSION << 16, | ||
499 | unitinfo_dmaaddr, len, 0, 0); | ||
500 | if (hvrc != HvLpEvent_Rc_Good) { | ||
501 | printk(KERN_WARNING "get_viotape_info: hv error on op %d\n", | ||
502 | (int)hvrc); | ||
503 | goto hv_free; | ||
504 | } | ||
505 | |||
506 | wait_for_completion(&we.com); | ||
507 | |||
508 | for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) && | ||
509 | unitinfo[unit].rsrcname[0]; unit++) { | ||
510 | if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit, | ||
511 | unit, "byte", "IBM,iSeries-viotape", | ||
512 | &unitinfo[unit])) | ||
513 | break; | ||
514 | } | ||
515 | |||
516 | hv_free: | ||
517 | iseries_hv_free(len, unitinfo, unitinfo_dmaaddr); | ||
518 | clear_handler: | ||
519 | vio_clearHandler(viomajorsubtype_tape); | ||
520 | viopath_close(viopath_hostLp, viomajorsubtype_tape, 2); | ||
521 | } | ||
522 | |||
523 | static int __init iseries_vio_init(void) | ||
524 | { | ||
525 | struct device_node *vio_root; | ||
526 | |||
527 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
528 | return -ENODEV; | ||
529 | |||
530 | iommu_vio_init(); | ||
531 | |||
532 | vio_root = of_find_node_by_path("/vdevice"); | ||
533 | if (!vio_root) | ||
534 | return -ENODEV; | ||
535 | |||
536 | if (viopath_hostLp == HvLpIndexInvalid) { | ||
537 | vio_set_hostlp(); | ||
538 | /* If we don't have a host, bail out */ | ||
539 | if (viopath_hostLp == HvLpIndexInvalid) | ||
540 | goto put_node; | ||
541 | } | ||
542 | |||
543 | get_viodasd_info(vio_root); | ||
544 | get_viocd_info(vio_root); | ||
545 | get_viotape_info(vio_root); | ||
546 | |||
547 | return 0; | ||
548 | |||
549 | put_node: | ||
550 | of_node_put(vio_root); | ||
551 | return -ENODEV; | ||
552 | } | ||
553 | arch_initcall(iseries_vio_init); | ||
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 6a0060a5f2ec..df23331eb25c 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c | |||
@@ -124,8 +124,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) | |||
124 | if (!buf) | 124 | if (!buf) |
125 | return 0; | 125 | return 0; |
126 | 126 | ||
127 | handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, | 127 | handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE); |
128 | DMA_FROM_DEVICE); | ||
129 | 128 | ||
130 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | 129 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, |
131 | HvLpEvent_Type_VirtualIo, | 130 | HvLpEvent_Type_VirtualIo, |
@@ -146,8 +145,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) | |||
146 | buf[HW_PAGE_SIZE-1] = '\0'; | 145 | buf[HW_PAGE_SIZE-1] = '\0'; |
147 | seq_printf(m, "%s", buf); | 146 | seq_printf(m, "%s", buf); |
148 | 147 | ||
149 | dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE, | 148 | iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE); |
150 | DMA_FROM_DEVICE); | ||
151 | kfree(buf); | 149 | kfree(buf); |
152 | 150 | ||
153 | seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); | 151 | seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); |
@@ -596,7 +594,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq) | |||
596 | numOpen += viopathStatus[remoteLp].users[i]; | 594 | numOpen += viopathStatus[remoteLp].users[i]; |
597 | 595 | ||
598 | if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { | 596 | if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { |
599 | printk(VIOPATH_KERN_INFO "closing connection to partition %d", | 597 | printk(VIOPATH_KERN_INFO "closing connection to partition %d\n", |
600 | remoteLp); | 598 | remoteLp); |
601 | 599 | ||
602 | HvCallEvent_closeLpEventPath(remoteLp, | 600 | HvCallEvent_closeLpEventPath(remoteLp, |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 2542403288f9..771ed0cf29a5 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -169,15 +169,12 @@ static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn, | |||
169 | switch (len) { | 169 | switch (len) { |
170 | case 1: | 170 | case 1: |
171 | out_8(addr, val); | 171 | out_8(addr, val); |
172 | (void) in_8(addr); | ||
173 | break; | 172 | break; |
174 | case 2: | 173 | case 2: |
175 | out_le16(addr, val); | 174 | out_le16(addr, val); |
176 | (void) in_le16(addr); | ||
177 | break; | 175 | break; |
178 | default: | 176 | default: |
179 | out_le32(addr, val); | 177 | out_le32(addr, val); |
180 | (void) in_le32(addr); | ||
181 | break; | 178 | break; |
182 | } | 179 | } |
183 | return PCIBIOS_SUCCESSFUL; | 180 | return PCIBIOS_SUCCESSFUL; |
@@ -185,8 +182,8 @@ static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn, | |||
185 | 182 | ||
186 | static struct pci_ops u3_agp_pci_ops = | 183 | static struct pci_ops u3_agp_pci_ops = |
187 | { | 184 | { |
188 | u3_agp_read_config, | 185 | .read = u3_agp_read_config, |
189 | u3_agp_write_config | 186 | .write = u3_agp_write_config, |
190 | }; | 187 | }; |
191 | 188 | ||
192 | static unsigned long u3_ht_cfa0(u8 devfn, u8 off) | 189 | static unsigned long u3_ht_cfa0(u8 devfn, u8 off) |
@@ -268,15 +265,12 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, | |||
268 | switch (len) { | 265 | switch (len) { |
269 | case 1: | 266 | case 1: |
270 | out_8(addr, val); | 267 | out_8(addr, val); |
271 | (void) in_8(addr); | ||
272 | break; | 268 | break; |
273 | case 2: | 269 | case 2: |
274 | out_le16(addr, val); | 270 | out_le16(addr, val); |
275 | (void) in_le16(addr); | ||
276 | break; | 271 | break; |
277 | default: | 272 | default: |
278 | out_le32(addr, val); | 273 | out_le32(addr, val); |
279 | (void) in_le32(addr); | ||
280 | break; | 274 | break; |
281 | } | 275 | } |
282 | return PCIBIOS_SUCCESSFUL; | 276 | return PCIBIOS_SUCCESSFUL; |
@@ -284,8 +278,8 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, | |||
284 | 278 | ||
285 | static struct pci_ops u3_ht_pci_ops = | 279 | static struct pci_ops u3_ht_pci_ops = |
286 | { | 280 | { |
287 | u3_ht_read_config, | 281 | .read = u3_ht_read_config, |
288 | u3_ht_write_config | 282 | .write = u3_ht_write_config, |
289 | }; | 283 | }; |
290 | 284 | ||
291 | static unsigned int u4_pcie_cfa0(unsigned int devfn, unsigned int off) | 285 | static unsigned int u4_pcie_cfa0(unsigned int devfn, unsigned int off) |
@@ -376,15 +370,12 @@ static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | |||
376 | switch (len) { | 370 | switch (len) { |
377 | case 1: | 371 | case 1: |
378 | out_8(addr, val); | 372 | out_8(addr, val); |
379 | (void) in_8(addr); | ||
380 | break; | 373 | break; |
381 | case 2: | 374 | case 2: |
382 | out_le16(addr, val); | 375 | out_le16(addr, val); |
383 | (void) in_le16(addr); | ||
384 | break; | 376 | break; |
385 | default: | 377 | default: |
386 | out_le32(addr, val); | 378 | out_le32(addr, val); |
387 | (void) in_le32(addr); | ||
388 | break; | 379 | break; |
389 | } | 380 | } |
390 | return PCIBIOS_SUCCESSFUL; | 381 | return PCIBIOS_SUCCESSFUL; |
@@ -392,8 +383,8 @@ static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | |||
392 | 383 | ||
393 | static struct pci_ops u4_pcie_pci_ops = | 384 | static struct pci_ops u4_pcie_pci_ops = |
394 | { | 385 | { |
395 | u4_pcie_read_config, | 386 | .read = u4_pcie_read_config, |
396 | u4_pcie_write_config | 387 | .write = u4_pcie_write_config, |
397 | }; | 388 | }; |
398 | 389 | ||
399 | static void __init setup_u3_agp(struct pci_controller* hose) | 390 | static void __init setup_u3_agp(struct pci_controller* hose) |
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index e95261ef6f98..735e1536cbfc 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig | |||
@@ -5,6 +5,7 @@ config PPC_PASEMI | |||
5 | select MPIC | 5 | select MPIC |
6 | select PPC_UDBG_16550 | 6 | select PPC_UDBG_16550 |
7 | select PPC_NATIVE | 7 | select PPC_NATIVE |
8 | select MPIC_BROKEN_REGREAD | ||
8 | help | 9 | help |
9 | This option enables support for PA Semi's PWRficient line | 10 | This option enables support for PA Semi's PWRficient line |
10 | of SoC processors, including PA6T-1682M | 11 | of SoC processors, including PA6T-1682M |
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index c91a33593bb8..dae9f658122e 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c | |||
@@ -320,10 +320,12 @@ static struct of_device_id gpio_mdio_match[] = | |||
320 | 320 | ||
321 | static struct of_platform_driver gpio_mdio_driver = | 321 | static struct of_platform_driver gpio_mdio_driver = |
322 | { | 322 | { |
323 | .name = "gpio-mdio-bitbang", | ||
324 | .match_table = gpio_mdio_match, | 323 | .match_table = gpio_mdio_match, |
325 | .probe = gpio_mdio_probe, | 324 | .probe = gpio_mdio_probe, |
326 | .remove = gpio_mdio_remove, | 325 | .remove = gpio_mdio_remove, |
326 | .driver = { | ||
327 | .name = "gpio-mdio-bitbang", | ||
328 | }, | ||
327 | }; | 329 | }; |
328 | 330 | ||
329 | int gpio_mdio_init(void) | 331 | int gpio_mdio_init(void) |
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c index 3c962d5757be..d8e1fcc78513 100644 --- a/arch/powerpc/platforms/pasemi/idle.c +++ b/arch/powerpc/platforms/pasemi/idle.c | |||
@@ -72,8 +72,11 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) | |||
72 | return 1; | 72 | return 1; |
73 | } | 73 | } |
74 | 74 | ||
75 | void __init pasemi_idle_init(void) | 75 | static int __init pasemi_idle_init(void) |
76 | { | 76 | { |
77 | if (!machine_is(pasemi)) | ||
78 | return -ENODEV; | ||
79 | |||
77 | #ifndef CONFIG_PPC_PASEMI_CPUFREQ | 80 | #ifndef CONFIG_PPC_PASEMI_CPUFREQ |
78 | printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); | 81 | printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); |
79 | current_mode = 0; | 82 | current_mode = 0; |
@@ -82,7 +85,10 @@ void __init pasemi_idle_init(void) | |||
82 | ppc_md.system_reset_exception = pasemi_system_reset_exception; | 85 | ppc_md.system_reset_exception = pasemi_system_reset_exception; |
83 | ppc_md.power_save = modes[current_mode].entry; | 86 | ppc_md.power_save = modes[current_mode].entry; |
84 | printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); | 87 | printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); |
88 | |||
89 | return 0; | ||
85 | } | 90 | } |
91 | late_initcall(pasemi_idle_init); | ||
86 | 92 | ||
87 | static int __init idle_param(char *p) | 93 | static int __init idle_param(char *p) |
88 | { | 94 | { |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index a1111b5c6cb4..9916a0f3e431 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
@@ -192,7 +192,7 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev) | |||
192 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } | 192 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } |
193 | static void pci_dma_dev_setup_null(struct pci_dev *d) { } | 193 | static void pci_dma_dev_setup_null(struct pci_dev *d) { } |
194 | 194 | ||
195 | int iob_init(struct device_node *dn) | 195 | int __init iob_init(struct device_node *dn) |
196 | { | 196 | { |
197 | unsigned long tmp; | 197 | unsigned long tmp; |
198 | u32 regword; | 198 | u32 regword; |
@@ -238,7 +238,7 @@ int iob_init(struct device_node *dn) | |||
238 | 238 | ||
239 | 239 | ||
240 | /* These are called very early. */ | 240 | /* These are called very early. */ |
241 | void iommu_init_early_pasemi(void) | 241 | void __init iommu_init_early_pasemi(void) |
242 | { | 242 | { |
243 | int iommu_off; | 243 | int iommu_off; |
244 | 244 | ||
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index be8495497611..516acabb4e96 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h | |||
@@ -6,9 +6,9 @@ extern void pas_pci_init(void); | |||
6 | extern void __devinit pas_pci_irq_fixup(struct pci_dev *dev); | 6 | extern void __devinit pas_pci_irq_fixup(struct pci_dev *dev); |
7 | extern void __devinit pas_pci_dma_dev_setup(struct pci_dev *dev); | 7 | extern void __devinit pas_pci_dma_dev_setup(struct pci_dev *dev); |
8 | 8 | ||
9 | extern void __init alloc_iobmap_l2(void); | 9 | extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset); |
10 | 10 | ||
11 | extern void __init pasemi_idle_init(void); | 11 | extern void __init alloc_iobmap_l2(void); |
12 | 12 | ||
13 | /* Power savings modes, implemented in asm */ | 13 | /* Power savings modes, implemented in asm */ |
14 | extern void idle_spin(void); | 14 | extern void idle_spin(void); |
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index ab1f5f62bcd8..b6a0ec45c695 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c | |||
@@ -51,6 +51,61 @@ static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose, | |||
51 | return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset); | 51 | return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset); |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline int is_root_port(int busno, int devfn) | ||
55 | { | ||
56 | return ((busno == 0) && (PCI_FUNC(devfn) < 4) && | ||
57 | ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17))); | ||
58 | } | ||
59 | |||
60 | static inline int is_5945_reg(int reg) | ||
61 | { | ||
62 | return (((reg >= 0x18) && (reg < 0x34)) || | ||
63 | ((reg >= 0x158) && (reg < 0x178))); | ||
64 | } | ||
65 | |||
66 | static int workaround_5945(struct pci_bus *bus, unsigned int devfn, | ||
67 | int offset, int len, u32 *val) | ||
68 | { | ||
69 | struct pci_controller *hose; | ||
70 | void volatile __iomem *addr, *dummy; | ||
71 | int byte; | ||
72 | u32 tmp; | ||
73 | |||
74 | if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset)) | ||
75 | return 0; | ||
76 | |||
77 | hose = pci_bus_to_host(bus); | ||
78 | |||
79 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3); | ||
80 | byte = offset & 0x3; | ||
81 | |||
82 | /* Workaround bug 5945: write 0 to a dummy register before reading, | ||
83 | * and write back what we read. We must read/write the full 32-bit | ||
84 | * contents so we need to shift and mask by hand. | ||
85 | */ | ||
86 | dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10); | ||
87 | out_le32(dummy, 0); | ||
88 | tmp = in_le32(addr); | ||
89 | out_le32(addr, tmp); | ||
90 | |||
91 | switch (len) { | ||
92 | case 1: | ||
93 | *val = (tmp >> (8*byte)) & 0xff; | ||
94 | break; | ||
95 | case 2: | ||
96 | if (byte == 0) | ||
97 | *val = tmp & 0xffff; | ||
98 | else | ||
99 | *val = (tmp >> 16) & 0xffff; | ||
100 | break; | ||
101 | default: | ||
102 | *val = tmp; | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | return 1; | ||
107 | } | ||
108 | |||
54 | static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, | 109 | static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, |
55 | int offset, int len, u32 *val) | 110 | int offset, int len, u32 *val) |
56 | { | 111 | { |
@@ -64,6 +119,9 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, | |||
64 | if (!pa_pxp_offset_valid(bus->number, devfn, offset)) | 119 | if (!pa_pxp_offset_valid(bus->number, devfn, offset)) |
65 | return PCIBIOS_BAD_REGISTER_NUMBER; | 120 | return PCIBIOS_BAD_REGISTER_NUMBER; |
66 | 121 | ||
122 | if (workaround_5945(bus, devfn, offset, len, val)) | ||
123 | return PCIBIOS_SUCCESSFUL; | ||
124 | |||
67 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); | 125 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); |
68 | 126 | ||
69 | /* | 127 | /* |
@@ -107,23 +165,20 @@ static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn, | |||
107 | switch (len) { | 165 | switch (len) { |
108 | case 1: | 166 | case 1: |
109 | out_8(addr, val); | 167 | out_8(addr, val); |
110 | (void) in_8(addr); | ||
111 | break; | 168 | break; |
112 | case 2: | 169 | case 2: |
113 | out_le16(addr, val); | 170 | out_le16(addr, val); |
114 | (void) in_le16(addr); | ||
115 | break; | 171 | break; |
116 | default: | 172 | default: |
117 | out_le32(addr, val); | 173 | out_le32(addr, val); |
118 | (void) in_le32(addr); | ||
119 | break; | 174 | break; |
120 | } | 175 | } |
121 | return PCIBIOS_SUCCESSFUL; | 176 | return PCIBIOS_SUCCESSFUL; |
122 | } | 177 | } |
123 | 178 | ||
124 | static struct pci_ops pa_pxp_ops = { | 179 | static struct pci_ops pa_pxp_ops = { |
125 | pa_pxp_read_config, | 180 | .read = pa_pxp_read_config, |
126 | pa_pxp_write_config, | 181 | .write = pa_pxp_write_config, |
127 | }; | 182 | }; |
128 | 183 | ||
129 | static void __init setup_pa_pxp(struct pci_controller *hose) | 184 | static void __init setup_pa_pxp(struct pci_controller *hose) |
@@ -178,3 +233,12 @@ void __init pas_pci_init(void) | |||
178 | /* Use the common resource allocation mechanism */ | 233 | /* Use the common resource allocation mechanism */ |
179 | pci_probe_only = 1; | 234 | pci_probe_only = 1; |
180 | } | 235 | } |
236 | |||
237 | void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset) | ||
238 | { | ||
239 | struct pci_controller *hose; | ||
240 | |||
241 | hose = pci_bus_to_host(dev->bus); | ||
242 | |||
243 | return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset); | ||
244 | } | ||
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index ffe6528048b5..5ddf40a66ae8 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -39,8 +39,21 @@ | |||
39 | 39 | ||
40 | #include "pasemi.h" | 40 | #include "pasemi.h" |
41 | 41 | ||
42 | /* SDC reset register, must be pre-mapped at reset time */ | ||
42 | static void __iomem *reset_reg; | 43 | static void __iomem *reset_reg; |
43 | 44 | ||
45 | /* Various error status registers, must be pre-mapped at MCE time */ | ||
46 | |||
47 | #define MAX_MCE_REGS 32 | ||
48 | struct mce_regs { | ||
49 | char *name; | ||
50 | void __iomem *addr; | ||
51 | }; | ||
52 | |||
53 | static struct mce_regs mce_regs[MAX_MCE_REGS]; | ||
54 | static int num_mce_regs; | ||
55 | |||
56 | |||
44 | static void pas_restart(char *cmd) | 57 | static void pas_restart(char *cmd) |
45 | { | 58 | { |
46 | printk("Restarting...\n"); | 59 | printk("Restarting...\n"); |
@@ -50,26 +63,30 @@ static void pas_restart(char *cmd) | |||
50 | 63 | ||
51 | #ifdef CONFIG_SMP | 64 | #ifdef CONFIG_SMP |
52 | static DEFINE_SPINLOCK(timebase_lock); | 65 | static DEFINE_SPINLOCK(timebase_lock); |
66 | static unsigned long timebase; | ||
53 | 67 | ||
54 | static void __devinit pas_give_timebase(void) | 68 | static void __devinit pas_give_timebase(void) |
55 | { | 69 | { |
56 | unsigned long tb; | ||
57 | |||
58 | spin_lock(&timebase_lock); | 70 | spin_lock(&timebase_lock); |
59 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); | 71 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); |
60 | tb = mftb(); | 72 | isync(); |
61 | mtspr(SPRN_TBCTL, TBCTL_UPDATE_LOWER | (tb & 0xffffffff)); | 73 | timebase = get_tb(); |
62 | mtspr(SPRN_TBCTL, TBCTL_UPDATE_UPPER | (tb >> 32)); | ||
63 | mtspr(SPRN_TBCTL, TBCTL_RESTART); | ||
64 | spin_unlock(&timebase_lock); | 74 | spin_unlock(&timebase_lock); |
65 | pr_debug("pas_give_timebase: cpu %d gave tb %lx\n", | 75 | |
66 | smp_processor_id(), tb); | 76 | while (timebase) |
77 | barrier(); | ||
78 | mtspr(SPRN_TBCTL, TBCTL_RESTART); | ||
67 | } | 79 | } |
68 | 80 | ||
69 | static void __devinit pas_take_timebase(void) | 81 | static void __devinit pas_take_timebase(void) |
70 | { | 82 | { |
71 | pr_debug("pas_take_timebase: cpu %d has tb %lx\n", | 83 | while (!timebase) |
72 | smp_processor_id(), mftb()); | 84 | smp_rmb(); |
85 | |||
86 | spin_lock(&timebase_lock); | ||
87 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
88 | timebase = 0; | ||
89 | spin_unlock(&timebase_lock); | ||
73 | } | 90 | } |
74 | 91 | ||
75 | struct smp_ops_t pas_smp_ops = { | 92 | struct smp_ops_t pas_smp_ops = { |
@@ -98,9 +115,60 @@ void __init pas_setup_arch(void) | |||
98 | /* Remap SDC register for doing reset */ | 115 | /* Remap SDC register for doing reset */ |
99 | /* XXXOJN This should maybe come out of the device tree */ | 116 | /* XXXOJN This should maybe come out of the device tree */ |
100 | reset_reg = ioremap(0xfc101100, 4); | 117 | reset_reg = ioremap(0xfc101100, 4); |
118 | } | ||
119 | |||
120 | static int __init pas_setup_mce_regs(void) | ||
121 | { | ||
122 | struct pci_dev *dev; | ||
123 | int reg; | ||
124 | |||
125 | if (!machine_is(pasemi)) | ||
126 | return -ENODEV; | ||
127 | |||
128 | /* Remap various SoC status registers for use by the MCE handler */ | ||
129 | |||
130 | reg = 0; | ||
131 | |||
132 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, NULL); | ||
133 | while (dev && reg < MAX_MCE_REGS) { | ||
134 | mce_regs[reg].name = kasprintf(GFP_KERNEL, | ||
135 | "mc%d_mcdebug_errsta", reg); | ||
136 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x730); | ||
137 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, dev); | ||
138 | reg++; | ||
139 | } | ||
140 | |||
141 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL); | ||
142 | if (dev && reg+4 < MAX_MCE_REGS) { | ||
143 | mce_regs[reg].name = "iobdbg_IntStatus1"; | ||
144 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x438); | ||
145 | reg++; | ||
146 | mce_regs[reg].name = "iobdbg_IOCTbusIntDbgReg"; | ||
147 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x454); | ||
148 | reg++; | ||
149 | mce_regs[reg].name = "iobiom_IntStatus"; | ||
150 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0xc10); | ||
151 | reg++; | ||
152 | mce_regs[reg].name = "iobiom_IntDbgReg"; | ||
153 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0xc1c); | ||
154 | reg++; | ||
155 | } | ||
156 | |||
157 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa009, NULL); | ||
158 | if (dev && reg+2 < MAX_MCE_REGS) { | ||
159 | mce_regs[reg].name = "l2csts_IntStatus"; | ||
160 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x200); | ||
161 | reg++; | ||
162 | mce_regs[reg].name = "l2csts_Cnt"; | ||
163 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x214); | ||
164 | reg++; | ||
165 | } | ||
101 | 166 | ||
102 | pasemi_idle_init(); | 167 | num_mce_regs = reg; |
168 | |||
169 | return 0; | ||
103 | } | 170 | } |
171 | device_initcall(pas_setup_mce_regs); | ||
104 | 172 | ||
105 | static __init void pas_init_IRQ(void) | 173 | static __init void pas_init_IRQ(void) |
106 | { | 174 | { |
@@ -162,25 +230,34 @@ static int pas_machine_check_handler(struct pt_regs *regs) | |||
162 | { | 230 | { |
163 | int cpu = smp_processor_id(); | 231 | int cpu = smp_processor_id(); |
164 | unsigned long srr0, srr1, dsisr; | 232 | unsigned long srr0, srr1, dsisr; |
233 | int dump_slb = 0; | ||
234 | int i; | ||
165 | 235 | ||
166 | srr0 = regs->nip; | 236 | srr0 = regs->nip; |
167 | srr1 = regs->msr; | 237 | srr1 = regs->msr; |
168 | dsisr = mfspr(SPRN_DSISR); | 238 | dsisr = mfspr(SPRN_DSISR); |
169 | printk(KERN_ERR "Machine Check on CPU %d\n", cpu); | 239 | printk(KERN_ERR "Machine Check on CPU %d\n", cpu); |
170 | printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); | 240 | printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); |
171 | printk(KERN_ERR "DSISR 0x%016lx DAR 0x%016lx\n", dsisr, regs->dar); | 241 | printk(KERN_ERR "DSISR 0x%016lx DAR 0x%016lx\n", dsisr, regs->dar); |
242 | printk(KERN_ERR "BER 0x%016lx MER 0x%016lx\n", mfspr(SPRN_PA6T_BER), | ||
243 | mfspr(SPRN_PA6T_MER)); | ||
244 | printk(KERN_ERR "IER 0x%016lx DER 0x%016lx\n", mfspr(SPRN_PA6T_IER), | ||
245 | mfspr(SPRN_PA6T_DER)); | ||
172 | printk(KERN_ERR "Cause:\n"); | 246 | printk(KERN_ERR "Cause:\n"); |
173 | 247 | ||
174 | if (srr1 & 0x200000) | 248 | if (srr1 & 0x200000) |
175 | printk(KERN_ERR "Signalled by SDC\n"); | 249 | printk(KERN_ERR "Signalled by SDC\n"); |
250 | |||
176 | if (srr1 & 0x100000) { | 251 | if (srr1 & 0x100000) { |
177 | printk(KERN_ERR "Load/Store detected error:\n"); | 252 | printk(KERN_ERR "Load/Store detected error:\n"); |
178 | if (dsisr & 0x8000) | 253 | if (dsisr & 0x8000) |
179 | printk(KERN_ERR "D-cache ECC double-bit error or bus error\n"); | 254 | printk(KERN_ERR "D-cache ECC double-bit error or bus error\n"); |
180 | if (dsisr & 0x4000) | 255 | if (dsisr & 0x4000) |
181 | printk(KERN_ERR "LSU snoop response error\n"); | 256 | printk(KERN_ERR "LSU snoop response error\n"); |
182 | if (dsisr & 0x2000) | 257 | if (dsisr & 0x2000) { |
183 | printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n"); | 258 | printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n"); |
259 | dump_slb = 1; | ||
260 | } | ||
184 | if (dsisr & 0x1000) | 261 | if (dsisr & 0x1000) |
185 | printk(KERN_ERR "Recoverable Duptags\n"); | 262 | printk(KERN_ERR "Recoverable Duptags\n"); |
186 | if (dsisr & 0x800) | 263 | if (dsisr & 0x800) |
@@ -188,13 +265,40 @@ static int pas_machine_check_handler(struct pt_regs *regs) | |||
188 | if (dsisr & 0x400) | 265 | if (dsisr & 0x400) |
189 | printk(KERN_ERR "TLB parity error count overflow\n"); | 266 | printk(KERN_ERR "TLB parity error count overflow\n"); |
190 | } | 267 | } |
268 | |||
191 | if (srr1 & 0x80000) | 269 | if (srr1 & 0x80000) |
192 | printk(KERN_ERR "Bus Error\n"); | 270 | printk(KERN_ERR "Bus Error\n"); |
193 | if (srr1 & 0x40000) | 271 | |
272 | if (srr1 & 0x40000) { | ||
194 | printk(KERN_ERR "I-side SLB multiple hit\n"); | 273 | printk(KERN_ERR "I-side SLB multiple hit\n"); |
274 | dump_slb = 1; | ||
275 | } | ||
276 | |||
195 | if (srr1 & 0x20000) | 277 | if (srr1 & 0x20000) |
196 | printk(KERN_ERR "I-cache parity error hit\n"); | 278 | printk(KERN_ERR "I-cache parity error hit\n"); |
197 | 279 | ||
280 | if (num_mce_regs == 0) | ||
281 | printk(KERN_ERR "No MCE registers mapped yet, can't dump\n"); | ||
282 | else | ||
283 | printk(KERN_ERR "SoC debug registers:\n"); | ||
284 | |||
285 | for (i = 0; i < num_mce_regs; i++) | ||
286 | printk(KERN_ERR "%s: 0x%08x\n", mce_regs[i].name, | ||
287 | in_le32(mce_regs[i].addr)); | ||
288 | |||
289 | if (dump_slb) { | ||
290 | unsigned long e, v; | ||
291 | int i; | ||
292 | |||
293 | printk(KERN_ERR "slb contents:\n"); | ||
294 | for (i = 0; i < SLB_NUM_ENTRIES; i++) { | ||
295 | asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i)); | ||
296 | asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i)); | ||
297 | printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | |||
198 | /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ | 302 | /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ |
199 | return !!(srr1 & 0x2); | 303 | return !!(srr1 & 0x2); |
200 | } | 304 | } |
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index 9d73d0234c5d..cf660916ae0b 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
18 | #include <asm/page.h> | 18 | #include <asm/page.h> |
19 | #include <asm/bootx.h> | 19 | #include <asm/bootx.h> |
20 | #include <asm/bootinfo.h> | ||
21 | #include <asm/btext.h> | 20 | #include <asm/btext.h> |
22 | #include <asm/io.h> | 21 | #include <asm/io.h> |
23 | 22 | ||
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index efdf5eb81ecc..da2007e3db0e 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/completion.h> | 40 | #include <linux/completion.h> |
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/completion.h> | ||
44 | #include <linux/timer.h> | 43 | #include <linux/timer.h> |
45 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
46 | #include <asm/keylargo.h> | 45 | #include <asm/keylargo.h> |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 92586db19754..ec49099830d5 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -209,15 +209,12 @@ static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, | |||
209 | switch (len) { | 209 | switch (len) { |
210 | case 1: | 210 | case 1: |
211 | out_8(addr, val); | 211 | out_8(addr, val); |
212 | (void) in_8(addr); | ||
213 | break; | 212 | break; |
214 | case 2: | 213 | case 2: |
215 | out_le16(addr, val); | 214 | out_le16(addr, val); |
216 | (void) in_le16(addr); | ||
217 | break; | 215 | break; |
218 | default: | 216 | default: |
219 | out_le32(addr, val); | 217 | out_le32(addr, val); |
220 | (void) in_le32(addr); | ||
221 | break; | 218 | break; |
222 | } | 219 | } |
223 | return PCIBIOS_SUCCESSFUL; | 220 | return PCIBIOS_SUCCESSFUL; |
@@ -225,8 +222,8 @@ static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, | |||
225 | 222 | ||
226 | static struct pci_ops macrisc_pci_ops = | 223 | static struct pci_ops macrisc_pci_ops = |
227 | { | 224 | { |
228 | macrisc_read_config, | 225 | .read = macrisc_read_config, |
229 | macrisc_write_config | 226 | .write = macrisc_write_config, |
230 | }; | 227 | }; |
231 | 228 | ||
232 | #ifdef CONFIG_PPC32 | 229 | #ifdef CONFIG_PPC32 |
@@ -280,8 +277,8 @@ chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
280 | 277 | ||
281 | static struct pci_ops chaos_pci_ops = | 278 | static struct pci_ops chaos_pci_ops = |
282 | { | 279 | { |
283 | chaos_read_config, | 280 | .read = chaos_read_config, |
284 | chaos_write_config | 281 | .write = chaos_write_config, |
285 | }; | 282 | }; |
286 | 283 | ||
287 | static void __init setup_chaos(struct pci_controller *hose, | 284 | static void __init setup_chaos(struct pci_controller *hose, |
@@ -440,15 +437,12 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, | |||
440 | switch (len) { | 437 | switch (len) { |
441 | case 1: | 438 | case 1: |
442 | out_8(addr, val); | 439 | out_8(addr, val); |
443 | (void) in_8(addr); | ||
444 | break; | 440 | break; |
445 | case 2: | 441 | case 2: |
446 | out_le16(addr, val); | 442 | out_le16(addr, val); |
447 | (void) in_le16(addr); | ||
448 | break; | 443 | break; |
449 | default: | 444 | default: |
450 | out_le32((u32 __iomem *)addr, val); | 445 | out_le32((u32 __iomem *)addr, val); |
451 | (void) in_le32(addr); | ||
452 | break; | 446 | break; |
453 | } | 447 | } |
454 | return PCIBIOS_SUCCESSFUL; | 448 | return PCIBIOS_SUCCESSFUL; |
@@ -456,8 +450,8 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, | |||
456 | 450 | ||
457 | static struct pci_ops u3_ht_pci_ops = | 451 | static struct pci_ops u3_ht_pci_ops = |
458 | { | 452 | { |
459 | u3_ht_read_config, | 453 | .read = u3_ht_read_config, |
460 | u3_ht_write_config | 454 | .write = u3_ht_write_config, |
461 | }; | 455 | }; |
462 | 456 | ||
463 | #define U4_PCIE_CFA0(devfn, off) \ | 457 | #define U4_PCIE_CFA0(devfn, off) \ |
@@ -545,15 +539,12 @@ static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | |||
545 | switch (len) { | 539 | switch (len) { |
546 | case 1: | 540 | case 1: |
547 | out_8(addr, val); | 541 | out_8(addr, val); |
548 | (void) in_8(addr); | ||
549 | break; | 542 | break; |
550 | case 2: | 543 | case 2: |
551 | out_le16(addr, val); | 544 | out_le16(addr, val); |
552 | (void) in_le16(addr); | ||
553 | break; | 545 | break; |
554 | default: | 546 | default: |
555 | out_le32(addr, val); | 547 | out_le32(addr, val); |
556 | (void) in_le32(addr); | ||
557 | break; | 548 | break; |
558 | } | 549 | } |
559 | return PCIBIOS_SUCCESSFUL; | 550 | return PCIBIOS_SUCCESSFUL; |
@@ -561,8 +552,8 @@ static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | |||
561 | 552 | ||
562 | static struct pci_ops u4_pcie_pci_ops = | 553 | static struct pci_ops u4_pcie_pci_ops = |
563 | { | 554 | { |
564 | u4_pcie_read_config, | 555 | .read = u4_pcie_read_config, |
565 | u4_pcie_write_config | 556 | .write = u4_pcie_write_config, |
566 | }; | 557 | }; |
567 | 558 | ||
568 | #endif /* CONFIG_PPC64 */ | 559 | #endif /* CONFIG_PPC64 */ |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 87cd6805171a..999f5e160897 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -384,7 +384,7 @@ static void __init pmac_pic_probe_oldstyle(void) | |||
384 | /* | 384 | /* |
385 | * Allocate an irq host | 385 | * Allocate an irq host |
386 | */ | 386 | */ |
387 | pmac_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, max_irqs, | 387 | pmac_pic_host = irq_alloc_host(master, IRQ_HOST_MAP_LINEAR, max_irqs, |
388 | &pmac_pic_host_ops, | 388 | &pmac_pic_host_ops, |
389 | max_irqs); | 389 | max_irqs); |
390 | BUG_ON(pmac_pic_host == NULL); | 390 | BUG_ON(pmac_pic_host == NULL); |
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 6e090a7dea83..fcde070f7054 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h | |||
@@ -22,9 +22,6 @@ extern void pmac_read_rtc_time(void); | |||
22 | extern void pmac_calibrate_decr(void); | 22 | extern void pmac_calibrate_decr(void); |
23 | extern void pmac_pci_irq_fixup(struct pci_dev *); | 23 | extern void pmac_pci_irq_fixup(struct pci_dev *); |
24 | extern void pmac_pci_init(void); | 24 | extern void pmac_pci_init(void); |
25 | extern unsigned long pmac_ide_get_base(int index); | ||
26 | extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, | ||
27 | unsigned long data_port, unsigned long ctrl_port, int *irq); | ||
28 | 25 | ||
29 | extern void pmac_nvram_update(void); | 26 | extern void pmac_nvram_update(void); |
30 | extern unsigned char pmac_nvram_read_byte(int addr); | 27 | extern unsigned char pmac_nvram_read_byte(int addr); |
@@ -33,7 +30,6 @@ extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial); | |||
33 | extern void pmac_pcibios_after_init(void); | 30 | extern void pmac_pcibios_after_init(void); |
34 | extern int of_show_percpuinfo(struct seq_file *m, int i); | 31 | extern int of_show_percpuinfo(struct seq_file *m, int i); |
35 | 32 | ||
36 | extern void pmac_pci_init(void); | ||
37 | extern void pmac_setup_pci_dma(void); | 33 | extern void pmac_setup_pci_dma(void); |
38 | extern void pmac_check_ht_link(void); | 34 | extern void pmac_check_ht_link(void); |
39 | 35 | ||
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 7ccb9236e8b4..02c533096627 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -387,69 +387,13 @@ static void __init pmac_setup_arch(void) | |||
387 | #endif /* CONFIG_ADB */ | 387 | #endif /* CONFIG_ADB */ |
388 | } | 388 | } |
389 | 389 | ||
390 | char *bootpath; | ||
391 | char *bootdevice; | ||
392 | void *boot_host; | ||
393 | int boot_target; | ||
394 | int boot_part; | ||
395 | static dev_t boot_dev; | ||
396 | |||
397 | #ifdef CONFIG_SCSI | 390 | #ifdef CONFIG_SCSI |
398 | void note_scsi_host(struct device_node *node, void *host) | 391 | void note_scsi_host(struct device_node *node, void *host) |
399 | { | 392 | { |
400 | int l; | ||
401 | char *p; | ||
402 | |||
403 | l = strlen(node->full_name); | ||
404 | if (bootpath != NULL && bootdevice != NULL | ||
405 | && strncmp(node->full_name, bootdevice, l) == 0 | ||
406 | && (bootdevice[l] == '/' || bootdevice[l] == 0)) { | ||
407 | boot_host = host; | ||
408 | /* | ||
409 | * There's a bug in OF 1.0.5. (Why am I not surprised.) | ||
410 | * If you pass a path like scsi/sd@1:0 to canon, it returns | ||
411 | * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 | ||
412 | * That is, the scsi target number doesn't get preserved. | ||
413 | * So we pick the target number out of bootpath and use that. | ||
414 | */ | ||
415 | p = strstr(bootpath, "/sd@"); | ||
416 | if (p != NULL) { | ||
417 | p += 4; | ||
418 | boot_target = simple_strtoul(p, NULL, 10); | ||
419 | p = strchr(p, ':'); | ||
420 | if (p != NULL) | ||
421 | boot_part = simple_strtoul(p + 1, NULL, 10); | ||
422 | } | ||
423 | } | ||
424 | } | 393 | } |
425 | EXPORT_SYMBOL(note_scsi_host); | 394 | EXPORT_SYMBOL(note_scsi_host); |
426 | #endif | 395 | #endif |
427 | 396 | ||
428 | #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) | ||
429 | static dev_t __init find_ide_boot(void) | ||
430 | { | ||
431 | char *p; | ||
432 | int n; | ||
433 | dev_t __init pmac_find_ide_boot(char *bootdevice, int n); | ||
434 | |||
435 | if (bootdevice == NULL) | ||
436 | return 0; | ||
437 | p = strrchr(bootdevice, '/'); | ||
438 | if (p == NULL) | ||
439 | return 0; | ||
440 | n = p - bootdevice; | ||
441 | |||
442 | return pmac_find_ide_boot(bootdevice, n); | ||
443 | } | ||
444 | #endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ | ||
445 | |||
446 | static void __init find_boot_device(void) | ||
447 | { | ||
448 | #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) | ||
449 | boot_dev = find_ide_boot(); | ||
450 | #endif | ||
451 | } | ||
452 | |||
453 | static int initializing = 1; | 397 | static int initializing = 1; |
454 | 398 | ||
455 | static int pmac_late_init(void) | 399 | static int pmac_late_init(void) |
@@ -466,10 +410,14 @@ static int pmac_late_init(void) | |||
466 | 410 | ||
467 | late_initcall(pmac_late_init); | 411 | late_initcall(pmac_late_init); |
468 | 412 | ||
469 | /* can't be __init - can be called whenever a disk is first accessed */ | 413 | /* |
470 | void note_bootable_part(dev_t dev, int part, int goodness) | 414 | * This is __init_refok because we check for "initializing" before |
415 | * touching any of the __init sensitive things and "initializing" | ||
416 | * will be false after __init time. This can't be __init because it | ||
417 | * can be called whenever a disk is first accessed. | ||
418 | */ | ||
419 | void __init_refok note_bootable_part(dev_t dev, int part, int goodness) | ||
471 | { | 420 | { |
472 | static int found_boot = 0; | ||
473 | char *p; | 421 | char *p; |
474 | 422 | ||
475 | if (!initializing) | 423 | if (!initializing) |
@@ -481,15 +429,8 @@ void note_bootable_part(dev_t dev, int part, int goodness) | |||
481 | if (p != NULL && (p == boot_command_line || p[-1] == ' ')) | 429 | if (p != NULL && (p == boot_command_line || p[-1] == ' ')) |
482 | return; | 430 | return; |
483 | 431 | ||
484 | if (!found_boot) { | 432 | ROOT_DEV = dev + part; |
485 | find_boot_device(); | 433 | current_root_goodness = goodness; |
486 | found_boot = 1; | ||
487 | } | ||
488 | if (!boot_dev || dev == boot_dev) { | ||
489 | ROOT_DEV = dev + part; | ||
490 | boot_dev = 0; | ||
491 | current_root_goodness = goodness; | ||
492 | } | ||
493 | } | 434 | } |
494 | 435 | ||
495 | #ifdef CONFIG_ADB_CUDA | 436 | #ifdef CONFIG_ADB_CUDA |
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c index 6124e59e1038..44e0b55a2a02 100644 --- a/arch/powerpc/platforms/powermac/udbg_adb.c +++ b/arch/powerpc/platforms/powermac/udbg_adb.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <asm/xmon.h> | 12 | #include <asm/xmon.h> |
13 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
14 | #include <asm/bootx.h> | 14 | #include <asm/bootx.h> |
15 | #include <asm/machdep.h> | ||
16 | #include <asm/errno.h> | 15 | #include <asm/errno.h> |
17 | #include <asm/pmac_feature.h> | 16 | #include <asm/pmac_feature.h> |
18 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
@@ -150,7 +149,7 @@ static void udbg_adb_putc(char c) | |||
150 | return udbg_adb_old_putc(c); | 149 | return udbg_adb_old_putc(c); |
151 | } | 150 | } |
152 | 151 | ||
153 | void udbg_adb_init_early(void) | 152 | void __init udbg_adb_init_early(void) |
154 | { | 153 | { |
155 | #ifdef CONFIG_BOOTX_TEXT | 154 | #ifdef CONFIG_BOOTX_TEXT |
156 | if (btext_find_display(1) == 0) { | 155 | if (btext_find_display(1) == 0) { |
@@ -160,7 +159,7 @@ void udbg_adb_init_early(void) | |||
160 | #endif | 159 | #endif |
161 | } | 160 | } |
162 | 161 | ||
163 | int udbg_adb_init(int force_btext) | 162 | int __init udbg_adb_init(int force_btext) |
164 | { | 163 | { |
165 | struct device_node *np; | 164 | struct device_node *np; |
166 | 165 | ||
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c index ce15cada88d4..fd063fe0c9b3 100644 --- a/arch/powerpc/platforms/ps3/device-init.c +++ b/arch/powerpc/platforms/ps3/device-init.c | |||
@@ -297,8 +297,8 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | |||
297 | u64 dev_port; | 297 | u64 dev_port; |
298 | } *notify_event; | 298 | } *notify_event; |
299 | 299 | ||
300 | pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__, | 300 | pr_debug(" -> %s:%u: (%u:%u:%u)\n", __func__, __LINE__, repo->bus_id, |
301 | __LINE__, repo->bus_id, repo->dev_id, repo->dev_type); | 301 | repo->dev_id, repo->dev_type); |
302 | 302 | ||
303 | buf = kzalloc(512, GFP_KERNEL); | 303 | buf = kzalloc(512, GFP_KERNEL); |
304 | if (!buf) | 304 | if (!buf) |
@@ -359,6 +359,11 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | |||
359 | break; | 359 | break; |
360 | } | 360 | } |
361 | 361 | ||
362 | pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, " | ||
363 | "port %lu\n", __func__, __LINE__, repo->bus_index, | ||
364 | repo->dev_index, repo->dev_type, | ||
365 | notify_event->event_type, notify_event->dev_port); | ||
366 | |||
362 | if (notify_event->event_type != notify_region_probe || | 367 | if (notify_event->event_type != notify_region_probe || |
363 | notify_event->bus_id != repo->bus_id) { | 368 | notify_event->bus_id != repo->bus_id) { |
364 | pr_debug("%s:%u: bad notify_event: event %lu, " | 369 | pr_debug("%s:%u: bad notify_event: event %lu, " |
@@ -370,8 +375,9 @@ static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | |||
370 | 375 | ||
371 | if (notify_event->dev_id == repo->dev_id && | 376 | if (notify_event->dev_id == repo->dev_id && |
372 | notify_event->dev_type == repo->dev_type) { | 377 | notify_event->dev_type == repo->dev_type) { |
373 | pr_debug("%s:%u: device ready: dev_id %u\n", __func__, | 378 | pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__, |
374 | __LINE__, repo->dev_id); | 379 | __LINE__, repo->bus_index, repo->dev_index, |
380 | repo->dev_type); | ||
375 | error = 0; | 381 | error = 0; |
376 | break; | 382 | break; |
377 | } | 383 | } |
@@ -412,9 +418,10 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | |||
412 | return -ENODEV; | 418 | return -ENODEV; |
413 | } | 419 | } |
414 | 420 | ||
415 | pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu " | 421 | pr_debug("%s:%u: (%u:%u:%u): port %lu blk_size %lu num_blocks %lu " |
416 | "num_regions %u\n", __func__, __LINE__, repo->bus_index, | 422 | "num_regions %u\n", __func__, __LINE__, repo->bus_index, |
417 | repo->dev_index, port, blk_size, num_blocks, num_regions); | 423 | repo->dev_index, repo->dev_type, port, blk_size, num_blocks, |
424 | num_regions); | ||
418 | 425 | ||
419 | p = kzalloc(sizeof(struct ps3_storage_device) + | 426 | p = kzalloc(sizeof(struct ps3_storage_device) + |
420 | num_regions * sizeof(struct ps3_storage_region), | 427 | num_regions * sizeof(struct ps3_storage_region), |
@@ -681,8 +688,9 @@ static int ps3_probe_thread(void *data) | |||
681 | pr_debug("%s:%u: find device error.\n", | 688 | pr_debug("%s:%u: find device error.\n", |
682 | __func__, __LINE__); | 689 | __func__, __LINE__); |
683 | else { | 690 | else { |
684 | pr_debug("%s:%u: found device\n", __func__, | 691 | pr_debug("%s:%u: found device (%u:%u:%u)\n", |
685 | __LINE__); | 692 | __func__, __LINE__, repo->bus_index, |
693 | repo->dev_index, repo->dev_type); | ||
686 | ps3_register_repository_device(repo); | 694 | ps3_register_repository_device(repo); |
687 | ps3_repository_bump_device(repo); | 695 | ps3_repository_bump_device(repo); |
688 | ms = 250; | 696 | ms = 250; |
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index 5d2e176a1b18..7382f195c4f8 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c | |||
@@ -60,7 +60,8 @@ static void _debug_dump_hpte(unsigned long pa, unsigned long va, | |||
60 | } | 60 | } |
61 | 61 | ||
62 | static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | 62 | static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, |
63 | unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) | 63 | unsigned long pa, unsigned long rflags, unsigned long vflags, |
64 | int psize, int ssize) | ||
64 | { | 65 | { |
65 | unsigned long slot; | 66 | unsigned long slot; |
66 | struct hash_pte lhpte; | 67 | struct hash_pte lhpte; |
@@ -72,7 +73,8 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
72 | 73 | ||
73 | vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */ | 74 | vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */ |
74 | 75 | ||
75 | lhpte.v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; | 76 | lhpte.v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) | |
77 | vflags | HPTE_V_VALID; | ||
76 | lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; | 78 | lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; |
77 | 79 | ||
78 | p_pteg = hpte_group / HPTES_PER_GROUP; | 80 | p_pteg = hpte_group / HPTES_PER_GROUP; |
@@ -167,14 +169,14 @@ static long ps3_hpte_remove(unsigned long hpte_group) | |||
167 | } | 169 | } |
168 | 170 | ||
169 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | 171 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, |
170 | unsigned long va, int psize, int local) | 172 | unsigned long va, int psize, int ssize, int local) |
171 | { | 173 | { |
172 | unsigned long flags; | 174 | unsigned long flags; |
173 | unsigned long result; | 175 | unsigned long result; |
174 | unsigned long pteg, bit; | 176 | unsigned long pteg, bit; |
175 | unsigned long hpte_v, want_v; | 177 | unsigned long hpte_v, want_v; |
176 | 178 | ||
177 | want_v = hpte_encode_v(va, psize); | 179 | want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M); |
178 | 180 | ||
179 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | 181 | spin_lock_irqsave(&ps3_bolttab_lock, flags); |
180 | 182 | ||
@@ -205,13 +207,13 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
205 | } | 207 | } |
206 | 208 | ||
207 | static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | 209 | static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, |
208 | int psize) | 210 | int psize, int ssize) |
209 | { | 211 | { |
210 | panic("ps3_hpte_updateboltedpp() not implemented"); | 212 | panic("ps3_hpte_updateboltedpp() not implemented"); |
211 | } | 213 | } |
212 | 214 | ||
213 | static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, | 215 | static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, |
214 | int psize, int local) | 216 | int psize, int ssize, int local) |
215 | { | 217 | { |
216 | unsigned long flags; | 218 | unsigned long flags; |
217 | unsigned long result; | 219 | unsigned long result; |
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 67e32ec9b37e..3a6db04aa940 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c | |||
@@ -673,9 +673,16 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq, | |||
673 | return 0; | 673 | return 0; |
674 | } | 674 | } |
675 | 675 | ||
676 | static int ps3_host_match(struct irq_host *h, struct device_node *np) | ||
677 | { | ||
678 | /* Match all */ | ||
679 | return 1; | ||
680 | } | ||
681 | |||
676 | static struct irq_host_ops ps3_host_ops = { | 682 | static struct irq_host_ops ps3_host_ops = { |
677 | .map = ps3_host_map, | 683 | .map = ps3_host_map, |
678 | .unmap = ps3_host_unmap, | 684 | .unmap = ps3_host_unmap, |
685 | .match = ps3_host_match, | ||
679 | }; | 686 | }; |
680 | 687 | ||
681 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) | 688 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) |
@@ -726,7 +733,7 @@ void __init ps3_init_IRQ(void) | |||
726 | unsigned cpu; | 733 | unsigned cpu; |
727 | struct irq_host *host; | 734 | struct irq_host *host; |
728 | 735 | ||
729 | host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, | 736 | host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, |
730 | PS3_INVALID_OUTLET); | 737 | PS3_INVALID_OUTLET); |
731 | irq_set_default_host(host); | 738 | irq_set_default_host(host); |
732 | irq_set_virq_count(PS3_PLUG_MAX + 1); | 739 | irq_set_virq_count(PS3_PLUG_MAX + 1); |
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index b70e474014f0..766685ab26f8 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * PS3 'Other OS' area data. | 2 | * PS3 flash memory os area. |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. |
5 | * Copyright 2006 Sony Corp. | 5 | * Copyright 2006 Sony Corp. |
@@ -20,6 +20,9 @@ | |||
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/fs.h> | ||
25 | #include <linux/syscalls.h> | ||
23 | 26 | ||
24 | #include <asm/lmb.h> | 27 | #include <asm/lmb.h> |
25 | 28 | ||
@@ -29,7 +32,7 @@ enum { | |||
29 | OS_AREA_SEGMENT_SIZE = 0X200, | 32 | OS_AREA_SEGMENT_SIZE = 0X200, |
30 | }; | 33 | }; |
31 | 34 | ||
32 | enum { | 35 | enum os_area_ldr_format { |
33 | HEADER_LDR_FORMAT_RAW = 0, | 36 | HEADER_LDR_FORMAT_RAW = 0, |
34 | HEADER_LDR_FORMAT_GZIP = 1, | 37 | HEADER_LDR_FORMAT_GZIP = 1, |
35 | }; | 38 | }; |
@@ -38,7 +41,7 @@ enum { | |||
38 | * struct os_area_header - os area header segment. | 41 | * struct os_area_header - os area header segment. |
39 | * @magic_num: Always 'cell_ext_os_area'. | 42 | * @magic_num: Always 'cell_ext_os_area'. |
40 | * @hdr_version: Header format version number. | 43 | * @hdr_version: Header format version number. |
41 | * @os_area_offset: Starting segment number of os image area. | 44 | * @db_area_offset: Starting segment number of other os database area. |
42 | * @ldr_area_offset: Starting segment number of bootloader image area. | 45 | * @ldr_area_offset: Starting segment number of bootloader image area. |
43 | * @ldr_format: HEADER_LDR_FORMAT flag. | 46 | * @ldr_format: HEADER_LDR_FORMAT flag. |
44 | * @ldr_size: Size of bootloader image in bytes. | 47 | * @ldr_size: Size of bootloader image in bytes. |
@@ -50,9 +53,9 @@ enum { | |||
50 | */ | 53 | */ |
51 | 54 | ||
52 | struct os_area_header { | 55 | struct os_area_header { |
53 | s8 magic_num[16]; | 56 | u8 magic_num[16]; |
54 | u32 hdr_version; | 57 | u32 hdr_version; |
55 | u32 os_area_offset; | 58 | u32 db_area_offset; |
56 | u32 ldr_area_offset; | 59 | u32 ldr_area_offset; |
57 | u32 _reserved_1; | 60 | u32 _reserved_1; |
58 | u32 ldr_format; | 61 | u32 ldr_format; |
@@ -60,12 +63,12 @@ struct os_area_header { | |||
60 | u32 _reserved_2[6]; | 63 | u32 _reserved_2[6]; |
61 | }; | 64 | }; |
62 | 65 | ||
63 | enum { | 66 | enum os_area_boot_flag { |
64 | PARAM_BOOT_FLAG_GAME_OS = 0, | 67 | PARAM_BOOT_FLAG_GAME_OS = 0, |
65 | PARAM_BOOT_FLAG_OTHER_OS = 1, | 68 | PARAM_BOOT_FLAG_OTHER_OS = 1, |
66 | }; | 69 | }; |
67 | 70 | ||
68 | enum { | 71 | enum os_area_ctrl_button { |
69 | PARAM_CTRL_BUTTON_O_IS_YES = 0, | 72 | PARAM_CTRL_BUTTON_O_IS_YES = 0, |
70 | PARAM_CTRL_BUTTON_X_IS_YES = 1, | 73 | PARAM_CTRL_BUTTON_X_IS_YES = 1, |
71 | }; | 74 | }; |
@@ -84,6 +87,9 @@ enum { | |||
84 | * @dns_primary: User preference of static primary dns server. | 87 | * @dns_primary: User preference of static primary dns server. |
85 | * @dns_secondary: User preference of static secondary dns server. | 88 | * @dns_secondary: User preference of static secondary dns server. |
86 | * | 89 | * |
90 | * The ps3 rtc maintains a read-only value that approximates seconds since | ||
91 | * 2000-01-01 00:00:00 UTC. | ||
92 | * | ||
87 | * User preference of zero for static_ip_addr means use dhcp. | 93 | * User preference of zero for static_ip_addr means use dhcp. |
88 | */ | 94 | */ |
89 | 95 | ||
@@ -108,45 +114,172 @@ struct os_area_params { | |||
108 | u8 _reserved_5[8]; | 114 | u8 _reserved_5[8]; |
109 | }; | 115 | }; |
110 | 116 | ||
117 | enum { | ||
118 | OS_AREA_DB_MAGIC_NUM = 0x2d64622dU, | ||
119 | }; | ||
120 | |||
111 | /** | 121 | /** |
112 | * struct saved_params - Static working copies of data from the 'Other OS' area. | 122 | * struct os_area_db - Shared flash memory database. |
123 | * @magic_num: Always '-db-' = 0x2d64622d. | ||
124 | * @version: os_area_db format version number. | ||
125 | * @index_64: byte offset of the database id index for 64 bit variables. | ||
126 | * @count_64: number of usable 64 bit index entries | ||
127 | * @index_32: byte offset of the database id index for 32 bit variables. | ||
128 | * @count_32: number of usable 32 bit index entries | ||
129 | * @index_16: byte offset of the database id index for 16 bit variables. | ||
130 | * @count_16: number of usable 16 bit index entries | ||
113 | * | 131 | * |
114 | * For the convinience of the guest, the HV makes a copy of the 'Other OS' area | 132 | * Flash rom storage for exclusive use by guests running in the other os lpar. |
115 | * in flash to a high address in the boot memory region and then puts that RAM | 133 | * The current system configuration allocates 1K (two segments) for other os |
116 | * address and the byte count into the repository for retreval by the guest. | 134 | * use. |
117 | * We copy the data we want into a static variable and allow the memory setup | 135 | */ |
118 | * by the HV to be claimed by the lmb manager. | 136 | |
137 | struct os_area_db { | ||
138 | u32 magic_num; | ||
139 | u16 version; | ||
140 | u16 _reserved_1; | ||
141 | u16 index_64; | ||
142 | u16 count_64; | ||
143 | u16 index_32; | ||
144 | u16 count_32; | ||
145 | u16 index_16; | ||
146 | u16 count_16; | ||
147 | u32 _reserved_2; | ||
148 | u8 _db_data[1000]; | ||
149 | }; | ||
150 | |||
151 | /** | ||
152 | * enum os_area_db_owner - Data owners. | ||
153 | */ | ||
154 | |||
155 | enum os_area_db_owner { | ||
156 | OS_AREA_DB_OWNER_ANY = -1, | ||
157 | OS_AREA_DB_OWNER_NONE = 0, | ||
158 | OS_AREA_DB_OWNER_PROTOTYPE = 1, | ||
159 | OS_AREA_DB_OWNER_LINUX = 2, | ||
160 | OS_AREA_DB_OWNER_PETITBOOT = 3, | ||
161 | OS_AREA_DB_OWNER_MAX = 32, | ||
162 | }; | ||
163 | |||
164 | enum os_area_db_key { | ||
165 | OS_AREA_DB_KEY_ANY = -1, | ||
166 | OS_AREA_DB_KEY_NONE = 0, | ||
167 | OS_AREA_DB_KEY_RTC_DIFF = 1, | ||
168 | OS_AREA_DB_KEY_VIDEO_MODE = 2, | ||
169 | OS_AREA_DB_KEY_MAX = 8, | ||
170 | }; | ||
171 | |||
172 | struct os_area_db_id { | ||
173 | int owner; | ||
174 | int key; | ||
175 | }; | ||
176 | |||
177 | static const struct os_area_db_id os_area_db_id_empty = { | ||
178 | .owner = OS_AREA_DB_OWNER_NONE, | ||
179 | .key = OS_AREA_DB_KEY_NONE | ||
180 | }; | ||
181 | |||
182 | static const struct os_area_db_id os_area_db_id_any = { | ||
183 | .owner = OS_AREA_DB_OWNER_ANY, | ||
184 | .key = OS_AREA_DB_KEY_ANY | ||
185 | }; | ||
186 | |||
187 | static const struct os_area_db_id os_area_db_id_rtc_diff = { | ||
188 | .owner = OS_AREA_DB_OWNER_LINUX, | ||
189 | .key = OS_AREA_DB_KEY_RTC_DIFF | ||
190 | }; | ||
191 | |||
192 | static const struct os_area_db_id os_area_db_id_video_mode = { | ||
193 | .owner = OS_AREA_DB_OWNER_LINUX, | ||
194 | .key = OS_AREA_DB_KEY_VIDEO_MODE | ||
195 | }; | ||
196 | |||
197 | #define SECONDS_FROM_1970_TO_2000 946684800LL | ||
198 | |||
199 | /** | ||
200 | * struct saved_params - Static working copies of data from the PS3 'os area'. | ||
201 | * | ||
202 | * The order of preference we use for the rtc_diff source: | ||
203 | * 1) The database value. | ||
204 | * 2) The game os value. | ||
205 | * 3) The number of seconds from 1970 to 2000. | ||
119 | */ | 206 | */ |
120 | 207 | ||
121 | struct saved_params { | 208 | struct saved_params { |
122 | /* param 0 */ | 209 | unsigned int valid; |
123 | s64 rtc_diff; | 210 | s64 rtc_diff; |
124 | unsigned int av_multi_out; | 211 | unsigned int av_multi_out; |
125 | unsigned int ctrl_button; | ||
126 | /* param 1 */ | ||
127 | u8 static_ip_addr[4]; | ||
128 | u8 network_mask[4]; | ||
129 | u8 default_gateway[4]; | ||
130 | /* param 2 */ | ||
131 | u8 dns_primary[4]; | ||
132 | u8 dns_secondary[4]; | ||
133 | } static saved_params; | 212 | } static saved_params; |
134 | 213 | ||
214 | static struct property property_rtc_diff = { | ||
215 | .name = "linux,rtc_diff", | ||
216 | .length = sizeof(saved_params.rtc_diff), | ||
217 | .value = &saved_params.rtc_diff, | ||
218 | }; | ||
219 | |||
220 | static struct property property_av_multi_out = { | ||
221 | .name = "linux,av_multi_out", | ||
222 | .length = sizeof(saved_params.av_multi_out), | ||
223 | .value = &saved_params.av_multi_out, | ||
224 | }; | ||
225 | |||
226 | /** | ||
227 | * os_area_set_property - Add or overwrite a saved_params value to the device tree. | ||
228 | * | ||
229 | * Overwrites an existing property. | ||
230 | */ | ||
231 | |||
232 | static void os_area_set_property(struct device_node *node, | ||
233 | struct property *prop) | ||
234 | { | ||
235 | int result; | ||
236 | struct property *tmp = of_find_property(node, prop->name, NULL); | ||
237 | |||
238 | if (tmp) { | ||
239 | pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name); | ||
240 | prom_remove_property(node, tmp); | ||
241 | } | ||
242 | |||
243 | result = prom_add_property(node, prop); | ||
244 | |||
245 | if (result) | ||
246 | pr_debug("%s:%d prom_set_property failed\n", __func__, | ||
247 | __LINE__); | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * os_area_get_property - Get a saved_params value from the device tree. | ||
252 | * | ||
253 | */ | ||
254 | |||
255 | static void __init os_area_get_property(struct device_node *node, | ||
256 | struct property *prop) | ||
257 | { | ||
258 | const struct property *tmp = of_find_property(node, prop->name, NULL); | ||
259 | |||
260 | if (tmp) { | ||
261 | BUG_ON(prop->length != tmp->length); | ||
262 | memcpy(prop->value, tmp->value, prop->length); | ||
263 | } else | ||
264 | pr_debug("%s:%d not found %s\n", __func__, __LINE__, | ||
265 | prop->name); | ||
266 | } | ||
267 | |||
135 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) | 268 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) |
136 | static void _dump_header(const struct os_area_header *h, const char *func, | 269 | static void _dump_header(const struct os_area_header *h, const char *func, |
137 | int line) | 270 | int line) |
138 | { | 271 | { |
139 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, | 272 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, |
140 | h->magic_num); | 273 | h->magic_num); |
141 | pr_debug("%s:%d: h.hdr_version: %u\n", func, line, | 274 | pr_debug("%s:%d: h.hdr_version: %u\n", func, line, |
142 | h->hdr_version); | 275 | h->hdr_version); |
143 | pr_debug("%s:%d: h.os_area_offset: %u\n", func, line, | 276 | pr_debug("%s:%d: h.db_area_offset: %u\n", func, line, |
144 | h->os_area_offset); | 277 | h->db_area_offset); |
145 | pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line, | 278 | pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line, |
146 | h->ldr_area_offset); | 279 | h->ldr_area_offset); |
147 | pr_debug("%s:%d: h.ldr_format: %u\n", func, line, | 280 | pr_debug("%s:%d: h.ldr_format: %u\n", func, line, |
148 | h->ldr_format); | 281 | h->ldr_format); |
149 | pr_debug("%s:%d: h.ldr_size: %xh\n", func, line, | 282 | pr_debug("%s:%d: h.ldr_size: %xh\n", func, line, |
150 | h->ldr_size); | 283 | h->ldr_size); |
151 | } | 284 | } |
152 | 285 | ||
@@ -176,7 +309,7 @@ static void _dump_params(const struct os_area_params *p, const char *func, | |||
176 | p->dns_secondary[2], p->dns_secondary[3]); | 309 | p->dns_secondary[2], p->dns_secondary[3]); |
177 | } | 310 | } |
178 | 311 | ||
179 | static int __init verify_header(const struct os_area_header *header) | 312 | static int verify_header(const struct os_area_header *header) |
180 | { | 313 | { |
181 | if (memcmp(header->magic_num, "cell_ext_os_area", 16)) { | 314 | if (memcmp(header->magic_num, "cell_ext_os_area", 16)) { |
182 | pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); | 315 | pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); |
@@ -188,7 +321,7 @@ static int __init verify_header(const struct os_area_header *header) | |||
188 | return -1; | 321 | return -1; |
189 | } | 322 | } |
190 | 323 | ||
191 | if (header->os_area_offset > header->ldr_area_offset) { | 324 | if (header->db_area_offset > header->ldr_area_offset) { |
192 | pr_debug("%s:%d offsets failed\n", __func__, __LINE__); | 325 | pr_debug("%s:%d offsets failed\n", __func__, __LINE__); |
193 | return -1; | 326 | return -1; |
194 | } | 327 | } |
@@ -196,58 +329,477 @@ static int __init verify_header(const struct os_area_header *header) | |||
196 | return 0; | 329 | return 0; |
197 | } | 330 | } |
198 | 331 | ||
199 | int __init ps3_os_area_init(void) | 332 | static int db_verify(const struct os_area_db *db) |
333 | { | ||
334 | if (db->magic_num != OS_AREA_DB_MAGIC_NUM) { | ||
335 | pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); | ||
336 | return -1; | ||
337 | } | ||
338 | |||
339 | if (db->version != 1) { | ||
340 | pr_debug("%s:%d version failed\n", __func__, __LINE__); | ||
341 | return -1; | ||
342 | } | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | struct db_index { | ||
348 | uint8_t owner:5; | ||
349 | uint8_t key:3; | ||
350 | }; | ||
351 | |||
352 | struct db_iterator { | ||
353 | const struct os_area_db *db; | ||
354 | struct os_area_db_id match_id; | ||
355 | struct db_index *idx; | ||
356 | struct db_index *last_idx; | ||
357 | union { | ||
358 | uint64_t *value_64; | ||
359 | uint32_t *value_32; | ||
360 | uint16_t *value_16; | ||
361 | }; | ||
362 | }; | ||
363 | |||
364 | static unsigned int db_align_up(unsigned int val, unsigned int size) | ||
365 | { | ||
366 | return (val + (size - 1)) & (~(size - 1)); | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * db_for_each_64 - Iterator for 64 bit entries. | ||
371 | * | ||
372 | * A NULL value for id can be used to match all entries. | ||
373 | * OS_AREA_DB_OWNER_ANY and OS_AREA_DB_KEY_ANY can be used to match all. | ||
374 | */ | ||
375 | |||
376 | static int db_for_each_64(const struct os_area_db *db, | ||
377 | const struct os_area_db_id *match_id, struct db_iterator *i) | ||
378 | { | ||
379 | next: | ||
380 | if (!i->db) { | ||
381 | i->db = db; | ||
382 | i->match_id = match_id ? *match_id : os_area_db_id_any; | ||
383 | i->idx = (void *)db + db->index_64; | ||
384 | i->last_idx = i->idx + db->count_64; | ||
385 | i->value_64 = (void *)db + db->index_64 | ||
386 | + db_align_up(db->count_64, 8); | ||
387 | } else { | ||
388 | i->idx++; | ||
389 | i->value_64++; | ||
390 | } | ||
391 | |||
392 | if (i->idx >= i->last_idx) { | ||
393 | pr_debug("%s:%d: reached end\n", __func__, __LINE__); | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | if (i->match_id.owner != OS_AREA_DB_OWNER_ANY | ||
398 | && i->match_id.owner != (int)i->idx->owner) | ||
399 | goto next; | ||
400 | if (i->match_id.key != OS_AREA_DB_KEY_ANY | ||
401 | && i->match_id.key != (int)i->idx->key) | ||
402 | goto next; | ||
403 | |||
404 | return 1; | ||
405 | } | ||
406 | |||
407 | static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id) | ||
408 | { | ||
409 | struct db_iterator i; | ||
410 | |||
411 | for (i.db = NULL; db_for_each_64(db, id, &i); ) { | ||
412 | |||
413 | pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__, | ||
414 | i.idx->owner, i.idx->key, | ||
415 | (unsigned long long)*i.value_64); | ||
416 | |||
417 | i.idx->owner = 0; | ||
418 | i.idx->key = 0; | ||
419 | *i.value_64 = 0; | ||
420 | } | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id, | ||
425 | uint64_t value) | ||
426 | { | ||
427 | struct db_iterator i; | ||
428 | |||
429 | pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__, | ||
430 | id->owner, id->key, (unsigned long long)value); | ||
431 | |||
432 | if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY | ||
433 | || id->key == OS_AREA_DB_KEY_ANY) { | ||
434 | pr_debug("%s:%d: bad id: (%d:%d)\n", __func__, | ||
435 | __LINE__, id->owner, id->key); | ||
436 | return -1; | ||
437 | } | ||
438 | |||
439 | db_delete_64(db, id); | ||
440 | |||
441 | i.db = NULL; | ||
442 | if (db_for_each_64(db, &os_area_db_id_empty, &i)) { | ||
443 | |||
444 | pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__, | ||
445 | i.idx->owner, i.idx->key, | ||
446 | (unsigned long long)*i.value_64); | ||
447 | |||
448 | i.idx->owner = id->owner; | ||
449 | i.idx->key = id->key; | ||
450 | *i.value_64 = value; | ||
451 | |||
452 | pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__, | ||
453 | i.idx->owner, i.idx->key, | ||
454 | (unsigned long long)*i.value_64); | ||
455 | return 0; | ||
456 | } | ||
457 | pr_debug("%s:%d: database full.\n", | ||
458 | __func__, __LINE__); | ||
459 | return -1; | ||
460 | } | ||
461 | |||
462 | static int db_get_64(const struct os_area_db *db, | ||
463 | const struct os_area_db_id *id, uint64_t *value) | ||
464 | { | ||
465 | struct db_iterator i; | ||
466 | |||
467 | i.db = NULL; | ||
468 | if (db_for_each_64(db, id, &i)) { | ||
469 | *value = *i.value_64; | ||
470 | pr_debug("%s:%d: found %lld\n", __func__, __LINE__, | ||
471 | (long long int)*i.value_64); | ||
472 | return 0; | ||
473 | } | ||
474 | pr_debug("%s:%d: not found\n", __func__, __LINE__); | ||
475 | return -1; | ||
476 | } | ||
477 | |||
478 | static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff) | ||
479 | { | ||
480 | return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff); | ||
481 | } | ||
482 | |||
483 | #define dump_db(a) _dump_db(a, __func__, __LINE__) | ||
484 | static void _dump_db(const struct os_area_db *db, const char *func, | ||
485 | int line) | ||
486 | { | ||
487 | pr_debug("%s:%d: db.magic_num: '%s'\n", func, line, | ||
488 | (const char*)&db->magic_num); | ||
489 | pr_debug("%s:%d: db.version: %u\n", func, line, | ||
490 | db->version); | ||
491 | pr_debug("%s:%d: db.index_64: %u\n", func, line, | ||
492 | db->index_64); | ||
493 | pr_debug("%s:%d: db.count_64: %u\n", func, line, | ||
494 | db->count_64); | ||
495 | pr_debug("%s:%d: db.index_32: %u\n", func, line, | ||
496 | db->index_32); | ||
497 | pr_debug("%s:%d: db.count_32: %u\n", func, line, | ||
498 | db->count_32); | ||
499 | pr_debug("%s:%d: db.index_16: %u\n", func, line, | ||
500 | db->index_16); | ||
501 | pr_debug("%s:%d: db.count_16: %u\n", func, line, | ||
502 | db->count_16); | ||
503 | } | ||
504 | |||
505 | static void os_area_db_init(struct os_area_db *db) | ||
506 | { | ||
507 | enum { | ||
508 | HEADER_SIZE = offsetof(struct os_area_db, _db_data), | ||
509 | INDEX_64_COUNT = 64, | ||
510 | VALUES_64_COUNT = 57, | ||
511 | INDEX_32_COUNT = 64, | ||
512 | VALUES_32_COUNT = 57, | ||
513 | INDEX_16_COUNT = 64, | ||
514 | VALUES_16_COUNT = 57, | ||
515 | }; | ||
516 | |||
517 | memset(db, 0, sizeof(struct os_area_db)); | ||
518 | |||
519 | db->magic_num = OS_AREA_DB_MAGIC_NUM; | ||
520 | db->version = 1; | ||
521 | db->index_64 = HEADER_SIZE; | ||
522 | db->count_64 = VALUES_64_COUNT; | ||
523 | db->index_32 = HEADER_SIZE | ||
524 | + INDEX_64_COUNT * sizeof(struct db_index) | ||
525 | + VALUES_64_COUNT * sizeof(u64); | ||
526 | db->count_32 = VALUES_32_COUNT; | ||
527 | db->index_16 = HEADER_SIZE | ||
528 | + INDEX_64_COUNT * sizeof(struct db_index) | ||
529 | + VALUES_64_COUNT * sizeof(u64) | ||
530 | + INDEX_32_COUNT * sizeof(struct db_index) | ||
531 | + VALUES_32_COUNT * sizeof(u32); | ||
532 | db->count_16 = VALUES_16_COUNT; | ||
533 | |||
534 | /* Rules to check db layout. */ | ||
535 | |||
536 | BUILD_BUG_ON(sizeof(struct db_index) != 1); | ||
537 | BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE); | ||
538 | BUILD_BUG_ON(INDEX_64_COUNT & 0x7); | ||
539 | BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT); | ||
540 | BUILD_BUG_ON(INDEX_32_COUNT & 0x7); | ||
541 | BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT); | ||
542 | BUILD_BUG_ON(INDEX_16_COUNT & 0x7); | ||
543 | BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT); | ||
544 | BUILD_BUG_ON(HEADER_SIZE | ||
545 | + INDEX_64_COUNT * sizeof(struct db_index) | ||
546 | + VALUES_64_COUNT * sizeof(u64) | ||
547 | + INDEX_32_COUNT * sizeof(struct db_index) | ||
548 | + VALUES_32_COUNT * sizeof(u32) | ||
549 | + INDEX_16_COUNT * sizeof(struct db_index) | ||
550 | + VALUES_16_COUNT * sizeof(u16) | ||
551 | > sizeof(struct os_area_db)); | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * update_flash_db - Helper for os_area_queue_work_handler. | ||
556 | * | ||
557 | */ | ||
558 | |||
559 | static void update_flash_db(void) | ||
560 | { | ||
561 | int result; | ||
562 | int file; | ||
563 | off_t offset; | ||
564 | ssize_t count; | ||
565 | static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE; | ||
566 | const struct os_area_header *header; | ||
567 | struct os_area_db* db; | ||
568 | |||
569 | /* Read in header and db from flash. */ | ||
570 | |||
571 | file = sys_open("/dev/ps3flash", O_RDWR, 0); | ||
572 | |||
573 | if (file < 0) { | ||
574 | pr_debug("%s:%d sys_open failed\n", __func__, __LINE__); | ||
575 | goto fail_open; | ||
576 | } | ||
577 | |||
578 | header = kmalloc(buf_len, GFP_KERNEL); | ||
579 | |||
580 | if (!header) { | ||
581 | pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__); | ||
582 | goto fail_malloc; | ||
583 | } | ||
584 | |||
585 | offset = sys_lseek(file, 0, SEEK_SET); | ||
586 | |||
587 | if (offset != 0) { | ||
588 | pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__); | ||
589 | goto fail_header_seek; | ||
590 | } | ||
591 | |||
592 | count = sys_read(file, (char __user *)header, buf_len); | ||
593 | |||
594 | result = count < OS_AREA_SEGMENT_SIZE || verify_header(header) | ||
595 | || count < header->db_area_offset * OS_AREA_SEGMENT_SIZE; | ||
596 | |||
597 | if (result) { | ||
598 | pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); | ||
599 | dump_header(header); | ||
600 | goto fail_header; | ||
601 | } | ||
602 | |||
603 | /* Now got a good db offset and some maybe good db data. */ | ||
604 | |||
605 | db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE; | ||
606 | |||
607 | result = db_verify(db); | ||
608 | |||
609 | if (result) { | ||
610 | printk(KERN_NOTICE "%s:%d: Verify of flash database failed, " | ||
611 | "formatting.\n", __func__, __LINE__); | ||
612 | dump_db(db); | ||
613 | os_area_db_init(db); | ||
614 | } | ||
615 | |||
616 | /* Now got good db data. */ | ||
617 | |||
618 | db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff); | ||
619 | |||
620 | offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE, | ||
621 | SEEK_SET); | ||
622 | |||
623 | if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) { | ||
624 | pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__); | ||
625 | goto fail_db_seek; | ||
626 | } | ||
627 | |||
628 | count = sys_write(file, (const char __user *)db, | ||
629 | sizeof(struct os_area_db)); | ||
630 | |||
631 | if (count < sizeof(struct os_area_db)) { | ||
632 | pr_debug("%s:%d sys_write failed\n", __func__, __LINE__); | ||
633 | } | ||
634 | |||
635 | fail_db_seek: | ||
636 | fail_header: | ||
637 | fail_header_seek: | ||
638 | kfree(header); | ||
639 | fail_malloc: | ||
640 | sys_close(file); | ||
641 | fail_open: | ||
642 | return; | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * os_area_queue_work_handler - Asynchronous write handler. | ||
647 | * | ||
648 | * An asynchronous write for flash memory and the device tree. Do not | ||
649 | * call directly, use os_area_queue_work(). | ||
650 | */ | ||
651 | |||
652 | static void os_area_queue_work_handler(struct work_struct *work) | ||
653 | { | ||
654 | struct device_node *node; | ||
655 | |||
656 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
657 | |||
658 | node = of_find_node_by_path("/"); | ||
659 | |||
660 | if (node) { | ||
661 | os_area_set_property(node, &property_rtc_diff); | ||
662 | of_node_put(node); | ||
663 | } else | ||
664 | pr_debug("%s:%d of_find_node_by_path failed\n", | ||
665 | __func__, __LINE__); | ||
666 | |||
667 | #if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | ||
668 | update_flash_db(); | ||
669 | #else | ||
670 | printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n", | ||
671 | __func__, __LINE__); | ||
672 | #endif | ||
673 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
674 | } | ||
675 | |||
676 | static void os_area_queue_work(void) | ||
677 | { | ||
678 | static DECLARE_WORK(q, os_area_queue_work_handler); | ||
679 | |||
680 | wmb(); | ||
681 | schedule_work(&q); | ||
682 | } | ||
683 | |||
684 | /** | ||
685 | * ps3_os_area_save_params - Copy data from os area mirror to @saved_params. | ||
686 | * | ||
687 | * For the convenience of the guest the HV makes a copy of the os area in | ||
688 | * flash to a high address in the boot memory region and then puts that RAM | ||
689 | * address and the byte count into the repository for retrieval by the guest. | ||
690 | * We copy the data we want into a static variable and allow the memory setup | ||
691 | * by the HV to be claimed by the lmb manager. | ||
692 | * | ||
693 | * The os area mirror will not be available to a second stage kernel, and | ||
694 | * the header verify will fail. In this case, the saved_params values will | ||
695 | * be set from flash memory or the passed in device tree in ps3_os_area_init(). | ||
696 | */ | ||
697 | |||
698 | void __init ps3_os_area_save_params(void) | ||
200 | { | 699 | { |
201 | int result; | 700 | int result; |
202 | u64 lpar_addr; | 701 | u64 lpar_addr; |
203 | unsigned int size; | 702 | unsigned int size; |
204 | struct os_area_header *header; | 703 | struct os_area_header *header; |
205 | struct os_area_params *params; | 704 | struct os_area_params *params; |
705 | struct os_area_db *db; | ||
706 | |||
707 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
206 | 708 | ||
207 | result = ps3_repository_read_boot_dat_info(&lpar_addr, &size); | 709 | result = ps3_repository_read_boot_dat_info(&lpar_addr, &size); |
208 | 710 | ||
209 | if (result) { | 711 | if (result) { |
210 | pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n", | 712 | pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n", |
211 | __func__, __LINE__); | 713 | __func__, __LINE__); |
212 | return result; | 714 | return; |
213 | } | 715 | } |
214 | 716 | ||
215 | header = (struct os_area_header *)__va(lpar_addr); | 717 | header = (struct os_area_header *)__va(lpar_addr); |
216 | params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE); | 718 | params = (struct os_area_params *)__va(lpar_addr |
719 | + OS_AREA_SEGMENT_SIZE); | ||
217 | 720 | ||
218 | result = verify_header(header); | 721 | result = verify_header(header); |
219 | 722 | ||
220 | if (result) { | 723 | if (result) { |
724 | /* Second stage kernels exit here. */ | ||
221 | pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); | 725 | pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); |
222 | dump_header(header); | 726 | dump_header(header); |
223 | return -EIO; | 727 | return; |
224 | } | 728 | } |
225 | 729 | ||
730 | db = (struct os_area_db *)__va(lpar_addr | ||
731 | + header->db_area_offset * OS_AREA_SEGMENT_SIZE); | ||
732 | |||
226 | dump_header(header); | 733 | dump_header(header); |
227 | dump_params(params); | 734 | dump_params(params); |
735 | dump_db(db); | ||
228 | 736 | ||
229 | saved_params.rtc_diff = params->rtc_diff; | 737 | result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff); |
738 | if (result) | ||
739 | saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff | ||
740 | : SECONDS_FROM_1970_TO_2000; | ||
230 | saved_params.av_multi_out = params->av_multi_out; | 741 | saved_params.av_multi_out = params->av_multi_out; |
231 | saved_params.ctrl_button = params->ctrl_button; | 742 | saved_params.valid = 1; |
232 | memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4); | 743 | |
233 | memcpy(saved_params.network_mask, params->network_mask, 4); | 744 | memset(header, 0, sizeof(*header)); |
234 | memcpy(saved_params.default_gateway, params->default_gateway, 4); | ||
235 | memcpy(saved_params.dns_secondary, params->dns_secondary, 4); | ||
236 | 745 | ||
237 | return result; | 746 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
238 | } | 747 | } |
239 | 748 | ||
240 | /** | 749 | /** |
241 | * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value. | 750 | * ps3_os_area_init - Setup os area device tree properties as needed. |
751 | */ | ||
752 | |||
753 | void __init ps3_os_area_init(void) | ||
754 | { | ||
755 | struct device_node *node; | ||
756 | |||
757 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
758 | |||
759 | node = of_find_node_by_path("/"); | ||
760 | |||
761 | if (!saved_params.valid && node) { | ||
762 | /* Second stage kernels should have a dt entry. */ | ||
763 | os_area_get_property(node, &property_rtc_diff); | ||
764 | os_area_get_property(node, &property_av_multi_out); | ||
765 | } | ||
766 | |||
767 | if(!saved_params.rtc_diff) | ||
768 | saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000; | ||
769 | |||
770 | if (node) { | ||
771 | os_area_set_property(node, &property_rtc_diff); | ||
772 | os_area_set_property(node, &property_av_multi_out); | ||
773 | of_node_put(node); | ||
774 | } else | ||
775 | pr_debug("%s:%d of_find_node_by_path failed\n", | ||
776 | __func__, __LINE__); | ||
777 | |||
778 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
779 | } | ||
780 | |||
781 | /** | ||
782 | * ps3_os_area_get_rtc_diff - Returns the rtc diff value. | ||
783 | */ | ||
784 | |||
785 | u64 ps3_os_area_get_rtc_diff(void) | ||
786 | { | ||
787 | return saved_params.rtc_diff; | ||
788 | } | ||
789 | |||
790 | /** | ||
791 | * ps3_os_area_set_rtc_diff - Set the rtc diff value. | ||
242 | * | 792 | * |
243 | * The ps3 rtc maintains a value that approximates seconds since | 793 | * An asynchronous write is needed to support writing updates from |
244 | * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to | 794 | * the timer interrupt context. |
245 | * 2000 when saved_params.rtc_diff has not been properly set up. | ||
246 | */ | 795 | */ |
247 | 796 | ||
248 | u64 ps3_os_area_rtc_diff(void) | 797 | void ps3_os_area_set_rtc_diff(u64 rtc_diff) |
249 | { | 798 | { |
250 | return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL; | 799 | if (saved_params.rtc_diff != rtc_diff) { |
800 | saved_params.rtc_diff = rtc_diff; | ||
801 | os_area_queue_work(); | ||
802 | } | ||
251 | } | 803 | } |
252 | 804 | ||
253 | /** | 805 | /** |
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 2eb8f92704b4..01f0c9506e11 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h | |||
@@ -47,7 +47,11 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); | |||
47 | /* smp */ | 47 | /* smp */ |
48 | 48 | ||
49 | void smp_init_ps3(void); | 49 | void smp_init_ps3(void); |
50 | #ifdef CONFIG_SMP | ||
50 | void ps3_smp_cleanup_cpu(int cpu); | 51 | void ps3_smp_cleanup_cpu(int cpu); |
52 | #else | ||
53 | static inline void ps3_smp_cleanup_cpu(int cpu) { } | ||
54 | #endif | ||
51 | 55 | ||
52 | /* time */ | 56 | /* time */ |
53 | 57 | ||
@@ -58,8 +62,10 @@ int ps3_set_rtc_time(struct rtc_time *time); | |||
58 | 62 | ||
59 | /* os area */ | 63 | /* os area */ |
60 | 64 | ||
61 | int __init ps3_os_area_init(void); | 65 | void __init ps3_os_area_save_params(void); |
62 | u64 ps3_os_area_rtc_diff(void); | 66 | void __init ps3_os_area_init(void); |
67 | u64 ps3_os_area_get_rtc_diff(void); | ||
68 | void ps3_os_area_set_rtc_diff(u64 rtc_diff); | ||
63 | 69 | ||
64 | /* spu */ | 70 | /* spu */ |
65 | 71 | ||
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 609945dbe394..5c2cbb08eb52 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c | |||
@@ -206,6 +206,7 @@ static void __init ps3_setup_arch(void) | |||
206 | prealloc_ps3flash_bounce_buffer(); | 206 | prealloc_ps3flash_bounce_buffer(); |
207 | 207 | ||
208 | ppc_md.power_save = ps3_power_save; | 208 | ppc_md.power_save = ps3_power_save; |
209 | ps3_os_area_init(); | ||
209 | 210 | ||
210 | DBG(" <- %s:%d\n", __func__, __LINE__); | 211 | DBG(" <- %s:%d\n", __func__, __LINE__); |
211 | } | 212 | } |
@@ -228,7 +229,7 @@ static int __init ps3_probe(void) | |||
228 | 229 | ||
229 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; | 230 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; |
230 | 231 | ||
231 | ps3_os_area_init(); | 232 | ps3_os_area_save_params(); |
232 | ps3_mm_init(); | 233 | ps3_mm_init(); |
233 | ps3_mm_vas_create(&htab_size); | 234 | ps3_mm_vas_create(&htab_size); |
234 | ps3_hpte_init(htab_size); | 235 | ps3_hpte_init(htab_size); |
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c index 802a9ccacb5e..d0daf7d6d3b2 100644 --- a/arch/powerpc/platforms/ps3/time.c +++ b/arch/powerpc/platforms/ps3/time.c | |||
@@ -50,12 +50,6 @@ static void __maybe_unused _dump_time(int time, const char *func, | |||
50 | _dump_tm(&tm, func, line); | 50 | _dump_tm(&tm, func, line); |
51 | } | 51 | } |
52 | 52 | ||
53 | /** | ||
54 | * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value. | ||
55 | */ | ||
56 | |||
57 | static s64 rtc_shift; | ||
58 | |||
59 | void __init ps3_calibrate_decr(void) | 53 | void __init ps3_calibrate_decr(void) |
60 | { | 54 | { |
61 | int result; | 55 | int result; |
@@ -66,8 +60,6 @@ void __init ps3_calibrate_decr(void) | |||
66 | 60 | ||
67 | ppc_tb_freq = tmp; | 61 | ppc_tb_freq = tmp; |
68 | ppc_proc_freq = ppc_tb_freq * 40; | 62 | ppc_proc_freq = ppc_tb_freq * 40; |
69 | |||
70 | rtc_shift = ps3_os_area_rtc_diff(); | ||
71 | } | 63 | } |
72 | 64 | ||
73 | static u64 read_rtc(void) | 65 | static u64 read_rtc(void) |
@@ -87,18 +79,18 @@ int ps3_set_rtc_time(struct rtc_time *tm) | |||
87 | u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | 79 | u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, |
88 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 80 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
89 | 81 | ||
90 | rtc_shift = now - read_rtc(); | 82 | ps3_os_area_set_rtc_diff(now - read_rtc()); |
91 | return 0; | 83 | return 0; |
92 | } | 84 | } |
93 | 85 | ||
94 | void ps3_get_rtc_time(struct rtc_time *tm) | 86 | void ps3_get_rtc_time(struct rtc_time *tm) |
95 | { | 87 | { |
96 | to_tm(read_rtc() + rtc_shift, tm); | 88 | to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm); |
97 | tm->tm_year -= 1900; | 89 | tm->tm_year -= 1900; |
98 | tm->tm_mon -= 1; | 90 | tm->tm_mon -= 1; |
99 | } | 91 | } |
100 | 92 | ||
101 | unsigned long __init ps3_get_boot_time(void) | 93 | unsigned long __init ps3_get_boot_time(void) |
102 | { | 94 | { |
103 | return read_rtc() + rtc_shift; | 95 | return read_rtc() + ps3_os_area_get_rtc_diff(); |
104 | } | 96 | } |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index b8770395013d..22322b35a0ff 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -169,6 +169,8 @@ static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, | |||
169 | */ | 169 | */ |
170 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | 170 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) |
171 | { | 171 | { |
172 | struct device_node *dn; | ||
173 | struct pci_dev *dev = pdn->pcidev; | ||
172 | u32 cfg; | 174 | u32 cfg; |
173 | int cap, i; | 175 | int cap, i; |
174 | int n = 0; | 176 | int n = 0; |
@@ -184,6 +186,17 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
184 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); | 186 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); |
185 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); | 187 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); |
186 | 188 | ||
189 | /* Gather bridge-specific registers */ | ||
190 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { | ||
191 | rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg); | ||
192 | n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); | ||
193 | printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg); | ||
194 | |||
195 | rtas_read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg); | ||
196 | n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); | ||
197 | printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg); | ||
198 | } | ||
199 | |||
187 | /* Dump out the PCI-X command and status regs */ | 200 | /* Dump out the PCI-X command and status regs */ |
188 | cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX); | 201 | cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX); |
189 | if (cap) { | 202 | if (cap) { |
@@ -209,7 +222,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
209 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); | 222 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); |
210 | } | 223 | } |
211 | 224 | ||
212 | cap = pci_find_ext_capability(pdn->pcidev,PCI_EXT_CAP_ID_ERR); | 225 | cap = pci_find_ext_capability(pdn->pcidev, PCI_EXT_CAP_ID_ERR); |
213 | if (cap) { | 226 | if (cap) { |
214 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); | 227 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); |
215 | printk(KERN_WARNING | 228 | printk(KERN_WARNING |
@@ -222,6 +235,18 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
222 | } | 235 | } |
223 | } | 236 | } |
224 | } | 237 | } |
238 | |||
239 | /* Gather status on devices under the bridge */ | ||
240 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { | ||
241 | dn = pdn->node->child; | ||
242 | while (dn) { | ||
243 | pdn = PCI_DN(dn); | ||
244 | if (pdn) | ||
245 | n += gather_pci_data(pdn, buf+n, len-n); | ||
246 | dn = dn->sibling; | ||
247 | } | ||
248 | } | ||
249 | |||
225 | return n; | 250 | return n; |
226 | } | 251 | } |
227 | 252 | ||
@@ -750,12 +775,12 @@ int rtas_set_slot_reset(struct pci_dn *pdn) | |||
750 | return 0; | 775 | return 0; |
751 | 776 | ||
752 | if (rc < 0) { | 777 | if (rc < 0) { |
753 | printk (KERN_ERR "EEH: unrecoverable slot failure %s\n", | 778 | printk(KERN_ERR "EEH: unrecoverable slot failure %s\n", |
754 | pdn->node->full_name); | 779 | pdn->node->full_name); |
755 | return -1; | 780 | return -1; |
756 | } | 781 | } |
757 | printk (KERN_ERR "EEH: bus reset %d failed on slot %s\n", | 782 | printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n", |
758 | i+1, pdn->node->full_name); | 783 | i+1, pdn->node->full_name, rc); |
759 | } | 784 | } |
760 | 785 | ||
761 | return -1; | 786 | return -1; |
@@ -930,7 +955,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
930 | pdn->eeh_freeze_count = 0; | 955 | pdn->eeh_freeze_count = 0; |
931 | pdn->eeh_false_positives = 0; | 956 | pdn->eeh_false_positives = 0; |
932 | 957 | ||
933 | if (status && strcmp(status, "ok") != 0) | 958 | if (status && strncmp(status, "ok", 2) != 0) |
934 | return NULL; /* ignore devices with bad status */ | 959 | return NULL; /* ignore devices with bad status */ |
935 | 960 | ||
936 | /* Ignore bad nodes. */ | 961 | /* Ignore bad nodes. */ |
@@ -944,23 +969,6 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
944 | } | 969 | } |
945 | pdn->class_code = *class_code; | 970 | pdn->class_code = *class_code; |
946 | 971 | ||
947 | /* | ||
948 | * Now decide if we are going to "Disable" EEH checking | ||
949 | * for this device. We still run with the EEH hardware active, | ||
950 | * but we won't be checking for ff's. This means a driver | ||
951 | * could return bad data (very bad!), an interrupt handler could | ||
952 | * hang waiting on status bits that won't change, etc. | ||
953 | * But there are a few cases like display devices that make sense. | ||
954 | */ | ||
955 | enable = 1; /* i.e. we will do checking */ | ||
956 | #if 0 | ||
957 | if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY) | ||
958 | enable = 0; | ||
959 | #endif | ||
960 | |||
961 | if (!enable) | ||
962 | pdn->eeh_mode |= EEH_MODE_NOCHECK; | ||
963 | |||
964 | /* Ok... see if this device supports EEH. Some do, some don't, | 972 | /* Ok... see if this device supports EEH. Some do, some don't, |
965 | * and the only way to find out is to check each and every one. */ | 973 | * and the only way to find out is to check each and every one. */ |
966 | regs = of_get_property(dn, "reg", NULL); | 974 | regs = of_get_property(dn, "reg", NULL); |
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index e49c815eae23..1e83fcd0df31 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
@@ -225,6 +225,10 @@ void pci_addr_cache_insert_device(struct pci_dev *dev) | |||
225 | { | 225 | { |
226 | unsigned long flags; | 226 | unsigned long flags; |
227 | 227 | ||
228 | /* Ignore PCI bridges */ | ||
229 | if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) | ||
230 | return; | ||
231 | |||
228 | spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); | 232 | spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); |
229 | __pci_addr_cache_insert_device(dev); | 233 | __pci_addr_cache_insert_device(dev); |
230 | spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); | 234 | spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); |
@@ -285,16 +289,13 @@ void __init pci_addr_cache_build(void) | |||
285 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); | 289 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); |
286 | 290 | ||
287 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 291 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { |
288 | /* Ignore PCI bridges */ | ||
289 | if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) | ||
290 | continue; | ||
291 | 292 | ||
292 | pci_addr_cache_insert_device(dev); | 293 | pci_addr_cache_insert_device(dev); |
293 | 294 | ||
294 | dn = pci_device_to_OF_node(dev); | 295 | dn = pci_device_to_OF_node(dev); |
295 | if (!dn) | 296 | if (!dn) |
296 | continue; | 297 | continue; |
297 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ | 298 | pci_dev_get(dev); /* matching put is in eeh_remove_device() */ |
298 | PCI_DN(dn)->pcidev = dev; | 299 | PCI_DN(dn)->pcidev = dev; |
299 | 300 | ||
300 | eeh_sysfs_add_device(dev); | 301 | eeh_sysfs_add_device(dev); |
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 9711eb0d5496..fc48b96c81bf 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
@@ -252,6 +252,20 @@ static struct notifier_block pseries_smp_nb = { | |||
252 | 252 | ||
253 | static int __init pseries_cpu_hotplug_init(void) | 253 | static int __init pseries_cpu_hotplug_init(void) |
254 | { | 254 | { |
255 | struct device_node *np; | ||
256 | const char *typep; | ||
257 | |||
258 | for_each_node_by_name(np, "interrupt-controller") { | ||
259 | typep = of_get_property(np, "compatible", NULL); | ||
260 | if (strstr(typep, "open-pic")) { | ||
261 | of_node_put(np); | ||
262 | |||
263 | printk(KERN_INFO "CPU Hotplug not supported on " | ||
264 | "systems using MPIC\n"); | ||
265 | return 0; | ||
266 | } | ||
267 | } | ||
268 | |||
255 | rtas_stop_self_args.token = rtas_token("stop-self"); | 269 | rtas_stop_self_args.token = rtas_token("stop-self"); |
256 | qcss_tok = rtas_token("query-cpu-stopped-state"); | 270 | qcss_tok = rtas_token("query-cpu-stopped-state"); |
257 | 271 | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 8cc6eeeaae2f..9a455d46379d 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
36 | #include <asm/tlb.h> | 36 | #include <asm/tlb.h> |
37 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
38 | #include <asm/abs_addr.h> | ||
39 | #include <asm/cputable.h> | 38 | #include <asm/cputable.h> |
40 | #include <asm/udbg.h> | 39 | #include <asm/udbg.h> |
41 | #include <asm/smp.h> | 40 | #include <asm/smp.h> |
@@ -285,7 +284,7 @@ void vpa_init(int cpu) | |||
285 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 284 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
286 | unsigned long va, unsigned long pa, | 285 | unsigned long va, unsigned long pa, |
287 | unsigned long rflags, unsigned long vflags, | 286 | unsigned long rflags, unsigned long vflags, |
288 | int psize) | 287 | int psize, int ssize) |
289 | { | 288 | { |
290 | unsigned long lpar_rc; | 289 | unsigned long lpar_rc; |
291 | unsigned long flags; | 290 | unsigned long flags; |
@@ -297,7 +296,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
297 | "rflags=%lx, vflags=%lx, psize=%d)\n", | 296 | "rflags=%lx, vflags=%lx, psize=%d)\n", |
298 | hpte_group, va, pa, rflags, vflags, psize); | 297 | hpte_group, va, pa, rflags, vflags, psize); |
299 | 298 | ||
300 | hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; | 299 | hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID; |
301 | hpte_r = hpte_encode_r(pa, psize) | rflags; | 300 | hpte_r = hpte_encode_r(pa, psize) | rflags; |
302 | 301 | ||
303 | if (!(vflags & HPTE_V_BOLTED)) | 302 | if (!(vflags & HPTE_V_BOLTED)) |
@@ -393,6 +392,22 @@ static void pSeries_lpar_hptab_clear(void) | |||
393 | } | 392 | } |
394 | 393 | ||
395 | /* | 394 | /* |
395 | * This computes the AVPN and B fields of the first dword of a HPTE, | ||
396 | * for use when we want to match an existing PTE. The bottom 7 bits | ||
397 | * of the returned value are zero. | ||
398 | */ | ||
399 | static inline unsigned long hpte_encode_avpn(unsigned long va, int psize, | ||
400 | int ssize) | ||
401 | { | ||
402 | unsigned long v; | ||
403 | |||
404 | v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); | ||
405 | v <<= HPTE_V_AVPN_SHIFT; | ||
406 | v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT; | ||
407 | return v; | ||
408 | } | ||
409 | |||
410 | /* | ||
396 | * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and | 411 | * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and |
397 | * the low 3 bits of flags happen to line up. So no transform is needed. | 412 | * the low 3 bits of flags happen to line up. So no transform is needed. |
398 | * We can probably optimize here and assume the high bits of newpp are | 413 | * We can probably optimize here and assume the high bits of newpp are |
@@ -401,18 +416,18 @@ static void pSeries_lpar_hptab_clear(void) | |||
401 | static long pSeries_lpar_hpte_updatepp(unsigned long slot, | 416 | static long pSeries_lpar_hpte_updatepp(unsigned long slot, |
402 | unsigned long newpp, | 417 | unsigned long newpp, |
403 | unsigned long va, | 418 | unsigned long va, |
404 | int psize, int local) | 419 | int psize, int ssize, int local) |
405 | { | 420 | { |
406 | unsigned long lpar_rc; | 421 | unsigned long lpar_rc; |
407 | unsigned long flags = (newpp & 7) | H_AVPN; | 422 | unsigned long flags = (newpp & 7) | H_AVPN; |
408 | unsigned long want_v; | 423 | unsigned long want_v; |
409 | 424 | ||
410 | want_v = hpte_encode_v(va, psize); | 425 | want_v = hpte_encode_avpn(va, psize, ssize); |
411 | 426 | ||
412 | DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ", | 427 | DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ", |
413 | want_v & HPTE_V_AVPN, slot, flags, psize); | 428 | want_v, slot, flags, psize); |
414 | 429 | ||
415 | lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN); | 430 | lpar_rc = plpar_pte_protect(flags, slot, want_v); |
416 | 431 | ||
417 | if (lpar_rc == H_NOT_FOUND) { | 432 | if (lpar_rc == H_NOT_FOUND) { |
418 | DBG_LOW("not found !\n"); | 433 | DBG_LOW("not found !\n"); |
@@ -445,32 +460,25 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot) | |||
445 | return dword0; | 460 | return dword0; |
446 | } | 461 | } |
447 | 462 | ||
448 | static long pSeries_lpar_hpte_find(unsigned long va, int psize) | 463 | static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize) |
449 | { | 464 | { |
450 | unsigned long hash; | 465 | unsigned long hash; |
451 | unsigned long i, j; | 466 | unsigned long i; |
452 | long slot; | 467 | long slot; |
453 | unsigned long want_v, hpte_v; | 468 | unsigned long want_v, hpte_v; |
454 | 469 | ||
455 | hash = hpt_hash(va, mmu_psize_defs[psize].shift); | 470 | hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize); |
456 | want_v = hpte_encode_v(va, psize); | 471 | want_v = hpte_encode_avpn(va, psize, ssize); |
457 | 472 | ||
458 | for (j = 0; j < 2; j++) { | 473 | /* Bolted entries are always in the primary group */ |
459 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 474 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
460 | for (i = 0; i < HPTES_PER_GROUP; i++) { | 475 | for (i = 0; i < HPTES_PER_GROUP; i++) { |
461 | hpte_v = pSeries_lpar_hpte_getword0(slot); | 476 | hpte_v = pSeries_lpar_hpte_getword0(slot); |
462 | 477 | ||
463 | if (HPTE_V_COMPARE(hpte_v, want_v) | 478 | if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) |
464 | && (hpte_v & HPTE_V_VALID) | 479 | /* HPTE matches */ |
465 | && (!!(hpte_v & HPTE_V_SECONDARY) == j)) { | 480 | return slot; |
466 | /* HPTE matches */ | 481 | ++slot; |
467 | if (j) | ||
468 | slot = -slot; | ||
469 | return slot; | ||
470 | } | ||
471 | ++slot; | ||
472 | } | ||
473 | hash = ~hash; | ||
474 | } | 482 | } |
475 | 483 | ||
476 | return -1; | 484 | return -1; |
@@ -478,14 +486,14 @@ static long pSeries_lpar_hpte_find(unsigned long va, int psize) | |||
478 | 486 | ||
479 | static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, | 487 | static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, |
480 | unsigned long ea, | 488 | unsigned long ea, |
481 | int psize) | 489 | int psize, int ssize) |
482 | { | 490 | { |
483 | unsigned long lpar_rc, slot, vsid, va, flags; | 491 | unsigned long lpar_rc, slot, vsid, va, flags; |
484 | 492 | ||
485 | vsid = get_kernel_vsid(ea); | 493 | vsid = get_kernel_vsid(ea, ssize); |
486 | va = (vsid << 28) | (ea & 0x0fffffff); | 494 | va = hpt_va(ea, vsid, ssize); |
487 | 495 | ||
488 | slot = pSeries_lpar_hpte_find(va, psize); | 496 | slot = pSeries_lpar_hpte_find(va, psize, ssize); |
489 | BUG_ON(slot == -1); | 497 | BUG_ON(slot == -1); |
490 | 498 | ||
491 | flags = newpp & 7; | 499 | flags = newpp & 7; |
@@ -495,7 +503,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, | |||
495 | } | 503 | } |
496 | 504 | ||
497 | static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | 505 | static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, |
498 | int psize, int local) | 506 | int psize, int ssize, int local) |
499 | { | 507 | { |
500 | unsigned long want_v; | 508 | unsigned long want_v; |
501 | unsigned long lpar_rc; | 509 | unsigned long lpar_rc; |
@@ -504,9 +512,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
504 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d", | 512 | DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d", |
505 | slot, va, psize, local); | 513 | slot, va, psize, local); |
506 | 514 | ||
507 | want_v = hpte_encode_v(va, psize); | 515 | want_v = hpte_encode_avpn(va, psize, ssize); |
508 | lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN, | 516 | lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2); |
509 | &dummy1, &dummy2); | ||
510 | if (lpar_rc == H_NOT_FOUND) | 517 | if (lpar_rc == H_NOT_FOUND) |
511 | return; | 518 | return; |
512 | 519 | ||
@@ -534,18 +541,19 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
534 | unsigned long va; | 541 | unsigned long va; |
535 | unsigned long hash, index, shift, hidx, slot; | 542 | unsigned long hash, index, shift, hidx, slot; |
536 | real_pte_t pte; | 543 | real_pte_t pte; |
537 | int psize; | 544 | int psize, ssize; |
538 | 545 | ||
539 | if (lock_tlbie) | 546 | if (lock_tlbie) |
540 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); | 547 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); |
541 | 548 | ||
542 | psize = batch->psize; | 549 | psize = batch->psize; |
550 | ssize = batch->ssize; | ||
543 | pix = 0; | 551 | pix = 0; |
544 | for (i = 0; i < number; i++) { | 552 | for (i = 0; i < number; i++) { |
545 | va = batch->vaddr[i]; | 553 | va = batch->vaddr[i]; |
546 | pte = batch->pte[i]; | 554 | pte = batch->pte[i]; |
547 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { | 555 | pte_iterate_hashed_subpages(pte, psize, va, index, shift) { |
548 | hash = hpt_hash(va, shift); | 556 | hash = hpt_hash(va, shift, ssize); |
549 | hidx = __rpte_to_hidx(pte, index); | 557 | hidx = __rpte_to_hidx(pte, index); |
550 | if (hidx & _PTEIDX_SECONDARY) | 558 | if (hidx & _PTEIDX_SECONDARY) |
551 | hash = ~hash; | 559 | hash = ~hash; |
@@ -553,11 +561,11 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
553 | slot += hidx & _PTEIDX_GROUP_IX; | 561 | slot += hidx & _PTEIDX_GROUP_IX; |
554 | if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { | 562 | if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { |
555 | pSeries_lpar_hpte_invalidate(slot, va, psize, | 563 | pSeries_lpar_hpte_invalidate(slot, va, psize, |
556 | local); | 564 | ssize, local); |
557 | } else { | 565 | } else { |
558 | param[pix] = HBR_REQUEST | HBR_AVPN | slot; | 566 | param[pix] = HBR_REQUEST | HBR_AVPN | slot; |
559 | param[pix+1] = hpte_encode_v(va, psize) & | 567 | param[pix+1] = hpte_encode_avpn(va, psize, |
560 | HPTE_V_AVPN; | 568 | ssize); |
561 | pix += 2; | 569 | pix += 2; |
562 | if (pix == 8) { | 570 | if (pix == 8) { |
563 | rc = plpar_hcall9(H_BULK_REMOVE, param, | 571 | rc = plpar_hcall9(H_BULK_REMOVE, param, |
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 6063ea2f67ad..2793a1b100e6 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
@@ -70,11 +70,15 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) | |||
70 | seq_num = rtas_ret[1]; | 70 | seq_num = rtas_ret[1]; |
71 | } while (rtas_busy_delay(rc)); | 71 | } while (rtas_busy_delay(rc)); |
72 | 72 | ||
73 | if (rc == 0) /* Success */ | 73 | /* |
74 | rc = rtas_ret[0]; | 74 | * If the RTAS call succeeded, check the number of irqs is actually |
75 | * what we asked for. If not, return an error. | ||
76 | */ | ||
77 | if (rc == 0 && rtas_ret[0] != num_irqs) | ||
78 | rc = -ENOSPC; | ||
75 | 79 | ||
76 | pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d) = (%d)\n", | 80 | pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d), got %d rc = %d\n", |
77 | func, num_irqs, rc); | 81 | func, num_irqs, rtas_ret[0], rc); |
78 | 82 | ||
79 | return rc; | 83 | return rc; |
80 | } | 84 | } |
@@ -87,7 +91,7 @@ static void rtas_disable_msi(struct pci_dev *pdev) | |||
87 | if (!pdn) | 91 | if (!pdn) |
88 | return; | 92 | return; |
89 | 93 | ||
90 | if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0) | 94 | if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0)) |
91 | pr_debug("rtas_msi: Setting MSIs to 0 failed!\n"); | 95 | pr_debug("rtas_msi: Setting MSIs to 0 failed!\n"); |
92 | } | 96 | } |
93 | 97 | ||
@@ -180,38 +184,31 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
180 | if (type == PCI_CAP_ID_MSI) { | 184 | if (type == PCI_CAP_ID_MSI) { |
181 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); | 185 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); |
182 | 186 | ||
183 | if (rc != nvec) { | 187 | if (rc) { |
184 | pr_debug("rtas_msi: trying the old firmware call.\n"); | 188 | pr_debug("rtas_msi: trying the old firmware call.\n"); |
185 | rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); | 189 | rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); |
186 | } | 190 | } |
187 | } else | 191 | } else |
188 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); | 192 | rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); |
189 | 193 | ||
190 | if (rc != nvec) { | 194 | if (rc) { |
191 | pr_debug("rtas_msi: rtas_change_msi() failed\n"); | 195 | pr_debug("rtas_msi: rtas_change_msi() failed\n"); |
192 | 196 | return rc; | |
193 | /* | ||
194 | * In case of an error it's not clear whether the device is | ||
195 | * left with MSI enabled or not, so we explicitly disable. | ||
196 | */ | ||
197 | goto out_free; | ||
198 | } | 197 | } |
199 | 198 | ||
200 | i = 0; | 199 | i = 0; |
201 | list_for_each_entry(entry, &pdev->msi_list, list) { | 200 | list_for_each_entry(entry, &pdev->msi_list, list) { |
202 | hwirq = rtas_query_irq_number(pdn, i); | 201 | hwirq = rtas_query_irq_number(pdn, i); |
203 | if (hwirq < 0) { | 202 | if (hwirq < 0) { |
204 | rc = hwirq; | ||
205 | pr_debug("rtas_msi: error (%d) getting hwirq\n", rc); | 203 | pr_debug("rtas_msi: error (%d) getting hwirq\n", rc); |
206 | goto out_free; | 204 | return hwirq; |
207 | } | 205 | } |
208 | 206 | ||
209 | virq = irq_create_mapping(NULL, hwirq); | 207 | virq = irq_create_mapping(NULL, hwirq); |
210 | 208 | ||
211 | if (virq == NO_IRQ) { | 209 | if (virq == NO_IRQ) { |
212 | pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq); | 210 | pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq); |
213 | rc = -ENOSPC; | 211 | return -ENOSPC; |
214 | goto out_free; | ||
215 | } | 212 | } |
216 | 213 | ||
217 | dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq); | 214 | dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq); |
@@ -220,10 +217,6 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
220 | } | 217 | } |
221 | 218 | ||
222 | return 0; | 219 | return 0; |
223 | |||
224 | out_free: | ||
225 | rtas_teardown_msi_irqs(pdev); | ||
226 | return rc; | ||
227 | } | 220 | } |
228 | 221 | ||
229 | static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev) | 222 | static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev) |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 9797b10b2935..73401c820110 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -44,15 +44,20 @@ static unsigned long rtas_log_start; | |||
44 | static unsigned long rtas_log_size; | 44 | static unsigned long rtas_log_size; |
45 | 45 | ||
46 | static int surveillance_timeout = -1; | 46 | static int surveillance_timeout = -1; |
47 | static unsigned int rtas_event_scan_rate; | ||
48 | static unsigned int rtas_error_log_max; | 47 | static unsigned int rtas_error_log_max; |
49 | static unsigned int rtas_error_log_buffer_max; | 48 | static unsigned int rtas_error_log_buffer_max; |
50 | 49 | ||
51 | static int full_rtas_msgs = 0; | 50 | /* RTAS service tokens */ |
51 | static unsigned int event_scan; | ||
52 | static unsigned int rtas_event_scan_rate; | ||
52 | 53 | ||
53 | extern int no_logging; | 54 | static int full_rtas_msgs = 0; |
54 | 55 | ||
55 | volatile int error_log_cnt = 0; | 56 | /* Stop logging to nvram after first fatal error */ |
57 | static int logging_enabled; /* Until we initialize everything, | ||
58 | * make sure we don't try logging | ||
59 | * anything */ | ||
60 | static int error_log_cnt; | ||
56 | 61 | ||
57 | /* | 62 | /* |
58 | * Since we use 32 bit RTAS, the physical address of this must be below | 63 | * Since we use 32 bit RTAS, the physical address of this must be below |
@@ -61,8 +66,6 @@ volatile int error_log_cnt = 0; | |||
61 | */ | 66 | */ |
62 | static unsigned char logdata[RTAS_ERROR_LOG_MAX]; | 67 | static unsigned char logdata[RTAS_ERROR_LOG_MAX]; |
63 | 68 | ||
64 | static int get_eventscan_parms(void); | ||
65 | |||
66 | static char *rtas_type[] = { | 69 | static char *rtas_type[] = { |
67 | "Unknown", "Retry", "TCE Error", "Internal Device Failure", | 70 | "Unknown", "Retry", "TCE Error", "Internal Device Failure", |
68 | "Timeout", "Data Parity", "Address Parity", "Cache Parity", | 71 | "Timeout", "Data Parity", "Address Parity", "Cache Parity", |
@@ -166,9 +169,9 @@ static int log_rtas_len(char * buf) | |||
166 | len += err->extended_log_length; | 169 | len += err->extended_log_length; |
167 | } | 170 | } |
168 | 171 | ||
169 | if (rtas_error_log_max == 0) { | 172 | if (rtas_error_log_max == 0) |
170 | get_eventscan_parms(); | 173 | rtas_error_log_max = rtas_get_error_log_max(); |
171 | } | 174 | |
172 | if (len > rtas_error_log_max) | 175 | if (len > rtas_error_log_max) |
173 | len = rtas_error_log_max; | 176 | len = rtas_error_log_max; |
174 | 177 | ||
@@ -215,8 +218,8 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
215 | } | 218 | } |
216 | 219 | ||
217 | /* Write error to NVRAM */ | 220 | /* Write error to NVRAM */ |
218 | if (!no_logging && !(err_type & ERR_FLAG_BOOT)) | 221 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) |
219 | nvram_write_error_log(buf, len, err_type); | 222 | nvram_write_error_log(buf, len, err_type, error_log_cnt); |
220 | 223 | ||
221 | /* | 224 | /* |
222 | * rtas errors can occur during boot, and we do want to capture | 225 | * rtas errors can occur during boot, and we do want to capture |
@@ -227,8 +230,8 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
227 | printk_log_rtas(buf, len); | 230 | printk_log_rtas(buf, len); |
228 | 231 | ||
229 | /* Check to see if we need to or have stopped logging */ | 232 | /* Check to see if we need to or have stopped logging */ |
230 | if (fatal || no_logging) { | 233 | if (fatal || !logging_enabled) { |
231 | no_logging = 1; | 234 | logging_enabled = 0; |
232 | spin_unlock_irqrestore(&rtasd_log_lock, s); | 235 | spin_unlock_irqrestore(&rtasd_log_lock, s); |
233 | return; | 236 | return; |
234 | } | 237 | } |
@@ -300,7 +303,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, | |||
300 | 303 | ||
301 | spin_lock_irqsave(&rtasd_log_lock, s); | 304 | spin_lock_irqsave(&rtasd_log_lock, s); |
302 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ | 305 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ |
303 | if (rtas_log_size == 0 && !no_logging) | 306 | if (rtas_log_size == 0 && logging_enabled) |
304 | nvram_clear_error_log(); | 307 | nvram_clear_error_log(); |
305 | spin_unlock_irqrestore(&rtasd_log_lock, s); | 308 | spin_unlock_irqrestore(&rtasd_log_lock, s); |
306 | 309 | ||
@@ -356,32 +359,7 @@ static int enable_surveillance(int timeout) | |||
356 | return -1; | 359 | return -1; |
357 | } | 360 | } |
358 | 361 | ||
359 | static int get_eventscan_parms(void) | 362 | static void do_event_scan(void) |
360 | { | ||
361 | struct device_node *node; | ||
362 | const int *ip; | ||
363 | |||
364 | node = of_find_node_by_path("/rtas"); | ||
365 | |||
366 | ip = of_get_property(node, "rtas-event-scan-rate", NULL); | ||
367 | if (ip == NULL) { | ||
368 | printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); | ||
369 | of_node_put(node); | ||
370 | return -1; | ||
371 | } | ||
372 | rtas_event_scan_rate = *ip; | ||
373 | DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate); | ||
374 | |||
375 | /* Make room for the sequence number */ | ||
376 | rtas_error_log_max = rtas_get_error_log_max(); | ||
377 | rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); | ||
378 | |||
379 | of_node_put(node); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static void do_event_scan(int event_scan) | ||
385 | { | 363 | { |
386 | int error; | 364 | int error; |
387 | do { | 365 | do { |
@@ -408,7 +386,7 @@ static void do_event_scan_all_cpus(long delay) | |||
408 | cpu = first_cpu(cpu_online_map); | 386 | cpu = first_cpu(cpu_online_map); |
409 | for (;;) { | 387 | for (;;) { |
410 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 388 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
411 | do_event_scan(rtas_token("event-scan")); | 389 | do_event_scan(); |
412 | set_cpus_allowed(current, CPU_MASK_ALL); | 390 | set_cpus_allowed(current, CPU_MASK_ALL); |
413 | 391 | ||
414 | /* Drop hotplug lock, and sleep for the specified delay */ | 392 | /* Drop hotplug lock, and sleep for the specified delay */ |
@@ -426,31 +404,19 @@ static void do_event_scan_all_cpus(long delay) | |||
426 | static int rtasd(void *unused) | 404 | static int rtasd(void *unused) |
427 | { | 405 | { |
428 | unsigned int err_type; | 406 | unsigned int err_type; |
429 | int event_scan = rtas_token("event-scan"); | ||
430 | int rc; | 407 | int rc; |
431 | 408 | ||
432 | daemonize("rtasd"); | 409 | daemonize("rtasd"); |
433 | 410 | ||
434 | if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1) | ||
435 | goto error; | ||
436 | |||
437 | rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER); | ||
438 | if (!rtas_log_buf) { | ||
439 | printk(KERN_ERR "rtasd: no memory\n"); | ||
440 | goto error; | ||
441 | } | ||
442 | |||
443 | printk(KERN_DEBUG "RTAS daemon started\n"); | 411 | printk(KERN_DEBUG "RTAS daemon started\n"); |
444 | |||
445 | DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); | 412 | DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); |
446 | 413 | ||
447 | /* See if we have any error stored in NVRAM */ | 414 | /* See if we have any error stored in NVRAM */ |
448 | memset(logdata, 0, rtas_error_log_max); | 415 | memset(logdata, 0, rtas_error_log_max); |
449 | 416 | rc = nvram_read_error_log(logdata, rtas_error_log_max, | |
450 | rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type); | 417 | &err_type, &error_log_cnt); |
451 | |||
452 | /* We can use rtas_log_buf now */ | 418 | /* We can use rtas_log_buf now */ |
453 | no_logging = 0; | 419 | logging_enabled = 1; |
454 | 420 | ||
455 | if (!rc) { | 421 | if (!rc) { |
456 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { | 422 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { |
@@ -473,8 +439,6 @@ static int rtasd(void *unused) | |||
473 | for (;;) | 439 | for (;;) |
474 | do_event_scan_all_cpus(30000/rtas_event_scan_rate); | 440 | do_event_scan_all_cpus(30000/rtas_event_scan_rate); |
475 | 441 | ||
476 | error: | ||
477 | /* Should delete proc entries */ | ||
478 | return -EINVAL; | 442 | return -EINVAL; |
479 | } | 443 | } |
480 | 444 | ||
@@ -486,11 +450,28 @@ static int __init rtas_init(void) | |||
486 | return 0; | 450 | return 0; |
487 | 451 | ||
488 | /* No RTAS */ | 452 | /* No RTAS */ |
489 | if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { | 453 | event_scan = rtas_token("event-scan"); |
454 | if (event_scan == RTAS_UNKNOWN_SERVICE) { | ||
490 | printk(KERN_DEBUG "rtasd: no event-scan on system\n"); | 455 | printk(KERN_DEBUG "rtasd: no event-scan on system\n"); |
491 | return -ENODEV; | 456 | return -ENODEV; |
492 | } | 457 | } |
493 | 458 | ||
459 | rtas_event_scan_rate = rtas_token("rtas-event-scan-rate"); | ||
460 | if (rtas_event_scan_rate == RTAS_UNKNOWN_SERVICE) { | ||
461 | printk(KERN_ERR "rtasd: no rtas-event-scan-rate on system\n"); | ||
462 | return -ENODEV; | ||
463 | } | ||
464 | |||
465 | /* Make room for the sequence number */ | ||
466 | rtas_error_log_max = rtas_get_error_log_max(); | ||
467 | rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); | ||
468 | |||
469 | rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER); | ||
470 | if (!rtas_log_buf) { | ||
471 | printk(KERN_ERR "rtasd: no memory\n"); | ||
472 | return -ENOMEM; | ||
473 | } | ||
474 | |||
494 | entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL); | 475 | entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL); |
495 | if (entry) | 476 | if (entry) |
496 | entry->proc_fops = &proc_rtas_log_operations; | 477 | entry->proc_fops = &proc_rtas_log_operations; |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f0b7146a110f..fdb9b1c8f977 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -257,11 +257,6 @@ static void __init pSeries_setup_arch(void) | |||
257 | /* init to some ~sane value until calibrate_delay() runs */ | 257 | /* init to some ~sane value until calibrate_delay() runs */ |
258 | loops_per_jiffy = 50000000; | 258 | loops_per_jiffy = 50000000; |
259 | 259 | ||
260 | if (ROOT_DEV == 0) { | ||
261 | printk("No ramdisk, default root is /dev/sda2\n"); | ||
262 | ROOT_DEV = Root_SDA2; | ||
263 | } | ||
264 | |||
265 | fwnmi_init(); | 260 | fwnmi_init(); |
266 | 261 | ||
267 | /* Find and initialize PCI host bridges */ | 262 | /* Find and initialize PCI host bridges */ |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index f0b5ff17d860..66e7d68ffeb1 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -540,7 +540,7 @@ static void __init xics_init_host(void) | |||
540 | ops = &xics_host_lpar_ops; | 540 | ops = &xics_host_lpar_ops; |
541 | else | 541 | else |
542 | ops = &xics_host_direct_ops; | 542 | ops = &xics_host_direct_ops; |
543 | xics_host = irq_alloc_host(IRQ_HOST_MAP_TREE, 0, ops, | 543 | xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, ops, |
544 | XICS_IRQ_SPURIOUS); | 544 | XICS_IRQ_SPURIOUS); |
545 | BUG_ON(xics_host == NULL); | 545 | BUG_ON(xics_host == NULL); |
546 | irq_set_default_host(xics_host); | 546 | irq_set_default_host(xics_host); |