aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/Kconfig14
-rw-r--r--arch/powerpc/boot/.gitignore7
-rw-r--r--arch/powerpc/boot/Makefile9
-rw-r--r--arch/powerpc/boot/flatdevtree.c880
-rw-r--r--arch/powerpc/boot/flatdevtree.h62
-rw-r--r--arch/powerpc/boot/flatdevtree_env.h47
-rw-r--r--arch/powerpc/boot/flatdevtree_misc.c56
-rw-r--r--arch/powerpc/boot/io.h53
-rw-r--r--arch/powerpc/boot/main.c27
-rw-r--r--arch/powerpc/boot/mktree.c152
-rw-r--r--arch/powerpc/boot/ns16550.c74
-rw-r--r--arch/powerpc/boot/of.c8
-rw-r--r--arch/powerpc/boot/ops.h25
-rw-r--r--arch/powerpc/boot/serial.c142
-rw-r--r--arch/powerpc/boot/simple_alloc.c149
-rw-r--r--arch/powerpc/boot/stdio.c3
-rw-r--r--arch/powerpc/boot/util.S88
-rwxr-xr-xarch/powerpc/boot/wrapper3
-rw-r--r--arch/powerpc/boot/zImage.coff.lds.S4
-rw-r--r--arch/powerpc/configs/cell_defconfig16
-rw-r--r--arch/powerpc/kernel/Makefile3
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/cpu_setup_ppc970.S16
-rw-r--r--arch/powerpc/kernel/cputable.c3
-rw-r--r--arch/powerpc/kernel/crash.c4
-rw-r--r--arch/powerpc/kernel/entry_64.S47
-rw-r--r--arch/powerpc/kernel/head_64.S153
-rw-r--r--arch/powerpc/kernel/idle.c7
-rw-r--r--arch/powerpc/kernel/idle_power4.S8
-rw-r--r--arch/powerpc/kernel/irq.c30
-rw-r--r--arch/powerpc/kernel/pci_64.c14
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c4
-rw-r--r--arch/powerpc/kernel/prom.c1
-rw-r--r--arch/powerpc/kernel/prom_parse.c288
-rw-r--r--arch/powerpc/kernel/setup_32.c4
-rw-r--r--arch/powerpc/kernel/setup_64.c8
-rw-r--r--arch/powerpc/kernel/smp.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c66
-rw-r--r--arch/powerpc/mm/fault.c25
-rw-r--r--arch/powerpc/mm/hash_native_64.c2
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/Kconfig14
-rw-r--r--arch/powerpc/platforms/cell/Makefile6
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c248
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c59
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h201
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c225
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c96
-rw-r--r--arch/powerpc/platforms/cell/pmu.c328
-rw-r--r--arch/powerpc/platforms/cell/pmu.h57
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c110
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1_mmio.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c27
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c54
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c5
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c143
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c12
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h8
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c63
-rw-r--r--arch/powerpc/platforms/efika/Makefile1
-rw-r--r--arch/powerpc/platforms/efika/efika.h19
-rw-r--r--arch/powerpc/platforms/efika/pci.c119
-rw-r--r--arch/powerpc/platforms/efika/setup.c149
-rw-r--r--arch/powerpc/platforms/iseries/dt.c15
-rw-r--r--arch/powerpc/platforms/iseries/ksyms.c6
-rw-r--r--arch/powerpc/platforms/iseries/misc.S35
-rw-r--r--arch/powerpc/platforms/iseries/setup.c32
-rw-r--r--arch/powerpc/platforms/powermac/feature.c8
-rw-r--r--arch/powerpc/platforms/powermac/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c4
-rw-r--r--arch/powerpc/sysdev/Makefile2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c28
-rw-r--r--arch/powerpc/sysdev/mpc52xx_pic.c538
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c3
-rw-r--r--arch/powerpc/sysdev/todc.c392
-rw-r--r--arch/powerpc/xmon/xmon.c207
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c4
-rw-r--r--arch/ppc/platforms/85xx/mpc8540_ads.c4
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c4
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c6
-rw-r--r--arch/ppc/platforms/85xx/sbc8560.c2
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c2
-rw-r--r--arch/ppc/platforms/85xx/tqm85xx.c4
-rw-r--r--arch/ppc/platforms/mpc8272ads_setup.c6
-rw-r--r--arch/ppc/platforms/mpc866ads_setup.c4
-rw-r--r--drivers/ide/pci/via82cxxx.c4
-rw-r--r--drivers/net/phy/fixed.c2
-rw-r--r--drivers/net/tulip/de4x5.c8
-rw-r--r--include/asm-powerpc/hw_irq.h31
-rw-r--r--include/asm-powerpc/immap_qe.h17
-rw-r--r--include/asm-powerpc/iommu.h8
-rw-r--r--include/asm-powerpc/mmu.h15
-rw-r--r--include/asm-powerpc/mpc52xx.h287
-rw-r--r--include/asm-powerpc/mpc85xx.h8
-rw-r--r--include/asm-powerpc/paca.h3
-rw-r--r--include/asm-powerpc/pci.h2
-rw-r--r--include/asm-powerpc/processor.h4
-rw-r--r--include/asm-powerpc/prom.h15
-rw-r--r--include/asm-powerpc/spu.h19
-rw-r--r--include/asm-powerpc/spu_csa.h1
-rw-r--r--include/asm-powerpc/spu_priv1.h6
-rw-r--r--include/asm-powerpc/todc.h487
-rw-r--r--include/asm-powerpc/xmon.h2
-rw-r--r--include/asm-ppc/io.h8
-rw-r--r--include/asm-ppc/mpc52xx.h11
-rw-r--r--include/asm-ppc/mpc83xx.h8
-rw-r--r--include/asm-ppc/mpc85xx.h8
-rw-r--r--include/linux/cpu.h8
108 files changed, 5152 insertions, 1575 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 116d7d3683ed..96316c866107 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -386,6 +386,14 @@ config PPC_CHRP
386 select PPC_UDBG_16550 386 select PPC_UDBG_16550
387 default y 387 default y
388 388
389config PPC_EFIKA
390 bool "bPlan Efika 5k2. MPC5200B based computer"
391 depends on PPC_MULTIPLATFORM && PPC32
392 select PPC_RTAS
393 select RTAS_PROC
394 select PPC_MPC52xx
395 default y
396
389config PPC_PMAC 397config PPC_PMAC
390 bool "Apple PowerMac based machines" 398 bool "Apple PowerMac based machines"
391 depends on PPC_MULTIPLATFORM 399 depends on PPC_MULTIPLATFORM
@@ -594,12 +602,6 @@ config TAU_AVERAGE
594 602
595 If in doubt, say N here. 603 If in doubt, say N here.
596 604
597config PPC_TODC
598 depends on EMBEDDED6xx
599 bool "Generic Time-of-day Clock (TODC) support"
600 ---help---
601 This adds support for many TODC/RTC chips.
602
603endmenu 605endmenu
604 606
605source arch/powerpc/platforms/embedded6xx/Kconfig 607source arch/powerpc/platforms/embedded6xx/Kconfig
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
index 45c9ad23526e..590e72f06d5e 100644
--- a/arch/powerpc/boot/.gitignore
+++ b/arch/powerpc/boot/.gitignore
@@ -1,20 +1,27 @@
1addnote 1addnote
2empty.c
3hack-coff
2infblock.c 4infblock.c
3infblock.h 5infblock.h
4infcodes.c 6infcodes.c
5infcodes.h 7infcodes.h
6inffast.c 8inffast.c
7inffast.h 9inffast.h
10inffixed.h
8inflate.c 11inflate.c
12inflate.h
9inftrees.c 13inftrees.c
10inftrees.h 14inftrees.h
11infutil.c 15infutil.c
12infutil.h 16infutil.h
13kernel-vmlinux.strip.c 17kernel-vmlinux.strip.c
14kernel-vmlinux.strip.gz 18kernel-vmlinux.strip.gz
19mktree
15uImage 20uImage
16zImage 21zImage
17zImage.vmode 22zImage.vmode
23zImage.coff.lds
24zImage.lds
18zconf.h 25zconf.h
19zlib.h 26zlib.h
20zutil.h 27zutil.h
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 4b2be611f77f..4a6f0f054b72 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h
40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ 40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
41 $(addprefix $(obj)/,$(zlibheader)) 41 $(addprefix $(obj)/,$(zlibheader))
42 42
43src-wlib := string.S stdio.c main.c div64.S $(zlib) 43src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
44 ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib)
44src-plat := of.c 45src-plat := of.c
45src-boot := crt0.S $(src-wlib) $(src-plat) empty.c 46src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
46 47
@@ -74,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
74 @cp $< $@ 75 @cp $< $@
75 76
76clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ 77clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
77 $(obj)/empty.c 78 empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint
78 79
79quiet_cmd_bootcc = BOOTCC $@ 80quiet_cmd_bootcc = BOOTCC $@
80 cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< 81 cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -93,13 +94,13 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
93$(obj)/wrapper.a: $(obj-wlib) 94$(obj)/wrapper.a: $(obj-wlib)
94 $(call cmd,bootar) 95 $(call cmd,bootar)
95 96
96hostprogs-y := addnote addRamDisk hack-coff 97hostprogs-y := addnote addRamDisk hack-coff mktree
97 98
98extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ 99extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
99 $(obj)/zImage.lds $(obj)/zImage.coff.lds 100 $(obj)/zImage.lds $(obj)/zImage.coff.lds
100 101
101wrapper :=$(srctree)/$(src)/wrapper 102wrapper :=$(srctree)/$(src)/wrapper
102wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff) 103wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree)
103 104
104############# 105#############
105# Bits for building various flavours of zImage 106# Bits for building various flavours of zImage
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
new file mode 100644
index 000000000000..c76c194715b2
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree.c
@@ -0,0 +1,880 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright Pantelis Antoniou 2006
17 * Copyright (C) IBM Corporation 2006
18 *
19 * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
20 * Hollis Blanchard <hollisb@us.ibm.com>
21 * Mark A. Greer <mgreer@mvista.com>
22 * Paul Mackerras <paulus@samba.org>
23 */
24
25#include <string.h>
26#include <stddef.h>
27#include "flatdevtree.h"
28#include "flatdevtree_env.h"
29
30#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1))
31
32/* Routines for keeping node ptrs returned by ft_find_device current */
33/* First entry not used b/c it would return 0 and be taken as NULL/error */
34static void *ft_node_add(struct ft_cxt *cxt, char *node)
35{
36 unsigned int i;
37
38 for (i = 1; i < cxt->nodes_used; i++) /* already there? */
39 if (cxt->node_tbl[i] == node)
40 return (void *)i;
41
42 if (cxt->nodes_used < cxt->node_max) {
43 cxt->node_tbl[cxt->nodes_used] = node;
44 return (void *)cxt->nodes_used++;
45 }
46
47 return NULL;
48}
49
50static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
51{
52 unsigned int i = (unsigned int)phandle;
53
54 if (i < cxt->nodes_used)
55 return cxt->node_tbl[i];
56 return NULL;
57}
58
59static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
60{
61 unsigned int i;
62
63 if (shift == 0)
64 return;
65
66 for (i = 1; i < cxt->nodes_used; i++)
67 if (cxt->node_tbl[i] < addr)
68 cxt->node_tbl[i] += shift;
69}
70
71static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
72{
73 unsigned int i;
74
75 if (shift == 0)
76 return;
77
78 for (i = 1; i < cxt->nodes_used; i++)
79 if (cxt->node_tbl[i] >= addr)
80 cxt->node_tbl[i] += shift;
81}
82
83/* Struct used to return info from ft_next() */
84struct ft_atom {
85 u32 tag;
86 const char *name;
87 void *data;
88 u32 size;
89};
90
91/* Set ptrs to current one's info; return addr of next one */
92static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
93{
94 u32 sz;
95
96 if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
97 return NULL;
98
99 ret->tag = be32_to_cpu(*(u32 *) p);
100 p += 4;
101
102 switch (ret->tag) { /* Tag */
103 case OF_DT_BEGIN_NODE:
104 ret->name = p;
105 ret->data = (void *)(p - 4); /* start of node */
106 p += _ALIGN(strlen(p) + 1, 4);
107 break;
108 case OF_DT_PROP:
109 ret->size = sz = be32_to_cpu(*(u32 *) p);
110 ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
111 ret->data = (void *)(p + 8);
112 p += 8 + _ALIGN(sz, 4);
113 break;
114 case OF_DT_END_NODE:
115 case OF_DT_NOP:
116 break;
117 case OF_DT_END:
118 default:
119 p = NULL;
120 break;
121 }
122
123 return p;
124}
125
126#define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8)
127#define EXPAND_INCR 1024 /* alloc this much extra when expanding */
128
129/* See if the regions are in the standard order and non-overlapping */
130static int ft_ordered(struct ft_cxt *cxt)
131{
132 char *p = (char *)cxt->bph + HDR_SIZE;
133 enum ft_rgn_id r;
134
135 for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
136 if (p > cxt->rgn[r].start)
137 return 0;
138 p = cxt->rgn[r].start + cxt->rgn[r].size;
139 }
140 return p <= (char *)cxt->bph + cxt->max_size;
141}
142
143/* Copy the tree to a newly-allocated region and put things in order */
144static int ft_reorder(struct ft_cxt *cxt, int nextra)
145{
146 unsigned long tot;
147 enum ft_rgn_id r;
148 char *p, *pend;
149 int stroff;
150
151 tot = HDR_SIZE + EXPAND_INCR;
152 for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
153 tot += cxt->rgn[r].size;
154 if (nextra > 0)
155 tot += nextra;
156 tot = _ALIGN(tot, 8);
157
158 if (!cxt->realloc)
159 return 0;
160 p = cxt->realloc(NULL, tot);
161 if (!p)
162 return 0;
163
164 memcpy(p, cxt->bph, sizeof(struct boot_param_header));
165 /* offsets get fixed up later */
166
167 cxt->bph = (struct boot_param_header *)p;
168 cxt->max_size = tot;
169 pend = p + tot;
170 p += HDR_SIZE;
171
172 memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
173 cxt->rgn[FT_RSVMAP].start = p;
174 p += cxt->rgn[FT_RSVMAP].size;
175
176 memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
177 ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
178 p - cxt->rgn[FT_STRUCT].start);
179 cxt->p += p - cxt->rgn[FT_STRUCT].start;
180 cxt->rgn[FT_STRUCT].start = p;
181
182 p = pend - cxt->rgn[FT_STRINGS].size;
183 memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
184 stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
185 cxt->rgn[FT_STRINGS].start = p;
186 cxt->str_anchor = p + stroff;
187
188 cxt->isordered = 1;
189 return 1;
190}
191
192static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
193{
194 if (r > FT_RSVMAP)
195 return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
196 return (char *)cxt->bph + HDR_SIZE;
197}
198
199static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
200{
201 if (r < FT_STRINGS)
202 return cxt->rgn[r + 1].start;
203 return (char *)cxt->bph + cxt->max_size;
204}
205
206/*
207 * See if we can expand region rgn by nextra bytes by using up
208 * free space after or before the region.
209 */
210static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
211 int nextra)
212{
213 char *p = *pp;
214 char *rgn_start, *rgn_end;
215
216 rgn_start = cxt->rgn[rgn].start;
217 rgn_end = rgn_start + cxt->rgn[rgn].size;
218 if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
219 /* move following stuff */
220 if (p < rgn_end) {
221 if (nextra < 0)
222 memmove(p, p - nextra, rgn_end - p + nextra);
223 else
224 memmove(p + nextra, p, rgn_end - p);
225 if (rgn == FT_STRUCT)
226 ft_node_update_after(cxt, p, nextra);
227 }
228 cxt->rgn[rgn].size += nextra;
229 if (rgn == FT_STRINGS)
230 /* assumes strings only added at beginning */
231 cxt->str_anchor += nextra;
232 return 1;
233 }
234 if (prev_end(cxt, rgn) <= rgn_start - nextra) {
235 /* move preceding stuff */
236 if (p > rgn_start) {
237 memmove(rgn_start - nextra, rgn_start, p - rgn_start);
238 if (rgn == FT_STRUCT)
239 ft_node_update_before(cxt, p, -nextra);
240 }
241 *p -= nextra;
242 cxt->rgn[rgn].start -= nextra;
243 cxt->rgn[rgn].size += nextra;
244 return 1;
245 }
246 return 0;
247}
248
249static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
250 int nextra)
251{
252 unsigned long size, ssize, tot;
253 char *str, *next;
254 enum ft_rgn_id r;
255
256 if (!cxt->isordered && !ft_reorder(cxt, nextra))
257 return 0;
258 if (ft_shuffle(cxt, pp, rgn, nextra))
259 return 1;
260
261 /* See if there is space after the strings section */
262 ssize = cxt->rgn[FT_STRINGS].size;
263 if (cxt->rgn[FT_STRINGS].start + ssize
264 < (char *)cxt->bph + cxt->max_size) {
265 /* move strings up as far as possible */
266 str = (char *)cxt->bph + cxt->max_size - ssize;
267 cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
268 memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
269 cxt->rgn[FT_STRINGS].start = str;
270 /* enough space now? */
271 if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
272 return 1;
273 }
274
275 /* how much total free space is there following this region? */
276 tot = 0;
277 for (r = rgn; r < FT_STRINGS; ++r) {
278 char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
279 tot += next_start(cxt, rgn) - r_end;
280 }
281
282 /* cast is to shut gcc up; we know nextra >= 0 */
283 if (tot < (unsigned int)nextra) {
284 /* have to reallocate */
285 char *newp, *new_start;
286 int shift;
287
288 if (!cxt->realloc)
289 return 0;
290 size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
291 newp = cxt->realloc(cxt->bph, size);
292 if (!newp)
293 return 0;
294 cxt->max_size = size;
295 shift = newp - (char *)cxt->bph;
296
297 if (shift) { /* realloc can return same addr */
298 cxt->bph = (struct boot_param_header *)newp;
299 ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
300 shift);
301 for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
302 new_start = cxt->rgn[r].start + shift;
303 cxt->rgn[r].start = new_start;
304 }
305 *pp += shift;
306 cxt->str_anchor += shift;
307 }
308
309 /* move strings up to the end */
310 str = newp + size - ssize;
311 cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
312 memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
313 cxt->rgn[FT_STRINGS].start = str;
314
315 if (ft_shuffle(cxt, pp, rgn, nextra))
316 return 1;
317 }
318
319 /* must be FT_RSVMAP and we need to move FT_STRUCT up */
320 if (rgn == FT_RSVMAP) {
321 next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
322 + nextra;
323 ssize = cxt->rgn[FT_STRUCT].size;
324 if (next + ssize >= cxt->rgn[FT_STRINGS].start)
325 return 0; /* "can't happen" */
326 memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
327 ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
328 cxt->rgn[FT_STRUCT].start = next;
329
330 if (ft_shuffle(cxt, pp, rgn, nextra))
331 return 1;
332 }
333
334 return 0; /* "can't happen" */
335}
336
337static void ft_put_word(struct ft_cxt *cxt, u32 v)
338{
339 *(u32 *) cxt->p = cpu_to_be32(v);
340 cxt->p += 4;
341}
342
343static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
344{
345 unsigned long sza = _ALIGN(sz, 4);
346
347 /* zero out the alignment gap if necessary */
348 if (sz < sza)
349 *(u32 *) (cxt->p + sza - 4) = 0;
350
351 /* copy in the data */
352 memcpy(cxt->p, data, sz);
353
354 cxt->p += sza;
355}
356
357int ft_begin_node(struct ft_cxt *cxt, const char *name)
358{
359 unsigned long nlen = strlen(name) + 1;
360 unsigned long len = 8 + _ALIGN(nlen, 4);
361
362 if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
363 return -1;
364 ft_put_word(cxt, OF_DT_BEGIN_NODE);
365 ft_put_bin(cxt, name, strlen(name) + 1);
366 return 0;
367}
368
369void ft_end_node(struct ft_cxt *cxt)
370{
371 ft_put_word(cxt, OF_DT_END_NODE);
372}
373
374void ft_nop(struct ft_cxt *cxt)
375{
376 if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
377 ft_put_word(cxt, OF_DT_NOP);
378}
379
380#define NO_STRING 0x7fffffff
381
382static int lookup_string(struct ft_cxt *cxt, const char *name)
383{
384 char *p, *end;
385
386 p = cxt->rgn[FT_STRINGS].start;
387 end = p + cxt->rgn[FT_STRINGS].size;
388 while (p < end) {
389 if (strcmp(p, (char *)name) == 0)
390 return p - cxt->str_anchor;
391 p += strlen(p) + 1;
392 }
393
394 return NO_STRING;
395}
396
397/* lookup string and insert if not found */
398static int map_string(struct ft_cxt *cxt, const char *name)
399{
400 int off;
401 char *p;
402
403 off = lookup_string(cxt, name);
404 if (off != NO_STRING)
405 return off;
406 p = cxt->rgn[FT_STRINGS].start;
407 if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
408 return NO_STRING;
409 strcpy(p, name);
410 return p - cxt->str_anchor;
411}
412
413int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
414 unsigned int sz)
415{
416 int off, len;
417
418 off = lookup_string(cxt, name);
419 if (off == NO_STRING)
420 return -1;
421
422 len = 12 + _ALIGN(sz, 4);
423 if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
424 return -1;
425
426 ft_put_word(cxt, OF_DT_PROP);
427 ft_put_word(cxt, sz);
428 ft_put_word(cxt, off);
429 ft_put_bin(cxt, data, sz);
430 return 0;
431}
432
433int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
434{
435 return ft_prop(cxt, name, str, strlen(str) + 1);
436}
437
438int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
439{
440 u32 v = cpu_to_be32((u32) val);
441
442 return ft_prop(cxt, name, &v, 4);
443}
444
445/* Calculate the size of the reserved map */
446static unsigned long rsvmap_size(struct ft_cxt *cxt)
447{
448 struct ft_reserve *res;
449
450 res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
451 while (res->start || res->len)
452 ++res;
453 return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
454}
455
456/* Calculate the size of the struct region by stepping through it */
457static unsigned long struct_size(struct ft_cxt *cxt)
458{
459 char *p = cxt->rgn[FT_STRUCT].start;
460 char *next;
461 struct ft_atom atom;
462
463 /* make check in ft_next happy */
464 if (cxt->rgn[FT_STRUCT].size == 0)
465 cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
466
467 while ((next = ft_next(cxt, p, &atom)) != NULL)
468 p = next;
469 return p + 4 - cxt->rgn[FT_STRUCT].start;
470}
471
472/* add `adj' on to all string offset values in the struct area */
473static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
474{
475 char *p = cxt->rgn[FT_STRUCT].start;
476 char *next;
477 struct ft_atom atom;
478 int off;
479
480 while ((next = ft_next(cxt, p, &atom)) != NULL) {
481 if (atom.tag == OF_DT_PROP) {
482 off = be32_to_cpu(*(u32 *) (p + 8));
483 *(u32 *) (p + 8) = cpu_to_be32(off + adj);
484 }
485 p = next;
486 }
487}
488
489/* start construction of the flat OF tree from scratch */
490void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
491 void *(*realloc_fn) (void *, unsigned long))
492{
493 struct boot_param_header *bph = blob;
494 char *p;
495 struct ft_reserve *pres;
496
497 /* clear the cxt */
498 memset(cxt, 0, sizeof(*cxt));
499
500 cxt->bph = bph;
501 cxt->max_size = max_size;
502 cxt->realloc = realloc_fn;
503 cxt->isordered = 1;
504
505 /* zero everything in the header area */
506 memset(bph, 0, sizeof(*bph));
507
508 bph->magic = cpu_to_be32(OF_DT_HEADER);
509 bph->version = cpu_to_be32(0x10);
510 bph->last_comp_version = cpu_to_be32(0x10);
511
512 /* start pointers */
513 cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
514 cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
515 pres = (struct ft_reserve *)p;
516 cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
517 cxt->rgn[FT_STRUCT].size = 4;
518 cxt->rgn[FT_STRINGS].start = blob + max_size;
519 cxt->rgn[FT_STRINGS].size = 0;
520
521 /* init rsvmap and struct */
522 pres->start = 0;
523 pres->len = 0;
524 *(u32 *) p = cpu_to_be32(OF_DT_END);
525
526 cxt->str_anchor = blob;
527}
528
529/* open up an existing blob to be examined or modified */
530int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
531 unsigned int max_find_device,
532 void *(*realloc_fn) (void *, unsigned long))
533{
534 struct boot_param_header *bph = blob;
535
536 /* can't cope with version < 16 */
537 if (be32_to_cpu(bph->version) < 16)
538 return -1;
539
540 /* clear the cxt */
541 memset(cxt, 0, sizeof(*cxt));
542
543 /* alloc node_tbl to track node ptrs returned by ft_find_device */
544 ++max_find_device;
545 cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
546 if (!cxt->node_tbl)
547 return -1;
548 memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
549 cxt->node_max = max_find_device;
550 cxt->nodes_used = 1; /* don't use idx 0 b/c looks like NULL */
551
552 cxt->bph = bph;
553 cxt->max_size = max_size;
554 cxt->realloc = realloc_fn;
555
556 cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
557 cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
558 cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
559 cxt->rgn[FT_STRUCT].size = struct_size(cxt);
560 cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
561 cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
562 /* Leave as '0' to force first ft_make_space call to do a ft_reorder
563 * and move dt to an area allocated by realloc.
564 cxt->isordered = ft_ordered(cxt);
565 */
566
567 cxt->p = cxt->rgn[FT_STRUCT].start;
568 cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
569
570 return 0;
571}
572
573/* add a reserver physical area to the rsvmap */
574int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
575{
576 char *p;
577 struct ft_reserve *pres;
578
579 p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
580 - sizeof(struct ft_reserve);
581 if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
582 return -1;
583
584 pres = (struct ft_reserve *)p;
585 pres->start = cpu_to_be64(physaddr);
586 pres->len = cpu_to_be64(size);
587
588 return 0;
589}
590
591void ft_begin_tree(struct ft_cxt *cxt)
592{
593 cxt->p = cxt->rgn[FT_STRUCT].start;
594}
595
596void ft_end_tree(struct ft_cxt *cxt)
597{
598 struct boot_param_header *bph = cxt->bph;
599 char *p, *oldstr, *str, *endp;
600 unsigned long ssize;
601 int adj;
602
603 if (!cxt->isordered)
604 return; /* we haven't touched anything */
605
606 /* adjust string offsets */
607 oldstr = cxt->rgn[FT_STRINGS].start;
608 adj = cxt->str_anchor - oldstr;
609 if (adj)
610 adjust_string_offsets(cxt, adj);
611
612 /* make strings end on 8-byte boundary */
613 ssize = cxt->rgn[FT_STRINGS].size;
614 endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
615 + cxt->rgn[FT_STRUCT].size + ssize, 8);
616 str = endp - ssize;
617
618 /* move strings down to end of structs */
619 memmove(str, oldstr, ssize);
620 cxt->str_anchor = str;
621 cxt->rgn[FT_STRINGS].start = str;
622
623 /* fill in header fields */
624 p = (char *)bph;
625 bph->totalsize = cpu_to_be32(endp - p);
626 bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
627 bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
628 bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
629 bph->dt_strings_size = cpu_to_be32(ssize);
630}
631
632void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
633{
634 char *node;
635
636 /* require absolute path */
637 if (srch_path[0] != '/')
638 return NULL;
639 node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
640 return ft_node_add(cxt, node);
641}
642
643void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
644{
645 struct ft_atom atom;
646 char *p;
647 const char *cp, *q;
648 int cl;
649 int depth = -1;
650 int dmatch = 0;
651 const char *path_comp[FT_MAX_DEPTH];
652
653 cp = srch_path;
654 cl = 0;
655 p = top;
656
657 while ((p = ft_next(cxt, p, &atom)) != NULL) {
658 switch (atom.tag) {
659 case OF_DT_BEGIN_NODE:
660 ++depth;
661 if (depth != dmatch)
662 break;
663 cxt->genealogy[depth] = atom.data;
664 cxt->genealogy[depth + 1] = NULL;
665 if (depth && !(strncmp(atom.name, cp, cl) == 0
666 && (atom.name[cl] == '/'
667 || atom.name[cl] == '\0'
668 || atom.name[cl] == '@')))
669 break;
670 path_comp[dmatch] = cp;
671 /* it matches so far, advance to next path component */
672 cp += cl;
673 /* skip slashes */
674 while (*cp == '/')
675 ++cp;
676 /* we're done if this is the end of the string */
677 if (*cp == 0)
678 return atom.data;
679 /* look for end of this component */
680 q = strchr(cp, '/');
681 if (q)
682 cl = q - cp;
683 else
684 cl = strlen(cp);
685 ++dmatch;
686 break;
687 case OF_DT_END_NODE:
688 if (depth == 0)
689 return NULL;
690 if (dmatch > depth) {
691 --dmatch;
692 cl = cp - path_comp[dmatch] - 1;
693 cp = path_comp[dmatch];
694 while (cl > 0 && cp[cl - 1] == '/')
695 --cl;
696 }
697 --depth;
698 break;
699 }
700 }
701 return NULL;
702}
703
704void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
705{
706 void *node;
707 int d;
708 struct ft_atom atom;
709 char *p;
710
711 node = ft_node_ph2node(cxt, phandle);
712 if (node == NULL)
713 return NULL;
714
715 for (d = 0; cxt->genealogy[d] != NULL; ++d)
716 if (cxt->genealogy[d] == node)
717 return cxt->genealogy[d > 0 ? d - 1 : 0];
718
719 /* have to do it the hard way... */
720 p = cxt->rgn[FT_STRUCT].start;
721 d = 0;
722 while ((p = ft_next(cxt, p, &atom)) != NULL) {
723 switch (atom.tag) {
724 case OF_DT_BEGIN_NODE:
725 cxt->genealogy[d] = atom.data;
726 if (node == atom.data) {
727 /* found it */
728 cxt->genealogy[d + 1] = NULL;
729 return d > 0 ? cxt->genealogy[d - 1] : node;
730 }
731 ++d;
732 break;
733 case OF_DT_END_NODE:
734 --d;
735 break;
736 }
737 }
738 return NULL;
739}
740
741int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
742 void *buf, const unsigned int buflen)
743{
744 struct ft_atom atom;
745 void *node;
746 char *p;
747 int depth;
748 unsigned int size;
749
750 node = ft_node_ph2node(cxt, phandle);
751 if (node == NULL)
752 return -1;
753
754 depth = 0;
755 p = (char *)node;
756
757 while ((p = ft_next(cxt, p, &atom)) != NULL) {
758 switch (atom.tag) {
759 case OF_DT_BEGIN_NODE:
760 ++depth;
761 break;
762 case OF_DT_PROP:
763 if ((depth != 1) || strcmp(atom.name, propname))
764 break;
765 size = min(atom.size, buflen);
766 memcpy(buf, atom.data, size);
767 return atom.size;
768 case OF_DT_END_NODE:
769 if (--depth <= 0)
770 return -1;
771 }
772 }
773 return -1;
774}
775
776int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
777 const void *buf, const unsigned int buflen)
778{
779 struct ft_atom atom;
780 void *node;
781 char *p, *next;
782 int nextra, depth;
783
784 node = ft_node_ph2node(cxt, phandle);
785 if (node == NULL)
786 return -1;
787
788 depth = 0;
789 p = node;
790
791 while ((next = ft_next(cxt, p, &atom)) != NULL) {
792 switch (atom.tag) {
793 case OF_DT_BEGIN_NODE:
794 ++depth;
795 break;
796 case OF_DT_END_NODE:
797 if (--depth > 0)
798 break;
799 /* haven't found the property, insert here */
800 cxt->p = p;
801 return ft_prop(cxt, propname, buf, buflen);
802 case OF_DT_PROP:
803 if ((depth != 1) || strcmp(atom.name, propname))
804 break;
805 /* found an existing property, overwrite it */
806 nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
807 cxt->p = atom.data;
808 if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
809 nextra))
810 return -1;
811 *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
812 ft_put_bin(cxt, buf, buflen);
813 return 0;
814 }
815 p = next;
816 }
817 return -1;
818}
819
820int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
821{
822 struct ft_atom atom;
823 void *node;
824 char *p, *next;
825 int size;
826
827 node = ft_node_ph2node(cxt, phandle);
828 if (node == NULL)
829 return -1;
830
831 p = node;
832 while ((next = ft_next(cxt, p, &atom)) != NULL) {
833 switch (atom.tag) {
834 case OF_DT_BEGIN_NODE:
835 case OF_DT_END_NODE:
836 return -1;
837 case OF_DT_PROP:
838 if (strcmp(atom.name, propname))
839 break;
840 /* found the property, remove it */
841 size = 12 + -_ALIGN(atom.size, 4);
842 cxt->p = p;
843 if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
844 return -1;
845 return 0;
846 }
847 p = next;
848 }
849 return -1;
850}
851
852void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
853{
854 struct ft_atom atom;
855 char *p, *next;
856 int depth = 0;
857
858 p = cxt->rgn[FT_STRUCT].start;
859 while ((next = ft_next(cxt, p, &atom)) != NULL) {
860 switch (atom.tag) {
861 case OF_DT_BEGIN_NODE:
862 ++depth;
863 if (depth == 1 && strcmp(atom.name, path) == 0)
864 /* duplicate node path, return error */
865 return NULL;
866 break;
867 case OF_DT_END_NODE:
868 --depth;
869 if (depth > 0)
870 break;
871 /* end of node, insert here */
872 cxt->p = p;
873 ft_begin_node(cxt, path);
874 ft_end_node(cxt);
875 return p;
876 }
877 p = next;
878 }
879 return NULL;
880}
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
index 761c8dc84008..b9cd9f61f351 100644
--- a/arch/powerpc/boot/flatdevtree.h
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -17,7 +17,7 @@
17#ifndef FLATDEVTREE_H 17#ifndef FLATDEVTREE_H
18#define FLATDEVTREE_H 18#define FLATDEVTREE_H
19 19
20#include "types.h" 20#include "flatdevtree_env.h"
21 21
22/* Definitions used by the flattened device tree */ 22/* Definitions used by the flattened device tree */
23#define OF_DT_HEADER 0xd00dfeed /* marker */ 23#define OF_DT_HEADER 0xd00dfeed /* marker */
@@ -43,4 +43,64 @@ struct boot_param_header {
43 u32 dt_strings_size; /* size of the DT strings block */ 43 u32 dt_strings_size; /* size of the DT strings block */
44}; 44};
45 45
46struct ft_reserve {
47 u64 start;
48 u64 len;
49};
50
51struct ft_region {
52 char *start;
53 unsigned long size;
54};
55
56enum ft_rgn_id {
57 FT_RSVMAP,
58 FT_STRUCT,
59 FT_STRINGS,
60 FT_N_REGION
61};
62
63#define FT_MAX_DEPTH 50
64
65struct ft_cxt {
66 struct boot_param_header *bph;
67 int max_size; /* maximum size of tree */
68 int isordered; /* everything in standard order */
69 void *(*realloc)(void *, unsigned long);
70 char *str_anchor;
71 char *p; /* current insertion point in structs */
72 struct ft_region rgn[FT_N_REGION];
73 void *genealogy[FT_MAX_DEPTH+1];
74 char **node_tbl;
75 unsigned int node_max;
76 unsigned int nodes_used;
77};
78
79int ft_begin_node(struct ft_cxt *cxt, const char *name);
80void ft_end_node(struct ft_cxt *cxt);
81
82void ft_begin_tree(struct ft_cxt *cxt);
83void ft_end_tree(struct ft_cxt *cxt);
84
85void ft_nop(struct ft_cxt *cxt);
86int ft_prop(struct ft_cxt *cxt, const char *name,
87 const void *data, unsigned int sz);
88int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
89int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
90void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
91 void *(*realloc_fn)(void *, unsigned long));
92int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
93 unsigned int max_find_device,
94 void *(*realloc_fn)(void *, unsigned long));
95int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
96
97void ft_dump_blob(const void *bphp);
98void ft_merge_blob(struct ft_cxt *cxt, void *blob);
99void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
100void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
101int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
102 void *buf, const unsigned int buflen);
103int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
104 const void *buf, const unsigned int buflen);
105
46#endif /* FLATDEVTREE_H */ 106#endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h
new file mode 100644
index 000000000000..83bc1c718836
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_env.h
@@ -0,0 +1,47 @@
1/*
2 * This file adds the header file glue so that the shared files
3 * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
4 *
5 * strncmp & strchr copied from <file:lib/strings.c>
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 *
8 * Maintained by: Mark A. Greer <mgreer@mvista.com>
9 */
10#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
11#define _PPC_BOOT_FLATDEVTREE_ENV_H_
12
13#include <stdarg.h>
14#include <stddef.h>
15#include "types.h"
16#include "string.h"
17#include "stdio.h"
18#include "ops.h"
19
20#define be16_to_cpu(x) (x)
21#define cpu_to_be16(x) (x)
22#define be32_to_cpu(x) (x)
23#define cpu_to_be32(x) (x)
24#define be64_to_cpu(x) (x)
25#define cpu_to_be64(x) (x)
26
27static inline int strncmp(const char *cs, const char *ct, size_t count)
28{
29 signed char __res = 0;
30
31 while (count) {
32 if ((__res = *cs - *ct++) != 0 || !*cs++)
33 break;
34 count--;
35 }
36 return __res;
37}
38
39static inline char *strchr(const char *s, int c)
40{
41 for (; *s != (char)c; ++s)
42 if (*s == '\0')
43 return NULL;
44 return (char *)s;
45}
46
47#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c
new file mode 100644
index 000000000000..c7f9adbf827d
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_misc.c
@@ -0,0 +1,56 @@
1/*
2 * This file does the necessary interface mapping between the bootwrapper
3 * device tree operations and the interface provided by shared source
4 * files flatdevicetree.[ch].
5 *
6 * Author: Mark A. Greer <mgreer@mvista.com>
7 *
8 * 2006 (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#include <stddef.h>
14#include "flatdevtree.h"
15#include "ops.h"
16
17static struct ft_cxt cxt;
18
19static void *ft_finddevice(const char *name)
20{
21 return ft_find_device(&cxt, name);
22}
23
24static int ft_getprop(const void *phandle, const char *propname, void *buf,
25 const int buflen)
26{
27 return ft_get_prop(&cxt, phandle, propname, buf, buflen);
28}
29
30static int ft_setprop(const void *phandle, const char *propname,
31 const void *buf, const int buflen)
32{
33 return ft_set_prop(&cxt, phandle, propname, buf, buflen);
34}
35
36static void ft_pack(void)
37{
38 ft_end_tree(&cxt);
39}
40
41static unsigned long ft_addr(void)
42{
43 return (unsigned long)cxt.bph;
44}
45
46int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
47{
48 dt_ops.finddevice = ft_finddevice;
49 dt_ops.getprop = ft_getprop;
50 dt_ops.setprop = ft_setprop;
51 dt_ops.ft_pack = ft_pack;
52 dt_ops.ft_addr = ft_addr;
53
54 return ft_open(&cxt, dt_blob, max_size, max_find_device,
55 platform_ops.realloc);
56}
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 000000000000..32974ed49e02
--- /dev/null
+++ b/arch/powerpc/boot/io.h
@@ -0,0 +1,53 @@
1#ifndef _IO_H
2#define __IO_H
3/*
4 * Low-level I/O routines.
5 *
6 * Copied from <file:include/asm-powerpc/io.h> (which has no copyright)
7 */
8static inline int in_8(const volatile unsigned char *addr)
9{
10 int ret;
11
12 __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
13 : "=r" (ret) : "m" (*addr));
14 return ret;
15}
16
17static inline void out_8(volatile unsigned char *addr, int val)
18{
19 __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
20 : "=m" (*addr) : "r" (val));
21}
22
23static inline unsigned in_le32(const volatile unsigned *addr)
24{
25 unsigned ret;
26
27 __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
28 : "=r" (ret) : "r" (addr), "m" (*addr));
29 return ret;
30}
31
32static inline unsigned in_be32(const volatile unsigned *addr)
33{
34 unsigned ret;
35
36 __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
37 : "=r" (ret) : "m" (*addr));
38 return ret;
39}
40
41static inline void out_le32(volatile unsigned *addr, int val)
42{
43 __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
44 : "r" (val), "r" (addr));
45}
46
47static inline void out_be32(volatile unsigned *addr, int val)
48{
49 __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
50 : "=m" (*addr) : "r" (val));
51}
52
53#endif /* _IO_H */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index d719bb9333d1..418497482b6e 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -27,6 +27,8 @@ extern char _vmlinux_start[];
27extern char _vmlinux_end[]; 27extern char _vmlinux_end[];
28extern char _initrd_start[]; 28extern char _initrd_start[];
29extern char _initrd_end[]; 29extern char _initrd_end[];
30extern char _dtb_start[];
31extern char _dtb_end[];
30 32
31struct addr_range { 33struct addr_range {
32 unsigned long addr; 34 unsigned long addr;
@@ -250,10 +252,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
250 flush_cache((void *)vmlinux.addr, vmlinux.size); 252 flush_cache((void *)vmlinux.addr, vmlinux.size);
251} 253}
252 254
253void __attribute__ ((weak)) ft_init(void *dt_blob)
254{
255}
256
257/* A buffer that may be edited by tools operating on a zImage binary so as to 255/* A buffer that may be edited by tools operating on a zImage binary so as to
258 * edit the command line passed to vmlinux (by setting /chosen/bootargs). 256 * edit the command line passed to vmlinux (by setting /chosen/bootargs).
259 * The buffer is put in it's own section so that tools may locate it easier. 257 * The buffer is put in it's own section so that tools may locate it easier.
@@ -285,19 +283,12 @@ static void set_cmdline(char *buf)
285 setprop(devp, "bootargs", buf, strlen(buf) + 1); 283 setprop(devp, "bootargs", buf, strlen(buf) + 1);
286} 284}
287 285
288/* Section where ft can be tacked on after zImage is built */
289union blobspace {
290 struct boot_param_header hdr;
291 char space[8*1024];
292} dt_blob __attribute__((__section__("__builtin_ft")));
293
294struct platform_ops platform_ops; 286struct platform_ops platform_ops;
295struct dt_ops dt_ops; 287struct dt_ops dt_ops;
296struct console_ops console_ops; 288struct console_ops console_ops;
297 289
298void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) 290void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
299{ 291{
300 int have_dt = 0;
301 kernel_entry_t kentry; 292 kernel_entry_t kentry;
302 char cmdline[COMMAND_LINE_SIZE]; 293 char cmdline[COMMAND_LINE_SIZE];
303 294
@@ -306,15 +297,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
306 memset(&dt_ops, 0, sizeof(dt_ops)); 297 memset(&dt_ops, 0, sizeof(dt_ops));
307 memset(&console_ops, 0, sizeof(console_ops)); 298 memset(&console_ops, 0, sizeof(console_ops));
308 299
309 /* Override the dt_ops and device tree if there was an flat dev 300 if (platform_init(promptr, _dtb_start, _dtb_end))
310 * tree attached to the zImage.
311 */
312 if (dt_blob.hdr.magic == OF_DT_HEADER) {
313 have_dt = 1;
314 ft_init(&dt_blob);
315 }
316
317 if (platform_init(promptr))
318 exit(); 301 exit();
319 if (console_ops.open && (console_ops.open() < 0)) 302 if (console_ops.open && (console_ops.open() < 0))
320 exit(); 303 exit();
@@ -342,8 +325,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
342 console_ops.close(); 325 console_ops.close();
343 326
344 kentry = (kernel_entry_t) vmlinux.addr; 327 kentry = (kernel_entry_t) vmlinux.addr;
345 if (have_dt) 328 if (_dtb_end > _dtb_start) {
329 dt_ops.ft_pack();
346 kentry(dt_ops.ft_addr(), 0, NULL); 330 kentry(dt_ops.ft_addr(), 0, NULL);
331 }
347 else 332 else
348 /* XXX initrd addr/size should be passed in properties */ 333 /* XXX initrd addr/size should be passed in properties */
349 kentry(a1, a2, promptr); 334 kentry(a1, a2, promptr);
diff --git a/arch/powerpc/boot/mktree.c b/arch/powerpc/boot/mktree.c
new file mode 100644
index 000000000000..4cb892993651
--- /dev/null
+++ b/arch/powerpc/boot/mktree.c
@@ -0,0 +1,152 @@
1/*
2 * Makes a tree bootable image for IBM Evaluation boards.
3 * Basically, just take a zImage, skip the ELF header, and stuff
4 * a 32 byte header on the front.
5 *
6 * We use htonl, which is a network macro, to make sure we're doing
7 * The Right Thing on an LE machine. It's non-obvious, but it should
8 * work on anything BSD'ish.
9 */
10
11#include <fcntl.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <netinet/in.h>
18#ifdef __sun__
19#include <inttypes.h>
20#else
21#include <stdint.h>
22#endif
23
24/* This gets tacked on the front of the image. There are also a few
25 * bytes allocated after the _start label used by the boot rom (see
26 * head.S for details).
27 */
28typedef struct boot_block {
29 uint32_t bb_magic; /* 0x0052504F */
30 uint32_t bb_dest; /* Target address of the image */
31 uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */
32 uint32_t bb_debug_flag; /* Run debugger or image after load */
33 uint32_t bb_entry_point; /* The image address to start */
34 uint32_t bb_checksum; /* 32 bit checksum including header */
35 uint32_t reserved[2];
36} boot_block_t;
37
38#define IMGBLK 512
39char tmpbuf[IMGBLK];
40
41int main(int argc, char *argv[])
42{
43 int in_fd, out_fd;
44 int nblks, i;
45 uint cksum, *cp;
46 struct stat st;
47 boot_block_t bt;
48
49 if (argc < 3) {
50 fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]);
51 exit(1);
52 }
53
54 if (stat(argv[1], &st) < 0) {
55 perror("stat");
56 exit(2);
57 }
58
59 nblks = (st.st_size + IMGBLK) / IMGBLK;
60
61 bt.bb_magic = htonl(0x0052504F);
62
63 /* If we have the optional entry point parameter, use it */
64 if (argc == 4)
65 bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0));
66 else
67 bt.bb_dest = bt.bb_entry_point = htonl(0x500000);
68
69 /* We know these from the linker command.
70 * ...and then move it up into memory a little more so the
71 * relocation can happen.
72 */
73 bt.bb_num_512blocks = htonl(nblks);
74 bt.bb_debug_flag = 0;
75
76 bt.bb_checksum = 0;
77
78 /* To be neat and tidy :-).
79 */
80 bt.reserved[0] = 0;
81 bt.reserved[1] = 0;
82
83 if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
84 perror("zImage open");
85 exit(3);
86 }
87
88 if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
89 perror("bootfile open");
90 exit(3);
91 }
92
93 cksum = 0;
94 cp = (void *)&bt;
95 for (i=0; i<sizeof(bt)/sizeof(uint); i++)
96 cksum += *cp++;
97
98 /* Assume zImage is an ELF file, and skip the 64K header.
99 */
100 if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) {
101 fprintf(stderr, "%s is too small to be an ELF image\n",
102 argv[1]);
103 exit(4);
104 }
105
106 if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) {
107 fprintf(stderr, "%s is not an ELF image\n", argv[1]);
108 exit(4);
109 }
110
111 if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) {
112 fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]);
113 exit(4);
114 }
115
116 nblks -= (64 * 1024) / IMGBLK;
117
118 /* And away we go......
119 */
120 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
121 perror("boot-image write");
122 exit(5);
123 }
124
125 while (nblks-- > 0) {
126 if (read(in_fd, tmpbuf, IMGBLK) < 0) {
127 perror("zImage read");
128 exit(5);
129 }
130 cp = (uint *)tmpbuf;
131 for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++)
132 cksum += *cp++;
133 if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
134 perror("boot-image write");
135 exit(5);
136 }
137 }
138
139 /* rewrite the header with the computed checksum.
140 */
141 bt.bb_checksum = htonl(cksum);
142 if (lseek(out_fd, 0, SEEK_SET) < 0) {
143 perror("rewrite seek");
144 exit(1);
145 }
146 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
147 perror("boot-image rewrite");
148 exit(1);
149 }
150
151 exit(0);
152}
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644
index 000000000000..1ffe72e35cdc
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,74 @@
1/*
2 * 16550 serial console support.
3 *
4 * Original copied from <file:arch/ppc/boot/common/ns16550.c>
5 * (which had no copyright)
6 * Modifications: 2006 (c) MontaVista Software, Inc.
7 *
8 * Modified by: Mark A. Greer <mgreer@mvista.com>
9 */
10#include <stdarg.h>
11#include <stddef.h>
12#include "types.h"
13#include "string.h"
14#include "stdio.h"
15#include "io.h"
16#include "ops.h"
17
18#define UART_DLL 0 /* Out: Divisor Latch Low */
19#define UART_DLM 1 /* Out: Divisor Latch High */
20#define UART_FCR 2 /* Out: FIFO Control Register */
21#define UART_LCR 3 /* Out: Line Control Register */
22#define UART_MCR 4 /* Out: Modem Control Register */
23#define UART_LSR 5 /* In: Line Status Register */
24#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
25#define UART_LSR_DR 0x01 /* Receiver data ready */
26#define UART_MSR 6 /* In: Modem Status Register */
27#define UART_SCR 7 /* I/O: Scratch Register */
28
29static unsigned char *reg_base;
30static u32 reg_shift;
31
32static int ns16550_open(void)
33{
34 out_8(reg_base + (UART_FCR << reg_shift), 0x06);
35 return 0;
36}
37
38static void ns16550_putc(unsigned char c)
39{
40 while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0);
41 out_8(reg_base, c);
42}
43
44static unsigned char ns16550_getc(void)
45{
46 while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0);
47 return in_8(reg_base);
48}
49
50static u8 ns16550_tstc(void)
51{
52 return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0);
53}
54
55int ns16550_console_init(void *devp, struct serial_console_data *scdp)
56{
57 int n;
58
59 n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
60 if (n != sizeof(reg_base))
61 return -1;
62
63 n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
64 if (n != sizeof(reg_shift))
65 reg_shift = 0;
66
67 scdp->open = ns16550_open;
68 scdp->putc = ns16550_putc;
69 scdp->getc = ns16550_getc;
70 scdp->tstc = ns16550_tstc;
71 scdp->close = NULL;
72
73 return 0;
74}
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index 3a71845afc6c..0182f384f3e6 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -256,24 +256,18 @@ static void of_console_write(char *buf, int len)
256 call_prom("write", 3, 1, of_stdout_handle, buf, len); 256 call_prom("write", 3, 1, of_stdout_handle, buf, len);
257} 257}
258 258
259int platform_init(void *promptr) 259int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
260{ 260{
261 platform_ops.fixups = NULL;
262 platform_ops.image_hdr = of_image_hdr; 261 platform_ops.image_hdr = of_image_hdr;
263 platform_ops.malloc = of_try_claim; 262 platform_ops.malloc = of_try_claim;
264 platform_ops.free = NULL;
265 platform_ops.exit = of_exit; 263 platform_ops.exit = of_exit;
266 264
267 dt_ops.finddevice = of_finddevice; 265 dt_ops.finddevice = of_finddevice;
268 dt_ops.getprop = of_getprop; 266 dt_ops.getprop = of_getprop;
269 dt_ops.setprop = of_setprop; 267 dt_ops.setprop = of_setprop;
270 dt_ops.translate_addr = NULL;
271 268
272 console_ops.open = of_console_open; 269 console_ops.open = of_console_open;
273 console_ops.write = of_console_write; 270 console_ops.write = of_console_write;
274 console_ops.edit_cmdline = NULL;
275 console_ops.close = NULL;
276 console_ops.data = NULL;
277 271
278 prom = (int (*)(void *))promptr; 272 prom = (int (*)(void *))promptr;
279 return 0; 273 return 0;
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 135eb4bb03b4..59832fb0f276 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -22,7 +22,8 @@ struct platform_ops {
22 void (*fixups)(void); 22 void (*fixups)(void);
23 void (*image_hdr)(const void *); 23 void (*image_hdr)(const void *);
24 void * (*malloc)(u32 size); 24 void * (*malloc)(u32 size);
25 void (*free)(void *ptr, u32 size); 25 void (*free)(void *ptr);
26 void * (*realloc)(void *ptr, unsigned long size);
26 void (*exit)(void); 27 void (*exit)(void);
27}; 28};
28extern struct platform_ops platform_ops; 29extern struct platform_ops platform_ops;
@@ -30,12 +31,11 @@ extern struct platform_ops platform_ops;
30/* Device Tree operations */ 31/* Device Tree operations */
31struct dt_ops { 32struct dt_ops {
32 void * (*finddevice)(const char *name); 33 void * (*finddevice)(const char *name);
33 int (*getprop)(const void *node, const char *name, void *buf, 34 int (*getprop)(const void *phandle, const char *name, void *buf,
34 const int buflen); 35 const int buflen);
35 int (*setprop)(const void *node, const char *name, 36 int (*setprop)(const void *phandle, const char *name,
36 const void *buf, const int buflen); 37 const void *buf, const int buflen);
37 u64 (*translate_addr)(const char *path, const u32 *in_addr, 38 void (*ft_pack)(void);
38 const u32 addr_len);
39 unsigned long (*ft_addr)(void); 39 unsigned long (*ft_addr)(void);
40}; 40};
41extern struct dt_ops dt_ops; 41extern struct dt_ops dt_ops;
@@ -59,10 +59,13 @@ struct serial_console_data {
59 void (*close)(void); 59 void (*close)(void);
60}; 60};
61 61
62extern int platform_init(void *promptr); 62int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
63extern void simple_alloc_init(void); 63int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
64extern void ft_init(void *dt_blob); 64int serial_console_init(void);
65extern int serial_console_init(void); 65int ns16550_console_init(void *devp, struct serial_console_data *scdp);
66void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
67 u32 max_allocs);
68
66 69
67static inline void *finddevice(const char *name) 70static inline void *finddevice(const char *name)
68{ 71{
@@ -84,10 +87,10 @@ static inline void *malloc(u32 size)
84 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; 87 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
85} 88}
86 89
87static inline void free(void *ptr, u32 size) 90static inline void free(void *ptr)
88{ 91{
89 if (platform_ops.free) 92 if (platform_ops.free)
90 platform_ops.free(ptr, size); 93 platform_ops.free(ptr);
91} 94}
92 95
93static inline void exit(void) 96static inline void exit(void)
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644
index 000000000000..e8de4cf59be7
--- /dev/null
+++ b/arch/powerpc/boot/serial.c
@@ -0,0 +1,142 @@
1/*
2 * Generic serial console support
3 *
4 * Author: Mark A. Greer <mgreer@mvista.com>
5 *
6 * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
7 * and was written by Matt Porter <mporter@kernel.crashing.org>.
8 *
9 * 2001,2006 (c) MontaVista Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
12 * or implied.
13 */
14#include <stdarg.h>
15#include <stddef.h>
16#include "types.h"
17#include "string.h"
18#include "stdio.h"
19#include "io.h"
20#include "ops.h"
21
22extern void udelay(long delay);
23
24static int serial_open(void)
25{
26 struct serial_console_data *scdp = console_ops.data;
27 return scdp->open();
28}
29
30static void serial_write(char *buf, int len)
31{
32 struct serial_console_data *scdp = console_ops.data;
33
34 while (*buf != '\0')
35 scdp->putc(*buf++);
36}
37
38static void serial_edit_cmdline(char *buf, int len)
39{
40 int timer = 0, count;
41 char ch, *cp;
42 struct serial_console_data *scdp = console_ops.data;
43
44 cp = buf;
45 count = strlen(buf);
46 cp = &buf[count];
47 count++;
48
49 while (timer++ < 5*1000) {
50 if (scdp->tstc()) {
51 while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
52 /* Test for backspace/delete */
53 if ((ch == '\b') || (ch == '\177')) {
54 if (cp != buf) {
55 cp--;
56 count--;
57 printf("\b \b");
58 }
59 /* Test for ^x/^u (and wipe the line) */
60 } else if ((ch == '\030') || (ch == '\025')) {
61 while (cp != buf) {
62 cp--;
63 count--;
64 printf("\b \b");
65 }
66 } else if (count < len) {
67 *cp++ = ch;
68 count++;
69 scdp->putc(ch);
70 }
71 }
72 break; /* Exit 'timer' loop */
73 }
74 udelay(1000); /* 1 msec */
75 }
76 *cp = 0;
77}
78
79static void serial_close(void)
80{
81 struct serial_console_data *scdp = console_ops.data;
82
83 if (scdp->close)
84 scdp->close();
85}
86
87static void *serial_get_stdout_devp(void)
88{
89 void *devp;
90 char devtype[MAX_PROP_LEN];
91 char path[MAX_PATH_LEN];
92
93 devp = finddevice("/chosen");
94 if (devp == NULL)
95 goto err_out;
96
97 if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
98 devp = finddevice(path);
99 if (devp == NULL)
100 goto err_out;
101
102 if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
103 && !strcmp(devtype, "serial"))
104 return devp;
105 }
106err_out:
107 return NULL;
108}
109
110static struct serial_console_data serial_cd;
111
112/* Node's "compatible" property determines which serial driver to use */
113int serial_console_init(void)
114{
115 void *devp;
116 int rc = -1;
117 char compat[MAX_PROP_LEN];
118
119 devp = serial_get_stdout_devp();
120 if (devp == NULL)
121 goto err_out;
122
123 if (getprop(devp, "compatible", compat, sizeof(compat)) < 0)
124 goto err_out;
125
126 if (!strcmp(compat, "ns16550"))
127 rc = ns16550_console_init(devp, &serial_cd);
128
129 /* Add other serial console driver calls here */
130
131 if (!rc) {
132 console_ops.open = serial_open;
133 console_ops.write = serial_write;
134 console_ops.edit_cmdline = serial_edit_cmdline;
135 console_ops.close = serial_close;
136 console_ops.data = &serial_cd;
137
138 return 0;
139 }
140err_out:
141 return -1;
142}
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
new file mode 100644
index 000000000000..cfe3a7505ba0
--- /dev/null
+++ b/arch/powerpc/boot/simple_alloc.c
@@ -0,0 +1,149 @@
1/*
2 * Implement primitive realloc(3) functionality.
3 *
4 * Author: Mark A. Greer <mgreer@mvista.com>
5 *
6 * 2006 (c) MontaVista, Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#include <stddef.h>
13#include "types.h"
14#include "page.h"
15#include "string.h"
16#include "ops.h"
17
18#define ENTRY_BEEN_USED 0x01
19#define ENTRY_IN_USE 0x02
20
21static struct alloc_info {
22 u32 flags;
23 u32 base;
24 u32 size;
25} *alloc_tbl;
26
27static u32 tbl_entries;
28static u32 alloc_min;
29static u32 next_base;
30static u32 space_left;
31
32/*
33 * First time an entry is used, its base and size are set.
34 * An entry can be freed and re-malloc'd but its base & size don't change.
35 * Should be smart enough for needs of bootwrapper.
36 */
37static void *simple_malloc(u32 size)
38{
39 u32 i;
40 struct alloc_info *p = alloc_tbl;
41
42 if (size == 0)
43 goto err_out;
44
45 size = _ALIGN_UP(size, alloc_min);
46
47 for (i=0; i<tbl_entries; i++, p++)
48 if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
49 if (size <= space_left) {
50 p->base = next_base;
51 p->size = size;
52 p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
53 next_base += size;
54 space_left -= size;
55 return (void *)p->base;
56 }
57 goto err_out; /* not enough space left */
58 }
59 /* reuse an entry keeping same base & size */
60 else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) {
61 p->flags |= ENTRY_IN_USE;
62 return (void *)p->base;
63 }
64err_out:
65 return NULL;
66}
67
68static struct alloc_info *simple_find_entry(void *ptr)
69{
70 u32 i;
71 struct alloc_info *p = alloc_tbl;
72
73 for (i=0; i<tbl_entries; i++,p++) {
74 if (!(p->flags & ENTRY_BEEN_USED))
75 break;
76 if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr))
77 return p;
78 }
79 return NULL;
80}
81
82static void simple_free(void *ptr)
83{
84 struct alloc_info *p = simple_find_entry(ptr);
85
86 if (p != NULL)
87 p->flags &= ~ENTRY_IN_USE;
88}
89
90/*
91 * Change size of area pointed to by 'ptr' to 'size'.
92 * If 'ptr' is NULL, then its a malloc(). If 'size' is 0, then its a free().
93 * 'ptr' must be NULL or a pointer to a non-freed area previously returned by
94 * simple_realloc() or simple_malloc().
95 */
96static void *simple_realloc(void *ptr, unsigned long size)
97{
98 struct alloc_info *p;
99 void *new;
100
101 if (size == 0) {
102 simple_free(ptr);
103 return NULL;
104 }
105
106 if (ptr == NULL)
107 return simple_malloc(size);
108
109 p = simple_find_entry(ptr);
110 if (p == NULL) /* ptr not from simple_malloc/simple_realloc */
111 return NULL;
112 if (size <= p->size) /* fits in current block */
113 return ptr;
114
115 new = simple_malloc(size);
116 memcpy(new, ptr, p->size);
117 simple_free(ptr);
118 return new;
119}
120
121/*
122 * Returns addr of first byte after heap so caller can see if it took
123 * too much space. If so, change args & try again.
124 */
125void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
126 u32 max_allocs)
127{
128 u32 heap_base, tbl_size;
129
130 heap_size = _ALIGN_UP(heap_size, granularity);
131 alloc_min = granularity;
132 tbl_entries = max_allocs;
133
134 tbl_size = tbl_entries * sizeof(struct alloc_info);
135
136 alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
137 memset(alloc_tbl, 0, tbl_size);
138
139 heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
140
141 next_base = heap_base;
142 space_left = heap_size;
143
144 platform_ops.malloc = simple_malloc;
145 platform_ops.free = simple_free;
146 platform_ops.realloc = simple_realloc;
147
148 return (void *)(heap_base + heap_size);
149}
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 6d5f6382e1ce..0a9feeb98342 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -320,6 +320,7 @@ printf(const char *fmt, ...)
320 va_start(args, fmt); 320 va_start(args, fmt);
321 n = vsprintf(sprint_buf, fmt, args); 321 n = vsprintf(sprint_buf, fmt, args);
322 va_end(args); 322 va_end(args);
323 console_ops.write(sprint_buf, n); 323 if (console_ops.write)
324 console_ops.write(sprint_buf, n);
324 return n; 325 return n;
325} 326}
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S
new file mode 100644
index 000000000000..427ddfc11991
--- /dev/null
+++ b/arch/powerpc/boot/util.S
@@ -0,0 +1,88 @@
1/*
2 * Copied from <file:arch/powerpc/kernel/misc_32.S>
3 *
4 * This file contains miscellaneous low-level functions.
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 *
7 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
8 * and Paul Mackerras.
9 *
10 * kexec bits:
11 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
12 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 *
19 */
20#include "ppc_asm.h"
21
22#define SPRN_PVR 0x11F /* Processor Version Register */
23
24 .text
25
26/* udelay (on non-601 processors) needs to know the period of the
27 * timebase in nanoseconds. This used to be hardcoded to be 60ns
28 * (period of 66MHz/4). Now a variable is used that is initialized to
29 * 60 for backward compatibility, but it can be overridden as necessary
30 * with code something like this:
31 * extern unsigned long timebase_period_ns;
32 * timebase_period_ns = 1000000000 / bd->bi_tbfreq;
33 */
34 .data
35 .globl timebase_period_ns
36timebase_period_ns:
37 .long 60
38
39 .text
40/*
41 * Delay for a number of microseconds
42 */
43 .globl udelay
44udelay:
45 mfspr r4,SPRN_PVR
46 srwi r4,r4,16
47 cmpwi 0,r4,1 /* 601 ? */
48 bne .udelay_not_601
4900: li r0,86 /* Instructions / microsecond? */
50 mtctr r0
5110: addi r0,r0,0 /* NOP */
52 bdnz 10b
53 subic. r3,r3,1
54 bne 00b
55 blr
56
57.udelay_not_601:
58 mulli r4,r3,1000 /* nanoseconds */
59 /* Change r4 to be the number of ticks using:
60 * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
61 * timebase_period_ns defaults to 60 (16.6MHz) */
62 mflr r5
63 bl 0f
640: mflr r6
65 mtlr r5
66 lis r5,0b@ha
67 addi r5,r5,0b@l
68 subf r5,r5,r6 /* In case we're relocated */
69 addis r5,r5,timebase_period_ns@ha
70 lwz r5,timebase_period_ns@l(r5)
71 add r4,r4,r5
72 addi r4,r4,-1
73 divw r4,r4,r5 /* BUS ticks */
741: mftbu r5
75 mftb r6
76 mftbu r7
77 cmpw 0,r5,r7
78 bne 1b /* Get [synced] base time */
79 addc r9,r6,r4 /* Compute end time */
80 addze r8,r5
812: mftbu r5
82 cmpw 0,r5,r8
83 blt 2b
84 bgt 3f
85 mftb r6
86 cmpw 0,r6,r9
87 blt 2b
883: blr
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index b5fb1fee76f8..024e4d425c59 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -184,6 +184,9 @@ fi
184 184
185if [ -n "$dtb" ]; then 185if [ -n "$dtb" ]; then
186 addsec $tmp "$dtb" .kernel:dtb 186 addsec $tmp "$dtb" .kernel:dtb
187 if [ -n "$dts" ]; then
188 rm $dtb
189 fi
187fi 190fi
188 191
189if [ "$platform" != "miboot" ]; then 192if [ "$platform" != "miboot" ]; then
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S
index 05f32388b953..a360905e5428 100644
--- a/arch/powerpc/boot/zImage.coff.lds.S
+++ b/arch/powerpc/boot/zImage.coff.lds.S
@@ -21,6 +21,10 @@ SECTIONS
21 *(.got2) 21 *(.got2)
22 __got2_end = .; 22 __got2_end = .;
23 23
24 _dtb_start = .;
25 *(.kernel:dtb)
26 _dtb_end = .;
27
24 _vmlinux_start = .; 28 _vmlinux_start = .;
25 *(.kernel:vmlinux.strip) 29 *(.kernel:vmlinux.strip)
26 _vmlinux_end = .; 30 _vmlinux_end = .;
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 0aba06d7d2ec..dbcd4e3329d0 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -139,7 +139,19 @@ CONFIG_RTAS_FLASH=y
139CONFIG_MMIO_NVRAM=y 139CONFIG_MMIO_NVRAM=y
140# CONFIG_PPC_MPC106 is not set 140# CONFIG_PPC_MPC106 is not set
141# CONFIG_PPC_970_NAP is not set 141# CONFIG_PPC_970_NAP is not set
142# CONFIG_CPU_FREQ is not set 142CONFIG_CPU_FREQ=y
143CONFIG_CPU_FREQ_TABLE=y
144CONFIG_CPU_FREQ_DEBUG=y
145CONFIG_CPU_FREQ_STAT=y
146# CONFIG_CPU_FREQ_STAT_DETAILS is not set
147CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
148# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
149CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
150CONFIG_CPU_FREQ_GOV_POWERSAVE=y
151CONFIG_CPU_FREQ_GOV_USERSPACE=y
152CONFIG_CPU_FREQ_GOV_ONDEMAND=y
153CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
154# CONFIG_CPU_FREQ_PMAC64 is not set
143# CONFIG_WANT_EARLY_SERIAL is not set 155# CONFIG_WANT_EARLY_SERIAL is not set
144# CONFIG_MPIC is not set 156# CONFIG_MPIC is not set
145 157
@@ -149,6 +161,8 @@ CONFIG_MMIO_NVRAM=y
149CONFIG_SPU_FS=m 161CONFIG_SPU_FS=m
150CONFIG_SPU_BASE=y 162CONFIG_SPU_BASE=y
151CONFIG_CBE_RAS=y 163CONFIG_CBE_RAS=y
164CONFIG_CBE_THERM=m
165CONFIG_CBE_CPUFREQ=m
152 166
153# 167#
154# Kernel options 168# Kernel options
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 7af23c43fd4b..d8240ce22120 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -17,7 +17,7 @@ obj-y += vdso32/
17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
18 signal_64.o ptrace32.o \ 18 signal_64.o ptrace32.o \
19 paca.o cpu_setup_ppc970.o \ 19 paca.o cpu_setup_ppc970.o \
20 firmware.o sysfs.o 20 firmware.o sysfs.o nvram_64.o
21obj-$(CONFIG_PPC64) += vdso64/ 21obj-$(CONFIG_PPC64) += vdso64/
22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
23obj-$(CONFIG_PPC_970_NAP) += idle_power4.o 23obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
@@ -32,7 +32,6 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
32obj-$(CONFIG_IBMVIO) += vio.o 32obj-$(CONFIG_IBMVIO) += vio.o
33obj-$(CONFIG_IBMEBUS) += ibmebus.o 33obj-$(CONFIG_IBMEBUS) += ibmebus.o
34obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 34obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
35obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
36obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 35obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
37obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o 36obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
38obj-$(CONFIG_TAU) += tau_6xx.o 37obj-$(CONFIG_TAU) += tau_6xx.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index d06f378597bb..e96521530d21 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -118,7 +118,8 @@ int main(void)
118 DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); 118 DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
119 DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); 119 DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
120 DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); 120 DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
121 DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); 121 DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
122 DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
122 DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); 123 DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
123 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); 124 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
124 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); 125 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S
index 652594891d58..bf118c385752 100644
--- a/arch/powerpc/kernel/cpu_setup_ppc970.S
+++ b/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -83,6 +83,22 @@ _GLOBAL(__setup_cpu_ppc970)
83 rldimi r0,r11,52,8 /* set NAP and DPM */ 83 rldimi r0,r11,52,8 /* set NAP and DPM */
84 li r11,0 84 li r11,0
85 rldimi r0,r11,32,31 /* clear EN_ATTN */ 85 rldimi r0,r11,32,31 /* clear EN_ATTN */
86 b load_hids /* Jump to shared code */
87
88
89_GLOBAL(__setup_cpu_ppc970MP)
90 /* Do nothing if not running in HV mode */
91 mfmsr r0
92 rldicl. r0,r0,4,63
93 beqlr
94
95 mfspr r0,SPRN_HID0
96 li r11,0x15 /* clear DOZE and SLEEP */
97 rldimi r0,r11,52,6 /* set DEEPNAP, NAP and DPM */
98 li r11,0
99 rldimi r0,r11,32,31 /* clear EN_ATTN */
100
101load_hids:
86 mtspr SPRN_HID0,r0 102 mtspr SPRN_HID0,r0
87 mfspr r0,SPRN_HID0 103 mfspr r0,SPRN_HID0
88 mfspr r0,SPRN_HID0 104 mfspr r0,SPRN_HID0
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index bfd499ee3753..1e4ed0731d15 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -42,6 +42,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
42#endif /* CONFIG_PPC32 */ 42#endif /* CONFIG_PPC32 */
43#ifdef CONFIG_PPC64 43#ifdef CONFIG_PPC64
44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); 44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
45extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
45extern void __restore_cpu_ppc970(void); 46extern void __restore_cpu_ppc970(void);
46#endif /* CONFIG_PPC64 */ 47#endif /* CONFIG_PPC64 */
47 48
@@ -222,7 +223,7 @@ static struct cpu_spec cpu_specs[] = {
222 .icache_bsize = 128, 223 .icache_bsize = 128,
223 .dcache_bsize = 128, 224 .dcache_bsize = 128,
224 .num_pmcs = 8, 225 .num_pmcs = 8,
225 .cpu_setup = __setup_cpu_ppc970, 226 .cpu_setup = __setup_cpu_ppc970MP,
226 .cpu_restore = __restore_cpu_ppc970, 227 .cpu_restore = __restore_cpu_ppc970,
227 .oprofile_cpu_type = "ppc64/970", 228 .oprofile_cpu_type = "ppc64/970",
228 .oprofile_type = PPC_OPROFILE_POWER4, 229 .oprofile_type = PPC_OPROFILE_POWER4,
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 1af41f7616dc..89b03c8da9d2 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs)
111 if (!cpu_online(cpu)) 111 if (!cpu_online(cpu))
112 return; 112 return;
113 113
114 local_irq_disable(); 114 hard_irq_disable();
115 if (!cpu_isset(cpu, cpus_in_crash)) 115 if (!cpu_isset(cpu, cpus_in_crash))
116 crash_save_this_cpu(regs, cpu); 116 crash_save_this_cpu(regs, cpu);
117 cpu_set(cpu, cpus_in_crash); 117 cpu_set(cpu, cpus_in_crash);
@@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
289 * an SMP system. 289 * an SMP system.
290 * The kernel is broken so disable interrupts. 290 * The kernel is broken so disable interrupts.
291 */ 291 */
292 local_irq_disable(); 292 hard_irq_disable();
293 293
294 for_each_irq(irq) { 294 for_each_irq(irq) {
295 struct irq_desc *desc = irq_desc + irq; 295 struct irq_desc *desc = irq_desc + irq;
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 748e74fcf541..ec754c92ba94 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -87,6 +87,10 @@ system_call_common:
87 addi r9,r1,STACK_FRAME_OVERHEAD 87 addi r9,r1,STACK_FRAME_OVERHEAD
88 ld r11,exception_marker@toc(r2) 88 ld r11,exception_marker@toc(r2)
89 std r11,-16(r9) /* "regshere" marker */ 89 std r11,-16(r9) /* "regshere" marker */
90 li r10,1
91 stb r10,PACASOFTIRQEN(r13)
92 stb r10,PACAHARDIRQEN(r13)
93 std r10,SOFTE(r1)
90#ifdef CONFIG_PPC_ISERIES 94#ifdef CONFIG_PPC_ISERIES
91BEGIN_FW_FTR_SECTION 95BEGIN_FW_FTR_SECTION
92 /* Hack for handling interrupts when soft-enabling on iSeries */ 96 /* Hack for handling interrupts when soft-enabling on iSeries */
@@ -94,8 +98,6 @@ BEGIN_FW_FTR_SECTION
94 andi. r10,r12,MSR_PR /* from kernel */ 98 andi. r10,r12,MSR_PR /* from kernel */
95 crand 4*cr0+eq,4*cr1+eq,4*cr0+eq 99 crand 4*cr0+eq,4*cr1+eq,4*cr0+eq
96 beq hardware_interrupt_entry 100 beq hardware_interrupt_entry
97 lbz r10,PACAPROCENABLED(r13)
98 std r10,SOFTE(r1)
99END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 101END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
100#endif 102#endif
101 mfmsr r11 103 mfmsr r11
@@ -460,9 +462,9 @@ _GLOBAL(ret_from_except_lite)
460#endif 462#endif
461 463
462restore: 464restore:
465 ld r5,SOFTE(r1)
463#ifdef CONFIG_PPC_ISERIES 466#ifdef CONFIG_PPC_ISERIES
464BEGIN_FW_FTR_SECTION 467BEGIN_FW_FTR_SECTION
465 ld r5,SOFTE(r1)
466 cmpdi 0,r5,0 468 cmpdi 0,r5,0
467 beq 4f 469 beq 4f
468 /* Check for pending interrupts (iSeries) */ 470 /* Check for pending interrupts (iSeries) */
@@ -472,21 +474,25 @@ BEGIN_FW_FTR_SECTION
472 beq+ 4f /* skip do_IRQ if no interrupts */ 474 beq+ 4f /* skip do_IRQ if no interrupts */
473 475
474 li r3,0 476 li r3,0
475 stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ 477 stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */
476 ori r10,r10,MSR_EE 478 ori r10,r10,MSR_EE
477 mtmsrd r10 /* hard-enable again */ 479 mtmsrd r10 /* hard-enable again */
478 addi r3,r1,STACK_FRAME_OVERHEAD 480 addi r3,r1,STACK_FRAME_OVERHEAD
479 bl .do_IRQ 481 bl .do_IRQ
480 b .ret_from_except_lite /* loop back and handle more */ 482 b .ret_from_except_lite /* loop back and handle more */
481 4834:
4824: stb r5,PACAPROCENABLED(r13)
483END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 484END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
484#endif 485#endif
486 stb r5,PACASOFTIRQEN(r13)
485 487
486 ld r3,_MSR(r1) 488 ld r3,_MSR(r1)
487 andi. r0,r3,MSR_RI 489 andi. r0,r3,MSR_RI
488 beq- unrecov_restore 490 beq- unrecov_restore
489 491
492 /* extract EE bit and use it to restore paca->hard_enabled */
493 rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
494 stb r4,PACAHARDIRQEN(r13)
495
490 andi. r0,r3,MSR_PR 496 andi. r0,r3,MSR_PR
491 497
492 /* 498 /*
@@ -538,25 +544,15 @@ do_work:
538 /* Check that preempt_count() == 0 and interrupts are enabled */ 544 /* Check that preempt_count() == 0 and interrupts are enabled */
539 lwz r8,TI_PREEMPT(r9) 545 lwz r8,TI_PREEMPT(r9)
540 cmpwi cr1,r8,0 546 cmpwi cr1,r8,0
541#ifdef CONFIG_PPC_ISERIES
542BEGIN_FW_FTR_SECTION
543 ld r0,SOFTE(r1) 547 ld r0,SOFTE(r1)
544 cmpdi r0,0 548 cmpdi r0,0
545END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
546#endif
547BEGIN_FW_FTR_SECTION
548 andi. r0,r3,MSR_EE
549END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
550 crandc eq,cr1*4+eq,eq 549 crandc eq,cr1*4+eq,eq
551 bne restore 550 bne restore
552 /* here we are preempting the current task */ 551 /* here we are preempting the current task */
5531: 5521:
554#ifdef CONFIG_PPC_ISERIES
555BEGIN_FW_FTR_SECTION
556 li r0,1 553 li r0,1
557 stb r0,PACAPROCENABLED(r13) 554 stb r0,PACASOFTIRQEN(r13)
558END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 555 stb r0,PACAHARDIRQEN(r13)
559#endif
560 ori r10,r10,MSR_EE 556 ori r10,r10,MSR_EE
561 mtmsrd r10,1 /* reenable interrupts */ 557 mtmsrd r10,1 /* reenable interrupts */
562 bl .preempt_schedule 558 bl .preempt_schedule
@@ -639,8 +635,7 @@ _GLOBAL(enter_rtas)
639 /* There is no way it is acceptable to get here with interrupts enabled, 635 /* There is no way it is acceptable to get here with interrupts enabled,
640 * check it with the asm equivalent of WARN_ON 636 * check it with the asm equivalent of WARN_ON
641 */ 637 */
642 mfmsr r6 638 lbz r0,PACASOFTIRQEN(r13)
643 andi. r0,r6,MSR_EE
6441: tdnei r0,0 6391: tdnei r0,0
645.section __bug_table,"a" 640.section __bug_table,"a"
646 .llong 1b,__LINE__ + 0x1000000, 1f, 2f 641 .llong 1b,__LINE__ + 0x1000000, 1f, 2f
@@ -649,7 +644,13 @@ _GLOBAL(enter_rtas)
6491: .asciz __FILE__ 6441: .asciz __FILE__
6502: .asciz "enter_rtas" 6452: .asciz "enter_rtas"
651.previous 646.previous
652 647
648 /* Hard-disable interrupts */
649 mfmsr r6
650 rldicl r7,r6,48,1
651 rotldi r7,r7,16
652 mtmsrd r7,1
653
653 /* Unfortunately, the stack pointer and the MSR are also clobbered, 654 /* Unfortunately, the stack pointer and the MSR are also clobbered,
654 * so they are saved in the PACA which allows us to restore 655 * so they are saved in the PACA which allows us to restore
655 * our original state after RTAS returns. 656 * our original state after RTAS returns.
@@ -735,8 +736,6 @@ _STATIC(rtas_restore_regs)
735 736
736#endif /* CONFIG_PPC_RTAS */ 737#endif /* CONFIG_PPC_RTAS */
737 738
738#ifdef CONFIG_PPC_MULTIPLATFORM
739
740_GLOBAL(enter_prom) 739_GLOBAL(enter_prom)
741 mflr r0 740 mflr r0
742 std r0,16(r1) 741 std r0,16(r1)
@@ -821,5 +820,3 @@ _GLOBAL(enter_prom)
821 ld r0,16(r1) 820 ld r0,16(r1)
822 mtlr r0 821 mtlr r0
823 blr 822 blr
824
825#endif /* CONFIG_PPC_MULTIPLATFORM */
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e720729f3e55..8cdff5a1f3e2 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -35,9 +35,7 @@
35#include <asm/thread_info.h> 35#include <asm/thread_info.h>
36#include <asm/firmware.h> 36#include <asm/firmware.h>
37 37
38#ifdef CONFIG_PPC_ISERIES
39#define DO_SOFT_DISABLE 38#define DO_SOFT_DISABLE
40#endif
41 39
42/* 40/*
43 * We layout physical memory as follows: 41 * We layout physical memory as follows:
@@ -74,13 +72,11 @@
74 .text 72 .text
75 .globl _stext 73 .globl _stext
76_stext: 74_stext:
77#ifdef CONFIG_PPC_MULTIPLATFORM
78_GLOBAL(__start) 75_GLOBAL(__start)
79 /* NOP this out unconditionally */ 76 /* NOP this out unconditionally */
80BEGIN_FTR_SECTION 77BEGIN_FTR_SECTION
81 b .__start_initialization_multiplatform 78 b .__start_initialization_multiplatform
82END_FTR_SECTION(0, 1) 79END_FTR_SECTION(0, 1)
83#endif /* CONFIG_PPC_MULTIPLATFORM */
84 80
85 /* Catch branch to 0 in real mode */ 81 /* Catch branch to 0 in real mode */
86 trap 82 trap
@@ -308,7 +304,9 @@ exception_marker:
308 std r9,_LINK(r1); \ 304 std r9,_LINK(r1); \
309 mfctr r10; /* save CTR in stackframe */ \ 305 mfctr r10; /* save CTR in stackframe */ \
310 std r10,_CTR(r1); \ 306 std r10,_CTR(r1); \
307 lbz r10,PACASOFTIRQEN(r13); \
311 mfspr r11,SPRN_XER; /* save XER in stackframe */ \ 308 mfspr r11,SPRN_XER; /* save XER in stackframe */ \
309 std r10,SOFTE(r1); \
312 std r11,_XER(r1); \ 310 std r11,_XER(r1); \
313 li r9,(n)+1; \ 311 li r9,(n)+1; \
314 std r9,_TRAP(r1); /* set trap number */ \ 312 std r9,_TRAP(r1); /* set trap number */ \
@@ -343,6 +341,34 @@ label##_pSeries: \
343 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) 341 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
344 342
345 343
344#define MASKABLE_EXCEPTION_PSERIES(n, label) \
345 . = n; \
346 .globl label##_pSeries; \
347label##_pSeries: \
348 HMT_MEDIUM; \
349 mtspr SPRN_SPRG1,r13; /* save r13 */ \
350 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
351 std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \
352 std r10,PACA_EXGEN+EX_R10(r13); \
353 lbz r10,PACASOFTIRQEN(r13); \
354 mfcr r9; \
355 cmpwi r10,0; \
356 beq masked_interrupt; \
357 mfspr r10,SPRN_SPRG1; \
358 std r10,PACA_EXGEN+EX_R13(r13); \
359 std r11,PACA_EXGEN+EX_R11(r13); \
360 std r12,PACA_EXGEN+EX_R12(r13); \
361 clrrdi r12,r13,32; /* get high part of &label */ \
362 mfmsr r10; \
363 mfspr r11,SPRN_SRR0; /* save SRR0 */ \
364 LOAD_HANDLER(r12,label##_common) \
365 ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
366 mtspr SPRN_SRR0,r12; \
367 mfspr r12,SPRN_SRR1; /* and SRR1 */ \
368 mtspr SPRN_SRR1,r10; \
369 rfid; \
370 b . /* prevent speculative execution */
371
346#define STD_EXCEPTION_ISERIES(n, label, area) \ 372#define STD_EXCEPTION_ISERIES(n, label, area) \
347 .globl label##_iSeries; \ 373 .globl label##_iSeries; \
348label##_iSeries: \ 374label##_iSeries: \
@@ -358,40 +384,32 @@ label##_iSeries: \
358 HMT_MEDIUM; \ 384 HMT_MEDIUM; \
359 mtspr SPRN_SPRG1,r13; /* save r13 */ \ 385 mtspr SPRN_SPRG1,r13; /* save r13 */ \
360 EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ 386 EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
361 lbz r10,PACAPROCENABLED(r13); \ 387 lbz r10,PACASOFTIRQEN(r13); \
362 cmpwi 0,r10,0; \ 388 cmpwi 0,r10,0; \
363 beq- label##_iSeries_masked; \ 389 beq- label##_iSeries_masked; \
364 EXCEPTION_PROLOG_ISERIES_2; \ 390 EXCEPTION_PROLOG_ISERIES_2; \
365 b label##_common; \ 391 b label##_common; \
366 392
367#ifdef DO_SOFT_DISABLE 393#ifdef CONFIG_PPC_ISERIES
368#define DISABLE_INTS \ 394#define DISABLE_INTS \
369BEGIN_FW_FTR_SECTION; \
370 lbz r10,PACAPROCENABLED(r13); \
371 li r11,0; \ 395 li r11,0; \
372 std r10,SOFTE(r1); \ 396 stb r11,PACASOFTIRQEN(r13); \
397BEGIN_FW_FTR_SECTION; \
398 stb r11,PACAHARDIRQEN(r13); \
399END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
400BEGIN_FW_FTR_SECTION; \
373 mfmsr r10; \ 401 mfmsr r10; \
374 stb r11,PACAPROCENABLED(r13); \
375 ori r10,r10,MSR_EE; \ 402 ori r10,r10,MSR_EE; \
376 mtmsrd r10,1; \ 403 mtmsrd r10,1; \
377END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 404END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
378 405
379#define ENABLE_INTS \ 406#else
380BEGIN_FW_FTR_SECTION; \ 407#define DISABLE_INTS \
381 lbz r10,PACAPROCENABLED(r13); \ 408 li r11,0; \
382 mfmsr r11; \ 409 stb r11,PACASOFTIRQEN(r13); \
383 std r10,SOFTE(r1); \ 410 stb r11,PACAHARDIRQEN(r13)
384 ori r11,r11,MSR_EE; \
385END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \
386BEGIN_FW_FTR_SECTION; \
387 ld r12,_MSR(r1); \
388 mfmsr r11; \
389 rlwimi r11,r12,0,MSR_EE; \
390END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
391 mtmsrd r11,1
392 411
393#else /* hard enable/disable interrupts */ 412#endif /* CONFIG_PPC_ISERIES */
394#define DISABLE_INTS
395 413
396#define ENABLE_INTS \ 414#define ENABLE_INTS \
397 ld r12,_MSR(r1); \ 415 ld r12,_MSR(r1); \
@@ -399,8 +417,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
399 rlwimi r11,r12,0,MSR_EE; \ 417 rlwimi r11,r12,0,MSR_EE; \
400 mtmsrd r11,1 418 mtmsrd r11,1
401 419
402#endif
403
404#define STD_EXCEPTION_COMMON(trap, label, hdlr) \ 420#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
405 .align 7; \ 421 .align 7; \
406 .globl label##_common; \ 422 .globl label##_common; \
@@ -541,11 +557,11 @@ instruction_access_slb_pSeries:
541 mfspr r12,SPRN_SRR1 /* and SRR1 */ 557 mfspr r12,SPRN_SRR1 /* and SRR1 */
542 b .slb_miss_realmode /* Rel. branch works in real mode */ 558 b .slb_miss_realmode /* Rel. branch works in real mode */
543 559
544 STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) 560 MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
545 STD_EXCEPTION_PSERIES(0x600, alignment) 561 STD_EXCEPTION_PSERIES(0x600, alignment)
546 STD_EXCEPTION_PSERIES(0x700, program_check) 562 STD_EXCEPTION_PSERIES(0x700, program_check)
547 STD_EXCEPTION_PSERIES(0x800, fp_unavailable) 563 STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
548 STD_EXCEPTION_PSERIES(0x900, decrementer) 564 MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
549 STD_EXCEPTION_PSERIES(0xa00, trap_0a) 565 STD_EXCEPTION_PSERIES(0xa00, trap_0a)
550 STD_EXCEPTION_PSERIES(0xb00, trap_0b) 566 STD_EXCEPTION_PSERIES(0xb00, trap_0b)
551 567
@@ -597,7 +613,24 @@ system_call_pSeries:
597/*** pSeries interrupt support ***/ 613/*** pSeries interrupt support ***/
598 614
599 /* moved from 0xf00 */ 615 /* moved from 0xf00 */
600 STD_EXCEPTION_PSERIES(., performance_monitor) 616 MASKABLE_EXCEPTION_PSERIES(., performance_monitor)
617
618/*
619 * An interrupt came in while soft-disabled; clear EE in SRR1,
620 * clear paca->hard_enabled and return.
621 */
622masked_interrupt:
623 stb r10,PACAHARDIRQEN(r13)
624 mtcrf 0x80,r9
625 ld r9,PACA_EXGEN+EX_R9(r13)
626 mfspr r10,SPRN_SRR1
627 rldicl r10,r10,48,1 /* clear MSR_EE */
628 rotldi r10,r10,16
629 mtspr SPRN_SRR1,r10
630 ld r10,PACA_EXGEN+EX_R10(r13)
631 mfspr r13,SPRN_SPRG1
632 rfid
633 b .
601 634
602 .align 7 635 .align 7
603do_stab_bolted_pSeries: 636do_stab_bolted_pSeries:
@@ -926,10 +959,18 @@ bad_stack:
926 * any task or sent any task a signal, you should use 959 * any task or sent any task a signal, you should use
927 * ret_from_except or ret_from_except_lite instead of this. 960 * ret_from_except or ret_from_except_lite instead of this.
928 */ 961 */
962fast_exc_return_irq: /* restores irq state too */
963 ld r3,SOFTE(r1)
964 ld r12,_MSR(r1)
965 stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */
966 rldicl r4,r12,49,63 /* get MSR_EE to LSB */
967 stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
968 b 1f
969
929 .globl fast_exception_return 970 .globl fast_exception_return
930fast_exception_return: 971fast_exception_return:
931 ld r12,_MSR(r1) 972 ld r12,_MSR(r1)
932 ld r11,_NIP(r1) 9731: ld r11,_NIP(r1)
933 andi. r3,r12,MSR_RI /* check if RI is set */ 974 andi. r3,r12,MSR_RI /* check if RI is set */
934 beq- unrecov_fer 975 beq- unrecov_fer
935 976
@@ -952,7 +993,8 @@ fast_exception_return:
952 REST_8GPRS(2, r1) 993 REST_8GPRS(2, r1)
953 994
954 mfmsr r10 995 mfmsr r10
955 clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ 996 rldicl r10,r10,48,1 /* clear EE */
997 rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */
956 mtmsrd r10,1 998 mtmsrd r10,1
957 999
958 mtspr SPRN_SRR1,r12 1000 mtspr SPRN_SRR1,r12
@@ -1326,6 +1368,16 @@ BEGIN_FW_FTR_SECTION
1326 * interrupts if necessary. 1368 * interrupts if necessary.
1327 */ 1369 */
1328 beq 13f 1370 beq 13f
1371END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1372#endif
1373BEGIN_FW_FTR_SECTION
1374 /*
1375 * Here we have interrupts hard-disabled, so it is sufficient
1376 * to restore paca->{soft,hard}_enable and get out.
1377 */
1378 beq fast_exc_return_irq /* Return from exception on success */
1379END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1380
1329 /* For a hash failure, we don't bother re-enabling interrupts */ 1381 /* For a hash failure, we don't bother re-enabling interrupts */
1330 ble- 12f 1382 ble- 12f
1331 1383
@@ -1337,14 +1389,6 @@ BEGIN_FW_FTR_SECTION
1337 ld r3,SOFTE(r1) 1389 ld r3,SOFTE(r1)
1338 bl .local_irq_restore 1390 bl .local_irq_restore
1339 b 11f 1391 b 11f
1340END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1341#endif
1342BEGIN_FW_FTR_SECTION
1343 beq fast_exception_return /* Return from exception on success */
1344 ble- 12f /* Failure return from hash_page */
1345
1346 /* fall through */
1347END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1348 1392
1349/* Here we have a page fault that hash_page can't handle. */ 1393/* Here we have a page fault that hash_page can't handle. */
1350handle_page_fault: 1394handle_page_fault:
@@ -1362,6 +1406,8 @@ handle_page_fault:
1362 bl .bad_page_fault 1406 bl .bad_page_fault
1363 b .ret_from_except 1407 b .ret_from_except
1364 1408
140913: b .ret_from_except_lite
1410
1365/* We have a page fault that hash_page could handle but HV refused 1411/* We have a page fault that hash_page could handle but HV refused
1366 * the PTE insertion 1412 * the PTE insertion
1367 */ 1413 */
@@ -1371,8 +1417,6 @@ handle_page_fault:
1371 bl .low_hash_fault 1417 bl .low_hash_fault
1372 b .ret_from_except 1418 b .ret_from_except
1373 1419
137413: b .ret_from_except_lite
1375
1376 /* here we have a segment miss */ 1420 /* here we have a segment miss */
1377do_ste_alloc: 1421do_ste_alloc:
1378 bl .ste_allocate /* try to insert stab entry */ 1422 bl .ste_allocate /* try to insert stab entry */
@@ -1595,7 +1639,6 @@ _STATIC(__start_initialization_iSeries)
1595 b .start_here_common 1639 b .start_here_common
1596#endif /* CONFIG_PPC_ISERIES */ 1640#endif /* CONFIG_PPC_ISERIES */
1597 1641
1598#ifdef CONFIG_PPC_MULTIPLATFORM
1599 1642
1600_STATIC(__mmu_off) 1643_STATIC(__mmu_off)
1601 mfmsr r3 1644 mfmsr r3
@@ -1621,13 +1664,11 @@ _STATIC(__mmu_off)
1621 * 1664 *
1622 */ 1665 */
1623_GLOBAL(__start_initialization_multiplatform) 1666_GLOBAL(__start_initialization_multiplatform)
1624#ifdef CONFIG_PPC_MULTIPLATFORM
1625 /* 1667 /*
1626 * Are we booted from a PROM Of-type client-interface ? 1668 * Are we booted from a PROM Of-type client-interface ?
1627 */ 1669 */
1628 cmpldi cr0,r5,0 1670 cmpldi cr0,r5,0
1629 bne .__boot_from_prom /* yes -> prom */ 1671 bne .__boot_from_prom /* yes -> prom */
1630#endif
1631 1672
1632 /* Save parameters */ 1673 /* Save parameters */
1633 mr r31,r3 1674 mr r31,r3
@@ -1656,7 +1697,6 @@ _GLOBAL(__start_initialization_multiplatform)
1656 bl .__mmu_off 1697 bl .__mmu_off
1657 b .__after_prom_start 1698 b .__after_prom_start
1658 1699
1659#ifdef CONFIG_PPC_MULTIPLATFORM
1660_STATIC(__boot_from_prom) 1700_STATIC(__boot_from_prom)
1661 /* Save parameters */ 1701 /* Save parameters */
1662 mr r31,r3 1702 mr r31,r3
@@ -1696,7 +1736,6 @@ _STATIC(__boot_from_prom)
1696 bl .prom_init 1736 bl .prom_init
1697 /* We never return */ 1737 /* We never return */
1698 trap 1738 trap
1699#endif
1700 1739
1701/* 1740/*
1702 * At this point, r3 contains the physical address we are running at, 1741 * At this point, r3 contains the physical address we are running at,
@@ -1752,8 +1791,6 @@ _STATIC(__after_prom_start)
1752 bl .copy_and_flush /* copy the rest */ 1791 bl .copy_and_flush /* copy the rest */
1753 b .start_here_multiplatform 1792 b .start_here_multiplatform
1754 1793
1755#endif /* CONFIG_PPC_MULTIPLATFORM */
1756
1757/* 1794/*
1758 * Copy routine used to copy the kernel to start at physical address 0 1795 * Copy routine used to copy the kernel to start at physical address 0
1759 * and flush and invalidate the caches as needed. 1796 * and flush and invalidate the caches as needed.
@@ -1877,11 +1914,16 @@ _GLOBAL(__secondary_start)
1877 /* enable MMU and jump to start_secondary */ 1914 /* enable MMU and jump to start_secondary */
1878 LOAD_REG_ADDR(r3, .start_secondary_prolog) 1915 LOAD_REG_ADDR(r3, .start_secondary_prolog)
1879 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) 1916 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
1880#ifdef DO_SOFT_DISABLE 1917#ifdef CONFIG_PPC_ISERIES
1881BEGIN_FW_FTR_SECTION 1918BEGIN_FW_FTR_SECTION
1882 ori r4,r4,MSR_EE 1919 ori r4,r4,MSR_EE
1883END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 1920END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1884#endif 1921#endif
1922BEGIN_FW_FTR_SECTION
1923 stb r7,PACASOFTIRQEN(r13)
1924 stb r7,PACAHARDIRQEN(r13)
1925END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1926
1885 mtspr SPRN_SRR0,r3 1927 mtspr SPRN_SRR0,r3
1886 mtspr SPRN_SRR1,r4 1928 mtspr SPRN_SRR1,r4
1887 rfid 1929 rfid
@@ -1913,7 +1955,6 @@ _GLOBAL(enable_64b_mode)
1913 isync 1955 isync
1914 blr 1956 blr
1915 1957
1916#ifdef CONFIG_PPC_MULTIPLATFORM
1917/* 1958/*
1918 * This is where the main kernel code starts. 1959 * This is where the main kernel code starts.
1919 */ 1960 */
@@ -1977,7 +2018,6 @@ _STATIC(start_here_multiplatform)
1977 mtspr SPRN_SRR1,r4 2018 mtspr SPRN_SRR1,r4
1978 rfid 2019 rfid
1979 b . /* prevent speculative execution */ 2020 b . /* prevent speculative execution */
1980#endif /* CONFIG_PPC_MULTIPLATFORM */
1981 2021
1982 /* This is where all platforms converge execution */ 2022 /* This is where all platforms converge execution */
1983_STATIC(start_here_common) 2023_STATIC(start_here_common)
@@ -2005,15 +2045,18 @@ _STATIC(start_here_common)
2005 2045
2006 /* Load up the kernel context */ 2046 /* Load up the kernel context */
20075: 20475:
2008#ifdef DO_SOFT_DISABLE
2009BEGIN_FW_FTR_SECTION
2010 li r5,0 2048 li r5,0
2011 stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ 2049 stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */
2050#ifdef CONFIG_PPC_ISERIES
2051BEGIN_FW_FTR_SECTION
2012 mfmsr r5 2052 mfmsr r5
2013 ori r5,r5,MSR_EE /* Hard Enabled */ 2053 ori r5,r5,MSR_EE /* Hard Enabled */
2014 mtmsrd r5 2054 mtmsrd r5
2015END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 2055END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
2016#endif 2056#endif
2057BEGIN_FW_FTR_SECTION
2058 stb r5,PACAHARDIRQEN(r13)
2059END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
2017 2060
2018 bl .start_kernel 2061 bl .start_kernel
2019 2062
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 4180c3998b39..8994af327b47 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -39,6 +39,13 @@
39#define cpu_should_die() 0 39#define cpu_should_die() 0
40#endif 40#endif
41 41
42static int __init powersave_off(char *arg)
43{
44 ppc_md.power_save = NULL;
45 return 0;
46}
47__setup("powersave=off", powersave_off);
48
42/* 49/*
43 * The body of the idle task. 50 * The body of the idle task.
44 */ 51 */
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 30de81da7b40..ba3195478600 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
30 beqlr 30 beqlr
31 31
32 /* Go to NAP now */ 32 /* Go to NAP now */
33 mfmsr r7
34 rldicl r0,r7,48,1
35 rotldi r0,r0,16
36 mtmsrd r0,1 /* hard-disable interrupts */
37 li r0,1
38 stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */
39 stb r0,PACAHARDIRQEN(r13)
33BEGIN_FTR_SECTION 40BEGIN_FTR_SECTION
34 DSSALL 41 DSSALL
35 sync 42 sync
@@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
38 ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ 45 ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
39 ori r8,r8,_TLF_NAPPING /* so when we take an exception */ 46 ori r8,r8,_TLF_NAPPING /* so when we take an exception */
40 std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ 47 std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
41 mfmsr r7
42 ori r7,r7,MSR_EE 48 ori r7,r7,MSR_EE
43 oris r7,r7,MSR_POW@h 49 oris r7,r7,MSR_POW@h
441: sync 501: sync
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5e37bf14ef2d..eb9fc621e057 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -64,8 +64,9 @@
64#include <asm/ptrace.h> 64#include <asm/ptrace.h>
65#include <asm/machdep.h> 65#include <asm/machdep.h>
66#include <asm/udbg.h> 66#include <asm/udbg.h>
67#ifdef CONFIG_PPC_ISERIES 67#ifdef CONFIG_PPC64
68#include <asm/paca.h> 68#include <asm/paca.h>
69#include <asm/firmware.h>
69#endif 70#endif
70 71
71int __irq_offset_value; 72int __irq_offset_value;
@@ -95,6 +96,27 @@ extern atomic_t ipi_sent;
95EXPORT_SYMBOL(irq_desc); 96EXPORT_SYMBOL(irq_desc);
96 97
97int distribute_irqs = 1; 98int distribute_irqs = 1;
99
100void local_irq_restore(unsigned long en)
101{
102 get_paca()->soft_enabled = en;
103 if (!en)
104 return;
105
106 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
107 if (get_paca()->lppaca_ptr->int_dword.any_int)
108 iseries_handle_interrupts();
109 return;
110 }
111
112 if (get_paca()->hard_enabled)
113 return;
114 /* need to hard-enable interrupts here */
115 get_paca()->hard_enabled = en;
116 if ((int)mfspr(SPRN_DEC) < 0)
117 mtspr(SPRN_DEC, 1);
118 hard_irq_enable();
119}
98#endif /* CONFIG_PPC64 */ 120#endif /* CONFIG_PPC64 */
99 121
100int show_interrupts(struct seq_file *p, void *v) 122int show_interrupts(struct seq_file *p, void *v)
@@ -626,10 +648,14 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
626 648
627void irq_dispose_mapping(unsigned int virq) 649void irq_dispose_mapping(unsigned int virq)
628{ 650{
629 struct irq_host *host = irq_map[virq].host; 651 struct irq_host *host;
630 irq_hw_number_t hwirq; 652 irq_hw_number_t hwirq;
631 unsigned long flags; 653 unsigned long flags;
632 654
655 if (virq == NO_IRQ)
656 return;
657
658 host = irq_map[virq].host;
633 WARN_ON (host == NULL); 659 WARN_ON (host == NULL);
634 if (host == NULL) 660 if (host == NULL)
635 return; 661 return;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 9bae8a5bf671..80ae9ea15cdc 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -42,11 +42,9 @@
42unsigned long pci_probe_only = 1; 42unsigned long pci_probe_only = 1;
43int pci_assign_all_buses = 0; 43int pci_assign_all_buses = 0;
44 44
45#ifdef CONFIG_PPC_MULTIPLATFORM
46static void fixup_resource(struct resource *res, struct pci_dev *dev); 45static void fixup_resource(struct resource *res, struct pci_dev *dev);
47static void do_bus_setup(struct pci_bus *bus); 46static void do_bus_setup(struct pci_bus *bus);
48static void phbs_remap_io(void); 47static void phbs_remap_io(void);
49#endif
50 48
51/* pci_io_base -- the base address from which io bars are offsets. 49/* pci_io_base -- the base address from which io bars are offsets.
52 * This is the lowest I/O base address (so bar values are always positive), 50 * This is the lowest I/O base address (so bar values are always positive),
@@ -251,7 +249,6 @@ static void __init pcibios_claim_of_setup(void)
251 pcibios_claim_one_bus(b); 249 pcibios_claim_one_bus(b);
252} 250}
253 251
254#ifdef CONFIG_PPC_MULTIPLATFORM
255static u32 get_int_prop(struct device_node *np, const char *name, u32 def) 252static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
256{ 253{
257 const u32 *prop; 254 const u32 *prop;
@@ -506,7 +503,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
506 pci_scan_child_bus(bus); 503 pci_scan_child_bus(bus);
507} 504}
508EXPORT_SYMBOL(of_scan_pci_bridge); 505EXPORT_SYMBOL(of_scan_pci_bridge);
509#endif /* CONFIG_PPC_MULTIPLATFORM */
510 506
511void __devinit scan_phb(struct pci_controller *hose) 507void __devinit scan_phb(struct pci_controller *hose)
512{ 508{
@@ -540,7 +536,7 @@ void __devinit scan_phb(struct pci_controller *hose)
540 } 536 }
541 537
542 mode = PCI_PROBE_NORMAL; 538 mode = PCI_PROBE_NORMAL;
543#ifdef CONFIG_PPC_MULTIPLATFORM 539
544 if (node && ppc_md.pci_probe_mode) 540 if (node && ppc_md.pci_probe_mode)
545 mode = ppc_md.pci_probe_mode(bus); 541 mode = ppc_md.pci_probe_mode(bus);
546 DBG(" probe mode: %d\n", mode); 542 DBG(" probe mode: %d\n", mode);
@@ -548,7 +544,7 @@ void __devinit scan_phb(struct pci_controller *hose)
548 bus->subordinate = hose->last_busno; 544 bus->subordinate = hose->last_busno;
549 of_scan_bus(node, bus); 545 of_scan_bus(node, bus);
550 } 546 }
551#endif /* CONFIG_PPC_MULTIPLATFORM */ 547
552 if (mode == PCI_PROBE_NORMAL) 548 if (mode == PCI_PROBE_NORMAL)
553 hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); 549 hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
554} 550}
@@ -592,11 +588,9 @@ static int __init pcibios_init(void)
592 if (ppc64_isabridge_dev != NULL) 588 if (ppc64_isabridge_dev != NULL)
593 printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); 589 printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
594 590
595#ifdef CONFIG_PPC_MULTIPLATFORM
596 if (!firmware_has_feature(FW_FEATURE_ISERIES)) 591 if (!firmware_has_feature(FW_FEATURE_ISERIES))
597 /* map in PCI I/O space */ 592 /* map in PCI I/O space */
598 phbs_remap_io(); 593 phbs_remap_io();
599#endif
600 594
601 printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); 595 printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
602 596
@@ -873,8 +867,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev)
873 device_create_file(&pdev->dev, &dev_attr_devspec); 867 device_create_file(&pdev->dev, &dev_attr_devspec);
874} 868}
875 869
876#ifdef CONFIG_PPC_MULTIPLATFORM
877
878#define ISA_SPACE_MASK 0x1 870#define ISA_SPACE_MASK 0x1
879#define ISA_SPACE_IO 0x1 871#define ISA_SPACE_IO 0x1
880 872
@@ -1343,8 +1335,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
1343 return NULL; 1335 return NULL;
1344} 1336}
1345 1337
1346#endif /* CONFIG_PPC_MULTIPLATFORM */
1347
1348unsigned long pci_address_to_pio(phys_addr_t address) 1338unsigned long pci_address_to_pio(phys_addr_t address)
1349{ 1339{
1350 struct pci_controller *hose, *tmp; 1340 struct pci_controller *hose, *tmp;
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 807193a3c784..9179f0739ea2 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -49,6 +49,10 @@
49#include <asm/commproc.h> 49#include <asm/commproc.h>
50#endif 50#endif
51 51
52#ifdef CONFIG_PPC64
53EXPORT_SYMBOL(local_irq_restore);
54#endif
55
52#ifdef CONFIG_PPC32 56#ifdef CONFIG_PPC32
53extern void transfer_to_handler(void); 57extern void transfer_to_handler(void);
54extern void do_IRQ(struct pt_regs *regs); 58extern void do_IRQ(struct pt_regs *regs);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index bdb412d4b748..16d29d16b96f 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1674,6 +1674,7 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
1674 } 1674 }
1675 return NULL; 1675 return NULL;
1676} 1676}
1677EXPORT_SYMBOL(of_get_cpu_node);
1677 1678
1678#ifdef DEBUG 1679#ifdef DEBUG
1679static struct debugfs_blob_wrapper flat_dt_blob; 1680static struct debugfs_blob_wrapper flat_dt_blob;
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 603dff3ad62a..346fb7bf9a05 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -25,6 +25,12 @@
25#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ 25#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
26 (ns) > 0) 26 (ns) > 0)
27 27
28static struct of_bus *of_match_bus(struct device_node *np);
29static int __of_address_to_resource(struct device_node *dev,
30 const u32 *addrp, u64 size, unsigned int flags,
31 struct resource *r);
32
33
28/* Debug utility */ 34/* Debug utility */
29#ifdef DEBUG 35#ifdef DEBUG
30static void of_dump_addr(const char *s, const u32 *addr, int na) 36static void of_dump_addr(const char *s, const u32 *addr, int na)
@@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr)
101} 107}
102 108
103 109
110#ifdef CONFIG_PCI
104/* 111/*
105 * PCI bus specific translator 112 * PCI bus specific translator
106 */ 113 */
@@ -162,6 +169,145 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
162 return flags; 169 return flags;
163} 170}
164 171
172const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
173 unsigned int *flags)
174{
175 const u32 *prop;
176 unsigned int psize;
177 struct device_node *parent;
178 struct of_bus *bus;
179 int onesize, i, na, ns;
180
181 /* Get parent & match bus type */
182 parent = of_get_parent(dev);
183 if (parent == NULL)
184 return NULL;
185 bus = of_match_bus(parent);
186 if (strcmp(bus->name, "pci")) {
187 of_node_put(parent);
188 return NULL;
189 }
190 bus->count_cells(dev, &na, &ns);
191 of_node_put(parent);
192 if (!OF_CHECK_COUNTS(na, ns))
193 return NULL;
194
195 /* Get "reg" or "assigned-addresses" property */
196 prop = get_property(dev, bus->addresses, &psize);
197 if (prop == NULL)
198 return NULL;
199 psize /= 4;
200
201 onesize = na + ns;
202 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
203 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
204 if (size)
205 *size = of_read_number(prop + na, ns);
206 if (flags)
207 *flags = bus->get_flags(prop);
208 return prop;
209 }
210 return NULL;
211}
212EXPORT_SYMBOL(of_get_pci_address);
213
214int of_pci_address_to_resource(struct device_node *dev, int bar,
215 struct resource *r)
216{
217 const u32 *addrp;
218 u64 size;
219 unsigned int flags;
220
221 addrp = of_get_pci_address(dev, bar, &size, &flags);
222 if (addrp == NULL)
223 return -EINVAL;
224 return __of_address_to_resource(dev, addrp, size, flags, r);
225}
226EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
227
228static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
229{
230 return (((pin - 1) + slot) % 4) + 1;
231}
232
233int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
234{
235 struct device_node *dn, *ppnode;
236 struct pci_dev *ppdev;
237 u32 lspec;
238 u32 laddr[3];
239 u8 pin;
240 int rc;
241
242 /* Check if we have a device node, if yes, fallback to standard OF
243 * parsing
244 */
245 dn = pci_device_to_OF_node(pdev);
246 if (dn)
247 return of_irq_map_one(dn, 0, out_irq);
248
249 /* Ok, we don't, time to have fun. Let's start by building up an
250 * interrupt spec. we assume #interrupt-cells is 1, which is standard
251 * for PCI. If you do different, then don't use that routine.
252 */
253 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
254 if (rc != 0)
255 return rc;
256 /* No pin, exit */
257 if (pin == 0)
258 return -ENODEV;
259
260 /* Now we walk up the PCI tree */
261 lspec = pin;
262 for (;;) {
263 /* Get the pci_dev of our parent */
264 ppdev = pdev->bus->self;
265
266 /* Ouch, it's a host bridge... */
267 if (ppdev == NULL) {
268#ifdef CONFIG_PPC64
269 ppnode = pci_bus_to_OF_node(pdev->bus);
270#else
271 struct pci_controller *host;
272 host = pci_bus_to_host(pdev->bus);
273 ppnode = host ? host->arch_data : NULL;
274#endif
275 /* No node for host bridge ? give up */
276 if (ppnode == NULL)
277 return -EINVAL;
278 } else
279 /* We found a P2P bridge, check if it has a node */
280 ppnode = pci_device_to_OF_node(ppdev);
281
282 /* Ok, we have found a parent with a device-node, hand over to
283 * the OF parsing code.
284 * We build a unit address from the linux device to be used for
285 * resolution. Note that we use the linux bus number which may
286 * not match your firmware bus numbering.
287 * Fortunately, in most cases, interrupt-map-mask doesn't include
288 * the bus number as part of the matching.
289 * You should still be careful about that though if you intend
290 * to rely on this function (you ship a firmware that doesn't
291 * create device nodes for all PCI devices).
292 */
293 if (ppnode)
294 break;
295
296 /* We can only get here if we hit a P2P bridge with no node,
297 * let's do standard swizzling and try again
298 */
299 lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
300 pdev = ppdev;
301 }
302
303 laddr[0] = (pdev->bus->number << 16)
304 | (pdev->devfn << 8);
305 laddr[1] = laddr[2] = 0;
306 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
307}
308EXPORT_SYMBOL_GPL(of_irq_map_pci);
309#endif /* CONFIG_PCI */
310
165/* 311/*
166 * ISA bus specific translator 312 * ISA bus specific translator
167 */ 313 */
@@ -223,6 +369,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr)
223 */ 369 */
224 370
225static struct of_bus of_busses[] = { 371static struct of_bus of_busses[] = {
372#ifdef CONFIG_PCI
226 /* PCI */ 373 /* PCI */
227 { 374 {
228 .name = "pci", 375 .name = "pci",
@@ -233,6 +380,7 @@ static struct of_bus of_busses[] = {
233 .translate = of_bus_pci_translate, 380 .translate = of_bus_pci_translate,
234 .get_flags = of_bus_pci_get_flags, 381 .get_flags = of_bus_pci_get_flags,
235 }, 382 },
383#endif /* CONFIG_PCI */
236 /* ISA */ 384 /* ISA */
237 { 385 {
238 .name = "isa", 386 .name = "isa",
@@ -445,48 +593,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
445} 593}
446EXPORT_SYMBOL(of_get_address); 594EXPORT_SYMBOL(of_get_address);
447 595
448const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
449 unsigned int *flags)
450{
451 const u32 *prop;
452 unsigned int psize;
453 struct device_node *parent;
454 struct of_bus *bus;
455 int onesize, i, na, ns;
456
457 /* Get parent & match bus type */
458 parent = of_get_parent(dev);
459 if (parent == NULL)
460 return NULL;
461 bus = of_match_bus(parent);
462 if (strcmp(bus->name, "pci")) {
463 of_node_put(parent);
464 return NULL;
465 }
466 bus->count_cells(dev, &na, &ns);
467 of_node_put(parent);
468 if (!OF_CHECK_COUNTS(na, ns))
469 return NULL;
470
471 /* Get "reg" or "assigned-addresses" property */
472 prop = get_property(dev, bus->addresses, &psize);
473 if (prop == NULL)
474 return NULL;
475 psize /= 4;
476
477 onesize = na + ns;
478 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
479 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
480 if (size)
481 *size = of_read_number(prop + na, ns);
482 if (flags)
483 *flags = bus->get_flags(prop);
484 return prop;
485 }
486 return NULL;
487}
488EXPORT_SYMBOL(of_get_pci_address);
489
490static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, 596static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
491 u64 size, unsigned int flags, 597 u64 size, unsigned int flags,
492 struct resource *r) 598 struct resource *r)
@@ -529,20 +635,6 @@ int of_address_to_resource(struct device_node *dev, int index,
529} 635}
530EXPORT_SYMBOL_GPL(of_address_to_resource); 636EXPORT_SYMBOL_GPL(of_address_to_resource);
531 637
532int of_pci_address_to_resource(struct device_node *dev, int bar,
533 struct resource *r)
534{
535 const u32 *addrp;
536 u64 size;
537 unsigned int flags;
538
539 addrp = of_get_pci_address(dev, bar, &size, &flags);
540 if (addrp == NULL)
541 return -EINVAL;
542 return __of_address_to_resource(dev, addrp, size, flags, r);
543}
544EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
545
546void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, 638void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
547 unsigned long *busno, unsigned long *phys, unsigned long *size) 639 unsigned long *busno, unsigned long *phys, unsigned long *size)
548{ 640{
@@ -898,87 +990,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
898 return res; 990 return res;
899} 991}
900EXPORT_SYMBOL_GPL(of_irq_map_one); 992EXPORT_SYMBOL_GPL(of_irq_map_one);
901
902#ifdef CONFIG_PCI
903static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
904{
905 return (((pin - 1) + slot) % 4) + 1;
906}
907
908int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
909{
910 struct device_node *dn, *ppnode;
911 struct pci_dev *ppdev;
912 u32 lspec;
913 u32 laddr[3];
914 u8 pin;
915 int rc;
916
917 /* Check if we have a device node, if yes, fallback to standard OF
918 * parsing
919 */
920 dn = pci_device_to_OF_node(pdev);
921 if (dn)
922 return of_irq_map_one(dn, 0, out_irq);
923
924 /* Ok, we don't, time to have fun. Let's start by building up an
925 * interrupt spec. we assume #interrupt-cells is 1, which is standard
926 * for PCI. If you do different, then don't use that routine.
927 */
928 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
929 if (rc != 0)
930 return rc;
931 /* No pin, exit */
932 if (pin == 0)
933 return -ENODEV;
934
935 /* Now we walk up the PCI tree */
936 lspec = pin;
937 for (;;) {
938 /* Get the pci_dev of our parent */
939 ppdev = pdev->bus->self;
940
941 /* Ouch, it's a host bridge... */
942 if (ppdev == NULL) {
943#ifdef CONFIG_PPC64
944 ppnode = pci_bus_to_OF_node(pdev->bus);
945#else
946 struct pci_controller *host;
947 host = pci_bus_to_host(pdev->bus);
948 ppnode = host ? host->arch_data : NULL;
949#endif
950 /* No node for host bridge ? give up */
951 if (ppnode == NULL)
952 return -EINVAL;
953 } else
954 /* We found a P2P bridge, check if it has a node */
955 ppnode = pci_device_to_OF_node(ppdev);
956
957 /* Ok, we have found a parent with a device-node, hand over to
958 * the OF parsing code.
959 * We build a unit address from the linux device to be used for
960 * resolution. Note that we use the linux bus number which may
961 * not match your firmware bus numbering.
962 * Fortunately, in most cases, interrupt-map-mask doesn't include
963 * the bus number as part of the matching.
964 * You should still be careful about that though if you intend
965 * to rely on this function (you ship a firmware that doesn't
966 * create device nodes for all PCI devices).
967 */
968 if (ppnode)
969 break;
970
971 /* We can only get here if we hit a P2P bridge with no node,
972 * let's do standard swizzling and try again
973 */
974 lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
975 pdev = ppdev;
976 }
977
978 laddr[0] = (pdev->bus->number << 16)
979 | (pdev->devfn << 8);
980 laddr[1] = laddr[2] = 0;
981 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
982}
983EXPORT_SYMBOL_GPL(of_irq_map_pci);
984#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index a4c2964a3ca6..04df53a3c86d 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -63,10 +63,6 @@ unsigned int DMA_MODE_WRITE;
63 63
64int have_of = 1; 64int have_of = 1;
65 65
66#ifdef CONFIG_PPC_MULTIPLATFORM
67dev_t boot_dev;
68#endif /* CONFIG_PPC_MULTIPLATFORM */
69
70#ifdef CONFIG_VGA_CONSOLE 66#ifdef CONFIG_VGA_CONSOLE
71unsigned long vgacon_remap_base; 67unsigned long vgacon_remap_base;
72#endif 68#endif
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 16278968dab6..b0f1c82df994 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -71,7 +71,6 @@
71 71
72int have_of = 1; 72int have_of = 1;
73int boot_cpuid = 0; 73int boot_cpuid = 0;
74dev_t boot_dev;
75u64 ppc64_pft_size; 74u64 ppc64_pft_size;
76 75
77/* Pick defaults since we might want to patch instructions 76/* Pick defaults since we might want to patch instructions
@@ -226,8 +225,8 @@ void early_setup_secondary(void)
226{ 225{
227 struct paca_struct *lpaca = get_paca(); 226 struct paca_struct *lpaca = get_paca();
228 227
229 /* Mark enabled in PACA */ 228 /* Mark interrupts enabled in PACA */
230 lpaca->proc_enabled = 0; 229 lpaca->soft_enabled = 0;
231 230
232 /* Initialize hash table for that CPU */ 231 /* Initialize hash table for that CPU */
233 htab_initialize_secondary(); 232 htab_initialize_secondary();
@@ -392,7 +391,8 @@ void __init setup_system(void)
392 * setting up the hash table pointers. It also sets up some interrupt-mapping 391 * setting up the hash table pointers. It also sets up some interrupt-mapping
393 * related options that will be used by finish_device_tree() 392 * related options that will be used by finish_device_tree()
394 */ 393 */
395 ppc_md.init_early(); 394 if (ppc_md.init_early)
395 ppc_md.init_early();
396 396
397 /* 397 /*
398 * We can discover serial ports now since the above did setup the 398 * We can discover serial ports now since the above did setup the
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 35c6309bdb76..9b28c238b6c0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -65,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
65 65
66EXPORT_SYMBOL(cpu_online_map); 66EXPORT_SYMBOL(cpu_online_map);
67EXPORT_SYMBOL(cpu_possible_map); 67EXPORT_SYMBOL(cpu_possible_map);
68EXPORT_SYMBOL(cpu_sibling_map);
68 69
69/* SMP operations for this machine */ 70/* SMP operations for this machine */
70struct smp_ops_t *smp_ops; 71struct smp_ops_t *smp_ops;
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index d45a168bdaca..cda21a27490a 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -299,6 +299,72 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
299 .notifier_call = sysfs_cpu_notify, 299 .notifier_call = sysfs_cpu_notify,
300}; 300};
301 301
302static DEFINE_MUTEX(cpu_mutex);
303
304int cpu_add_sysdev_attr(struct sysdev_attribute *attr)
305{
306 int cpu;
307
308 mutex_lock(&cpu_mutex);
309
310 for_each_possible_cpu(cpu) {
311 sysdev_create_file(get_cpu_sysdev(cpu), attr);
312 }
313
314 mutex_unlock(&cpu_mutex);
315 return 0;
316}
317EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr);
318
319int cpu_add_sysdev_attr_group(struct attribute_group *attrs)
320{
321 int cpu;
322 struct sys_device *sysdev;
323
324 mutex_lock(&cpu_mutex);
325
326 for_each_possible_cpu(cpu) {
327 sysdev = get_cpu_sysdev(cpu);
328 sysfs_create_group(&sysdev->kobj, attrs);
329 }
330
331 mutex_unlock(&cpu_mutex);
332 return 0;
333}
334EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group);
335
336
337void cpu_remove_sysdev_attr(struct sysdev_attribute *attr)
338{
339 int cpu;
340
341 mutex_lock(&cpu_mutex);
342
343 for_each_possible_cpu(cpu) {
344 sysdev_remove_file(get_cpu_sysdev(cpu), attr);
345 }
346
347 mutex_unlock(&cpu_mutex);
348}
349EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr);
350
351void cpu_remove_sysdev_attr_group(struct attribute_group *attrs)
352{
353 int cpu;
354 struct sys_device *sysdev;
355
356 mutex_lock(&cpu_mutex);
357
358 for_each_possible_cpu(cpu) {
359 sysdev = get_cpu_sysdev(cpu);
360 sysfs_remove_group(&sysdev->kobj, attrs);
361 }
362
363 mutex_unlock(&cpu_mutex);
364}
365EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group);
366
367
302/* NUMA stuff */ 368/* NUMA stuff */
303 369
304#ifdef CONFIG_NUMA 370#ifdef CONFIG_NUMA
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index e8fa50624b70..03aeb3a46077 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -426,18 +426,21 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
426 426
427 /* kernel has accessed a bad area */ 427 /* kernel has accessed a bad area */
428 428
429 printk(KERN_ALERT "Unable to handle kernel paging request for ");
430 switch (regs->trap) { 429 switch (regs->trap) {
431 case 0x300: 430 case 0x300:
432 case 0x380: 431 case 0x380:
433 printk("data at address 0x%08lx\n", regs->dar); 432 printk(KERN_ALERT "Unable to handle kernel paging request for "
434 break; 433 "data at address 0x%08lx\n", regs->dar);
435 case 0x400: 434 break;
436 case 0x480: 435 case 0x400:
437 printk("instruction fetch\n"); 436 case 0x480:
438 break; 437 printk(KERN_ALERT "Unable to handle kernel paging request for "
439 default: 438 "instruction fetch\n");
440 printk("unknown fault\n"); 439 break;
440 default:
441 printk(KERN_ALERT "Unable to handle kernel paging request for "
442 "unknown fault\n");
443 break;
441 } 444 }
442 printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", 445 printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
443 regs->nip); 446 regs->nip);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index c90f124f3c71..6f1016acdbf6 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep)
123 clear_bit(HPTE_LOCK_BIT, word); 123 clear_bit(HPTE_LOCK_BIT, word);
124} 124}
125 125
126long native_hpte_insert(unsigned long hpte_group, unsigned long va, 126static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
127 unsigned long pa, unsigned long rflags, 127 unsigned long pa, unsigned long rflags,
128 unsigned long vflags, int psize) 128 unsigned long vflags, int psize)
129{ 129{
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index e58fa953a50b..7ad2673d0aa5 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -5,6 +5,7 @@ ifeq ($(CONFIG_PPC64),y)
5obj-$(CONFIG_PPC_PMAC) += powermac/ 5obj-$(CONFIG_PPC_PMAC) += powermac/
6endif 6endif
7endif 7endif
8obj-$(CONFIG_PPC_EFIKA) += efika/
8obj-$(CONFIG_PPC_CHRP) += chrp/ 9obj-$(CONFIG_PPC_CHRP) += chrp/
9obj-$(CONFIG_4xx) += 4xx/ 10obj-$(CONFIG_4xx) += 4xx/
10obj-$(CONFIG_PPC_83xx) += 83xx/ 11obj-$(CONFIG_PPC_83xx) += 83xx/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3e430b489bb7..06a85b704331 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -20,4 +20,18 @@ config CBE_RAS
20 bool "RAS features for bare metal Cell BE" 20 bool "RAS features for bare metal Cell BE"
21 default y 21 default y
22 22
23config CBE_THERM
24 tristate "CBE thermal support"
25 default m
26 depends on CBE_RAS
27
28config CBE_CPUFREQ
29 tristate "CBE frequency scaling"
30 depends on CBE_RAS && CPU_FREQ
31 default m
32 help
33 This adds the cpufreq driver for Cell BE processors.
34 For details, take a look at <file:Documentation/cpu-freq/>.
35 If you don't have such processor, say N
36
23endmenu 37endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index c89cdd67383b..0f31db7a50a3 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -1,7 +1,11 @@
1obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ 1obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \
2 cbe_regs.o spider-pic.o pervasive.o 2 cbe_regs.o spider-pic.o pervasive.o \
3 pmu.o
3obj-$(CONFIG_CBE_RAS) += ras.o 4obj-$(CONFIG_CBE_RAS) += ras.o
4 5
6obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
7obj-$(CONFIG_CBE_CPUFREQ) += cbe_cpufreq.o
8
5ifeq ($(CONFIG_SMP),y) 9ifeq ($(CONFIG_SMP),y)
6obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o 10obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
7endif 11endif
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
new file mode 100644
index 000000000000..a3850fd1e94c
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -0,0 +1,248 @@
1/*
2 * cpufreq driver for the cell processor
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Christian Krafft <krafft@de.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/cpufreq.h>
24#include <linux/timer.h>
25
26#include <asm/hw_irq.h>
27#include <asm/io.h>
28#include <asm/processor.h>
29#include <asm/prom.h>
30#include <asm/time.h>
31
32#include "cbe_regs.h"
33
34static DEFINE_MUTEX(cbe_switch_mutex);
35
36
37/* the CBE supports an 8 step frequency scaling */
38static struct cpufreq_frequency_table cbe_freqs[] = {
39 {1, 0},
40 {2, 0},
41 {3, 0},
42 {4, 0},
43 {5, 0},
44 {6, 0},
45 {8, 0},
46 {10, 0},
47 {0, CPUFREQ_TABLE_END},
48};
49
50/* to write to MIC register */
51static u64 MIC_Slow_Fast_Timer_table[] = {
52 [0 ... 7] = 0x007fc00000000000ull,
53};
54
55/* more values for the MIC */
56static u64 MIC_Slow_Next_Timer_table[] = {
57 0x0000240000000000ull,
58 0x0000268000000000ull,
59 0x000029C000000000ull,
60 0x00002D0000000000ull,
61 0x0000300000000000ull,
62 0x0000334000000000ull,
63 0x000039C000000000ull,
64 0x00003FC000000000ull,
65};
66
67/*
68 * hardware specific functions
69 */
70
71static int get_pmode(int cpu)
72{
73 int ret;
74 struct cbe_pmd_regs __iomem *pmd_regs;
75
76 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
77 ret = in_be64(&pmd_regs->pmsr) & 0x07;
78
79 return ret;
80}
81
82static int set_pmode(int cpu, unsigned int pmode)
83{
84 struct cbe_pmd_regs __iomem *pmd_regs;
85 struct cbe_mic_tm_regs __iomem *mic_tm_regs;
86 u64 flags;
87 u64 value;
88
89 local_irq_save(flags);
90
91 mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
92 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
93
94 pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr);
95 pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0);
96
97 out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
98 out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
99
100 out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
101 out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
102
103 value = in_be64(&pmd_regs->pmcr);
104 /* set bits to zero */
105 value &= 0xFFFFFFFFFFFFFFF8ull;
106 /* set bits to next pmode */
107 value |= pmode;
108
109 out_be64(&pmd_regs->pmcr, value);
110
111 /* wait until new pmode appears in status register */
112 value = in_be64(&pmd_regs->pmsr) & 0x07;
113 while(value != pmode) {
114 cpu_relax();
115 value = in_be64(&pmd_regs->pmsr) & 0x07;
116 }
117
118 local_irq_restore(flags);
119
120 return 0;
121}
122
123/*
124 * cpufreq functions
125 */
126
127static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy)
128{
129 u32 *max_freq;
130 int i, cur_pmode;
131 struct device_node *cpu;
132
133 cpu = of_get_cpu_node(policy->cpu, NULL);
134
135 if(!cpu)
136 return -ENODEV;
137
138 pr_debug("init cpufreq on CPU %d\n", policy->cpu);
139
140 max_freq = (u32*) get_property(cpu, "clock-frequency", NULL);
141
142 if(!max_freq)
143 return -EINVAL;
144
145 // we need the freq in kHz
146 *max_freq /= 1000;
147
148 pr_debug("max clock-frequency is at %u kHz\n", *max_freq);
149 pr_debug("initializing frequency table\n");
150
151 // initialize frequency table
152 for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) {
153 cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index;
154 pr_debug("%d: %d\n", i, cbe_freqs[i].frequency);
155 }
156
157 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
158 /* if DEBUG is enabled set_pmode() measures the correct latency of a transition */
159 policy->cpuinfo.transition_latency = 25000;
160
161 cur_pmode = get_pmode(policy->cpu);
162 pr_debug("current pmode is at %d\n",cur_pmode);
163
164 policy->cur = cbe_freqs[cur_pmode].frequency;
165
166#ifdef CONFIG_SMP
167 policy->cpus = cpu_sibling_map[policy->cpu];
168#endif
169
170 cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu);
171
172 /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
173 return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs);
174}
175
176static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
177{
178 cpufreq_frequency_table_put_attr(policy->cpu);
179 return 0;
180}
181
182static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
183{
184 return cpufreq_frequency_table_verify(policy, cbe_freqs);
185}
186
187
188static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq,
189 unsigned int relation)
190{
191 int rc;
192 struct cpufreq_freqs freqs;
193 int cbe_pmode_new;
194
195 cpufreq_frequency_table_target(policy,
196 cbe_freqs,
197 target_freq,
198 relation,
199 &cbe_pmode_new);
200
201 freqs.old = policy->cur;
202 freqs.new = cbe_freqs[cbe_pmode_new].frequency;
203 freqs.cpu = policy->cpu;
204
205 mutex_lock (&cbe_switch_mutex);
206 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
207
208 pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
209 policy->cpu,
210 cbe_freqs[cbe_pmode_new].frequency,
211 cbe_freqs[cbe_pmode_new].index);
212
213 rc = set_pmode(policy->cpu, cbe_pmode_new);
214 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
215 mutex_unlock(&cbe_switch_mutex);
216
217 return rc;
218}
219
220static struct cpufreq_driver cbe_cpufreq_driver = {
221 .verify = cbe_cpufreq_verify,
222 .target = cbe_cpufreq_target,
223 .init = cbe_cpufreq_cpu_init,
224 .exit = cbe_cpufreq_cpu_exit,
225 .name = "cbe-cpufreq",
226 .owner = THIS_MODULE,
227 .flags = CPUFREQ_CONST_LOOPS,
228};
229
230/*
231 * module init and destoy
232 */
233
234static int __init cbe_cpufreq_init(void)
235{
236 return cpufreq_register_driver(&cbe_cpufreq_driver);
237}
238
239static void __exit cbe_cpufreq_exit(void)
240{
241 cpufreq_unregister_driver(&cbe_cpufreq_driver);
242}
243
244module_init(cbe_cpufreq_init);
245module_exit(cbe_cpufreq_exit);
246
247MODULE_LICENSE("GPL");
248MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index 2f194ba29899..5a91b75c2f01 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/percpu.h> 9#include <linux/percpu.h>
10#include <linux/types.h> 10#include <linux/types.h>
11#include <linux/module.h>
11 12
12#include <asm/io.h> 13#include <asm/io.h>
13#include <asm/pgtable.h> 14#include <asm/pgtable.h>
@@ -16,8 +17,6 @@
16 17
17#include "cbe_regs.h" 18#include "cbe_regs.h"
18 19
19#define MAX_CBE 2
20
21/* 20/*
22 * Current implementation uses "cpu" nodes. We build our own mapping 21 * Current implementation uses "cpu" nodes. We build our own mapping
23 * array of cpu numbers to cpu nodes locally for now to allow interrupt 22 * array of cpu numbers to cpu nodes locally for now to allow interrupt
@@ -30,6 +29,8 @@ static struct cbe_regs_map
30 struct device_node *cpu_node; 29 struct device_node *cpu_node;
31 struct cbe_pmd_regs __iomem *pmd_regs; 30 struct cbe_pmd_regs __iomem *pmd_regs;
32 struct cbe_iic_regs __iomem *iic_regs; 31 struct cbe_iic_regs __iomem *iic_regs;
32 struct cbe_mic_tm_regs __iomem *mic_tm_regs;
33 struct cbe_pmd_shadow_regs pmd_shadow_regs;
33} cbe_regs_maps[MAX_CBE]; 34} cbe_regs_maps[MAX_CBE];
34static int cbe_regs_map_count; 35static int cbe_regs_map_count;
35 36
@@ -42,6 +43,19 @@ static struct cbe_thread_map
42static struct cbe_regs_map *cbe_find_map(struct device_node *np) 43static struct cbe_regs_map *cbe_find_map(struct device_node *np)
43{ 44{
44 int i; 45 int i;
46 struct device_node *tmp_np;
47
48 if (strcasecmp(np->type, "spe") == 0) {
49 if (np->data == NULL) {
50 /* walk up path until cpu node was found */
51 tmp_np = np->parent;
52 while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0)
53 tmp_np = tmp_np->parent;
54
55 np->data = cbe_find_map(tmp_np);
56 }
57 return np->data;
58 }
45 59
46 for (i = 0; i < cbe_regs_map_count; i++) 60 for (i = 0; i < cbe_regs_map_count; i++)
47 if (cbe_regs_maps[i].cpu_node == np) 61 if (cbe_regs_maps[i].cpu_node == np)
@@ -56,6 +70,7 @@ struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
56 return NULL; 70 return NULL;
57 return map->pmd_regs; 71 return map->pmd_regs;
58} 72}
73EXPORT_SYMBOL_GPL(cbe_get_pmd_regs);
59 74
60struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) 75struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
61{ 76{
@@ -64,7 +79,23 @@ struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
64 return NULL; 79 return NULL;
65 return map->pmd_regs; 80 return map->pmd_regs;
66} 81}
82EXPORT_SYMBOL_GPL(cbe_get_cpu_pmd_regs);
83
84struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np)
85{
86 struct cbe_regs_map *map = cbe_find_map(np);
87 if (map == NULL)
88 return NULL;
89 return &map->pmd_shadow_regs;
90}
67 91
92struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu)
93{
94 struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
95 if (map == NULL)
96 return NULL;
97 return &map->pmd_shadow_regs;
98}
68 99
69struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) 100struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
70{ 101{
@@ -73,6 +104,7 @@ struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
73 return NULL; 104 return NULL;
74 return map->iic_regs; 105 return map->iic_regs;
75} 106}
107
76struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) 108struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
77{ 109{
78 struct cbe_regs_map *map = cbe_thread_map[cpu].regs; 110 struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
@@ -81,6 +113,24 @@ struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
81 return map->iic_regs; 113 return map->iic_regs;
82} 114}
83 115
116struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np)
117{
118 struct cbe_regs_map *map = cbe_find_map(np);
119 if (map == NULL)
120 return NULL;
121 return map->mic_tm_regs;
122}
123
124struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu)
125{
126 struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
127 if (map == NULL)
128 return NULL;
129 return map->mic_tm_regs;
130}
131EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs);
132
133
84void __init cbe_regs_init(void) 134void __init cbe_regs_init(void)
85{ 135{
86 int i; 136 int i;
@@ -119,6 +169,11 @@ void __init cbe_regs_init(void)
119 prop = get_property(cpu, "iic", NULL); 169 prop = get_property(cpu, "iic", NULL);
120 if (prop != NULL) 170 if (prop != NULL)
121 map->iic_regs = ioremap(prop->address, prop->len); 171 map->iic_regs = ioremap(prop->address, prop->len);
172
173 prop = (struct address_prop *)get_property(cpu, "mic-tm",
174 NULL);
175 if (prop != NULL)
176 map->mic_tm_regs = ioremap(prop->address, prop->len);
122 } 177 }
123} 178}
124 179
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
index e76e4a6af5bc..91083f51a0cb 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -4,6 +4,11 @@
4 * This file is intended to hold the various register definitions for CBE 4 * This file is intended to hold the various register definitions for CBE
5 * on-chip system devices (memory controller, IO controller, etc...) 5 * on-chip system devices (memory controller, IO controller, etc...)
6 * 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 *
7 * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. 12 * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
8 */ 13 */
9 14
@@ -22,6 +27,7 @@
22#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul 27#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul
23#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul 28#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
24 29
30#define MAX_CBE 2
25 31
26/* 32/*
27 * 33 *
@@ -29,51 +35,132 @@
29 * 35 *
30 */ 36 */
31 37
38/* Macros for the pm_control register. */
39#define CBE_PM_16BIT_CTR(ctr) (1 << (24 - ((ctr) & (NR_PHYS_CTRS - 1))))
40#define CBE_PM_ENABLE_PERF_MON 0x80000000
41
42
43union spe_reg {
44 u64 val;
45 u8 spe[8];
46};
47
48union ppe_spe_reg {
49 u64 val;
50 struct {
51 u32 ppe;
52 u32 spe;
53 };
54};
55
56
32struct cbe_pmd_regs { 57struct cbe_pmd_regs {
33 u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ 58 /* Debug Bus Control */
59 u64 pad_0x0000; /* 0x0000 */
60
61 u64 group_control; /* 0x0008 */
62
63 u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */
64
65 u64 debug_bus_control; /* 0x00a8 */
66
67 u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */
68
69 u64 trace_aux_data; /* 0x0100 */
70 u64 trace_buffer_0_63; /* 0x0108 */
71 u64 trace_buffer_64_127; /* 0x0110 */
72 u64 trace_address; /* 0x0118 */
73 u64 ext_tr_timer; /* 0x0120 */
74
75 u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */
76
77 /* Performance Monitor */
78 u64 pm_status; /* 0x0400 */
79 u64 pm_control; /* 0x0408 */
80 u64 pm_interval; /* 0x0410 */
81 u64 pm_ctr[4]; /* 0x0418 */
82 u64 pm_start_stop; /* 0x0438 */
83 u64 pm07_control[8]; /* 0x0440 */
84
85 u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */
34 86
35 /* Thermal Sensor Registers */ 87 /* Thermal Sensor Registers */
36 u64 ts_ctsr1; /* 0x0800 */ 88 union spe_reg ts_ctsr1; /* 0x0800 */
37 u64 ts_ctsr2; /* 0x0808 */ 89 u64 ts_ctsr2; /* 0x0808 */
38 u64 ts_mtsr1; /* 0x0810 */ 90 union spe_reg ts_mtsr1; /* 0x0810 */
39 u64 ts_mtsr2; /* 0x0818 */ 91 u64 ts_mtsr2; /* 0x0818 */
40 u64 ts_itr1; /* 0x0820 */ 92 union spe_reg ts_itr1; /* 0x0820 */
41 u64 ts_itr2; /* 0x0828 */ 93 u64 ts_itr2; /* 0x0828 */
42 u64 ts_gitr; /* 0x0830 */ 94 u64 ts_gitr; /* 0x0830 */
43 u64 ts_isr; /* 0x0838 */ 95 u64 ts_isr; /* 0x0838 */
44 u64 ts_imr; /* 0x0840 */ 96 u64 ts_imr; /* 0x0840 */
45 u64 tm_cr1; /* 0x0848 */ 97 union spe_reg tm_cr1; /* 0x0848 */
46 u64 tm_cr2; /* 0x0850 */ 98 u64 tm_cr2; /* 0x0850 */
47 u64 tm_simr; /* 0x0858 */ 99 u64 tm_simr; /* 0x0858 */
48 u64 tm_tpr; /* 0x0860 */ 100 union ppe_spe_reg tm_tpr; /* 0x0860 */
49 u64 tm_str1; /* 0x0868 */ 101 union spe_reg tm_str1; /* 0x0868 */
50 u64 tm_str2; /* 0x0870 */ 102 u64 tm_str2; /* 0x0870 */
51 u64 tm_tsr; /* 0x0878 */ 103 union ppe_spe_reg tm_tsr; /* 0x0878 */
52 104
53 /* Power Management */ 105 /* Power Management */
54 u64 pm_control; /* 0x0880 */ 106 u64 pmcr; /* 0x0880 */
55#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 107#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000
56 u64 pm_status; /* 0x0888 */ 108 u64 pmsr; /* 0x0888 */
57 109
58 /* Time Base Register */ 110 /* Time Base Register */
59 u64 tbr; /* 0x0890 */ 111 u64 tbr; /* 0x0890 */
60 112
61 u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ 113 u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */
62 114
63 /* Fault Isolation Registers */ 115 /* Fault Isolation Registers */
64 u64 checkstop_fir; /* 0x0c00 */ 116 u64 checkstop_fir; /* 0x0c00 */
65 u64 recoverable_fir; 117 u64 recoverable_fir; /* 0x0c08 */
66 u64 spec_att_mchk_fir; 118 u64 spec_att_mchk_fir; /* 0x0c10 */
67 u64 fir_mode_reg; 119 u64 fir_mode_reg; /* 0x0c18 */
68 u64 fir_enable_mask; 120 u64 fir_enable_mask; /* 0x0c20 */
69 121
70 u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ 122 u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */
71}; 123};
72 124
73extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); 125extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
74extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); 126extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
75 127
76/* 128/*
129 * PMU shadow registers
130 *
131 * Many of the registers in the performance monitoring unit are write-only,
132 * so we need to save a copy of what we write to those registers.
133 *
134 * The actual data counters are read/write. However, writing to the counters
135 * only takes effect if the PMU is enabled. Otherwise the value is stored in
136 * a hardware latch until the next time the PMU is enabled. So we save a copy
137 * of the counter values if we need to read them back while the PMU is
138 * disabled. The counter_value_in_latch field is a bitmap indicating which
139 * counters currently have a value waiting to be written.
140 */
141
142#define NR_PHYS_CTRS 4
143#define NR_CTRS (NR_PHYS_CTRS * 2)
144
145struct cbe_pmd_shadow_regs {
146 u32 group_control;
147 u32 debug_bus_control;
148 u32 trace_address;
149 u32 ext_tr_timer;
150 u32 pm_status;
151 u32 pm_control;
152 u32 pm_interval;
153 u32 pm_start_stop;
154 u32 pm07_control[NR_CTRS];
155
156 u32 pm_ctr[NR_PHYS_CTRS];
157 u32 counter_value_in_latch;
158};
159
160extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np);
161extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu);
162
163/*
77 * 164 *
78 * IIC unit register definitions 165 * IIC unit register definitions
79 * 166 *
@@ -102,18 +189,20 @@ struct cbe_iic_regs {
102 189
103 /* IIC interrupt registers */ 190 /* IIC interrupt registers */
104 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ 191 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
105 u64 iic_ir; /* 0x0440 */ 192
106 u64 iic_is; /* 0x0448 */ 193 u64 iic_ir; /* 0x0440 */
194 u64 iic_is; /* 0x0448 */
195#define CBE_IIC_IS_PMI 0x2
107 196
108 u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ 197 u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */
109 198
110 /* IOC FIR */ 199 /* IOC FIR */
111 u64 ioc_fir_reset; /* 0x0500 */ 200 u64 ioc_fir_reset; /* 0x0500 */
112 u64 ioc_fir_set; 201 u64 ioc_fir_set; /* 0x0508 */
113 u64 ioc_checkstop_enable; 202 u64 ioc_checkstop_enable; /* 0x0510 */
114 u64 ioc_fir_error_mask; 203 u64 ioc_fir_error_mask; /* 0x0518 */
115 u64 ioc_syserr_enable; 204 u64 ioc_syserr_enable; /* 0x0520 */
116 u64 ioc_fir; 205 u64 ioc_fir; /* 0x0528 */
117 206
118 u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ 207 u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */
119}; 208};
@@ -122,6 +211,48 @@ extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
122extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); 211extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
123 212
124 213
214struct cbe_mic_tm_regs {
215 u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */
216
217 u64 mic_ctl_cnfg2; /* 0x0040 */
218#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL
219#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL
220#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL
221#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL
222
223 u64 pad_0x0048; /* 0x0048 */
224
225 u64 mic_aux_trc_base; /* 0x0050 */
226 u64 mic_aux_trc_max_addr; /* 0x0058 */
227 u64 mic_aux_trc_cur_addr; /* 0x0060 */
228 u64 mic_aux_trc_grf_addr; /* 0x0068 */
229 u64 mic_aux_trc_grf_data; /* 0x0070 */
230
231 u64 pad_0x0078; /* 0x0078 */
232
233 u64 mic_ctl_cnfg_0; /* 0x0080 */
234#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL
235
236 u64 pad_0x0088; /* 0x0088 */
237
238 u64 slow_fast_timer_0; /* 0x0090 */
239 u64 slow_next_timer_0; /* 0x0098 */
240
241 u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */
242
243 u64 mic_ctl_cnfg_1; /* 0x01c0 */
244#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL
245 u64 pad_0x01c8; /* 0x01c8 */
246
247 u64 slow_fast_timer_1; /* 0x01d0 */
248 u64 slow_next_timer_1; /* 0x01d8 */
249
250 u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */
251};
252
253extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
254extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
255
125/* Init this module early */ 256/* Init this module early */
126extern void cbe_regs_init(void); 257extern void cbe_regs_init(void);
127 258
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
new file mode 100644
index 000000000000..17831a92d91e
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -0,0 +1,225 @@
1/*
2 * thermal support for the cell processor
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Christian Krafft <krafft@de.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/module.h>
24#include <linux/sysdev.h>
25#include <linux/kernel.h>
26#include <linux/cpu.h>
27#include <asm/spu.h>
28#include <asm/io.h>
29#include <asm/prom.h>
30
31#include "cbe_regs.h"
32
33static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
34{
35 struct spu *spu;
36
37 spu = container_of(sysdev, struct spu, sysdev);
38
39 return cbe_get_pmd_regs(spu->devnode);
40}
41
42/* returns the value for a given spu in a given register */
43static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg)
44{
45 unsigned int *id;
46 union spe_reg value;
47 struct spu *spu;
48
49 /* getting the id from the reg attribute will not work on future device-tree layouts
50 * in future we should store the id to the spu struct and use it here */
51 spu = container_of(sysdev, struct spu, sysdev);
52 id = (unsigned int *)get_property(spu->devnode, "reg", NULL);
53 value.val = in_be64(&reg->val);
54
55 return value.spe[*id];
56}
57
58static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
59{
60 int value;
61 struct cbe_pmd_regs __iomem *pmd_regs;
62
63 pmd_regs = get_pmd_regs(sysdev);
64
65 value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1);
66 /* clear all other bits */
67 value &= 0x3F;
68 /* temp is stored in steps of 2 degrees */
69 value *= 2;
70 /* base temp is 65 degrees */
71 value += 65;
72
73 return sprintf(buf, "%d\n", (int) value);
74}
75
76static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
77{
78 struct cbe_pmd_regs __iomem *pmd_regs;
79 u64 value;
80
81 pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
82 value = in_be64(&pmd_regs->ts_ctsr2);
83
84 /* access the corresponding byte */
85 value >>= pos;
86 /* clear all other bits */
87 value &= 0x3F;
88 /* temp is stored in steps of 2 degrees */
89 value *= 2;
90 /* base temp is 65 degrees */
91 value += 65;
92
93 return sprintf(buf, "%d\n", (int) value);
94}
95
96
97/* shows the temperature of the DTS on the PPE,
98 * located near the linear thermal sensor */
99static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf)
100{
101 return ppe_show_temp(sysdev, buf, 32);
102}
103
104/* shows the temperature of the second DTS on the PPE */
105static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf)
106{
107 return ppe_show_temp(sysdev, buf, 0);
108}
109
110static struct sysdev_attribute attr_spu_temperature = {
111 .attr = {.name = "temperature", .mode = 0400 },
112 .show = spu_show_temp,
113};
114
115static struct attribute *spu_attributes[] = {
116 &attr_spu_temperature.attr,
117};
118
119static struct attribute_group spu_attribute_group = {
120 .name = "thermal",
121 .attrs = spu_attributes,
122};
123
124static struct sysdev_attribute attr_ppe_temperature0 = {
125 .attr = {.name = "temperature0", .mode = 0400 },
126 .show = ppe_show_temp0,
127};
128
129static struct sysdev_attribute attr_ppe_temperature1 = {
130 .attr = {.name = "temperature1", .mode = 0400 },
131 .show = ppe_show_temp1,
132};
133
134static struct attribute *ppe_attributes[] = {
135 &attr_ppe_temperature0.attr,
136 &attr_ppe_temperature1.attr,
137};
138
139static struct attribute_group ppe_attribute_group = {
140 .name = "thermal",
141 .attrs = ppe_attributes,
142};
143
144/*
145 * initialize throttling with default values
146 */
147static void __init init_default_values(void)
148{
149 int cpu;
150 struct cbe_pmd_regs __iomem *pmd_regs;
151 struct sys_device *sysdev;
152 union ppe_spe_reg tpr;
153 union spe_reg str1;
154 u64 str2;
155 union spe_reg cr1;
156 u64 cr2;
157
158 /* TPR defaults */
159 /* ppe
160 * 1F - no full stop
161 * 08 - dynamic throttling starts if over 80 degrees
162 * 03 - dynamic throttling ceases if below 70 degrees */
163 tpr.ppe = 0x1F0803;
164 /* spe
165 * 10 - full stopped when over 96 degrees
166 * 08 - dynamic throttling starts if over 80 degrees
167 * 03 - dynamic throttling ceases if below 70 degrees
168 */
169 tpr.spe = 0x100803;
170
171 /* STR defaults */
172 /* str1
173 * 10 - stop 16 of 32 cycles
174 */
175 str1.val = 0x1010101010101010ull;
176 /* str2
177 * 10 - stop 16 of 32 cycles
178 */
179 str2 = 0x10;
180
181 /* CR defaults */
182 /* cr1
183 * 4 - normal operation
184 */
185 cr1.val = 0x0404040404040404ull;
186 /* cr2
187 * 4 - normal operation
188 */
189 cr2 = 0x04;
190
191 for_each_possible_cpu (cpu) {
192 pr_debug("processing cpu %d\n", cpu);
193 sysdev = get_cpu_sysdev(cpu);
194 pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
195
196 out_be64(&pmd_regs->tm_str2, str2);
197 out_be64(&pmd_regs->tm_str1.val, str1.val);
198 out_be64(&pmd_regs->tm_tpr.val, tpr.val);
199 out_be64(&pmd_regs->tm_cr1.val, cr1.val);
200 out_be64(&pmd_regs->tm_cr2, cr2);
201 }
202}
203
204
205static int __init thermal_init(void)
206{
207 init_default_values();
208
209 spu_add_sysdev_attr_group(&spu_attribute_group);
210 cpu_add_sysdev_attr_group(&ppe_attribute_group);
211
212 return 0;
213}
214module_init(thermal_init);
215
216static void __exit thermal_exit(void)
217{
218 spu_remove_sysdev_attr_group(&spu_attribute_group);
219 cpu_remove_sysdev_attr_group(&ppe_attribute_group);
220}
221module_exit(thermal_exit);
222
223MODULE_LICENSE("GPL");
224MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
225
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 9f2e4ed20a57..c68fabdc7874 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,32 +38,16 @@
38#include "pervasive.h" 38#include "pervasive.h"
39#include "cbe_regs.h" 39#include "cbe_regs.h"
40 40
41static DEFINE_SPINLOCK(cbe_pervasive_lock); 41static void cbe_power_save(void)
42
43static void __init cbe_enable_pause_zero(void)
44{ 42{
45 unsigned long thread_switch_control; 43 unsigned long ctrl, thread_switch_control;
46 unsigned long temp_register; 44 ctrl = mfspr(SPRN_CTRLF);
47 struct cbe_pmd_regs __iomem *pregs;
48
49 spin_lock_irq(&cbe_pervasive_lock);
50 pregs = cbe_get_cpu_pmd_regs(smp_processor_id());
51 if (pregs == NULL)
52 goto out;
53
54 pr_debug("Power Management: CPU %d\n", smp_processor_id());
55
56 /* Enable Pause(0) control bit */
57 temp_register = in_be64(&pregs->pm_control);
58
59 out_be64(&pregs->pm_control,
60 temp_register | CBE_PMD_PAUSE_ZERO_CONTROL);
61 45
62 /* Enable DEC and EE interrupt request */ 46 /* Enable DEC and EE interrupt request */
63 thread_switch_control = mfspr(SPRN_TSC_CELL); 47 thread_switch_control = mfspr(SPRN_TSC_CELL);
64 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; 48 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
65 49
66 switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { 50 switch (ctrl & CTRL_CT) {
67 case CTRL_CT0: 51 case CTRL_CT0:
68 thread_switch_control |= TSC_CELL_DEC_ENABLE_0; 52 thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
69 break; 53 break;
@@ -75,58 +59,21 @@ static void __init cbe_enable_pause_zero(void)
75 __FUNCTION__); 59 __FUNCTION__);
76 break; 60 break;
77 } 61 }
78
79 mtspr(SPRN_TSC_CELL, thread_switch_control); 62 mtspr(SPRN_TSC_CELL, thread_switch_control);
80 63
81out: 64 /*
82 spin_unlock_irq(&cbe_pervasive_lock); 65 * go into low thread priority, medium priority will be
83} 66 * restored for us after wake-up.
84
85static void cbe_idle(void)
86{
87 unsigned long ctrl;
88
89 /* Why do we do that on every idle ? Couldn't that be done once for
90 * all or do we lose the state some way ? Also, the pm_control
91 * register setting, that can't be set once at boot ? We really want
92 * to move that away in order to implement a simple powersave
93 */ 67 */
94 cbe_enable_pause_zero(); 68 HMT_low();
95
96 while (1) {
97 if (!need_resched()) {
98 local_irq_disable();
99 while (!need_resched()) {
100 /* go into low thread priority */
101 HMT_low();
102
103 /*
104 * atomically disable thread execution
105 * and runlatch.
106 * External and Decrementer exceptions
107 * are still handled when the thread
108 * is disabled but now enter in
109 * cbe_system_reset_exception()
110 */
111 ctrl = mfspr(SPRN_CTRLF);
112 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
113 mtspr(SPRN_CTRLT, ctrl);
114 }
115 /* restore thread prio */
116 HMT_medium();
117 local_irq_enable();
118 }
119 69
120 /* 70 /*
121 * turn runlatch on again before scheduling the 71 * atomically disable thread execution and runlatch.
122 * process we just woke up 72 * External and Decrementer exceptions are still handled when the
123 */ 73 * thread is disabled but now enter in cbe_system_reset_exception()
124 ppc64_runlatch_on(); 74 */
125 75 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
126 preempt_enable_no_resched(); 76 mtspr(SPRN_CTRLT, ctrl);
127 schedule();
128 preempt_disable();
129 }
130} 77}
131 78
132static int cbe_system_reset_exception(struct pt_regs *regs) 79static int cbe_system_reset_exception(struct pt_regs *regs)
@@ -158,9 +105,20 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
158 105
159void __init cbe_pervasive_init(void) 106void __init cbe_pervasive_init(void)
160{ 107{
108 int cpu;
161 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 109 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
162 return; 110 return;
163 111
164 ppc_md.idle_loop = cbe_idle; 112 for_each_possible_cpu(cpu) {
113 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
114 if (!regs)
115 continue;
116
117 /* Enable Pause(0) control bit */
118 out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
119 CBE_PMD_PAUSE_ZERO_CONTROL);
120 }
121
122 ppc_md.power_save = cbe_power_save;
165 ppc_md.system_reset_exception = cbe_system_reset_exception; 123 ppc_md.system_reset_exception = cbe_system_reset_exception;
166} 124}
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
new file mode 100644
index 000000000000..30d17ce236a7
--- /dev/null
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -0,0 +1,328 @@
1/*
2 * Cell Broadband Engine Performance Monitor
3 *
4 * (C) Copyright IBM Corporation 2001,2006
5 *
6 * Author:
7 * David Erb (djerb@us.ibm.com)
8 * Kevin Corry (kevcorry@us.ibm.com)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/types.h>
26#include <asm/io.h>
27#include <asm/machdep.h>
28#include <asm/reg.h>
29#include <asm/spu.h>
30
31#include "cbe_regs.h"
32#include "interrupt.h"
33#include "pmu.h"
34
35/*
36 * When writing to write-only mmio addresses, save a shadow copy. All of the
37 * registers are 32-bit, but stored in the upper-half of a 64-bit field in
38 * pmd_regs.
39 */
40
41#define WRITE_WO_MMIO(reg, x) \
42 do { \
43 u32 _x = (x); \
44 struct cbe_pmd_regs __iomem *pmd_regs; \
45 struct cbe_pmd_shadow_regs *shadow_regs; \
46 pmd_regs = cbe_get_cpu_pmd_regs(cpu); \
47 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
48 out_be64(&(pmd_regs->reg), (((u64)_x) << 32)); \
49 shadow_regs->reg = _x; \
50 } while (0)
51
52#define READ_SHADOW_REG(val, reg) \
53 do { \
54 struct cbe_pmd_shadow_regs *shadow_regs; \
55 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
56 (val) = shadow_regs->reg; \
57 } while (0)
58
59#define READ_MMIO_UPPER32(val, reg) \
60 do { \
61 struct cbe_pmd_regs __iomem *pmd_regs; \
62 pmd_regs = cbe_get_cpu_pmd_regs(cpu); \
63 (val) = (u32)(in_be64(&pmd_regs->reg) >> 32); \
64 } while (0)
65
66/*
67 * Physical counter registers.
68 * Each physical counter can act as one 32-bit counter or two 16-bit counters.
69 */
70
71u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr)
72{
73 u32 val_in_latch, val = 0;
74
75 if (phys_ctr < NR_PHYS_CTRS) {
76 READ_SHADOW_REG(val_in_latch, counter_value_in_latch);
77
78 /* Read the latch or the actual counter, whichever is newer. */
79 if (val_in_latch & (1 << phys_ctr)) {
80 READ_SHADOW_REG(val, pm_ctr[phys_ctr]);
81 } else {
82 READ_MMIO_UPPER32(val, pm_ctr[phys_ctr]);
83 }
84 }
85
86 return val;
87}
88
89void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
90{
91 struct cbe_pmd_shadow_regs *shadow_regs;
92 u32 pm_ctrl;
93
94 if (phys_ctr < NR_PHYS_CTRS) {
95 /* Writing to a counter only writes to a hardware latch.
96 * The new value is not propagated to the actual counter
97 * until the performance monitor is enabled.
98 */
99 WRITE_WO_MMIO(pm_ctr[phys_ctr], val);
100
101 pm_ctrl = cbe_read_pm(cpu, pm_control);
102 if (pm_ctrl & CBE_PM_ENABLE_PERF_MON) {
103 /* The counters are already active, so we need to
104 * rewrite the pm_control register to "re-enable"
105 * the PMU.
106 */
107 cbe_write_pm(cpu, pm_control, pm_ctrl);
108 } else {
109 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
110 shadow_regs->counter_value_in_latch |= (1 << phys_ctr);
111 }
112 }
113}
114
115/*
116 * "Logical" counter registers.
117 * These will read/write 16-bits or 32-bits depending on the
118 * current size of the counter. Counters 4 - 7 are always 16-bit.
119 */
120
121u32 cbe_read_ctr(u32 cpu, u32 ctr)
122{
123 u32 val;
124 u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
125
126 val = cbe_read_phys_ctr(cpu, phys_ctr);
127
128 if (cbe_get_ctr_size(cpu, phys_ctr) == 16)
129 val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
130
131 return val;
132}
133
134void cbe_write_ctr(u32 cpu, u32 ctr, u32 val)
135{
136 u32 phys_ctr;
137 u32 phys_val;
138
139 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
140
141 if (cbe_get_ctr_size(cpu, phys_ctr) == 16) {
142 phys_val = cbe_read_phys_ctr(cpu, phys_ctr);
143
144 if (ctr < NR_PHYS_CTRS)
145 val = (val << 16) | (phys_val & 0xffff);
146 else
147 val = (val & 0xffff) | (phys_val & 0xffff0000);
148 }
149
150 cbe_write_phys_ctr(cpu, phys_ctr, val);
151}
152
153/*
154 * Counter-control registers.
155 * Each "logical" counter has a corresponding control register.
156 */
157
158u32 cbe_read_pm07_control(u32 cpu, u32 ctr)
159{
160 u32 pm07_control = 0;
161
162 if (ctr < NR_CTRS)
163 READ_SHADOW_REG(pm07_control, pm07_control[ctr]);
164
165 return pm07_control;
166}
167
168void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val)
169{
170 if (ctr < NR_CTRS)
171 WRITE_WO_MMIO(pm07_control[ctr], val);
172}
173
174/*
175 * Other PMU control registers. Most of these are write-only.
176 */
177
178u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg)
179{
180 u32 val = 0;
181
182 switch (reg) {
183 case group_control:
184 READ_SHADOW_REG(val, group_control);
185 break;
186
187 case debug_bus_control:
188 READ_SHADOW_REG(val, debug_bus_control);
189 break;
190
191 case trace_address:
192 READ_MMIO_UPPER32(val, trace_address);
193 break;
194
195 case ext_tr_timer:
196 READ_SHADOW_REG(val, ext_tr_timer);
197 break;
198
199 case pm_status:
200 READ_MMIO_UPPER32(val, pm_status);
201 break;
202
203 case pm_control:
204 READ_SHADOW_REG(val, pm_control);
205 break;
206
207 case pm_interval:
208 READ_SHADOW_REG(val, pm_interval);
209 break;
210
211 case pm_start_stop:
212 READ_SHADOW_REG(val, pm_start_stop);
213 break;
214 }
215
216 return val;
217}
218
219void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
220{
221 switch (reg) {
222 case group_control:
223 WRITE_WO_MMIO(group_control, val);
224 break;
225
226 case debug_bus_control:
227 WRITE_WO_MMIO(debug_bus_control, val);
228 break;
229
230 case trace_address:
231 WRITE_WO_MMIO(trace_address, val);
232 break;
233
234 case ext_tr_timer:
235 WRITE_WO_MMIO(ext_tr_timer, val);
236 break;
237
238 case pm_status:
239 WRITE_WO_MMIO(pm_status, val);
240 break;
241
242 case pm_control:
243 WRITE_WO_MMIO(pm_control, val);
244 break;
245
246 case pm_interval:
247 WRITE_WO_MMIO(pm_interval, val);
248 break;
249
250 case pm_start_stop:
251 WRITE_WO_MMIO(pm_start_stop, val);
252 break;
253 }
254}
255
256/*
257 * Get/set the size of a physical counter to either 16 or 32 bits.
258 */
259
260u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr)
261{
262 u32 pm_ctrl, size = 0;
263
264 if (phys_ctr < NR_PHYS_CTRS) {
265 pm_ctrl = cbe_read_pm(cpu, pm_control);
266 size = (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
267 }
268
269 return size;
270}
271
272void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
273{
274 u32 pm_ctrl;
275
276 if (phys_ctr < NR_PHYS_CTRS) {
277 pm_ctrl = cbe_read_pm(cpu, pm_control);
278 switch (ctr_size) {
279 case 16:
280 pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
281 break;
282
283 case 32:
284 pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
285 break;
286 }
287 cbe_write_pm(cpu, pm_control, pm_ctrl);
288 }
289}
290
291/*
292 * Enable/disable the entire performance monitoring unit.
293 * When we enable the PMU, all pending writes to counters get committed.
294 */
295
296void cbe_enable_pm(u32 cpu)
297{
298 struct cbe_pmd_shadow_regs *shadow_regs;
299 u32 pm_ctrl;
300
301 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
302 shadow_regs->counter_value_in_latch = 0;
303
304 pm_ctrl = cbe_read_pm(cpu, pm_control) | CBE_PM_ENABLE_PERF_MON;
305 cbe_write_pm(cpu, pm_control, pm_ctrl);
306}
307
308void cbe_disable_pm(u32 cpu)
309{
310 u32 pm_ctrl;
311 pm_ctrl = cbe_read_pm(cpu, pm_control) & ~CBE_PM_ENABLE_PERF_MON;
312 cbe_write_pm(cpu, pm_control, pm_ctrl);
313}
314
315/*
316 * Reading from the trace_buffer.
317 * The trace buffer is two 64-bit registers. Reading from
318 * the second half automatically increments the trace_address.
319 */
320
321void cbe_read_trace_buffer(u32 cpu, u64 *buf)
322{
323 struct cbe_pmd_regs __iomem *pmd_regs = cbe_get_cpu_pmd_regs(cpu);
324
325 *buf++ = in_be64(&pmd_regs->trace_buffer_0_63);
326 *buf++ = in_be64(&pmd_regs->trace_buffer_64_127);
327}
328
diff --git a/arch/powerpc/platforms/cell/pmu.h b/arch/powerpc/platforms/cell/pmu.h
new file mode 100644
index 000000000000..eb1e8e0af910
--- /dev/null
+++ b/arch/powerpc/platforms/cell/pmu.h
@@ -0,0 +1,57 @@
1/*
2 * Cell Broadband Engine Performance Monitor
3 *
4 * (C) Copyright IBM Corporation 2001,2006
5 *
6 * Author:
7 * David Erb (djerb@us.ibm.com)
8 * Kevin Corry (kevcorry@us.ibm.com)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#ifndef __PERFMON_H__
26#define __PERFMON_H__
27
28enum pm_reg_name {
29 group_control,
30 debug_bus_control,
31 trace_address,
32 ext_tr_timer,
33 pm_status,
34 pm_control,
35 pm_interval,
36 pm_start_stop,
37};
38
39extern u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr);
40extern void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val);
41extern u32 cbe_read_ctr(u32 cpu, u32 ctr);
42extern void cbe_write_ctr(u32 cpu, u32 ctr, u32 val);
43
44extern u32 cbe_read_pm07_control(u32 cpu, u32 ctr);
45extern void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val);
46extern u32 cbe_read_pm (u32 cpu, enum pm_reg_name reg);
47extern void cbe_write_pm (u32 cpu, enum pm_reg_name reg, u32 val);
48
49extern u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr);
50extern void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size);
51
52extern void cbe_enable_pm(u32 cpu);
53extern void cbe_disable_pm(u32 cpu);
54
55extern void cbe_read_trace_buffer(u32 cpu, u64 *buf);
56
57#endif
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 7aa809d5a244..d5aeb3c6dd45 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -38,6 +38,7 @@
38#include <asm/spu.h> 38#include <asm/spu.h>
39#include <asm/spu_priv1.h> 39#include <asm/spu_priv1.h>
40#include <asm/mmu_context.h> 40#include <asm/mmu_context.h>
41#include <asm/xmon.h>
41 42
42#include "interrupt.h" 43#include "interrupt.h"
43 44
@@ -89,7 +90,30 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
89 printk("%s: invalid access during switch!\n", __func__); 90 printk("%s: invalid access during switch!\n", __func__);
90 return 1; 91 return 1;
91 } 92 }
92 if (!mm || (REGION_ID(ea) != USER_REGION_ID)) { 93 esid = (ea & ESID_MASK) | SLB_ESID_V;
94
95 switch(REGION_ID(ea)) {
96 case USER_REGION_ID:
97#ifdef CONFIG_HUGETLB_PAGE
98 if (in_hugepage_area(mm->context, ea))
99 llp = mmu_psize_defs[mmu_huge_psize].sllp;
100 else
101#endif
102 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
103 vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
104 SLB_VSID_USER | llp;
105 break;
106 case VMALLOC_REGION_ID:
107 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
108 vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
109 SLB_VSID_KERNEL | llp;
110 break;
111 case KERNEL_REGION_ID:
112 llp = mmu_psize_defs[mmu_linear_psize].sllp;
113 vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
114 SLB_VSID_KERNEL | llp;
115 break;
116 default:
93 /* Future: support kernel segments so that drivers 117 /* Future: support kernel segments so that drivers
94 * can use SPUs. 118 * can use SPUs.
95 */ 119 */
@@ -97,16 +121,6 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
97 return 1; 121 return 1;
98 } 122 }
99 123
100 esid = (ea & ESID_MASK) | SLB_ESID_V;
101#ifdef CONFIG_HUGETLB_PAGE
102 if (in_hugepage_area(mm->context, ea))
103 llp = mmu_psize_defs[mmu_huge_psize].sllp;
104 else
105#endif
106 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
107 vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
108 SLB_VSID_USER | llp;
109
110 out_be64(&priv2->slb_index_W, spu->slb_replace); 124 out_be64(&priv2->slb_index_W, spu->slb_replace);
111 out_be64(&priv2->slb_vsid_RW, vsid); 125 out_be64(&priv2->slb_vsid_RW, vsid);
112 out_be64(&priv2->slb_esid_RW, esid); 126 out_be64(&priv2->slb_esid_RW, esid);
@@ -320,6 +334,7 @@ static void spu_free_irqs(struct spu *spu)
320} 334}
321 335
322static struct list_head spu_list[MAX_NUMNODES]; 336static struct list_head spu_list[MAX_NUMNODES];
337static LIST_HEAD(spu_full_list);
323static DEFINE_MUTEX(spu_mutex); 338static DEFINE_MUTEX(spu_mutex);
324 339
325static void spu_init_channels(struct spu *spu) 340static void spu_init_channels(struct spu *spu)
@@ -364,8 +379,7 @@ struct spu *spu_alloc_node(int node)
364 if (!list_empty(&spu_list[node])) { 379 if (!list_empty(&spu_list[node])) {
365 spu = list_entry(spu_list[node].next, struct spu, list); 380 spu = list_entry(spu_list[node].next, struct spu, list);
366 list_del_init(&spu->list); 381 list_del_init(&spu->list);
367 pr_debug("Got SPU %x %d %d\n", 382 pr_debug("Got SPU %d %d\n", spu->number, spu->node);
368 spu->isrc, spu->number, spu->node);
369 spu_init_channels(spu); 383 spu_init_channels(spu);
370 } 384 }
371 mutex_unlock(&spu_mutex); 385 mutex_unlock(&spu_mutex);
@@ -591,7 +605,6 @@ static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np
591 605
592 /* Add the node number */ 606 /* Add the node number */
593 isrc |= spu->node << IIC_IRQ_NODE_SHIFT; 607 isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
594 spu->isrc = isrc;
595 608
596 /* Now map interrupts of all 3 classes */ 609 /* Now map interrupts of all 3 classes */
597 spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); 610 spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
@@ -758,15 +771,56 @@ struct sysdev_class spu_sysdev_class = {
758 set_kset_name("spu") 771 set_kset_name("spu")
759}; 772};
760 773
761static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) 774int spu_add_sysdev_attr(struct sysdev_attribute *attr)
762{ 775{
763 struct spu *spu = container_of(sysdev, struct spu, sysdev); 776 struct spu *spu;
764 return sprintf(buf, "%d\n", spu->isrc); 777 mutex_lock(&spu_mutex);
778
779 list_for_each_entry(spu, &spu_full_list, full_list)
780 sysdev_create_file(&spu->sysdev, attr);
765 781
782 mutex_unlock(&spu_mutex);
783 return 0;
766} 784}
767static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); 785EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
786
787int spu_add_sysdev_attr_group(struct attribute_group *attrs)
788{
789 struct spu *spu;
790 mutex_lock(&spu_mutex);
768 791
769extern int attach_sysdev_to_node(struct sys_device *dev, int nid); 792 list_for_each_entry(spu, &spu_full_list, full_list)
793 sysfs_create_group(&spu->sysdev.kobj, attrs);
794
795 mutex_unlock(&spu_mutex);
796 return 0;
797}
798EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
799
800
801void spu_remove_sysdev_attr(struct sysdev_attribute *attr)
802{
803 struct spu *spu;
804 mutex_lock(&spu_mutex);
805
806 list_for_each_entry(spu, &spu_full_list, full_list)
807 sysdev_remove_file(&spu->sysdev, attr);
808
809 mutex_unlock(&spu_mutex);
810}
811EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);
812
813void spu_remove_sysdev_attr_group(struct attribute_group *attrs)
814{
815 struct spu *spu;
816 mutex_lock(&spu_mutex);
817
818 list_for_each_entry(spu, &spu_full_list, full_list)
819 sysfs_remove_group(&spu->sysdev.kobj, attrs);
820
821 mutex_unlock(&spu_mutex);
822}
823EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);
770 824
771static int spu_create_sysdev(struct spu *spu) 825static int spu_create_sysdev(struct spu *spu)
772{ 826{
@@ -781,8 +835,6 @@ static int spu_create_sysdev(struct spu *spu)
781 return ret; 835 return ret;
782 } 836 }
783 837
784 if (spu->isrc != 0)
785 sysdev_create_file(&spu->sysdev, &attr_isrc);
786 sysfs_add_device_to_node(&spu->sysdev, spu->nid); 838 sysfs_add_device_to_node(&spu->sysdev, spu->nid);
787 839
788 return 0; 840 return 0;
@@ -790,7 +842,6 @@ static int spu_create_sysdev(struct spu *spu)
790 842
791static void spu_destroy_sysdev(struct spu *spu) 843static void spu_destroy_sysdev(struct spu *spu)
792{ 844{
793 sysdev_remove_file(&spu->sysdev, &attr_isrc);
794 sysfs_remove_device_from_node(&spu->sysdev, spu->nid); 845 sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
795 sysdev_unregister(&spu->sysdev); 846 sysdev_unregister(&spu->sysdev);
796} 847}
@@ -830,7 +881,7 @@ static int __init create_spu(struct device_node *spe)
830 if (ret) 881 if (ret)
831 goto out_unmap; 882 goto out_unmap;
832 spin_lock_init(&spu->register_lock); 883 spin_lock_init(&spu->register_lock);
833 spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); 884 spu_mfc_sdr_setup(spu);
834 spu_mfc_sr1_set(spu, 0x33); 885 spu_mfc_sr1_set(spu, 0x33);
835 mutex_lock(&spu_mutex); 886 mutex_lock(&spu_mutex);
836 887
@@ -844,10 +895,13 @@ static int __init create_spu(struct device_node *spe)
844 goto out_free_irqs; 895 goto out_free_irqs;
845 896
846 list_add(&spu->list, &spu_list[spu->node]); 897 list_add(&spu->list, &spu_list[spu->node]);
898 list_add(&spu->full_list, &spu_full_list);
899 spu->devnode = of_node_get(spe);
900
847 mutex_unlock(&spu_mutex); 901 mutex_unlock(&spu_mutex);
848 902
849 pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", 903 pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n",
850 spu->name, spu->isrc, spu->local_store, 904 spu->name, spu->local_store,
851 spu->problem, spu->priv1, spu->priv2, spu->number); 905 spu->problem, spu->priv1, spu->priv2, spu->number);
852 goto out; 906 goto out;
853 907
@@ -866,6 +920,9 @@ out:
866static void destroy_spu(struct spu *spu) 920static void destroy_spu(struct spu *spu)
867{ 921{
868 list_del_init(&spu->list); 922 list_del_init(&spu->list);
923 list_del_init(&spu->full_list);
924
925 of_node_put(spu->devnode);
869 926
870 spu_destroy_sysdev(spu); 927 spu_destroy_sysdev(spu);
871 spu_free_irqs(spu); 928 spu_free_irqs(spu);
@@ -912,6 +969,9 @@ static int __init init_spu_base(void)
912 break; 969 break;
913 } 970 }
914 } 971 }
972
973 xmon_register_spus(&spu_full_list);
974
915 return ret; 975 return ret;
916} 976}
917module_init(init_spu_base); 977module_init(init_spu_base);
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
index 71b69f0a1a48..90011f9aab3f 100644
--- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
@@ -84,9 +84,9 @@ static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
84 out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); 84 out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
85} 85}
86 86
87static void mfc_sdr_set(struct spu *spu, u64 sdr) 87static void mfc_sdr_setup(struct spu *spu)
88{ 88{
89 out_be64(&spu->priv1->mfc_sdr_RW, sdr); 89 out_be64(&spu->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1));
90} 90}
91 91
92static void mfc_sr1_set(struct spu *spu, u64 sr1) 92static void mfc_sr1_set(struct spu *spu, u64 sr1)
@@ -146,7 +146,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops =
146 .mfc_dar_get = mfc_dar_get, 146 .mfc_dar_get = mfc_dar_get,
147 .mfc_dsisr_get = mfc_dsisr_get, 147 .mfc_dsisr_get = mfc_dsisr_get,
148 .mfc_dsisr_set = mfc_dsisr_set, 148 .mfc_dsisr_set = mfc_dsisr_set,
149 .mfc_sdr_set = mfc_sdr_set, 149 .mfc_sdr_setup = mfc_sdr_setup,
150 .mfc_sr1_set = mfc_sr1_set, 150 .mfc_sr1_set = mfc_sr1_set,
151 .mfc_sr1_get = mfc_sr1_get, 151 .mfc_sr1_get = mfc_sr1_get,
152 .mfc_tclass_id_set = mfc_tclass_id_set, 152 .mfc_tclass_id_set = mfc_tclass_id_set,
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 034cf6af53a2..48eb050bcf4b 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -120,6 +120,33 @@ void spu_unmap_mappings(struct spu_context *ctx)
120 unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); 120 unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
121} 121}
122 122
123int spu_acquire_exclusive(struct spu_context *ctx)
124{
125 int ret = 0;
126
127 down_write(&ctx->state_sema);
128 /* ctx is about to be freed, can't acquire any more */
129 if (!ctx->owner) {
130 ret = -EINVAL;
131 goto out;
132 }
133
134 if (ctx->state == SPU_STATE_SAVED) {
135 ret = spu_activate(ctx, 0);
136 if (ret)
137 goto out;
138 ctx->state = SPU_STATE_RUNNABLE;
139 } else {
140 /* We need to exclude userspace access to the context. */
141 spu_unmap_mappings(ctx);
142 }
143
144out:
145 if (ret)
146 up_write(&ctx->state_sema);
147 return ret;
148}
149
123int spu_acquire_runnable(struct spu_context *ctx) 150int spu_acquire_runnable(struct spu_context *ctx)
124{ 151{
125 int ret = 0; 152 int ret = 0;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 533e2723e184..0ea2361865a2 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1343,6 +1343,37 @@ static struct file_operations spufs_mfc_fops = {
1343 .mmap = spufs_mfc_mmap, 1343 .mmap = spufs_mfc_mmap,
1344}; 1344};
1345 1345
1346
1347static int spufs_recycle_open(struct inode *inode, struct file *file)
1348{
1349 file->private_data = SPUFS_I(inode)->i_ctx;
1350 return nonseekable_open(inode, file);
1351}
1352
1353static ssize_t spufs_recycle_write(struct file *file,
1354 const char __user *buffer, size_t size, loff_t *pos)
1355{
1356 struct spu_context *ctx = file->private_data;
1357 int ret;
1358
1359 if (!(ctx->flags & SPU_CREATE_ISOLATE))
1360 return -EINVAL;
1361
1362 if (size < 1)
1363 return -EINVAL;
1364
1365 ret = spu_recycle_isolated(ctx);
1366
1367 if (ret)
1368 return ret;
1369 return size;
1370}
1371
1372static struct file_operations spufs_recycle_fops = {
1373 .open = spufs_recycle_open,
1374 .write = spufs_recycle_write,
1375};
1376
1346static void spufs_npc_set(void *data, u64 val) 1377static void spufs_npc_set(void *data, u64 val)
1347{ 1378{
1348 struct spu_context *ctx = data; 1379 struct spu_context *ctx = data;
@@ -1531,3 +1562,26 @@ struct tree_descr spufs_dir_contents[] = {
1531 { "object-id", &spufs_object_id_ops, 0666, }, 1562 { "object-id", &spufs_object_id_ops, 0666, },
1532 {}, 1563 {},
1533}; 1564};
1565
1566struct tree_descr spufs_dir_nosched_contents[] = {
1567 { "mem", &spufs_mem_fops, 0666, },
1568 { "mbox", &spufs_mbox_fops, 0444, },
1569 { "ibox", &spufs_ibox_fops, 0444, },
1570 { "wbox", &spufs_wbox_fops, 0222, },
1571 { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
1572 { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
1573 { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
1574 { "signal1", &spufs_signal1_fops, 0666, },
1575 { "signal2", &spufs_signal2_fops, 0666, },
1576 { "signal1_type", &spufs_signal1_type, 0666, },
1577 { "signal2_type", &spufs_signal2_type, 0666, },
1578 { "mss", &spufs_mss_fops, 0666, },
1579 { "mfc", &spufs_mfc_fops, 0666, },
1580 { "cntl", &spufs_cntl_fops, 0666, },
1581 { "npc", &spufs_npc_ops, 0666, },
1582 { "psmap", &spufs_psmap_fops, 0666, },
1583 { "phys-id", &spufs_id_ops, 0666, },
1584 { "object-id", &spufs_object_id_ops, 0666, },
1585 { "recycle", &spufs_recycle_fops, 0222, },
1586 {},
1587};
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index d805ffed892d..59c87f12da5a 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -219,8 +219,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx)
219 219
220static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) 220static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
221{ 221{
222 eieio(); 222 spin_lock_irq(&ctx->spu->register_lock);
223 if (val & SPU_RUNCNTL_ISOLATE)
224 out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL);
223 out_be32(&ctx->spu->problem->spu_runcntl_RW, val); 225 out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
226 spin_unlock_irq(&ctx->spu->register_lock);
224} 227}
225 228
226static void spu_hw_runcntl_stop(struct spu_context *ctx) 229static void spu_hw_runcntl_stop(struct spu_context *ctx)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 427d00a4f6a0..9e457be140ef 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -33,6 +33,8 @@
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/parser.h> 34#include <linux/parser.h>
35 35
36#include <asm/prom.h>
37#include <asm/spu_priv1.h>
36#include <asm/io.h> 38#include <asm/io.h>
37#include <asm/semaphore.h> 39#include <asm/semaphore.h>
38#include <asm/spu.h> 40#include <asm/spu.h>
@@ -41,6 +43,7 @@
41#include "spufs.h" 43#include "spufs.h"
42 44
43static kmem_cache_t *spufs_inode_cache; 45static kmem_cache_t *spufs_inode_cache;
46static char *isolated_loader;
44 47
45static struct inode * 48static struct inode *
46spufs_alloc_inode(struct super_block *sb) 49spufs_alloc_inode(struct super_block *sb)
@@ -232,6 +235,95 @@ struct file_operations spufs_context_fops = {
232 .fsync = simple_sync_file, 235 .fsync = simple_sync_file,
233}; 236};
234 237
238static int spu_setup_isolated(struct spu_context *ctx)
239{
240 int ret;
241 u64 __iomem *mfc_cntl;
242 u64 sr1;
243 u32 status;
244 unsigned long timeout;
245 const u32 status_loading = SPU_STATUS_RUNNING
246 | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
247
248 if (!isolated_loader)
249 return -ENODEV;
250
251 if ((ret = spu_acquire_exclusive(ctx)) != 0)
252 return ret;
253
254 mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
255
256 /* purge the MFC DMA queue to ensure no spurious accesses before we
257 * enter kernel mode */
258 timeout = jiffies + HZ;
259 out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
260 while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
261 != MFC_CNTL_PURGE_DMA_COMPLETE) {
262 if (time_after(jiffies, timeout)) {
263 printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
264 __FUNCTION__);
265 ret = -EIO;
266 goto out_unlock;
267 }
268 cond_resched();
269 }
270
271 /* put the SPE in kernel mode to allow access to the loader */
272 sr1 = spu_mfc_sr1_get(ctx->spu);
273 sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
274 spu_mfc_sr1_set(ctx->spu, sr1);
275
276 /* start the loader */
277 ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
278 ctx->ops->signal2_write(ctx,
279 (unsigned long)isolated_loader & 0xffffffff);
280
281 ctx->ops->runcntl_write(ctx,
282 SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
283
284 ret = 0;
285 timeout = jiffies + HZ;
286 while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
287 status_loading) {
288 if (time_after(jiffies, timeout)) {
289 printk(KERN_ERR "%s: timeout waiting for loader\n",
290 __FUNCTION__);
291 ret = -EIO;
292 goto out_drop_priv;
293 }
294 cond_resched();
295 }
296
297 if (!(status & SPU_STATUS_RUNNING)) {
298 /* If isolated LOAD has failed: run SPU, we will get a stop-and
299 * signal later. */
300 pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
301 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
302 ret = -EACCES;
303
304 } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
305 /* This isn't allowed by the CBEA, but check anyway */
306 pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
307 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
308 ret = -EINVAL;
309 }
310
311out_drop_priv:
312 /* Finished accessing the loader. Drop kernel mode */
313 sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
314 spu_mfc_sr1_set(ctx->spu, sr1);
315
316out_unlock:
317 spu_release_exclusive(ctx);
318 return ret;
319}
320
321int spu_recycle_isolated(struct spu_context *ctx)
322{
323 ctx->ops->runcntl_stop(ctx);
324 return spu_setup_isolated(ctx);
325}
326
235static int 327static int
236spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, 328spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
237 int mode) 329 int mode)
@@ -255,10 +347,14 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
255 goto out_iput; 347 goto out_iput;
256 348
257 ctx->flags = flags; 349 ctx->flags = flags;
258
259 inode->i_op = &spufs_dir_inode_operations; 350 inode->i_op = &spufs_dir_inode_operations;
260 inode->i_fop = &simple_dir_operations; 351 inode->i_fop = &simple_dir_operations;
261 ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); 352 if (flags & SPU_CREATE_NOSCHED)
353 ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
354 mode, ctx);
355 else
356 ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
357
262 if (ret) 358 if (ret)
263 goto out_free_ctx; 359 goto out_free_ctx;
264 360
@@ -307,6 +403,16 @@ static int spufs_create_context(struct inode *inode,
307{ 403{
308 int ret; 404 int ret;
309 405
406 ret = -EPERM;
407 if ((flags & SPU_CREATE_NOSCHED) &&
408 !capable(CAP_SYS_NICE))
409 goto out_unlock;
410
411 ret = -EINVAL;
412 if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
413 == SPU_CREATE_ISOLATE)
414 goto out_unlock;
415
310 ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); 416 ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
311 if (ret) 417 if (ret)
312 goto out_unlock; 418 goto out_unlock;
@@ -326,6 +432,13 @@ static int spufs_create_context(struct inode *inode,
326out_unlock: 432out_unlock:
327 mutex_unlock(&inode->i_mutex); 433 mutex_unlock(&inode->i_mutex);
328out: 434out:
435 if (ret >= 0 && (flags & SPU_CREATE_ISOLATE)) {
436 int setup_err = spu_setup_isolated(
437 SPUFS_I(dentry->d_inode)->i_ctx);
438 if (setup_err)
439 ret = setup_err;
440 }
441
329 dput(dentry); 442 dput(dentry);
330 return ret; 443 return ret;
331} 444}
@@ -540,6 +653,30 @@ spufs_parse_options(char *options, struct inode *root)
540 return 1; 653 return 1;
541} 654}
542 655
656static void
657spufs_init_isolated_loader(void)
658{
659 struct device_node *dn;
660 const char *loader;
661 int size;
662
663 dn = of_find_node_by_path("/spu-isolation");
664 if (!dn)
665 return;
666
667 loader = get_property(dn, "loader", &size);
668 if (!loader)
669 return;
670
671 /* kmalloc should align on a 16 byte boundary..* */
672 isolated_loader = kmalloc(size, GFP_KERNEL);
673 if (!isolated_loader)
674 return;
675
676 memcpy(isolated_loader, loader, size);
677 printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
678}
679
543static int 680static int
544spufs_create_root(struct super_block *sb, void *data) 681spufs_create_root(struct super_block *sb, void *data)
545{ 682{
@@ -625,6 +762,8 @@ static int __init spufs_init(void)
625 ret = register_spu_syscalls(&spufs_calls); 762 ret = register_spu_syscalls(&spufs_calls);
626 if (ret) 763 if (ret)
627 goto out_fs; 764 goto out_fs;
765
766 spufs_init_isolated_loader();
628 return 0; 767 return 0;
629out_fs: 768out_fs:
630 unregister_filesystem(&spufs_type); 769 unregister_filesystem(&spufs_type);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 63df8cf4ba16..a4a0080c2233 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -1,3 +1,5 @@
1#define DEBUG
2
1#include <linux/wait.h> 3#include <linux/wait.h>
2#include <linux/ptrace.h> 4#include <linux/ptrace.h>
3 5
@@ -51,11 +53,17 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
51static inline int spu_run_init(struct spu_context *ctx, u32 * npc) 53static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
52{ 54{
53 int ret; 55 int ret;
56 unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
54 57
55 if ((ret = spu_acquire_runnable(ctx)) != 0) 58 if ((ret = spu_acquire_runnable(ctx)) != 0)
56 return ret; 59 return ret;
57 ctx->ops->npc_write(ctx, *npc); 60
58 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); 61 /* if we're in isolated mode, we would have started the SPU
62 * earlier, so don't do it again now. */
63 if (!(ctx->flags & SPU_CREATE_ISOLATE)) {
64 ctx->ops->npc_write(ctx, *npc);
65 ctx->ops->runcntl_write(ctx, runcntl);
66 }
59 return 0; 67 return 0;
60} 68}
61 69
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index a0f55ca2d488..f438f0b8525d 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -135,6 +135,7 @@ struct spufs_inode_info {
135 container_of(inode, struct spufs_inode_info, vfs_inode) 135 container_of(inode, struct spufs_inode_info, vfs_inode)
136 136
137extern struct tree_descr spufs_dir_contents[]; 137extern struct tree_descr spufs_dir_contents[];
138extern struct tree_descr spufs_dir_nosched_contents[];
138 139
139/* system call implementation */ 140/* system call implementation */
140long spufs_run_spu(struct file *file, 141long spufs_run_spu(struct file *file,
@@ -162,6 +163,12 @@ void spu_acquire(struct spu_context *ctx);
162void spu_release(struct spu_context *ctx); 163void spu_release(struct spu_context *ctx);
163int spu_acquire_runnable(struct spu_context *ctx); 164int spu_acquire_runnable(struct spu_context *ctx);
164void spu_acquire_saved(struct spu_context *ctx); 165void spu_acquire_saved(struct spu_context *ctx);
166int spu_acquire_exclusive(struct spu_context *ctx);
167
168static inline void spu_release_exclusive(struct spu_context *ctx)
169{
170 up_write(&ctx->state_sema);
171}
165 172
166int spu_activate(struct spu_context *ctx, u64 flags); 173int spu_activate(struct spu_context *ctx, u64 flags);
167void spu_deactivate(struct spu_context *ctx); 174void spu_deactivate(struct spu_context *ctx);
@@ -169,6 +176,7 @@ void spu_yield(struct spu_context *ctx);
169int __init spu_sched_init(void); 176int __init spu_sched_init(void);
170void __exit spu_sched_exit(void); 177void __exit spu_sched_exit(void);
171 178
179int spu_recycle_isolated(struct spu_context *ctx);
172/* 180/*
173 * spufs_wait 181 * spufs_wait
174 * Same as wait_event_interruptible(), except that here 182 * Same as wait_event_interruptible(), except that here
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 0f782ca662ba..c08981ff7fc6 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu)
102 * saved at this time. 102 * saved at this time.
103 */ 103 */
104 isolate_state = SPU_STATUS_ISOLATED_STATE | 104 isolate_state = SPU_STATUS_ISOLATED_STATE |
105 SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS; 105 SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS;
106 return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; 106 return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0;
107} 107}
108 108
@@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu)
1046 */ 1046 */
1047 if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { 1047 if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) {
1048 if (in_be32(&prob->spu_status_R) & 1048 if (in_be32(&prob->spu_status_R) &
1049 SPU_STATUS_ISOLATED_EXIT_STAUTUS) { 1049 SPU_STATUS_ISOLATED_EXIT_STATUS) {
1050 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & 1050 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
1051 SPU_STATUS_RUNNING); 1051 SPU_STATUS_RUNNING);
1052 } 1052 }
1053 if ((in_be32(&prob->spu_status_R) & 1053 if ((in_be32(&prob->spu_status_R) &
1054 SPU_STATUS_ISOLATED_LOAD_STAUTUS) 1054 SPU_STATUS_ISOLATED_LOAD_STATUS)
1055 || (in_be32(&prob->spu_status_R) & 1055 || (in_be32(&prob->spu_status_R) &
1056 SPU_STATUS_ISOLATED_STATE)) { 1056 SPU_STATUS_ISOLATED_STATE)) {
1057 out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); 1057 out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
@@ -1085,7 +1085,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
1085 */ 1085 */
1086 if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { 1086 if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) {
1087 if (in_be32(&prob->spu_status_R) & 1087 if (in_be32(&prob->spu_status_R) &
1088 SPU_STATUS_ISOLATED_EXIT_STAUTUS) { 1088 SPU_STATUS_ISOLATED_EXIT_STATUS) {
1089 spu_mfc_sr1_set(spu, 1089 spu_mfc_sr1_set(spu,
1090 MFC_STATE1_MASTER_RUN_CONTROL_MASK); 1090 MFC_STATE1_MASTER_RUN_CONTROL_MASK);
1091 eieio(); 1091 eieio();
@@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
1095 SPU_STATUS_RUNNING); 1095 SPU_STATUS_RUNNING);
1096 } 1096 }
1097 if ((in_be32(&prob->spu_status_R) & 1097 if ((in_be32(&prob->spu_status_R) &
1098 SPU_STATUS_ISOLATED_LOAD_STAUTUS) 1098 SPU_STATUS_ISOLATED_LOAD_STATUS)
1099 || (in_be32(&prob->spu_status_R) & 1099 || (in_be32(&prob->spu_status_R) &
1100 SPU_STATUS_ISOLATED_STATE)) { 1100 SPU_STATUS_ISOLATED_STATE)) {
1101 spu_mfc_sr1_set(spu, 1101 spu_mfc_sr1_set(spu,
@@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu)
1916 wait_spu_stopped(prev, spu); /* Step 57. */ 1916 wait_spu_stopped(prev, spu); /* Step 57. */
1917} 1917}
1918 1918
1919static void force_spu_isolate_exit(struct spu *spu)
1920{
1921 struct spu_problem __iomem *prob = spu->problem;
1922 struct spu_priv2 __iomem *priv2 = spu->priv2;
1923
1924 /* Stop SPE execution and wait for completion. */
1925 out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
1926 iobarrier_rw();
1927 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
1928
1929 /* Restart SPE master runcntl. */
1930 spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK);
1931 iobarrier_w();
1932
1933 /* Initiate isolate exit request and wait for completion. */
1934 out_be64(&priv2->spu_privcntl_RW, 4LL);
1935 iobarrier_w();
1936 out_be32(&prob->spu_runcntl_RW, 2);
1937 iobarrier_rw();
1938 POLL_WHILE_FALSE((in_be32(&prob->spu_status_R)
1939 & SPU_STATUS_STOPPED_BY_STOP));
1940
1941 /* Reset load request to normal. */
1942 out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL);
1943 iobarrier_w();
1944}
1945
1946/**
1947 * stop_spu_isolate
1948 * Check SPU run-control state and force isolated
1949 * exit function as necessary.
1950 */
1951static void stop_spu_isolate(struct spu *spu)
1952{
1953 struct spu_problem __iomem *prob = spu->problem;
1954
1955 if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) {
1956 /* The SPU is in isolated state; the only way
1957 * to get it out is to perform an isolated
1958 * exit (clean) operation.
1959 */
1960 force_spu_isolate_exit(spu);
1961 }
1962}
1963
1919static void harvest(struct spu_state *prev, struct spu *spu) 1964static void harvest(struct spu_state *prev, struct spu *spu)
1920{ 1965{
1921 /* 1966 /*
@@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu)
1928 inhibit_user_access(prev, spu); /* Step 3. */ 1973 inhibit_user_access(prev, spu); /* Step 3. */
1929 terminate_spu_app(prev, spu); /* Step 4. */ 1974 terminate_spu_app(prev, spu); /* Step 4. */
1930 set_switch_pending(prev, spu); /* Step 5. */ 1975 set_switch_pending(prev, spu); /* Step 5. */
1976 stop_spu_isolate(spu); /* NEW. */
1931 remove_other_spu_access(prev, spu); /* Step 6. */ 1977 remove_other_spu_access(prev, spu); /* Step 6. */
1932 suspend_mfc(prev, spu); /* Step 7. */ 1978 suspend_mfc(prev, spu); /* Step 7. */
1933 wait_suspend_mfc_complete(prev, spu); /* Step 8. */ 1979 wait_suspend_mfc_complete(prev, spu); /* Step 8. */
@@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu)
2096 acquire_spu_lock(spu); /* Step 1. */ 2142 acquire_spu_lock(spu); /* Step 1. */
2097 rc = __do_spu_save(prev, spu); /* Steps 2-53. */ 2143 rc = __do_spu_save(prev, spu); /* Steps 2-53. */
2098 release_spu_lock(spu); 2144 release_spu_lock(spu);
2099 if (rc) { 2145 if (rc != 0 && rc != 2 && rc != 6) {
2100 panic("%s failed on SPU[%d], rc=%d.\n", 2146 panic("%s failed on SPU[%d], rc=%d.\n",
2101 __func__, spu->number, rc); 2147 __func__, spu->number, rc);
2102 } 2148 }
2103 return rc; 2149 return 0;
2104} 2150}
2105EXPORT_SYMBOL_GPL(spu_save); 2151EXPORT_SYMBOL_GPL(spu_save);
2106 2152
@@ -2165,9 +2211,6 @@ static void init_priv1(struct spu_state *csa)
2165 MFC_STATE1_PROBLEM_STATE_MASK | 2211 MFC_STATE1_PROBLEM_STATE_MASK |
2166 MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; 2212 MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK;
2167 2213
2168 /* Set storage description. */
2169 csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1);
2170
2171 /* Enable OS-specific set of interrupts. */ 2214 /* Enable OS-specific set of interrupts. */
2172 csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | 2215 csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR |
2173 CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | 2216 CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR |
diff --git a/arch/powerpc/platforms/efika/Makefile b/arch/powerpc/platforms/efika/Makefile
new file mode 100644
index 000000000000..17b2a781fbae
--- /dev/null
+++ b/arch/powerpc/platforms/efika/Makefile
@@ -0,0 +1 @@
obj-y += setup.o mpc52xx.o pci.o
diff --git a/arch/powerpc/platforms/efika/efika.h b/arch/powerpc/platforms/efika/efika.h
new file mode 100644
index 000000000000..2f060fd097d7
--- /dev/null
+++ b/arch/powerpc/platforms/efika/efika.h
@@ -0,0 +1,19 @@
1/*
2 * Efika 5K2 platform setup - Header file
3 *
4 * Copyright (C) 2006 bplan GmbH
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
12#ifndef __ARCH_POWERPC_EFIKA__
13#define __ARCH_POWERPC_EFIKA__
14
15#define EFIKA_PLATFORM_NAME "Efika"
16
17extern void __init efika_pcisetup(void);
18
19#endif
diff --git a/arch/powerpc/platforms/efika/pci.c b/arch/powerpc/platforms/efika/pci.c
new file mode 100644
index 000000000000..62e05b2a9227
--- /dev/null
+++ b/arch/powerpc/platforms/efika/pci.c
@@ -0,0 +1,119 @@
1
2#include <linux/kernel.h>
3#include <linux/pci.h>
4#include <linux/string.h>
5#include <linux/init.h>
6
7#include <asm/io.h>
8#include <asm/irq.h>
9#include <asm/prom.h>
10#include <asm/machdep.h>
11#include <asm/sections.h>
12#include <asm/pci-bridge.h>
13#include <asm/rtas.h>
14
15#include "efika.h"
16
17#ifdef CONFIG_PCI
18/*
19 * Access functions for PCI config space using RTAS calls.
20 */
21static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
22 int len, u32 * val)
23{
24 struct pci_controller *hose = bus->sysdata;
25 unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
26 | (((bus->number - hose->first_busno) & 0xff) << 16)
27 | (hose->index << 24);
28 int ret = -1;
29 int rval;
30
31 rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
32 *val = ret;
33 return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
34}
35
36static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
37 int offset, int len, u32 val)
38{
39 struct pci_controller *hose = bus->sysdata;
40 unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
41 | (((bus->number - hose->first_busno) & 0xff) << 16)
42 | (hose->index << 24);
43 int rval;
44
45 rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
46 addr, len, val);
47 return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
48}
49
50static struct pci_ops rtas_pci_ops = {
51 rtas_read_config,
52 rtas_write_config
53};
54
55void __init efika_pcisetup(void)
56{
57 const int *bus_range;
58 int len;
59 struct pci_controller *hose;
60 struct device_node *root;
61 struct device_node *pcictrl;
62
63 root = of_find_node_by_path("/");
64 if (root == NULL) {
65 printk(KERN_WARNING EFIKA_PLATFORM_NAME
66 ": Unable to find the root node\n");
67 return;
68 }
69
70 for (pcictrl = NULL;;) {
71 pcictrl = of_get_next_child(root, pcictrl);
72 if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
73 break;
74 }
75
76 of_node_put(root);
77
78 if (pcictrl == NULL) {
79 printk(KERN_WARNING EFIKA_PLATFORM_NAME
80 ": Unable to find the PCI bridge node\n");
81 return;
82 }
83
84 bus_range = get_property(pcictrl, "bus-range", &len);
85 if (bus_range == NULL || len < 2 * sizeof(int)) {
86 printk(KERN_WARNING EFIKA_PLATFORM_NAME
87 ": Can't get bus-range for %s\n", pcictrl->full_name);
88 return;
89 }
90
91 if (bus_range[1] == bus_range[0])
92 printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
93 bus_range[0]);
94 else
95 printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
96 bus_range[0], bus_range[1]);
97 printk(" controlled by %s\n", pcictrl->full_name);
98 printk("\n");
99
100 hose = pcibios_alloc_controller();
101 if (!hose) {
102 printk(KERN_WARNING EFIKA_PLATFORM_NAME
103 ": Can't allocate PCI controller structure for %s\n",
104 pcictrl->full_name);
105 return;
106 }
107
108 hose->arch_data = of_node_get(pcictrl);
109 hose->first_busno = bus_range[0];
110 hose->last_busno = bus_range[1];
111 hose->ops = &rtas_pci_ops;
112
113 pci_process_bridge_OF_ranges(hose, pcictrl, 0);
114}
115
116#else
117void __init efika_pcisetup(void)
118{}
119#endif
diff --git a/arch/powerpc/platforms/efika/setup.c b/arch/powerpc/platforms/efika/setup.c
new file mode 100644
index 000000000000..3bc1b5fe0cea
--- /dev/null
+++ b/arch/powerpc/platforms/efika/setup.c
@@ -0,0 +1,149 @@
1/*
2 *
3 * Efika 5K2 platform setup
4 * Some code really inspired from the lite5200b platform.
5 *
6 * Copyright (C) 2006 bplan GmbH
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 any
10 * kind, whether express or implied.
11 *
12 */
13
14#include <linux/errno.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/reboot.h>
18#include <linux/init.h>
19#include <linux/utsrelease.h>
20#include <linux/seq_file.h>
21#include <linux/root_dev.h>
22#include <linux/initrd.h>
23#include <linux/timer.h>
24#include <linux/pci.h>
25
26#include <asm/pgtable.h>
27#include <asm/prom.h>
28#include <asm/time.h>
29#include <asm/machdep.h>
30#include <asm/rtas.h>
31#include <asm/of_device.h>
32#include <asm/mpc52xx.h>
33
34#include "efika.h"
35
36static void efika_show_cpuinfo(struct seq_file *m)
37{
38 struct device_node *root;
39 const char *revision = NULL;
40 const char *codegendescription = NULL;
41 const char *codegenvendor = NULL;
42
43 root = of_find_node_by_path("/");
44 if (root) {
45 revision = get_property(root, "revision", NULL);
46 codegendescription =
47 get_property(root, "CODEGEN,description", NULL);
48 codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
49
50 of_node_put(root);
51 }
52
53 if (codegendescription)
54 seq_printf(m, "machine\t\t: %s\n", codegendescription);
55 else
56 seq_printf(m, "machine\t\t: Efika\n");
57
58 if (revision)
59 seq_printf(m, "revision\t: %s\n", revision);
60
61 if (codegenvendor)
62 seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
63
64 of_node_put(root);
65}
66
67static void __init efika_setup_arch(void)
68{
69 rtas_initialize();
70
71#ifdef CONFIG_BLK_DEV_INITRD
72 initrd_below_start_ok = 1;
73
74 if (initrd_start)
75 ROOT_DEV = Root_RAM0;
76 else
77#endif
78 ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
79
80 efika_pcisetup();
81
82 if (ppc_md.progress)
83 ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
84}
85
86static void __init efika_init(void)
87{
88 struct device_node *np;
89 struct device_node *cnp = NULL;
90 const u32 *base;
91
92 /* Find every child of the SOC node and add it to of_platform */
93 np = of_find_node_by_name(NULL, "builtin");
94 if (np) {
95 char name[BUS_ID_SIZE];
96 while ((cnp = of_get_next_child(np, cnp))) {
97 strcpy(name, cnp->name);
98
99 base = get_property(cnp, "reg", NULL);
100 if (base == NULL)
101 continue;
102
103 snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
104 of_platform_device_create(cnp, name, NULL);
105
106 printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
107 }
108 }
109
110 if (ppc_md.progress)
111 ppc_md.progress(" Have fun with your Efika! ", 0x7777);
112}
113
114static int __init efika_probe(void)
115{
116 char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
117 "model", NULL);
118
119 if (model == NULL)
120 return 0;
121 if (strcmp(model, "EFIKA5K2"))
122 return 0;
123
124 ISA_DMA_THRESHOLD = ~0L;
125 DMA_MODE_READ = 0x44;
126 DMA_MODE_WRITE = 0x48;
127
128 return 1;
129}
130
131define_machine(efika)
132{
133 .name = EFIKA_PLATFORM_NAME,
134 .probe = efika_probe,
135 .setup_arch = efika_setup_arch,
136 .init = efika_init,
137 .show_cpuinfo = efika_show_cpuinfo,
138 .init_IRQ = mpc52xx_init_irq,
139 .get_irq = mpc52xx_get_irq,
140 .restart = rtas_restart,
141 .power_off = rtas_power_off,
142 .halt = rtas_halt,
143 .set_rtc_time = rtas_set_rtc_time,
144 .get_rtc_time = rtas_get_rtc_time,
145 .progress = rtas_progress,
146 .get_boot_time = rtas_get_boot_time,
147 .calibrate_decr = generic_calibrate_decr,
148 .phys_mem_access_prot = pci_phys_mem_access_prot,
149};
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index e305deee7f44..9e8a334a518a 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -41,6 +41,7 @@
41#include "call_pci.h" 41#include "call_pci.h"
42#include "pci.h" 42#include "pci.h"
43#include "it_exp_vpd_panel.h" 43#include "it_exp_vpd_panel.h"
44#include "naca.h"
44 45
45#ifdef DEBUG 46#ifdef DEBUG
46#define DBG(fmt...) udbg_printf(fmt) 47#define DBG(fmt...) udbg_printf(fmt)
@@ -205,13 +206,11 @@ static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
205 dt_prop(dt, name, &data, sizeof(u32)); 206 dt_prop(dt, name, &data, sizeof(u32));
206} 207}
207 208
208#ifdef notyet
209static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, 209static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
210 u64 data) 210 u64 data)
211{ 211{
212 dt_prop(dt, name, &data, sizeof(u64)); 212 dt_prop(dt, name, &data, sizeof(u64));
213} 213}
214#endif
215 214
216static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, 215static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
217 const char *name, u64 *data, int n) 216 const char *name, u64 *data, int n)
@@ -306,6 +305,17 @@ static void __init dt_model(struct iseries_flat_dt *dt)
306 dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex()); 305 dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
307} 306}
308 307
308static void __init dt_initrd(struct iseries_flat_dt *dt)
309{
310#ifdef CONFIG_BLK_DEV_INITRD
311 if (naca.xRamDisk) {
312 dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk);
313 dt_prop_u64(dt, "linux,initrd-end",
314 (u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE);
315 }
316#endif
317}
318
309static void __init dt_do_vdevice(struct iseries_flat_dt *dt, 319static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
310 const char *name, u32 reg, int unit, 320 const char *name, u32 reg, int unit,
311 const char *type, const char *compat, int end) 321 const char *type, const char *compat, int end)
@@ -641,6 +651,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size)
641 /* /chosen */ 651 /* /chosen */
642 dt_start_node(iseries_dt, "chosen"); 652 dt_start_node(iseries_dt, "chosen");
643 dt_prop_str(iseries_dt, "bootargs", cmd_line); 653 dt_prop_str(iseries_dt, "bootargs", cmd_line);
654 dt_initrd(iseries_dt);
644 dt_end_node(iseries_dt); 655 dt_end_node(iseries_dt);
645 656
646 dt_cpus(iseries_dt); 657 dt_cpus(iseries_dt);
diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c
index a2200842f4e5..2430848b98e7 100644
--- a/arch/powerpc/platforms/iseries/ksyms.c
+++ b/arch/powerpc/platforms/iseries/ksyms.c
@@ -19,9 +19,3 @@ EXPORT_SYMBOL(HvCall4);
19EXPORT_SYMBOL(HvCall5); 19EXPORT_SYMBOL(HvCall5);
20EXPORT_SYMBOL(HvCall6); 20EXPORT_SYMBOL(HvCall6);
21EXPORT_SYMBOL(HvCall7); 21EXPORT_SYMBOL(HvCall7);
22
23#ifdef CONFIG_SMP
24EXPORT_SYMBOL(local_get_flags);
25EXPORT_SYMBOL(local_irq_disable);
26EXPORT_SYMBOL(local_irq_restore);
27#endif
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S
index 7641fc7e550a..2c6ff0fdac98 100644
--- a/arch/powerpc/platforms/iseries/misc.S
+++ b/arch/powerpc/platforms/iseries/misc.S
@@ -19,39 +19,8 @@
19 19
20 .text 20 .text
21 21
22/* unsigned long local_save_flags(void) */ 22/* Handle pending interrupts in interrupt context */
23_GLOBAL(local_get_flags) 23_GLOBAL(iseries_handle_interrupts)
24 lbz r3,PACAPROCENABLED(r13)
25 blr
26
27/* unsigned long local_irq_disable(void) */
28_GLOBAL(local_irq_disable)
29 lbz r3,PACAPROCENABLED(r13)
30 li r4,0
31 stb r4,PACAPROCENABLED(r13)
32 blr /* Done */
33
34/* void local_irq_restore(unsigned long flags) */
35_GLOBAL(local_irq_restore)
36 lbz r5,PACAPROCENABLED(r13)
37 /* Check if things are setup the way we want _already_. */
38 cmpw 0,r3,r5
39 beqlr
40 /* are we enabling interrupts? */
41 cmpdi 0,r3,0
42 stb r3,PACAPROCENABLED(r13)
43 beqlr
44 /* Check pending interrupts */
45 /* A decrementer, IPI or PMC interrupt may have occurred
46 * while we were in the hypervisor (which enables) */
47 ld r4,PACALPPACAPTR(r13)
48 ld r4,LPPACAANYINT(r4)
49 cmpdi r4,0
50 beqlr
51
52 /*
53 * Handle pending interrupts in interrupt context
54 */
55 li r0,0x5555 24 li r0,0x5555
56 sc 25 sc
57 blr 26 blr
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 6f73469fd3b0..cd8965ec9ddb 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -21,7 +21,6 @@
21#include <linux/smp.h> 21#include <linux/smp.h>
22#include <linux/param.h> 22#include <linux/param.h>
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/initrd.h>
25#include <linux/seq_file.h> 24#include <linux/seq_file.h>
26#include <linux/kdev_t.h> 25#include <linux/kdev_t.h>
27#include <linux/major.h> 26#include <linux/major.h>
@@ -80,8 +79,6 @@ extern void iSeries_pci_final_fixup(void);
80static void iSeries_pci_final_fixup(void) { } 79static void iSeries_pci_final_fixup(void) { }
81#endif 80#endif
82 81
83extern int rd_size; /* Defined in drivers/block/rd.c */
84
85extern unsigned long iSeries_recal_tb; 82extern unsigned long iSeries_recal_tb;
86extern unsigned long iSeries_recal_titan; 83extern unsigned long iSeries_recal_titan;
87 84
@@ -295,24 +292,6 @@ static void __init iSeries_init_early(void)
295{ 292{
296 DBG(" -> iSeries_init_early()\n"); 293 DBG(" -> iSeries_init_early()\n");
297 294
298#if defined(CONFIG_BLK_DEV_INITRD)
299 /*
300 * If the init RAM disk has been configured and there is
301 * a non-zero starting address for it, set it up
302 */
303 if (naca.xRamDisk) {
304 initrd_start = (unsigned long)__va(naca.xRamDisk);
305 initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE;
306 initrd_below_start_ok = 1; // ramdisk in kernel space
307 ROOT_DEV = Root_RAM0;
308 if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize)
309 rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024;
310 } else
311#endif /* CONFIG_BLK_DEV_INITRD */
312 {
313 /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
314 }
315
316 iSeries_recal_tb = get_tb(); 295 iSeries_recal_tb = get_tb();
317 iSeries_recal_titan = HvCallXm_loadTod(); 296 iSeries_recal_titan = HvCallXm_loadTod();
318 297
@@ -331,17 +310,6 @@ static void __init iSeries_init_early(void)
331 310
332 mf_init(); 311 mf_init();
333 312
334 /* If we were passed an initrd, set the ROOT_DEV properly if the values
335 * look sensible. If not, clear initrd reference.
336 */
337#ifdef CONFIG_BLK_DEV_INITRD
338 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
339 initrd_end > initrd_start)
340 ROOT_DEV = Root_RAM0;
341 else
342 initrd_start = initrd_end = 0;
343#endif /* CONFIG_BLK_DEV_INITRD */
344
345 DBG(" <- iSeries_init_early()\n"); 313 DBG(" <- iSeries_init_early()\n");
346} 314}
347 315
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index e49621be6640..c29a6a064d22 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -486,10 +486,6 @@ static long heathrow_sound_enable(struct device_node *node, long param,
486 486
487static u32 save_fcr[6]; 487static u32 save_fcr[6];
488static u32 save_mbcr; 488static u32 save_mbcr;
489static u32 save_gpio_levels[2];
490static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
491static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
492static u32 save_unin_clock_ctl;
493static struct dbdma_regs save_dbdma[13]; 489static struct dbdma_regs save_dbdma[13];
494static struct dbdma_regs save_alt_dbdma[13]; 490static struct dbdma_regs save_alt_dbdma[13];
495 491
@@ -1548,6 +1544,10 @@ void g5_phy_disable_cpu1(void)
1548 1544
1549 1545
1550#ifdef CONFIG_PM 1546#ifdef CONFIG_PM
1547static u32 save_gpio_levels[2];
1548static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
1549static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
1550static u32 save_unin_clock_ctl;
1551 1551
1552static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) 1552static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
1553{ 1553{
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 824a618396ab..cb1c342061e2 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -361,7 +361,7 @@ char *bootdevice;
361void *boot_host; 361void *boot_host;
362int boot_target; 362int boot_target;
363int boot_part; 363int boot_part;
364extern dev_t boot_dev; 364static dev_t boot_dev;
365 365
366#ifdef CONFIG_SCSI 366#ifdef CONFIG_SCSI
367void __init note_scsi_host(struct device_node *node, void *host) 367void __init note_scsi_host(struct device_node *node, void *host)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 1820a0b0a8c6..721436db3ef0 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -282,7 +282,7 @@ void vpa_init(int cpu)
282 } 282 }
283} 283}
284 284
285long pSeries_lpar_hpte_insert(unsigned long hpte_group, 285static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
286 unsigned long va, unsigned long pa, 286 unsigned long va, unsigned long pa,
287 unsigned long rflags, unsigned long vflags, 287 unsigned long rflags, unsigned long vflags,
288 int psize) 288 int psize)
@@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
506 * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie 506 * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
507 * lock. 507 * lock.
508 */ 508 */
509void pSeries_lpar_flush_hash_range(unsigned long number, int local) 509static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
510{ 510{
511 int i; 511 int i;
512 unsigned long flags = 0; 512 unsigned long flags = 0;
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 91f052d8cce0..5b87f7b42a1f 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -10,9 +10,9 @@ obj-$(CONFIG_40x) += dcr.o
10obj-$(CONFIG_U3_DART) += dart_iommu.o 10obj-$(CONFIG_U3_DART) += dart_iommu.o
11obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o 11obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
12obj-$(CONFIG_FSL_SOC) += fsl_soc.o 12obj-$(CONFIG_FSL_SOC) += fsl_soc.o
13obj-$(CONFIG_PPC_TODC) += todc.o
14obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o 13obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
15obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ 14obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
15obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_pic.o
16 16
17ifeq ($(CONFIG_PPC_MERGE),y) 17ifeq ($(CONFIG_PPC_MERGE),y)
18obj-$(CONFIG_PPC_I8259) += i8259.o 18obj-$(CONFIG_PPC_I8259) += i8259.o
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index dbe92ae20333..ad31e56e892b 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -22,6 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/phy.h>
25#include <linux/fsl_devices.h> 26#include <linux/fsl_devices.h>
26#include <linux/fs_enet_pd.h> 27#include <linux/fs_enet_pd.h>
27#include <linux/fs_uart_pd.h> 28#include <linux/fs_uart_pd.h>
@@ -146,7 +147,7 @@ static int __init gfar_mdio_of_init(void)
146 } 147 }
147 148
148 for (k = 0; k < 32; k++) 149 for (k = 0; k < 32; k++)
149 mdio_data.irq[k] = -1; 150 mdio_data.irq[k] = PHY_POLL;
150 151
151 while ((child = of_get_next_child(np, child)) != NULL) { 152 while ((child = of_get_next_child(np, child)) != NULL) {
152 int irq = irq_of_parse_and_map(child, 0); 153 int irq = irq_of_parse_and_map(child, 0);
@@ -177,6 +178,7 @@ static const char *gfar_tx_intr = "tx";
177static const char *gfar_rx_intr = "rx"; 178static const char *gfar_rx_intr = "rx";
178static const char *gfar_err_intr = "error"; 179static const char *gfar_err_intr = "error";
179 180
181
180static int __init gfar_of_init(void) 182static int __init gfar_of_init(void)
181{ 183{
182 struct device_node *np; 184 struct device_node *np;
@@ -204,8 +206,7 @@ static int __init gfar_of_init(void)
204 if (ret) 206 if (ret)
205 goto err; 207 goto err;
206 208
207 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 209 of_irq_to_resource(np, 0, &r[1]);
208 r[1].flags = IORESOURCE_IRQ;
209 210
210 model = get_property(np, "model", NULL); 211 model = get_property(np, "model", NULL);
211 212
@@ -214,12 +215,10 @@ static int __init gfar_of_init(void)
214 r[1].name = gfar_tx_intr; 215 r[1].name = gfar_tx_intr;
215 216
216 r[2].name = gfar_rx_intr; 217 r[2].name = gfar_rx_intr;
217 r[2].start = r[2].end = irq_of_parse_and_map(np, 1); 218 of_irq_to_resource(np, 1, &r[2]);
218 r[2].flags = IORESOURCE_IRQ;
219 219
220 r[3].name = gfar_err_intr; 220 r[3].name = gfar_err_intr;
221 r[3].start = r[3].end = irq_of_parse_and_map(np, 2); 221 of_irq_to_resource(np, 2, &r[3]);
222 r[3].flags = IORESOURCE_IRQ;
223 222
224 n_res += 2; 223 n_res += 2;
225 } 224 }
@@ -323,8 +322,7 @@ static int __init fsl_i2c_of_init(void)
323 if (ret) 322 if (ret)
324 goto err; 323 goto err;
325 324
326 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 325 of_irq_to_resource(np, 0, &r[1]);
327 r[1].flags = IORESOURCE_IRQ;
328 326
329 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); 327 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
330 if (IS_ERR(i2c_dev)) { 328 if (IS_ERR(i2c_dev)) {
@@ -459,8 +457,7 @@ static int __init fsl_usb_of_init(void)
459 if (ret) 457 if (ret)
460 goto err; 458 goto err;
461 459
462 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 460 of_irq_to_resource(np, 0, &r[1]);
463 r[1].flags = IORESOURCE_IRQ;
464 461
465 usb_dev_mph = 462 usb_dev_mph =
466 platform_device_register_simple("fsl-ehci", i, r, 2); 463 platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -507,8 +504,7 @@ static int __init fsl_usb_of_init(void)
507 if (ret) 504 if (ret)
508 goto unreg_mph; 505 goto unreg_mph;
509 506
510 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 507 of_irq_to_resource(np, 0, &r[1]);
511 r[1].flags = IORESOURCE_IRQ;
512 508
513 usb_dev_dr = 509 usb_dev_dr =
514 platform_device_register_simple("fsl-ehci", i, r, 2); 510 platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -591,8 +587,7 @@ static int __init fs_enet_of_init(void)
591 r[2].name = fcc_regs_c; 587 r[2].name = fcc_regs_c;
592 fs_enet_data.fcc_regs_c = r[2].start; 588 fs_enet_data.fcc_regs_c = r[2].start;
593 589
594 r[3].start = r[3].end = irq_of_parse_and_map(np, 0); 590 of_irq_to_resource(np, 0, &r[3]);
595 r[3].flags = IORESOURCE_IRQ;
596 591
597 fs_enet_dev = 592 fs_enet_dev =
598 platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4); 593 platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
@@ -754,8 +749,7 @@ static int __init cpm_uart_of_init(void)
754 goto err; 749 goto err;
755 r[1].name = scc_pram; 750 r[1].name = scc_pram;
756 751
757 r[2].start = r[2].end = irq_of_parse_and_map(np, 0); 752 of_irq_to_resource(np, 0, &r[2]);
758 r[2].flags = IORESOURCE_IRQ;
759 753
760 cpm_uart_dev = 754 cpm_uart_dev =
761 platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); 755 platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
diff --git a/arch/powerpc/sysdev/mpc52xx_pic.c b/arch/powerpc/sysdev/mpc52xx_pic.c
new file mode 100644
index 000000000000..6df51f04b8f5
--- /dev/null
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c
@@ -0,0 +1,538 @@
1/*
2 *
3 * Programmable Interrupt Controller functions for the Freescale MPC52xx.
4 *
5 * Copyright (C) 2006 bplan GmbH
6 *
7 * Based on the code from the 2.4 kernel by
8 * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
9 *
10 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
11 * Copyright (C) 2003 Montavista Software, Inc
12 *
13 * This file is licensed under the terms of the GNU General Public License
14 * version 2. This program is licensed "as is" without any warranty of any
15 * kind, whether express or implied.
16 *
17 */
18
19#undef DEBUG
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>
28#include <linux/hardirq.h>
29
30#include <asm/io.h>
31#include <asm/processor.h>
32#include <asm/system.h>
33#include <asm/irq.h>
34#include <asm/prom.h>
35#include <asm/mpc52xx.h>
36
37/*
38 *
39*/
40
41static struct mpc52xx_intr __iomem *intr;
42static struct mpc52xx_sdma __iomem *sdma;
43static struct irq_host *mpc52xx_irqhost = NULL;
44
45static unsigned char mpc52xx_map_senses[4] = {
46 IRQ_TYPE_LEVEL_HIGH,
47 IRQ_TYPE_EDGE_RISING,
48 IRQ_TYPE_EDGE_FALLING,
49 IRQ_TYPE_LEVEL_LOW,
50};
51
52/*
53 *
54*/
55
56static inline void io_be_setbit(u32 __iomem * addr, int bitno)
57{
58 out_be32(addr, in_be32(addr) | (1 << bitno));
59}
60
61static inline void io_be_clrbit(u32 __iomem * addr, int bitno)
62{
63 out_be32(addr, in_be32(addr) & ~(1 << bitno));
64}
65
66/*
67 * IRQ[0-3] interrupt irq_chip
68*/
69
70static void mpc52xx_extirq_mask(unsigned int virq)
71{
72 int irq;
73 int l2irq;
74
75 irq = irq_map[virq].hwirq;
76 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
77
78 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
79
80 io_be_clrbit(&intr->ctrl, 11 - l2irq);
81}
82
83static void mpc52xx_extirq_unmask(unsigned int virq)
84{
85 int irq;
86 int l2irq;
87
88 irq = irq_map[virq].hwirq;
89 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
90
91 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
92
93 io_be_setbit(&intr->ctrl, 11 - l2irq);
94}
95
96static void mpc52xx_extirq_ack(unsigned int virq)
97{
98 int irq;
99 int l2irq;
100
101 irq = irq_map[virq].hwirq;
102 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
103
104 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
105
106 io_be_setbit(&intr->ctrl, 27 - l2irq);
107}
108
109static struct irq_chip mpc52xx_extirq_irqchip = {
110 .typename = " MPC52xx IRQ[0-3] ",
111 .mask = mpc52xx_extirq_mask,
112 .unmask = mpc52xx_extirq_unmask,
113 .ack = mpc52xx_extirq_ack,
114};
115
116/*
117 * Main interrupt irq_chip
118*/
119
120static void mpc52xx_main_mask(unsigned int virq)
121{
122 int irq;
123 int l2irq;
124
125 irq = irq_map[virq].hwirq;
126 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
127
128 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
129
130 io_be_setbit(&intr->main_mask, 15 - l2irq);
131}
132
133static void mpc52xx_main_unmask(unsigned int virq)
134{
135 int irq;
136 int l2irq;
137
138 irq = irq_map[virq].hwirq;
139 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
140
141 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
142
143 io_be_clrbit(&intr->main_mask, 15 - l2irq);
144}
145
146static struct irq_chip mpc52xx_main_irqchip = {
147 .typename = "MPC52xx Main",
148 .mask = mpc52xx_main_mask,
149 .mask_ack = mpc52xx_main_mask,
150 .unmask = mpc52xx_main_unmask,
151};
152
153/*
154 * Peripherals interrupt irq_chip
155*/
156
157static void mpc52xx_periph_mask(unsigned int virq)
158{
159 int irq;
160 int l2irq;
161
162 irq = irq_map[virq].hwirq;
163 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
164
165 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
166
167 io_be_setbit(&intr->per_mask, 31 - l2irq);
168}
169
170static void mpc52xx_periph_unmask(unsigned int virq)
171{
172 int irq;
173 int l2irq;
174
175 irq = irq_map[virq].hwirq;
176 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
177
178 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
179
180 io_be_clrbit(&intr->per_mask, 31 - l2irq);
181}
182
183static struct irq_chip mpc52xx_periph_irqchip = {
184 .typename = "MPC52xx Peripherals",
185 .mask = mpc52xx_periph_mask,
186 .mask_ack = mpc52xx_periph_mask,
187 .unmask = mpc52xx_periph_unmask,
188};
189
190/*
191 * SDMA interrupt irq_chip
192*/
193
194static void mpc52xx_sdma_mask(unsigned int virq)
195{
196 int irq;
197 int l2irq;
198
199 irq = irq_map[virq].hwirq;
200 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
201
202 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
203
204 io_be_setbit(&sdma->IntMask, l2irq);
205}
206
207static void mpc52xx_sdma_unmask(unsigned int virq)
208{
209 int irq;
210 int l2irq;
211
212 irq = irq_map[virq].hwirq;
213 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
214
215 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
216
217 io_be_clrbit(&sdma->IntMask, l2irq);
218}
219
220static void mpc52xx_sdma_ack(unsigned int virq)
221{
222 int irq;
223 int l2irq;
224
225 irq = irq_map[virq].hwirq;
226 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
227
228 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
229
230 out_be32(&sdma->IntPend, 1 << l2irq);
231}
232
233static struct irq_chip mpc52xx_sdma_irqchip = {
234 .typename = "MPC52xx SDMA",
235 .mask = mpc52xx_sdma_mask,
236 .unmask = mpc52xx_sdma_unmask,
237 .ack = mpc52xx_sdma_ack,
238};
239
240/*
241 * irq_host
242*/
243
244static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
245{
246 pr_debug("%s: node=%p\n", __func__, node);
247 return mpc52xx_irqhost->host_data == node;
248}
249
250static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
251 u32 * intspec, unsigned int intsize,
252 irq_hw_number_t * out_hwirq,
253 unsigned int *out_flags)
254{
255 int intrvect_l1;
256 int intrvect_l2;
257 int intrvect_type;
258 int intrvect_linux;
259
260 if (intsize != 3)
261 return -1;
262
263 intrvect_l1 = (int)intspec[0];
264 intrvect_l2 = (int)intspec[1];
265 intrvect_type = (int)intspec[2];
266
267 intrvect_linux =
268 (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
269 intrvect_linux |=
270 (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
271
272 pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
273 intrvect_l2);
274
275 *out_hwirq = intrvect_linux;
276 *out_flags = mpc52xx_map_senses[intrvect_type];
277
278 return 0;
279}
280
281/*
282 * this function retrieves the correct IRQ type out
283 * of the MPC regs
284 * Only externals IRQs needs this
285*/
286static int mpc52xx_irqx_gettype(int irq)
287{
288 int type;
289 u32 ctrl_reg;
290
291 ctrl_reg = in_be32(&intr->ctrl);
292 type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
293
294 return mpc52xx_map_senses[type];
295}
296
297static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
298 irq_hw_number_t irq)
299{
300 int l1irq;
301 int l2irq;
302 struct irq_chip *good_irqchip;
303 void *good_handle;
304 int type;
305
306 l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
307 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
308
309 /*
310 * Most of ours IRQs will be level low
311 * Only external IRQs on some platform may be others
312 */
313 type = IRQ_TYPE_LEVEL_LOW;
314
315 switch (l1irq) {
316 case MPC52xx_IRQ_L1_CRIT:
317 pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
318
319 BUG_ON(l2irq != 0);
320
321 type = mpc52xx_irqx_gettype(l2irq);
322 good_irqchip = &mpc52xx_extirq_irqchip;
323 break;
324
325 case MPC52xx_IRQ_L1_MAIN:
326 pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
327
328 if ((l2irq >= 1) && (l2irq <= 3)) {
329 type = mpc52xx_irqx_gettype(l2irq);
330 good_irqchip = &mpc52xx_extirq_irqchip;
331 } else {
332 good_irqchip = &mpc52xx_main_irqchip;
333 }
334 break;
335
336 case MPC52xx_IRQ_L1_PERP:
337 pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
338 good_irqchip = &mpc52xx_periph_irqchip;
339 break;
340
341 case MPC52xx_IRQ_L1_SDMA:
342 pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
343 good_irqchip = &mpc52xx_sdma_irqchip;
344 break;
345
346 default:
347 pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
348 printk(KERN_ERR "Unknow IRQ!\n");
349 return -EINVAL;
350 }
351
352 switch (type) {
353 case IRQ_TYPE_EDGE_FALLING:
354 case IRQ_TYPE_EDGE_RISING:
355 good_handle = handle_edge_irq;
356 break;
357 default:
358 good_handle = handle_level_irq;
359 }
360
361 set_irq_chip_and_handler(virq, good_irqchip, good_handle);
362
363 pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
364 (int)irq, type);
365
366 return 0;
367}
368
369static struct irq_host_ops mpc52xx_irqhost_ops = {
370 .match = mpc52xx_irqhost_match,
371 .xlate = mpc52xx_irqhost_xlate,
372 .map = mpc52xx_irqhost_map,
373};
374
375/*
376 * init (public)
377*/
378
379void __init mpc52xx_init_irq(void)
380{
381 struct device_node *picnode = NULL;
382 int picnode_regsize;
383 u32 picnode_regoffset;
384
385 struct device_node *sdmanode = NULL;
386 int sdmanode_regsize;
387 u32 sdmanode_regoffset;
388
389 u64 size64;
390 int flags;
391
392 u32 intr_ctrl;
393
394 picnode = of_find_compatible_node(NULL, "interrupt-controller",
395 "mpc5200-pic");
396 if (picnode == NULL) {
397 printk(KERN_ERR "MPC52xx PIC: "
398 "Unable to find the interrupt controller "
399 "in the OpenFirmware device tree\n");
400 goto end;
401 }
402
403 sdmanode = of_find_compatible_node(NULL, "dma-controller",
404 "mpc5200-bestcomm");
405 if (sdmanode == NULL) {
406 printk(KERN_ERR "MPC52xx PIC"
407 "Unable to find the Bestcomm DMA controller device "
408 "in the OpenFirmware device tree\n");
409 goto end;
410 }
411
412 /* Retrieve PIC ressources */
413 picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
414 if (picnode_regoffset == 0) {
415 printk(KERN_ERR "MPC52xx PIC"
416 "Unable to get the interrupt controller address\n");
417 goto end;
418 }
419
420 picnode_regoffset =
421 of_translate_address(picnode, (u32 *) picnode_regoffset);
422 picnode_regsize = (int)size64;
423
424 /* Retrieve SDMA ressources */
425 sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
426 if (sdmanode_regoffset == 0) {
427 printk(KERN_ERR "MPC52xx PIC: "
428 "Unable to get the Bestcomm DMA controller address\n");
429 goto end;
430 }
431
432 sdmanode_regoffset =
433 of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
434 sdmanode_regsize = (int)size64;
435
436 /* Remap the necessary zones */
437 intr = ioremap(picnode_regoffset, picnode_regsize);
438 if (intr == NULL) {
439 printk(KERN_ERR "MPC52xx PIC: "
440 "Unable to ioremap interrupt controller registers!\n");
441 goto end;
442 }
443
444 sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
445 if (sdma == NULL) {
446 iounmap(intr);
447 printk(KERN_ERR "MPC52xx PIC: "
448 "Unable to ioremap Bestcomm DMA registers!\n");
449 goto end;
450 }
451
452 printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n",
453 picnode_regoffset);
454 printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n",
455 sdmanode_regoffset);
456
457 /* Disable all interrupt sources. */
458 out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
459 out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
460 out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
461 out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
462 intr_ctrl = in_be32(&intr->ctrl);
463 intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */
464 intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
465 0x00001000 | /* MEE master external enable */
466 0x00000000 | /* 0 means disable IRQ 0-3 */
467 0x00000001; /* CEb route critical normally */
468 out_be32(&intr->ctrl, intr_ctrl);
469
470 /* Zero a bunch of the priority settings. */
471 out_be32(&intr->per_pri1, 0);
472 out_be32(&intr->per_pri2, 0);
473 out_be32(&intr->per_pri3, 0);
474 out_be32(&intr->main_pri1, 0);
475 out_be32(&intr->main_pri2, 0);
476
477 /*
478 * As last step, add an irq host to translate the real
479 * hw irq information provided by the ofw to linux virq
480 */
481
482 mpc52xx_irqhost =
483 irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ,
484 &mpc52xx_irqhost_ops, -1);
485
486 if (mpc52xx_irqhost) {
487 mpc52xx_irqhost->host_data = picnode;
488 printk(KERN_INFO "MPC52xx PIC is up and running!\n");
489 } else {
490 printk(KERN_ERR
491 "MPC52xx PIC: Unable to allocate the IRQ host\n");
492 }
493
494end:
495 of_node_put(picnode);
496 of_node_put(sdmanode);
497}
498
499/*
500 * get_irq (public)
501*/
502unsigned int mpc52xx_get_irq(void)
503{
504 u32 status;
505 int irq = NO_IRQ_IGNORE;
506
507 status = in_be32(&intr->enc_status);
508 if (status & 0x00000400) { /* critical */
509 irq = (status >> 8) & 0x3;
510 if (irq == 2) /* high priority peripheral */
511 goto peripheral;
512 irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
513 MPC52xx_IRQ_L1_MASK;
514 } else if (status & 0x00200000) { /* main */
515 irq = (status >> 16) & 0x1f;
516 if (irq == 4) /* low priority peripheral */
517 goto peripheral;
518 irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
519 MPC52xx_IRQ_L1_MASK;
520 } else if (status & 0x20000000) { /* peripheral */
521 peripheral:
522 irq = (status >> 24) & 0x1f;
523 if (irq == 0) { /* bestcomm */
524 status = in_be32(&sdma->IntPend);
525 irq = ffs(status) - 1;
526 irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
527 MPC52xx_IRQ_L1_MASK;
528 } else
529 irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
530 MPC52xx_IRQ_L1_MASK;
531 }
532
533 pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
534 irq_linear_revmap(mpc52xx_irqhost, irq));
535
536 return irq_linear_revmap(mpc52xx_irqhost, irq);
537}
538
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index e4223226a7a8..e3d71e083f35 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -174,8 +174,7 @@ void qe_setbrg(u32 brg, u32 rate)
174 u32 divisor, tempval; 174 u32 divisor, tempval;
175 int div16 = 0; 175 int div16 = 0;
176 176
177 bp = &qe_immr->brg.brgc1; 177 bp = &qe_immr->brg.brgc[brg];
178 bp += brg;
179 178
180 divisor = (get_brg_clk() / rate); 179 divisor = (get_brg_clk() / rate);
181 if (divisor > QE_BRGC_DIVISOR_MAX + 1) { 180 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c
deleted file mode 100644
index 0a65980efb50..000000000000
--- a/arch/powerpc/sysdev/todc.c
+++ /dev/null
@@ -1,392 +0,0 @@
1/*
2 * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
3 * Real Time Clocks/Timekeepers.
4 *
5 * Author: Mark A. Greer <mgreer@mvista.com>
6 *
7 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
8 * the terms of the GNU General Public License version 2. This program
9 * is licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 */
12#include <linux/errno.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/time.h>
16#include <linux/timex.h>
17#include <linux/bcd.h>
18#include <linux/mc146818rtc.h>
19
20#include <asm/machdep.h>
21#include <asm/io.h>
22#include <asm/time.h>
23#include <asm/todc.h>
24
25/*
26 * Depending on the hardware on your board and your board design, the
27 * RTC/NVRAM may be accessed either directly (like normal memory) or via
28 * address/data registers. If your board uses the direct method, set
29 * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
30 * 'nvram_as1' NULL. If your board uses address/data regs to access nvram,
31 * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
32 * address of the upper byte (leave NULL if using mc146818), and set
33 * 'nvram_data' to the address of the 8-bit data register.
34 *
35 * Note: Even though the documentation for the various RTC chips say that it
36 * take up to a second before it starts updating once the 'R' bit is
37 * cleared, they always seem to update even though we bang on it many
38 * times a second. This is true, except for the Dallas Semi 1746/1747
39 * (possibly others). Those chips seem to have a real problem whenever
40 * we set the 'R' bit before reading them, they basically stop counting.
41 * --MAG
42 */
43
44/*
45 * 'todc_info' should be initialized in your *_setup.c file to
46 * point to a fully initialized 'todc_info_t' structure.
47 * This structure holds all the register offsets for your particular
48 * TODC/RTC chip.
49 * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you.
50 */
51
52#ifdef RTC_FREQ_SELECT
53#undef RTC_FREQ_SELECT
54#define RTC_FREQ_SELECT control_b /* Register A */
55#endif
56
57#ifdef RTC_CONTROL
58#undef RTC_CONTROL
59#define RTC_CONTROL control_a /* Register B */
60#endif
61
62#ifdef RTC_INTR_FLAGS
63#undef RTC_INTR_FLAGS
64#define RTC_INTR_FLAGS watchdog /* Register C */
65#endif
66
67#ifdef RTC_VALID
68#undef RTC_VALID
69#define RTC_VALID interrupts /* Register D */
70#endif
71
72/* Access routines when RTC accessed directly (like normal memory) */
73u_char
74todc_direct_read_val(int addr)
75{
76 return readb((void __iomem *)(todc_info->nvram_data + addr));
77}
78
79void
80todc_direct_write_val(int addr, unsigned char val)
81{
82 writeb(val, (void __iomem *)(todc_info->nvram_data + addr));
83 return;
84}
85
86/* Access routines for accessing m48txx type chips via addr/data regs */
87u_char
88todc_m48txx_read_val(int addr)
89{
90 outb(addr, todc_info->nvram_as0);
91 outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
92 return inb(todc_info->nvram_data);
93}
94
95void
96todc_m48txx_write_val(int addr, unsigned char val)
97{
98 outb(addr, todc_info->nvram_as0);
99 outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
100 outb(val, todc_info->nvram_data);
101 return;
102}
103
104/* Access routines for accessing mc146818 type chips via addr/data regs */
105u_char
106todc_mc146818_read_val(int addr)
107{
108 outb_p(addr, todc_info->nvram_as0);
109 return inb_p(todc_info->nvram_data);
110}
111
112void
113todc_mc146818_write_val(int addr, unsigned char val)
114{
115 outb_p(addr, todc_info->nvram_as0);
116 outb_p(val, todc_info->nvram_data);
117}
118
119
120/*
121 * Routines to make RTC chips with NVRAM buried behind an addr/data pair
122 * have the NVRAM and clock regs appear at the same level.
123 * The NVRAM will appear to start at addr 0 and the clock regs will appear
124 * to start immediately after the NVRAM (actually, start at offset
125 * todc_info->nvram_size).
126 */
127static inline u_char
128todc_read_val(int addr)
129{
130 u_char val;
131
132 if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
133 if (addr < todc_info->nvram_size) { /* NVRAM */
134 ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
135 val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
136 } else { /* Clock Reg */
137 addr -= todc_info->nvram_size;
138 val = ppc_md.rtc_read_val(addr);
139 }
140 } else
141 val = ppc_md.rtc_read_val(addr);
142
143 return val;
144}
145
146static inline void
147todc_write_val(int addr, u_char val)
148{
149 if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
150 if (addr < todc_info->nvram_size) { /* NVRAM */
151 ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
152 ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
153 } else { /* Clock Reg */
154 addr -= todc_info->nvram_size;
155 ppc_md.rtc_write_val(addr, val);
156 }
157 } else
158 ppc_md.rtc_write_val(addr, val);
159}
160
161/*
162 * TODC routines
163 *
164 * There is some ugly stuff in that there are assumptions for the mc146818.
165 *
166 * Assumptions:
167 * - todc_info->control_a has the offset as mc146818 Register B reg
168 * - todc_info->control_b has the offset as mc146818 Register A reg
169 * - m48txx control reg's write enable or 'W' bit is same as
170 * mc146818 Register B 'SET' bit (i.e., 0x80)
171 *
172 * These assumptions were made to make the code simpler.
173 */
174long __init
175todc_time_init(void)
176{
177 u_char cntl_b;
178
179 if (!ppc_md.rtc_read_val)
180 ppc_md.rtc_read_val = ppc_md.nvram_read_val;
181 if (!ppc_md.rtc_write_val)
182 ppc_md.rtc_write_val = ppc_md.nvram_write_val;
183
184 cntl_b = todc_read_val(todc_info->control_b);
185
186 if (todc_info->rtc_type == TODC_TYPE_MC146818) {
187 if ((cntl_b & 0x70) != 0x20) {
188 printk(KERN_INFO "TODC real-time-clock was stopped."
189 " Now starting...");
190 cntl_b &= ~0x70;
191 cntl_b |= 0x20;
192 }
193
194 todc_write_val(todc_info->control_b, cntl_b);
195 } else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
196 u_char mode;
197
198 mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
199 /* Make sure countdown clear is not set */
200 mode &= ~0x40;
201 /* Enable oscillator, extended register set */
202 mode |= 0x30;
203 todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
204
205 } else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
206 u_char month;
207
208 todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
209 todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
210
211 month = todc_read_val(todc_info->month);
212
213 if ((month & 0x80) == 0x80) {
214 printk(KERN_INFO "TODC %s %s\n",
215 "real-time-clock was stopped.",
216 "Now starting...");
217 month &= ~0x80;
218 todc_write_val(todc_info->month, month);
219 }
220
221 cntl_b &= ~TODC_DS1501_CNTL_B_TE;
222 todc_write_val(todc_info->control_b, cntl_b);
223 } else { /* must be a m48txx type */
224 u_char cntl_a;
225
226 todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
227 todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
228
229 cntl_a = todc_read_val(todc_info->control_a);
230
231 /* Check & clear STOP bit in control B register */
232 if (cntl_b & TODC_MK48TXX_DAY_CB) {
233 printk(KERN_INFO "TODC %s %s\n",
234 "real-time-clock was stopped.",
235 "Now starting...");
236
237 cntl_a |= todc_info->enable_write;
238 cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
239
240 todc_write_val(todc_info->control_a, cntl_a);
241 todc_write_val(todc_info->control_b, cntl_b);
242 }
243
244 /* Make sure READ & WRITE bits are cleared. */
245 cntl_a &= ~(todc_info->enable_write | todc_info->enable_read);
246 todc_write_val(todc_info->control_a, cntl_a);
247 }
248
249 return 0;
250}
251
252/*
253 * There is some ugly stuff in that there are assumptions that for a mc146818,
254 * the todc_info->control_a has the offset of the mc146818 Register B reg and
255 * that the register'ss 'SET' bit is the same as the m48txx's write enable
256 * bit in the control register of the m48txx (i.e., 0x80).
257 *
258 * It was done to make the code look simpler.
259 */
260void
261todc_get_rtc_time(struct rtc_time *tm)
262{
263 uint year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0;
264 uint limit, i;
265 u_char save_control, uip = 0;
266 extern void GregorianDay(struct rtc_time *);
267
268 spin_lock(&rtc_lock);
269 save_control = todc_read_val(todc_info->control_a);
270
271 if (todc_info->rtc_type != TODC_TYPE_MC146818) {
272 limit = 1;
273
274 switch (todc_info->rtc_type) {
275 case TODC_TYPE_DS1553:
276 case TODC_TYPE_DS1557:
277 case TODC_TYPE_DS1743:
278 case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
279 case TODC_TYPE_DS1747:
280 case TODC_TYPE_DS17285:
281 break;
282 default:
283 todc_write_val(todc_info->control_a,
284 (save_control | todc_info->enable_read));
285 }
286 } else
287 limit = 100000000;
288
289 for (i=0; i<limit; i++) {
290 if (todc_info->rtc_type == TODC_TYPE_MC146818)
291 uip = todc_read_val(todc_info->RTC_FREQ_SELECT);
292
293 sec = todc_read_val(todc_info->seconds) & 0x7f;
294 min = todc_read_val(todc_info->minutes) & 0x7f;
295 hour = todc_read_val(todc_info->hours) & 0x3f;
296 mday = todc_read_val(todc_info->day_of_month) & 0x3f;
297 mon = todc_read_val(todc_info->month) & 0x1f;
298 year = todc_read_val(todc_info->year) & 0xff;
299
300 if (todc_info->rtc_type == TODC_TYPE_MC146818) {
301 uip |= todc_read_val(todc_info->RTC_FREQ_SELECT);
302 if ((uip & RTC_UIP) == 0)
303 break;
304 }
305 }
306
307 if (todc_info->rtc_type != TODC_TYPE_MC146818) {
308 switch (todc_info->rtc_type) {
309 case TODC_TYPE_DS1553:
310 case TODC_TYPE_DS1557:
311 case TODC_TYPE_DS1743:
312 case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
313 case TODC_TYPE_DS1747:
314 case TODC_TYPE_DS17285:
315 break;
316 default:
317 save_control &= ~(todc_info->enable_read);
318 todc_write_val(todc_info->control_a, save_control);
319 }
320 }
321 spin_unlock(&rtc_lock);
322
323 if ((todc_info->rtc_type != TODC_TYPE_MC146818)
324 || ((save_control & RTC_DM_BINARY) == 0)
325 || RTC_ALWAYS_BCD) {
326 BCD_TO_BIN(sec);
327 BCD_TO_BIN(min);
328 BCD_TO_BIN(hour);
329 BCD_TO_BIN(mday);
330 BCD_TO_BIN(mon);
331 BCD_TO_BIN(year);
332 }
333
334 if ((year + 1900) < 1970) {
335 year += 100;
336 }
337
338 tm->tm_sec = sec;
339 tm->tm_min = min;
340 tm->tm_hour = hour;
341 tm->tm_mday = mday;
342 tm->tm_mon = mon;
343 tm->tm_year = year;
344
345 GregorianDay(tm);
346}
347
348int
349todc_set_rtc_time(struct rtc_time *tm)
350{
351 u_char save_control, save_freq_select = 0;
352
353 spin_lock(&rtc_lock);
354 save_control = todc_read_val(todc_info->control_a);
355
356 /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
357 todc_write_val(todc_info->control_a,
358 (save_control | todc_info->enable_write));
359 save_control &= ~(todc_info->enable_write); /* in case it was set */
360
361 if (todc_info->rtc_type == TODC_TYPE_MC146818) {
362 save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT);
363 todc_write_val(todc_info->RTC_FREQ_SELECT,
364 save_freq_select | RTC_DIV_RESET2);
365 }
366
367 if ((todc_info->rtc_type != TODC_TYPE_MC146818)
368 || ((save_control & RTC_DM_BINARY) == 0)
369 || RTC_ALWAYS_BCD) {
370 BIN_TO_BCD(tm->tm_sec);
371 BIN_TO_BCD(tm->tm_min);
372 BIN_TO_BCD(tm->tm_hour);
373 BIN_TO_BCD(tm->tm_mon);
374 BIN_TO_BCD(tm->tm_mday);
375 BIN_TO_BCD(tm->tm_year);
376 }
377
378 todc_write_val(todc_info->seconds, tm->tm_sec);
379 todc_write_val(todc_info->minutes, tm->tm_min);
380 todc_write_val(todc_info->hours, tm->tm_hour);
381 todc_write_val(todc_info->month, tm->tm_mon);
382 todc_write_val(todc_info->day_of_month, tm->tm_mday);
383 todc_write_val(todc_info->year, tm->tm_year);
384
385 todc_write_val(todc_info->control_a, save_control);
386
387 if (todc_info->rtc_type == TODC_TYPE_MC146818)
388 todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select);
389
390 spin_unlock(&rtc_lock);
391 return 0;
392}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f56ffef4defa..0689c0845777 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -37,6 +37,8 @@
37#include <asm/sstep.h> 37#include <asm/sstep.h>
38#include <asm/bug.h> 38#include <asm/bug.h>
39#include <asm/irq_regs.h> 39#include <asm/irq_regs.h>
40#include <asm/spu.h>
41#include <asm/spu_priv1.h>
40 42
41#ifdef CONFIG_PPC64 43#ifdef CONFIG_PPC64
42#include <asm/hvcall.h> 44#include <asm/hvcall.h>
@@ -147,6 +149,8 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
147 const char *after); 149 const char *after);
148static const char *getvecname(unsigned long vec); 150static const char *getvecname(unsigned long vec);
149 151
152static int do_spu_cmd(void);
153
150int xmon_no_auto_backtrace; 154int xmon_no_auto_backtrace;
151 155
152extern int print_insn_powerpc(unsigned long, unsigned long, int); 156extern int print_insn_powerpc(unsigned long, unsigned long, int);
@@ -209,8 +213,13 @@ Commands:\n\
209 mi show information about memory allocation\n\ 213 mi show information about memory allocation\n\
210 p call a procedure\n\ 214 p call a procedure\n\
211 r print registers\n\ 215 r print registers\n\
212 s single step\n\ 216 s single step\n"
213 S print special registers\n\ 217#ifdef CONFIG_PPC_CELL
218" ss stop execution on all spus\n\
219 sr restore execution on stopped spus\n\
220 sf # dump spu fields for spu # (in hex)\n"
221#endif
222" S print special registers\n\
214 t print backtrace\n\ 223 t print backtrace\n\
215 x exit monitor and recover\n\ 224 x exit monitor and recover\n\
216 X exit monitor and dont recover\n" 225 X exit monitor and dont recover\n"
@@ -518,6 +527,7 @@ int xmon(struct pt_regs *excp)
518 xmon_save_regs(&regs); 527 xmon_save_regs(&regs);
519 excp = &regs; 528 excp = &regs;
520 } 529 }
530
521 return xmon_core(excp, 0); 531 return xmon_core(excp, 0);
522} 532}
523EXPORT_SYMBOL(xmon); 533EXPORT_SYMBOL(xmon);
@@ -809,6 +819,8 @@ cmds(struct pt_regs *excp)
809 cacheflush(); 819 cacheflush();
810 break; 820 break;
811 case 's': 821 case 's':
822 if (do_spu_cmd() == 0)
823 break;
812 if (do_step(excp)) 824 if (do_step(excp))
813 return cmd; 825 return cmd;
814 break; 826 break;
@@ -2630,3 +2642,194 @@ void __init xmon_setup(void)
2630 if (xmon_early) 2642 if (xmon_early)
2631 debugger(NULL); 2643 debugger(NULL);
2632} 2644}
2645
2646#ifdef CONFIG_PPC_CELL
2647
2648struct spu_info {
2649 struct spu *spu;
2650 u64 saved_mfc_sr1_RW;
2651 u32 saved_spu_runcntl_RW;
2652 u8 stopped_ok;
2653};
2654
2655#define XMON_NUM_SPUS 16 /* Enough for current hardware */
2656
2657static struct spu_info spu_info[XMON_NUM_SPUS];
2658
2659void xmon_register_spus(struct list_head *list)
2660{
2661 struct spu *spu;
2662
2663 list_for_each_entry(spu, list, full_list) {
2664 if (spu->number >= XMON_NUM_SPUS) {
2665 WARN_ON(1);
2666 continue;
2667 }
2668
2669 spu_info[spu->number].spu = spu;
2670 spu_info[spu->number].stopped_ok = 0;
2671 }
2672}
2673
2674static void stop_spus(void)
2675{
2676 struct spu *spu;
2677 int i;
2678 u64 tmp;
2679
2680 for (i = 0; i < XMON_NUM_SPUS; i++) {
2681 if (!spu_info[i].spu)
2682 continue;
2683
2684 if (setjmp(bus_error_jmp) == 0) {
2685 catch_memory_errors = 1;
2686 sync();
2687
2688 spu = spu_info[i].spu;
2689
2690 spu_info[i].saved_spu_runcntl_RW =
2691 in_be32(&spu->problem->spu_runcntl_RW);
2692
2693 tmp = spu_mfc_sr1_get(spu);
2694 spu_info[i].saved_mfc_sr1_RW = tmp;
2695
2696 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2697 spu_mfc_sr1_set(spu, tmp);
2698
2699 sync();
2700 __delay(200);
2701
2702 spu_info[i].stopped_ok = 1;
2703 printf("Stopped spu %.2d\n", i);
2704 } else {
2705 catch_memory_errors = 0;
2706 printf("*** Error stopping spu %.2d\n", i);
2707 }
2708 catch_memory_errors = 0;
2709 }
2710}
2711
2712static void restart_spus(void)
2713{
2714 struct spu *spu;
2715 int i;
2716
2717 for (i = 0; i < XMON_NUM_SPUS; i++) {
2718 if (!spu_info[i].spu)
2719 continue;
2720
2721 if (!spu_info[i].stopped_ok) {
2722 printf("*** Error, spu %d was not successfully stopped"
2723 ", not restarting\n", i);
2724 continue;
2725 }
2726
2727 if (setjmp(bus_error_jmp) == 0) {
2728 catch_memory_errors = 1;
2729 sync();
2730
2731 spu = spu_info[i].spu;
2732 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
2733 out_be32(&spu->problem->spu_runcntl_RW,
2734 spu_info[i].saved_spu_runcntl_RW);
2735
2736 sync();
2737 __delay(200);
2738
2739 printf("Restarted spu %.2d\n", i);
2740 } else {
2741 catch_memory_errors = 0;
2742 printf("*** Error restarting spu %.2d\n", i);
2743 }
2744 catch_memory_errors = 0;
2745 }
2746}
2747
2748#define DUMP_WIDTH 23
2749#define DUMP_FIELD(obj, format, field) \
2750do { \
2751 if (setjmp(bus_error_jmp) == 0) { \
2752 catch_memory_errors = 1; \
2753 sync(); \
2754 printf(" %-*s = "format"\n", DUMP_WIDTH, \
2755 #field, obj->field); \
2756 sync(); \
2757 __delay(200); \
2758 } else { \
2759 catch_memory_errors = 0; \
2760 printf(" %-*s = *** Error reading field.\n", \
2761 DUMP_WIDTH, #field); \
2762 } \
2763 catch_memory_errors = 0; \
2764} while (0)
2765
2766static void dump_spu_fields(struct spu *spu)
2767{
2768 printf("Dumping spu fields at address %p:\n", spu);
2769
2770 DUMP_FIELD(spu, "0x%x", number);
2771 DUMP_FIELD(spu, "%s", name);
2772 DUMP_FIELD(spu, "%s", devnode->full_name);
2773 DUMP_FIELD(spu, "0x%x", nid);
2774 DUMP_FIELD(spu, "0x%lx", local_store_phys);
2775 DUMP_FIELD(spu, "0x%p", local_store);
2776 DUMP_FIELD(spu, "0x%lx", ls_size);
2777 DUMP_FIELD(spu, "0x%x", node);
2778 DUMP_FIELD(spu, "0x%lx", flags);
2779 DUMP_FIELD(spu, "0x%lx", dar);
2780 DUMP_FIELD(spu, "0x%lx", dsisr);
2781 DUMP_FIELD(spu, "%d", class_0_pending);
2782 DUMP_FIELD(spu, "0x%lx", irqs[0]);
2783 DUMP_FIELD(spu, "0x%lx", irqs[1]);
2784 DUMP_FIELD(spu, "0x%lx", irqs[2]);
2785 DUMP_FIELD(spu, "0x%x", slb_replace);
2786 DUMP_FIELD(spu, "%d", pid);
2787 DUMP_FIELD(spu, "%d", prio);
2788 DUMP_FIELD(spu, "0x%p", mm);
2789 DUMP_FIELD(spu, "0x%p", ctx);
2790 DUMP_FIELD(spu, "0x%p", rq);
2791 DUMP_FIELD(spu, "0x%p", timestamp);
2792 DUMP_FIELD(spu, "0x%lx", problem_phys);
2793 DUMP_FIELD(spu, "0x%p", problem);
2794 DUMP_FIELD(spu, "0x%x", problem->spu_runcntl_RW);
2795 DUMP_FIELD(spu, "0x%x", problem->spu_status_R);
2796 DUMP_FIELD(spu, "0x%x", problem->spu_npc_RW);
2797 DUMP_FIELD(spu, "0x%p", priv1);
2798
2799 if (spu->priv1)
2800 DUMP_FIELD(spu, "0x%lx", priv1->mfc_sr1_RW);
2801
2802 DUMP_FIELD(spu, "0x%p", priv2);
2803}
2804
2805static int do_spu_cmd(void)
2806{
2807 unsigned long num = 0;
2808 int cmd;
2809
2810 cmd = inchar();
2811 switch (cmd) {
2812 case 's':
2813 stop_spus();
2814 break;
2815 case 'r':
2816 restart_spus();
2817 break;
2818 case 'f':
2819 if (scanhex(&num) && num < XMON_NUM_SPUS && spu_info[num].spu)
2820 dump_spu_fields(spu_info[num].spu);
2821 else
2822 printf("*** Error: invalid spu number\n");
2823 break;
2824 default:
2825 return -1;
2826 }
2827
2828 return 0;
2829}
2830#else /* ! CONFIG_PPC_CELL */
2831static int do_spu_cmd(void)
2832{
2833 return -1;
2834}
2835#endif
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index 3397f0de1592..b84f8df325c4 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -121,8 +121,8 @@ mpc834x_sys_setup_arch(void)
121 121
122 mdata->irq[0] = MPC83xx_IRQ_EXT1; 122 mdata->irq[0] = MPC83xx_IRQ_EXT1;
123 mdata->irq[1] = MPC83xx_IRQ_EXT2; 123 mdata->irq[1] = MPC83xx_IRQ_EXT2;
124 mdata->irq[2] = -1; 124 mdata->irq[2] = PHY_POLL;
125 mdata->irq[31] = -1; 125 mdata->irq[31] = PHY_POLL;
126 126
127 /* setup the board related information for the enet controllers */ 127 /* setup the board related information for the enet controllers */
128 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); 128 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index 4f839da6782f..00a3ba57063f 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -92,9 +92,9 @@ mpc8540ads_setup_arch(void)
92 92
93 mdata->irq[0] = MPC85xx_IRQ_EXT5; 93 mdata->irq[0] = MPC85xx_IRQ_EXT5;
94 mdata->irq[1] = MPC85xx_IRQ_EXT5; 94 mdata->irq[1] = MPC85xx_IRQ_EXT5;
95 mdata->irq[2] = -1; 95 mdata->irq[2] = PHY_POLL;
96 mdata->irq[3] = MPC85xx_IRQ_EXT5; 96 mdata->irq[3] = MPC85xx_IRQ_EXT5;
97 mdata->irq[31] = -1; 97 mdata->irq[31] = PHY_POLL;
98 98
99 /* setup the board related information for the enet controllers */ 99 /* setup the board related information for the enet controllers */
100 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 100 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 14ecec7bbed7..3a060468dd95 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -156,9 +156,9 @@ mpc8560ads_setup_arch(void)
156 156
157 mdata->irq[0] = MPC85xx_IRQ_EXT5; 157 mdata->irq[0] = MPC85xx_IRQ_EXT5;
158 mdata->irq[1] = MPC85xx_IRQ_EXT5; 158 mdata->irq[1] = MPC85xx_IRQ_EXT5;
159 mdata->irq[2] = -1; 159 mdata->irq[2] = PHY_POLL;
160 mdata->irq[3] = MPC85xx_IRQ_EXT5; 160 mdata->irq[3] = MPC85xx_IRQ_EXT5;
161 mdata->irq[31] = -1; 161 mdata->irq[31] = PHY_POLL;
162 162
163 /* setup the board related information for the enet controllers */ 163 /* setup the board related information for the enet controllers */
164 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 164 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 5ce0f69c1db6..2d59eb776c95 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -451,9 +451,9 @@ mpc85xx_cds_setup_arch(void)
451 451
452 mdata->irq[0] = MPC85xx_IRQ_EXT5; 452 mdata->irq[0] = MPC85xx_IRQ_EXT5;
453 mdata->irq[1] = MPC85xx_IRQ_EXT5; 453 mdata->irq[1] = MPC85xx_IRQ_EXT5;
454 mdata->irq[2] = -1; 454 mdata->irq[2] = PHY_POLL;
455 mdata->irq[3] = -1; 455 mdata->irq[3] = PHY_POLL;
456 mdata->irq[31] = -1; 456 mdata->irq[31] = PHY_POLL;
457 457
458 /* setup the board related information for the enet controllers */ 458 /* setup the board related information for the enet controllers */
459 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 459 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 764d580ff535..1d10ab98f66d 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -129,7 +129,7 @@ sbc8560_setup_arch(void)
129 129
130 mdata->irq[25] = MPC85xx_IRQ_EXT6; 130 mdata->irq[25] = MPC85xx_IRQ_EXT6;
131 mdata->irq[26] = MPC85xx_IRQ_EXT7; 131 mdata->irq[26] = MPC85xx_IRQ_EXT7;
132 mdata->irq[31] = -1; 132 mdata->irq[31] = PHY_POLL;
133 133
134 /* setup the board related information for the enet controllers */ 134 /* setup the board related information for the enet controllers */
135 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 135 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 4bb18ab27672..b1f5b737c70d 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -123,7 +123,7 @@ gp3_setup_arch(void)
123 123
124 mdata->irq[2] = MPC85xx_IRQ_EXT5; 124 mdata->irq[2] = MPC85xx_IRQ_EXT5;
125 mdata->irq[4] = MPC85xx_IRQ_EXT5; 125 mdata->irq[4] = MPC85xx_IRQ_EXT5;
126 mdata->irq[31] = -1; 126 mdata->irq[31] = PHY_POLL;
127 127
128 /* setup the board related information for the enet controllers */ 128 /* setup the board related information for the enet controllers */
129 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 129 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c
index dd45f2e18449..4ee2bd156dc5 100644
--- a/arch/ppc/platforms/85xx/tqm85xx.c
+++ b/arch/ppc/platforms/85xx/tqm85xx.c
@@ -137,9 +137,9 @@ tqm85xx_setup_arch(void)
137 137
138 mdata->irq[0] = MPC85xx_IRQ_EXT8; 138 mdata->irq[0] = MPC85xx_IRQ_EXT8;
139 mdata->irq[1] = MPC85xx_IRQ_EXT8; 139 mdata->irq[1] = MPC85xx_IRQ_EXT8;
140 mdata->irq[2] = -1; 140 mdata->irq[2] = PHY_POLL;
141 mdata->irq[3] = MPC85xx_IRQ_EXT8; 141 mdata->irq[3] = MPC85xx_IRQ_EXT8;
142 mdata->irq[31] = -1; 142 mdata->irq[31] = PHY_POLL;
143 143
144 /* setup the board related information for the enet controllers */ 144 /* setup the board related information for the enet controllers */
145 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); 145 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index 1f9ea36837b1..0bc06768cf24 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -266,10 +266,10 @@ static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
266 int idx) 266 int idx)
267{ 267{
268 m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT; 268 m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
269 m82xx_mii_bb_pdata.irq[1] = -1; 269 m82xx_mii_bb_pdata.irq[1] = PHY_POLL;
270 m82xx_mii_bb_pdata.irq[2] = -1; 270 m82xx_mii_bb_pdata.irq[2] = PHY_POLL;
271 m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT; 271 m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
272 m82xx_mii_bb_pdata.irq[31] = -1; 272 m82xx_mii_bb_pdata.irq[31] = PHY_POLL;
273 273
274 274
275 m82xx_mii_bb_pdata.mdio_dat.offset = 275 m82xx_mii_bb_pdata.mdio_dat.offset =
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index e95d2c111747..8a0c07eb4449 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -361,7 +361,7 @@ int __init mpc866ads_init(void)
361 361
362 fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; 362 fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
363 /* No PHY interrupt line here */ 363 /* No PHY interrupt line here */
364 fmpi->irq[0xf] = -1; 364 fmpi->irq[0xf] = PHY_POLL;
365 365
366/* Since either of the uarts could be used as console, they need to ready */ 366/* Since either of the uarts could be used as console, they need to ready */
367#ifdef CONFIG_SERIAL_CPM_SMC1 367#ifdef CONFIG_SERIAL_CPM_SMC1
@@ -380,7 +380,7 @@ int __init mpc866ads_init(void)
380 380
381 fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; 381 fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
382 /* No PHY interrupt line here */ 382 /* No PHY interrupt line here */
383 fmpi->irq[0xf] = -1; 383 fmpi->irq[0xf] = PHY_POLL;
384 384
385 return 0; 385 return 0;
386} 386}
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 2af634d7acf4..eb7ab112c050 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -35,7 +35,7 @@
35#include <linux/ide.h> 35#include <linux/ide.h>
36#include <asm/io.h> 36#include <asm/io.h>
37 37
38#ifdef CONFIG_PPC_MULTIPLATFORM 38#ifdef CONFIG_PPC_CHRP
39#include <asm/processor.h> 39#include <asm/processor.h>
40#endif 40#endif
41 41
@@ -442,7 +442,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
442 hwif->speedproc = &via_set_drive; 442 hwif->speedproc = &via_set_drive;
443 443
444 444
445#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32) 445#ifdef CONFIG_PPC_CHRP
446 if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { 446 if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
447 hwif->irq = hwif->channel ? 15 : 14; 447 hwif->irq = hwif->channel ? 15 : 14;
448 } 448 }
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index f14e99276dba..096d4a100bf2 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -254,7 +254,7 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)
254 goto device_create_fail; 254 goto device_create_fail;
255 } 255 }
256 256
257 phydev->irq = -1; 257 phydev->irq = PHY_IGNORE_INTERRUPT;
258 phydev->dev.bus = &mdio_bus_type; 258 phydev->dev.bus = &mdio_bus_type;
259 259
260 if(number) 260 if(number)
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 3f4b6408b755..4b3cd3d8b62a 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -473,9 +473,9 @@
473#include <asm/byteorder.h> 473#include <asm/byteorder.h>
474#include <asm/unaligned.h> 474#include <asm/unaligned.h>
475#include <asm/uaccess.h> 475#include <asm/uaccess.h>
476#ifdef CONFIG_PPC_MULTIPLATFORM 476#ifdef CONFIG_PPC_PMAC
477#include <asm/machdep.h> 477#include <asm/machdep.h>
478#endif /* CONFIG_PPC_MULTIPLATFORM */ 478#endif /* CONFIG_PPC_PMAC */
479 479
480#include "de4x5.h" 480#include "de4x5.h"
481 481
@@ -4151,7 +4151,7 @@ get_hw_addr(struct net_device *dev)
4151 /* If possible, try to fix a broken card - SMC only so far */ 4151 /* If possible, try to fix a broken card - SMC only so far */
4152 srom_repair(dev, broken); 4152 srom_repair(dev, broken);
4153 4153
4154#ifdef CONFIG_PPC_MULTIPLATFORM 4154#ifdef CONFIG_PPC_PMAC
4155 /* 4155 /*
4156 ** If the address starts with 00 a0, we have to bit-reverse 4156 ** If the address starts with 00 a0, we have to bit-reverse
4157 ** each byte of the address. 4157 ** each byte of the address.
@@ -4168,7 +4168,7 @@ get_hw_addr(struct net_device *dev)
4168 dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1); 4168 dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
4169 } 4169 }
4170 } 4170 }
4171#endif /* CONFIG_PPC_MULTIPLATFORM */ 4171#endif /* CONFIG_PPC_PMAC */
4172 4172
4173 /* Test for a bad enet address */ 4173 /* Test for a bad enet address */
4174 status = test_bad_enet(dev, status); 4174 status = test_bad_enet(dev, status);
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index d40359204aba..c4a1ab608f6f 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -7,16 +7,30 @@
7#ifdef __KERNEL__ 7#ifdef __KERNEL__
8 8
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/compiler.h>
10#include <asm/ptrace.h> 11#include <asm/ptrace.h>
11#include <asm/processor.h> 12#include <asm/processor.h>
12 13
13extern void timer_interrupt(struct pt_regs *); 14extern void timer_interrupt(struct pt_regs *);
14 15
15#ifdef CONFIG_PPC_ISERIES 16#ifdef CONFIG_PPC64
17#include <asm/paca.h>
18
19static inline unsigned long local_get_flags(void)
20{
21 return get_paca()->soft_enabled;
22}
23
24static inline unsigned long local_irq_disable(void)
25{
26 unsigned long flag = get_paca()->soft_enabled;
27 get_paca()->soft_enabled = 0;
28 barrier();
29 return flag;
30}
16 31
17extern unsigned long local_get_flags(void);
18extern unsigned long local_irq_disable(void);
19extern void local_irq_restore(unsigned long); 32extern void local_irq_restore(unsigned long);
33extern void iseries_handle_interrupts(void);
20 34
21#define local_irq_enable() local_irq_restore(1) 35#define local_irq_enable() local_irq_restore(1)
22#define local_save_flags(flags) ((flags) = local_get_flags()) 36#define local_save_flags(flags) ((flags) = local_get_flags())
@@ -24,17 +38,14 @@ extern void local_irq_restore(unsigned long);
24 38
25#define irqs_disabled() (local_get_flags() == 0) 39#define irqs_disabled() (local_get_flags() == 0)
26 40
41#define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1)
42#define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1)
43
27#else 44#else
28 45
29#if defined(CONFIG_BOOKE) 46#if defined(CONFIG_BOOKE)
30#define SET_MSR_EE(x) mtmsr(x) 47#define SET_MSR_EE(x) mtmsr(x)
31#define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") 48#define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
32#elif defined(__powerpc64__)
33#define SET_MSR_EE(x) __mtmsrd(x, 1)
34#define local_irq_restore(flags) do { \
35 __asm__ __volatile__("": : :"memory"); \
36 __mtmsrd((flags), 1); \
37} while(0)
38#else 49#else
39#define SET_MSR_EE(x) mtmsr(x) 50#define SET_MSR_EE(x) mtmsr(x)
40#define local_irq_restore(flags) mtmsr(flags) 51#define local_irq_restore(flags) mtmsr(flags)
@@ -81,7 +92,7 @@ static inline void local_irq_save_ptr(unsigned long *flags)
81#define local_irq_save(flags) local_irq_save_ptr(&flags) 92#define local_irq_save(flags) local_irq_save_ptr(&flags)
82#define irqs_disabled() ((mfmsr() & MSR_EE) == 0) 93#define irqs_disabled() ((mfmsr() & MSR_EE) == 0)
83 94
84#endif /* CONFIG_PPC_ISERIES */ 95#endif /* CONFIG_PPC64 */
85 96
86#define mask_irq(irq) \ 97#define mask_irq(irq) \
87 ({ \ 98 ({ \
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index ce12f85fff9b..9fdd0491f6a3 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -136,22 +136,7 @@ struct qe_timers {
136 136
137/* BRG */ 137/* BRG */
138struct qe_brg { 138struct qe_brg {
139 __be32 brgc1; /* BRG1 configuration register */ 139 __be32 brgc[16]; /* BRG configuration registers */
140 __be32 brgc2; /* BRG2 configuration register */
141 __be32 brgc3; /* BRG3 configuration register */
142 __be32 brgc4; /* BRG4 configuration register */
143 __be32 brgc5; /* BRG5 configuration register */
144 __be32 brgc6; /* BRG6 configuration register */
145 __be32 brgc7; /* BRG7 configuration register */
146 __be32 brgc8; /* BRG8 configuration register */
147 __be32 brgc9; /* BRG9 configuration register */
148 __be32 brgc10; /* BRG10 configuration register */
149 __be32 brgc11; /* BRG11 configuration register */
150 __be32 brgc12; /* BRG12 configuration register */
151 __be32 brgc13; /* BRG13 configuration register */
152 __be32 brgc14; /* BRG14 configuration register */
153 __be32 brgc15; /* BRG15 configuration register */
154 __be32 brgc16; /* BRG16 configuration register */
155 u8 res0[0x40]; 140 u8 res0[0x40];
156} __attribute__ ((packed)); 141} __attribute__ ((packed));
157 142
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index 39fad685ffab..19e6f7e0a607 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -70,17 +70,9 @@ struct iommu_table {
70struct scatterlist; 70struct scatterlist;
71struct device_node; 71struct device_node;
72 72
73#ifdef CONFIG_PPC_MULTIPLATFORM
74
75/* Walks all buses and creates iommu tables */
76extern void iommu_setup_pSeries(void);
77extern void iommu_setup_dart(void);
78
79/* Frees table for an individual device node */ 73/* Frees table for an individual device node */
80extern void iommu_free_table(struct device_node *dn); 74extern void iommu_free_table(struct device_node *dn);
81 75
82#endif /* CONFIG_PPC_MULTIPLATFORM */
83
84/* Initializes an iommu_table based in values set in the passed-in 76/* Initializes an iommu_table based in values set in the passed-in
85 * structure 77 * structure
86 */ 78 */
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index c3fc7a28e3cd..41c8c9c5a254 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -248,21 +248,6 @@ extern void hpte_init_native(void);
248extern void hpte_init_lpar(void); 248extern void hpte_init_lpar(void);
249extern void hpte_init_iSeries(void); 249extern void hpte_init_iSeries(void);
250 250
251extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
252 unsigned long va, unsigned long prpn,
253 unsigned long rflags,
254 unsigned long vflags, int psize);
255
256extern long native_hpte_insert(unsigned long hpte_group,
257 unsigned long va, unsigned long prpn,
258 unsigned long rflags,
259 unsigned long vflags, int psize);
260
261extern long iSeries_hpte_insert(unsigned long hpte_group,
262 unsigned long va, unsigned long prpn,
263 unsigned long rflags,
264 unsigned long vflags, int psize);
265
266extern void stabs_alloc(void); 251extern void stabs_alloc(void);
267extern void slb_initialize(void); 252extern void slb_initialize(void);
268extern void slb_flush_and_rebolt(void); 253extern void slb_flush_and_rebolt(void);
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
new file mode 100644
index 000000000000..e9aa622f19f6
--- /dev/null
+++ b/include/asm-powerpc/mpc52xx.h
@@ -0,0 +1,287 @@
1/*
2 * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
3 * May need to be cleaned as the port goes on ...
4 *
5 * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
6 * Copyright (C) 2003 MontaVista, Software, Inc.
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 any
10 * kind, whether express or implied.
11 */
12
13#ifndef __ASM_POWERPC_MPC52xx_H__
14#define __ASM_POWERPC_MPC52xx_H__
15
16#ifndef __ASSEMBLY__
17#include <asm/types.h>
18#include <asm/prom.h>
19#endif /* __ASSEMBLY__ */
20
21
22/* ======================================================================== */
23/* HW IRQ mapping */
24/* ======================================================================== */
25
26#define MPC52xx_IRQ_L1_CRIT (0)
27#define MPC52xx_IRQ_L1_MAIN (1)
28#define MPC52xx_IRQ_L1_PERP (2)
29#define MPC52xx_IRQ_L1_SDMA (3)
30
31#define MPC52xx_IRQ_L1_OFFSET (6)
32#define MPC52xx_IRQ_L1_MASK (0xc0)
33
34#define MPC52xx_IRQ_L2_OFFSET (0)
35#define MPC52xx_IRQ_L2_MASK (0x3f)
36
37#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
38
39
40/* ======================================================================== */
41/* Structures mapping of some unit register set */
42/* ======================================================================== */
43
44#ifndef __ASSEMBLY__
45
46/* Interrupt controller Register set */
47struct mpc52xx_intr {
48 u32 per_mask; /* INTR + 0x00 */
49 u32 per_pri1; /* INTR + 0x04 */
50 u32 per_pri2; /* INTR + 0x08 */
51 u32 per_pri3; /* INTR + 0x0c */
52 u32 ctrl; /* INTR + 0x10 */
53 u32 main_mask; /* INTR + 0x14 */
54 u32 main_pri1; /* INTR + 0x18 */
55 u32 main_pri2; /* INTR + 0x1c */
56 u32 reserved1; /* INTR + 0x20 */
57 u32 enc_status; /* INTR + 0x24 */
58 u32 crit_status; /* INTR + 0x28 */
59 u32 main_status; /* INTR + 0x2c */
60 u32 per_status; /* INTR + 0x30 */
61 u32 reserved2; /* INTR + 0x34 */
62 u32 per_error; /* INTR + 0x38 */
63};
64
65/* Memory Mapping Control */
66struct mpc52xx_mmap_ctl {
67 u32 mbar; /* MMAP_CTRL + 0x00 */
68
69 u32 cs0_start; /* MMAP_CTRL + 0x04 */
70 u32 cs0_stop; /* MMAP_CTRL + 0x08 */
71 u32 cs1_start; /* MMAP_CTRL + 0x0c */
72 u32 cs1_stop; /* MMAP_CTRL + 0x10 */
73 u32 cs2_start; /* MMAP_CTRL + 0x14 */
74 u32 cs2_stop; /* MMAP_CTRL + 0x18 */
75 u32 cs3_start; /* MMAP_CTRL + 0x1c */
76 u32 cs3_stop; /* MMAP_CTRL + 0x20 */
77 u32 cs4_start; /* MMAP_CTRL + 0x24 */
78 u32 cs4_stop; /* MMAP_CTRL + 0x28 */
79 u32 cs5_start; /* MMAP_CTRL + 0x2c */
80 u32 cs5_stop; /* MMAP_CTRL + 0x30 */
81
82 u32 sdram0; /* MMAP_CTRL + 0x34 */
83 u32 sdram1; /* MMAP_CTRL + 0X38 */
84
85 u32 reserved[4]; /* MMAP_CTRL + 0x3c .. 0x48 */
86
87 u32 boot_start; /* MMAP_CTRL + 0x4c */
88 u32 boot_stop; /* MMAP_CTRL + 0x50 */
89
90 u32 ipbi_ws_ctrl; /* MMAP_CTRL + 0x54 */
91
92 u32 cs6_start; /* MMAP_CTRL + 0x58 */
93 u32 cs6_stop; /* MMAP_CTRL + 0x5c */
94 u32 cs7_start; /* MMAP_CTRL + 0x60 */
95 u32 cs7_stop; /* MMAP_CTRL + 0x64 */
96};
97
98/* SDRAM control */
99struct mpc52xx_sdram {
100 u32 mode; /* SDRAM + 0x00 */
101 u32 ctrl; /* SDRAM + 0x04 */
102 u32 config1; /* SDRAM + 0x08 */
103 u32 config2; /* SDRAM + 0x0c */
104};
105
106/* SDMA */
107struct mpc52xx_sdma {
108 u32 taskBar; /* SDMA + 0x00 */
109 u32 currentPointer; /* SDMA + 0x04 */
110 u32 endPointer; /* SDMA + 0x08 */
111 u32 variablePointer; /* SDMA + 0x0c */
112
113 u8 IntVect1; /* SDMA + 0x10 */
114 u8 IntVect2; /* SDMA + 0x11 */
115 u16 PtdCntrl; /* SDMA + 0x12 */
116
117 u32 IntPend; /* SDMA + 0x14 */
118 u32 IntMask; /* SDMA + 0x18 */
119
120 u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */
121
122 u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */
123
124 u32 cReqSelect; /* SDMA + 0x5c */
125 u32 task_size0; /* SDMA + 0x60 */
126 u32 task_size1; /* SDMA + 0x64 */
127 u32 MDEDebug; /* SDMA + 0x68 */
128 u32 ADSDebug; /* SDMA + 0x6c */
129 u32 Value1; /* SDMA + 0x70 */
130 u32 Value2; /* SDMA + 0x74 */
131 u32 Control; /* SDMA + 0x78 */
132 u32 Status; /* SDMA + 0x7c */
133 u32 PTDDebug; /* SDMA + 0x80 */
134};
135
136/* GPT */
137struct mpc52xx_gpt {
138 u32 mode; /* GPTx + 0x00 */
139 u32 count; /* GPTx + 0x04 */
140 u32 pwm; /* GPTx + 0x08 */
141 u32 status; /* GPTx + 0X0c */
142};
143
144/* GPIO */
145struct mpc52xx_gpio {
146 u32 port_config; /* GPIO + 0x00 */
147 u32 simple_gpioe; /* GPIO + 0x04 */
148 u32 simple_ode; /* GPIO + 0x08 */
149 u32 simple_ddr; /* GPIO + 0x0c */
150 u32 simple_dvo; /* GPIO + 0x10 */
151 u32 simple_ival; /* GPIO + 0x14 */
152 u8 outo_gpioe; /* GPIO + 0x18 */
153 u8 reserved1[3]; /* GPIO + 0x19 */
154 u8 outo_dvo; /* GPIO + 0x1c */
155 u8 reserved2[3]; /* GPIO + 0x1d */
156 u8 sint_gpioe; /* GPIO + 0x20 */
157 u8 reserved3[3]; /* GPIO + 0x21 */
158 u8 sint_ode; /* GPIO + 0x24 */
159 u8 reserved4[3]; /* GPIO + 0x25 */
160 u8 sint_ddr; /* GPIO + 0x28 */
161 u8 reserved5[3]; /* GPIO + 0x29 */
162 u8 sint_dvo; /* GPIO + 0x2c */
163 u8 reserved6[3]; /* GPIO + 0x2d */
164 u8 sint_inten; /* GPIO + 0x30 */
165 u8 reserved7[3]; /* GPIO + 0x31 */
166 u16 sint_itype; /* GPIO + 0x34 */
167 u16 reserved8; /* GPIO + 0x36 */
168 u8 gpio_control; /* GPIO + 0x38 */
169 u8 reserved9[3]; /* GPIO + 0x39 */
170 u8 sint_istat; /* GPIO + 0x3c */
171 u8 sint_ival; /* GPIO + 0x3d */
172 u8 bus_errs; /* GPIO + 0x3e */
173 u8 reserved10; /* GPIO + 0x3f */
174};
175
176#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD 4
177#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD 5
178#define MPC52xx_GPIO_PCI_DIS (1<<15)
179
180/* GPIO with WakeUp*/
181struct mpc52xx_gpio_wkup {
182 u8 wkup_gpioe; /* GPIO_WKUP + 0x00 */
183 u8 reserved1[3]; /* GPIO_WKUP + 0x03 */
184 u8 wkup_ode; /* GPIO_WKUP + 0x04 */
185 u8 reserved2[3]; /* GPIO_WKUP + 0x05 */
186 u8 wkup_ddr; /* GPIO_WKUP + 0x08 */
187 u8 reserved3[3]; /* GPIO_WKUP + 0x09 */
188 u8 wkup_dvo; /* GPIO_WKUP + 0x0C */
189 u8 reserved4[3]; /* GPIO_WKUP + 0x0D */
190 u8 wkup_inten; /* GPIO_WKUP + 0x10 */
191 u8 reserved5[3]; /* GPIO_WKUP + 0x11 */
192 u8 wkup_iinten; /* GPIO_WKUP + 0x14 */
193 u8 reserved6[3]; /* GPIO_WKUP + 0x15 */
194 u16 wkup_itype; /* GPIO_WKUP + 0x18 */
195 u8 reserved7[2]; /* GPIO_WKUP + 0x1A */
196 u8 wkup_maste; /* GPIO_WKUP + 0x1C */
197 u8 reserved8[3]; /* GPIO_WKUP + 0x1D */
198 u8 wkup_ival; /* GPIO_WKUP + 0x20 */
199 u8 reserved9[3]; /* GPIO_WKUP + 0x21 */
200 u8 wkup_istat; /* GPIO_WKUP + 0x24 */
201 u8 reserved10[3]; /* GPIO_WKUP + 0x25 */
202};
203
204/* XLB Bus control */
205struct mpc52xx_xlb {
206 u8 reserved[0x40];
207 u32 config; /* XLB + 0x40 */
208 u32 version; /* XLB + 0x44 */
209 u32 status; /* XLB + 0x48 */
210 u32 int_enable; /* XLB + 0x4c */
211 u32 addr_capture; /* XLB + 0x50 */
212 u32 bus_sig_capture; /* XLB + 0x54 */
213 u32 addr_timeout; /* XLB + 0x58 */
214 u32 data_timeout; /* XLB + 0x5c */
215 u32 bus_act_timeout; /* XLB + 0x60 */
216 u32 master_pri_enable; /* XLB + 0x64 */
217 u32 master_priority; /* XLB + 0x68 */
218 u32 base_address; /* XLB + 0x6c */
219 u32 snoop_window; /* XLB + 0x70 */
220};
221
222#define MPC52xx_XLB_CFG_PLDIS (1 << 31)
223#define MPC52xx_XLB_CFG_SNOOP (1 << 15)
224
225/* Clock Distribution control */
226struct mpc52xx_cdm {
227 u32 jtag_id; /* CDM + 0x00 reg0 read only */
228 u32 rstcfg; /* CDM + 0x04 reg1 read only */
229 u32 breadcrumb; /* CDM + 0x08 reg2 */
230
231 u8 mem_clk_sel; /* CDM + 0x0c reg3 byte0 */
232 u8 xlb_clk_sel; /* CDM + 0x0d reg3 byte1 read only */
233 u8 ipb_clk_sel; /* CDM + 0x0e reg3 byte2 */
234 u8 pci_clk_sel; /* CDM + 0x0f reg3 byte3 */
235
236 u8 ext_48mhz_en; /* CDM + 0x10 reg4 byte0 */
237 u8 fd_enable; /* CDM + 0x11 reg4 byte1 */
238 u16 fd_counters; /* CDM + 0x12 reg4 byte2,3 */
239
240 u32 clk_enables; /* CDM + 0x14 reg5 */
241
242 u8 osc_disable; /* CDM + 0x18 reg6 byte0 */
243 u8 reserved0[3]; /* CDM + 0x19 reg6 byte1,2,3 */
244
245 u8 ccs_sleep_enable; /* CDM + 0x1c reg7 byte0 */
246 u8 osc_sleep_enable; /* CDM + 0x1d reg7 byte1 */
247 u8 reserved1; /* CDM + 0x1e reg7 byte2 */
248 u8 ccs_qreq_test; /* CDM + 0x1f reg7 byte3 */
249
250 u8 soft_reset; /* CDM + 0x20 u8 byte0 */
251 u8 no_ckstp; /* CDM + 0x21 u8 byte0 */
252 u8 reserved2[2]; /* CDM + 0x22 u8 byte1,2,3 */
253
254 u8 pll_lock; /* CDM + 0x24 reg9 byte0 */
255 u8 pll_looselock; /* CDM + 0x25 reg9 byte1 */
256 u8 pll_sm_lockwin; /* CDM + 0x26 reg9 byte2 */
257 u8 reserved3; /* CDM + 0x27 reg9 byte3 */
258
259 u16 reserved4; /* CDM + 0x28 reg10 byte0,1 */
260 u16 mclken_div_psc1; /* CDM + 0x2a reg10 byte2,3 */
261
262 u16 reserved5; /* CDM + 0x2c reg11 byte0,1 */
263 u16 mclken_div_psc2; /* CDM + 0x2e reg11 byte2,3 */
264
265 u16 reserved6; /* CDM + 0x30 reg12 byte0,1 */
266 u16 mclken_div_psc3; /* CDM + 0x32 reg12 byte2,3 */
267
268 u16 reserved7; /* CDM + 0x34 reg13 byte0,1 */
269 u16 mclken_div_psc6; /* CDM + 0x36 reg13 byte2,3 */
270};
271
272#endif /* __ASSEMBLY__ */
273
274
275/* ========================================================================= */
276/* Prototypes for MPC52xx sysdev */
277/* ========================================================================= */
278
279#ifndef __ASSEMBLY__
280
281extern void mpc52xx_init_irq(void);
282extern unsigned int mpc52xx_get_irq(void);
283
284#endif /* __ASSEMBLY__ */
285
286#endif /* __ASM_POWERPC_MPC52xx_H__ */
287
diff --git a/include/asm-powerpc/mpc85xx.h b/include/asm-powerpc/mpc85xx.h
index ccdb8a21138f..54142997a584 100644
--- a/include/asm-powerpc/mpc85xx.h
+++ b/include/asm-powerpc/mpc85xx.h
@@ -31,14 +31,6 @@
31#include <platforms/85xx/mpc85xx_cds.h> 31#include <platforms/85xx/mpc85xx_cds.h>
32#endif 32#endif
33 33
34#define _IO_BASE isa_io_base
35#define _ISA_MEM_BASE isa_mem_base
36#ifdef CONFIG_PCI
37#define PCI_DRAM_OFFSET pci_dram_offset
38#else
39#define PCI_DRAM_OFFSET 0
40#endif
41
42/* Let modules/drivers get at CCSRBAR */ 34/* Let modules/drivers get at CCSRBAR */
43extern phys_addr_t get_ccsrbar(void); 35extern phys_addr_t get_ccsrbar(void);
44 36
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index 0a4e5c93e8e6..0d3adc09c847 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -93,7 +93,8 @@ struct paca_struct {
93 u64 stab_rr; /* stab/slb round-robin counter */ 93 u64 stab_rr; /* stab/slb round-robin counter */
94 u64 saved_r1; /* r1 save for RTAS calls */ 94 u64 saved_r1; /* r1 save for RTAS calls */
95 u64 saved_msr; /* MSR saved here by enter_rtas */ 95 u64 saved_msr; /* MSR saved here by enter_rtas */
96 u8 proc_enabled; /* irq soft-enable flag */ 96 u8 soft_enabled; /* irq soft-enable flag */
97 u8 hard_enabled; /* set if irqs are enabled in MSR */
97 u8 io_sync; /* writel() needs spin_unlock sync */ 98 u8 io_sync; /* writel() needs spin_unlock sync */
98 99
99 /* Stuff for accurate time accounting */ 100 /* Stuff for accurate time accounting */
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index 721c97f09b20..c77286051496 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -232,12 +232,10 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file,
232 unsigned long size, 232 unsigned long size,
233 pgprot_t prot); 233 pgprot_t prot);
234 234
235#if defined(CONFIG_PPC_MULTIPLATFORM) || defined(CONFIG_PPC32)
236#define HAVE_ARCH_PCI_RESOURCE_TO_USER 235#define HAVE_ARCH_PCI_RESOURCE_TO_USER
237extern void pci_resource_to_user(const struct pci_dev *dev, int bar, 236extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
238 const struct resource *rsrc, 237 const struct resource *rsrc,
239 resource_size_t *start, resource_size_t *end); 238 resource_size_t *start, resource_size_t *end);
240#endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */
241 239
242#endif /* __KERNEL__ */ 240#endif /* __KERNEL__ */
243#endif /* __ASM_POWERPC_PCI_H */ 241#endif /* __ASM_POWERPC_PCI_H */
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 6cb6fb19e57f..a26c32ee5527 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -53,10 +53,6 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin;
53 53
54#endif /* CONFIG_PPC_PREP */ 54#endif /* CONFIG_PPC_PREP */
55 55
56#ifndef CONFIG_PPC_MULTIPLATFORM
57#define _machine 0
58#endif /* CONFIG_PPC_MULTIPLATFORM */
59
60#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ 56#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
61 57
62/* 58/*
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index ec11d44eaeb5..0afee17f33b4 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -17,6 +17,7 @@
17 */ 17 */
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
20#include <linux/platform_device.h>
20#include <asm/atomic.h> 21#include <asm/atomic.h>
21 22
22/* Definitions used by the flattened device tree */ 23/* Definitions used by the flattened device tree */
@@ -333,6 +334,20 @@ extern int of_irq_map_one(struct device_node *device, int index,
333struct pci_dev; 334struct pci_dev;
334extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); 335extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
335 336
337static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
338{
339 int irq = irq_of_parse_and_map(dev, index);
340
341 /* Only dereference the resource if both the
342 * resource and the irq are valid. */
343 if (r && irq != NO_IRQ) {
344 r->start = r->end = irq;
345 r->flags = IORESOURCE_IRQ;
346 }
347
348 return irq;
349}
350
336 351
337#endif /* __KERNEL__ */ 352#endif /* __KERNEL__ */
338#endif /* _POWERPC_PROM_H */ 353#endif /* _POWERPC_PROM_H */
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index e73ea00efd8b..ffa4df083609 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -115,10 +115,10 @@ struct spu {
115 struct spu_priv2 __iomem *priv2; 115 struct spu_priv2 __iomem *priv2;
116 struct list_head list; 116 struct list_head list;
117 struct list_head sched_list; 117 struct list_head sched_list;
118 struct list_head full_list;
118 int number; 119 int number;
119 int nid; 120 int nid;
120 unsigned int irqs[3]; 121 unsigned int irqs[3];
121 u32 isrc;
122 u32 node; 122 u32 node;
123 u64 flags; 123 u64 flags;
124 u64 dar; 124 u64 dar;
@@ -144,6 +144,8 @@ struct spu {
144 char irq_c1[8]; 144 char irq_c1[8];
145 char irq_c2[8]; 145 char irq_c2[8];
146 146
147 struct device_node *devnode;
148
147 struct sys_device sysdev; 149 struct sys_device sysdev;
148}; 150};
149 151
@@ -182,8 +184,10 @@ extern struct spufs_calls {
182 */ 184 */
183#define SPU_CREATE_EVENTS_ENABLED 0x0001 185#define SPU_CREATE_EVENTS_ENABLED 0x0001
184#define SPU_CREATE_GANG 0x0002 186#define SPU_CREATE_GANG 0x0002
187#define SPU_CREATE_NOSCHED 0x0004
188#define SPU_CREATE_ISOLATE 0x0008
185 189
186#define SPU_CREATE_FLAG_ALL 0x0003 /* mask of all valid flags */ 190#define SPU_CREATE_FLAG_ALL 0x000f /* mask of all valid flags */
187 191
188 192
189#ifdef CONFIG_SPU_FS_MODULE 193#ifdef CONFIG_SPU_FS_MODULE
@@ -199,6 +203,12 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls)
199} 203}
200#endif /* MODULE */ 204#endif /* MODULE */
201 205
206int spu_add_sysdev_attr(struct sysdev_attribute *attr);
207void spu_remove_sysdev_attr(struct sysdev_attribute *attr);
208
209int spu_add_sysdev_attr_group(struct attribute_group *attrs);
210void spu_remove_sysdev_attr_group(struct attribute_group *attrs);
211
202 212
203/* 213/*
204 * Notifier blocks: 214 * Notifier blocks:
@@ -277,6 +287,7 @@ struct spu_problem {
277 u32 spu_runcntl_RW; /* 0x401c */ 287 u32 spu_runcntl_RW; /* 0x401c */
278#define SPU_RUNCNTL_STOP 0L 288#define SPU_RUNCNTL_STOP 0L
279#define SPU_RUNCNTL_RUNNABLE 1L 289#define SPU_RUNCNTL_RUNNABLE 1L
290#define SPU_RUNCNTL_ISOLATE 2L
280 u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */ 291 u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */
281 u32 spu_status_R; /* 0x4024 */ 292 u32 spu_status_R; /* 0x4024 */
282#define SPU_STOP_STATUS_SHIFT 16 293#define SPU_STOP_STATUS_SHIFT 16
@@ -289,8 +300,8 @@ struct spu_problem {
289#define SPU_STATUS_INVALID_INSTR 0x20 300#define SPU_STATUS_INVALID_INSTR 0x20
290#define SPU_STATUS_INVALID_CH 0x40 301#define SPU_STATUS_INVALID_CH 0x40
291#define SPU_STATUS_ISOLATED_STATE 0x80 302#define SPU_STATUS_ISOLATED_STATE 0x80
292#define SPU_STATUS_ISOLATED_LOAD_STAUTUS 0x200 303#define SPU_STATUS_ISOLATED_LOAD_STATUS 0x200
293#define SPU_STATUS_ISOLATED_EXIT_STAUTUS 0x400 304#define SPU_STATUS_ISOLATED_EXIT_STATUS 0x400
294 u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */ 305 u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */
295 u32 spu_spe_R; /* 0x402c */ 306 u32 spu_spe_R; /* 0x402c */
296 u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */ 307 u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */
diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h
index 964c2d38ccb7..bdbf906a767f 100644
--- a/include/asm-powerpc/spu_csa.h
+++ b/include/asm-powerpc/spu_csa.h
@@ -151,7 +151,6 @@ struct spu_priv1_collapsed {
151 u64 mfc_fir_chkstp_enable_RW; 151 u64 mfc_fir_chkstp_enable_RW;
152 u64 smf_sbi_signal_sel; 152 u64 smf_sbi_signal_sel;
153 u64 smf_ato_signal_sel; 153 u64 smf_ato_signal_sel;
154 u64 mfc_sdr_RW;
155 u64 tlb_index_hint_RO; 154 u64 tlb_index_hint_RO;
156 u64 tlb_index_W; 155 u64 tlb_index_W;
157 u64 tlb_vpn_RW; 156 u64 tlb_vpn_RW;
diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h
index 300c458b6d06..4f9a04db99f7 100644
--- a/include/asm-powerpc/spu_priv1.h
+++ b/include/asm-powerpc/spu_priv1.h
@@ -37,7 +37,7 @@ struct spu_priv1_ops
37 u64 (*mfc_dar_get) (struct spu *spu); 37 u64 (*mfc_dar_get) (struct spu *spu);
38 u64 (*mfc_dsisr_get) (struct spu *spu); 38 u64 (*mfc_dsisr_get) (struct spu *spu);
39 void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); 39 void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr);
40 void (*mfc_sdr_set) (struct spu *spu, u64 sdr); 40 void (*mfc_sdr_setup) (struct spu *spu);
41 void (*mfc_sr1_set) (struct spu *spu, u64 sr1); 41 void (*mfc_sr1_set) (struct spu *spu, u64 sr1);
42 u64 (*mfc_sr1_get) (struct spu *spu); 42 u64 (*mfc_sr1_get) (struct spu *spu);
43 void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); 43 void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id);
@@ -112,9 +112,9 @@ spu_mfc_dsisr_set (struct spu *spu, u64 dsisr)
112} 112}
113 113
114static inline void 114static inline void
115spu_mfc_sdr_set (struct spu *spu, u64 sdr) 115spu_mfc_sdr_setup (struct spu *spu)
116{ 116{
117 spu_priv1_ops->mfc_sdr_set(spu, sdr); 117 spu_priv1_ops->mfc_sdr_setup(spu);
118} 118}
119 119
120static inline void 120static inline void
diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h
deleted file mode 100644
index 60a8c39b8c11..000000000000
--- a/include/asm-powerpc/todc.h
+++ /dev/null
@@ -1,487 +0,0 @@
1/*
2 * Definitions for the M48Txx and mc146818 series of Time of day/Real Time
3 * Clock chips.
4 *
5 * Author: Mark A. Greer <mgreer@mvista.com>
6 *
7 * 2001 (c) MontaVista, Software, Inc. This file is licensed under
8 * the terms of the GNU General Public License version 2. This program
9 * is licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 */
12
13/*
14 * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips.
15 * Purpose is to make one generic file that handles all of these chips instead
16 * of every platform implementing the same code over & over again.
17 */
18
19#ifndef __PPC_KERNEL_TODC_H
20#define __PPC_KERNEL_TODC_H
21
22typedef struct {
23 uint rtc_type; /* your particular chip */
24
25 /*
26 * Following are the addresses of the AS0, AS1, and DATA registers
27 * of these chips. Note that these are board-specific.
28 */
29 unsigned int nvram_as0;
30 unsigned int nvram_as1;
31 unsigned int nvram_data;
32
33 /*
34 * Define bits to stop external set of regs from changing so
35 * the chip can be read/written reliably.
36 */
37 unsigned char enable_read;
38 unsigned char enable_write;
39
40 /*
41 * Following is the number of AS0 address bits. This is normally
42 * 8 but some bad hardware routes address lines incorrectly.
43 */
44 int as0_bits;
45
46 int nvram_size; /* Size of NVRAM on chip */
47 int sw_flags; /* Software control flags */
48
49 /* Following are the register offsets for the particular chip */
50 int year;
51 int month;
52 int day_of_month;
53 int day_of_week;
54 int hours;
55 int minutes;
56 int seconds;
57 int control_b;
58 int control_a;
59 int watchdog;
60 int interrupts;
61 int alarm_date;
62 int alarm_hour;
63 int alarm_minutes;
64 int alarm_seconds;
65 int century;
66 int flags;
67
68 /*
69 * Some RTC chips have their NVRAM buried behind a addr/data pair of
70 * regs on the first level/clock registers. The following fields
71 * are the addresses for those addr/data regs.
72 */
73 int nvram_addr_reg;
74 int nvram_data_reg;
75} todc_info_t;
76
77/*
78 * Define the types of TODC/RTC variants that are supported in
79 * arch/ppc/kernel/todc_time.c
80 * Make a new one of these for any chip somehow differs from what's already
81 * defined. That way, if you ever need to put in code to touch those
82 * bits/registers in todc_time.c, you can put it inside an
83 * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break
84 * anyone else.
85 */
86#define TODC_TYPE_MK48T35 1
87#define TODC_TYPE_MK48T37 2
88#define TODC_TYPE_MK48T59 3
89#define TODC_TYPE_DS1693 4 /* Dallas DS1693 RTC */
90#define TODC_TYPE_DS1743 5 /* Dallas DS1743 RTC */
91#define TODC_TYPE_DS1746 6 /* Dallas DS1746 RTC */
92#define TODC_TYPE_DS1747 7 /* Dallas DS1747 RTC */
93#define TODC_TYPE_DS1501 8 /* Dallas DS1501 RTC */
94#define TODC_TYPE_DS1643 9 /* Dallas DS1643 RTC */
95#define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */
96#define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */
97#define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */
98#define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */
99#define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */
100
101/*
102 * Bit to clear/set to enable reads/writes to the chip
103 */
104#define TODC_MK48TXX_CNTL_A_R 0x40
105#define TODC_MK48TXX_CNTL_A_W 0x80
106#define TODC_MK48TXX_DAY_CB 0x80
107
108#define TODC_DS1501_CNTL_B_TE 0x80
109
110/*
111 * Define flag bits used by todc routines.
112 */
113#define TODC_FLAG_2_LEVEL_NVRAM 0x00000001
114
115/*
116 * Define the values for the various RTC's that should to into the todc_info
117 * table.
118 * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only
119 * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set.
120 */
121#define TODC_TYPE_MK48T35_NVRAM_SIZE 0x7ff8
122#define TODC_TYPE_MK48T35_SW_FLAGS 0
123#define TODC_TYPE_MK48T35_YEAR 0x7fff
124#define TODC_TYPE_MK48T35_MONTH 0x7ffe
125#define TODC_TYPE_MK48T35_DOM 0x7ffd /* Day of Month */
126#define TODC_TYPE_MK48T35_DOW 0x7ffc /* Day of Week */
127#define TODC_TYPE_MK48T35_HOURS 0x7ffb
128#define TODC_TYPE_MK48T35_MINUTES 0x7ffa
129#define TODC_TYPE_MK48T35_SECONDS 0x7ff9
130#define TODC_TYPE_MK48T35_CNTL_B 0x7ff9
131#define TODC_TYPE_MK48T35_CNTL_A 0x7ff8
132#define TODC_TYPE_MK48T35_WATCHDOG 0x0000
133#define TODC_TYPE_MK48T35_INTERRUPTS 0x0000
134#define TODC_TYPE_MK48T35_ALARM_DATE 0x0000
135#define TODC_TYPE_MK48T35_ALARM_HOUR 0x0000
136#define TODC_TYPE_MK48T35_ALARM_MINUTES 0x0000
137#define TODC_TYPE_MK48T35_ALARM_SECONDS 0x0000
138#define TODC_TYPE_MK48T35_CENTURY 0x0000
139#define TODC_TYPE_MK48T35_FLAGS 0x0000
140#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG 0
141#define TODC_TYPE_MK48T35_NVRAM_DATA_REG 0
142
143#define TODC_TYPE_MK48T37_NVRAM_SIZE 0x7ff0
144#define TODC_TYPE_MK48T37_SW_FLAGS 0
145#define TODC_TYPE_MK48T37_YEAR 0x7fff
146#define TODC_TYPE_MK48T37_MONTH 0x7ffe
147#define TODC_TYPE_MK48T37_DOM 0x7ffd /* Day of Month */
148#define TODC_TYPE_MK48T37_DOW 0x7ffc /* Day of Week */
149#define TODC_TYPE_MK48T37_HOURS 0x7ffb
150#define TODC_TYPE_MK48T37_MINUTES 0x7ffa
151#define TODC_TYPE_MK48T37_SECONDS 0x7ff9
152#define TODC_TYPE_MK48T37_CNTL_B 0x7ff9
153#define TODC_TYPE_MK48T37_CNTL_A 0x7ff8
154#define TODC_TYPE_MK48T37_WATCHDOG 0x7ff7
155#define TODC_TYPE_MK48T37_INTERRUPTS 0x7ff6
156#define TODC_TYPE_MK48T37_ALARM_DATE 0x7ff5
157#define TODC_TYPE_MK48T37_ALARM_HOUR 0x7ff4
158#define TODC_TYPE_MK48T37_ALARM_MINUTES 0x7ff3
159#define TODC_TYPE_MK48T37_ALARM_SECONDS 0x7ff2
160#define TODC_TYPE_MK48T37_CENTURY 0x7ff1
161#define TODC_TYPE_MK48T37_FLAGS 0x7ff0
162#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG 0
163#define TODC_TYPE_MK48T37_NVRAM_DATA_REG 0
164
165#define TODC_TYPE_MK48T59_NVRAM_SIZE 0x1ff0
166#define TODC_TYPE_MK48T59_SW_FLAGS 0
167#define TODC_TYPE_MK48T59_YEAR 0x1fff
168#define TODC_TYPE_MK48T59_MONTH 0x1ffe
169#define TODC_TYPE_MK48T59_DOM 0x1ffd /* Day of Month */
170#define TODC_TYPE_MK48T59_DOW 0x1ffc /* Day of Week */
171#define TODC_TYPE_MK48T59_HOURS 0x1ffb
172#define TODC_TYPE_MK48T59_MINUTES 0x1ffa
173#define TODC_TYPE_MK48T59_SECONDS 0x1ff9
174#define TODC_TYPE_MK48T59_CNTL_B 0x1ff9
175#define TODC_TYPE_MK48T59_CNTL_A 0x1ff8
176#define TODC_TYPE_MK48T59_WATCHDOG 0x1fff
177#define TODC_TYPE_MK48T59_INTERRUPTS 0x1fff
178#define TODC_TYPE_MK48T59_ALARM_DATE 0x1fff
179#define TODC_TYPE_MK48T59_ALARM_HOUR 0x1fff
180#define TODC_TYPE_MK48T59_ALARM_MINUTES 0x1fff
181#define TODC_TYPE_MK48T59_ALARM_SECONDS 0x1fff
182#define TODC_TYPE_MK48T59_CENTURY 0x1fff
183#define TODC_TYPE_MK48T59_FLAGS 0x1fff
184#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG 0
185#define TODC_TYPE_MK48T59_NVRAM_DATA_REG 0
186
187#define TODC_TYPE_DS1501_NVRAM_SIZE 0x100
188#define TODC_TYPE_DS1501_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM
189#define TODC_TYPE_DS1501_YEAR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06)
190#define TODC_TYPE_DS1501_MONTH (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05)
191#define TODC_TYPE_DS1501_DOM (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04)
192#define TODC_TYPE_DS1501_DOW (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03)
193#define TODC_TYPE_DS1501_HOURS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02)
194#define TODC_TYPE_DS1501_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01)
195#define TODC_TYPE_DS1501_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00)
196#define TODC_TYPE_DS1501_CNTL_B (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
197#define TODC_TYPE_DS1501_CNTL_A (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
198#define TODC_TYPE_DS1501_WATCHDOG (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
199#define TODC_TYPE_DS1501_INTERRUPTS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
200#define TODC_TYPE_DS1501_ALARM_DATE (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b)
201#define TODC_TYPE_DS1501_ALARM_HOUR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a)
202#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09)
203#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08)
204#define TODC_TYPE_DS1501_CENTURY (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07)
205#define TODC_TYPE_DS1501_FLAGS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
206#define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10
207#define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13
208
209#define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0
210#define TODC_TYPE_DS1553_SW_FLAGS 0
211#define TODC_TYPE_DS1553_YEAR 0x1fff
212#define TODC_TYPE_DS1553_MONTH 0x1ffe
213#define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */
214#define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */
215#define TODC_TYPE_DS1553_HOURS 0x1ffb
216#define TODC_TYPE_DS1553_MINUTES 0x1ffa
217#define TODC_TYPE_DS1553_SECONDS 0x1ff9
218#define TODC_TYPE_DS1553_CNTL_B 0x1ff9
219#define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */
220#define TODC_TYPE_DS1553_WATCHDOG 0x1ff7
221#define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6
222#define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5
223#define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4
224#define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3
225#define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2
226#define TODC_TYPE_DS1553_CENTURY 0x1ff8
227#define TODC_TYPE_DS1553_FLAGS 0x1ff0
228#define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0
229#define TODC_TYPE_DS1553_NVRAM_DATA_REG 0
230
231#define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0
232#define TODC_TYPE_DS1557_SW_FLAGS 0
233#define TODC_TYPE_DS1557_YEAR 0x7ffff
234#define TODC_TYPE_DS1557_MONTH 0x7fffe
235#define TODC_TYPE_DS1557_DOM 0x7fffd /* Day of Month */
236#define TODC_TYPE_DS1557_DOW 0x7fffc /* Day of Week */
237#define TODC_TYPE_DS1557_HOURS 0x7fffb
238#define TODC_TYPE_DS1557_MINUTES 0x7fffa
239#define TODC_TYPE_DS1557_SECONDS 0x7fff9
240#define TODC_TYPE_DS1557_CNTL_B 0x7fff9
241#define TODC_TYPE_DS1557_CNTL_A 0x7fff8 /* control_a R/W regs */
242#define TODC_TYPE_DS1557_WATCHDOG 0x7fff7
243#define TODC_TYPE_DS1557_INTERRUPTS 0x7fff6
244#define TODC_TYPE_DS1557_ALARM_DATE 0x7fff5
245#define TODC_TYPE_DS1557_ALARM_HOUR 0x7fff4
246#define TODC_TYPE_DS1557_ALARM_MINUTES 0x7fff3
247#define TODC_TYPE_DS1557_ALARM_SECONDS 0x7fff2
248#define TODC_TYPE_DS1557_CENTURY 0x7fff8
249#define TODC_TYPE_DS1557_FLAGS 0x7fff0
250#define TODC_TYPE_DS1557_NVRAM_ADDR_REG 0
251#define TODC_TYPE_DS1557_NVRAM_DATA_REG 0
252
253#define TODC_TYPE_DS1643_NVRAM_SIZE 0x1ff8
254#define TODC_TYPE_DS1643_SW_FLAGS 0
255#define TODC_TYPE_DS1643_YEAR 0x1fff
256#define TODC_TYPE_DS1643_MONTH 0x1ffe
257#define TODC_TYPE_DS1643_DOM 0x1ffd /* Day of Month */
258#define TODC_TYPE_DS1643_DOW 0x1ffc /* Day of Week */
259#define TODC_TYPE_DS1643_HOURS 0x1ffb
260#define TODC_TYPE_DS1643_MINUTES 0x1ffa
261#define TODC_TYPE_DS1643_SECONDS 0x1ff9
262#define TODC_TYPE_DS1643_CNTL_B 0x1ff9
263#define TODC_TYPE_DS1643_CNTL_A 0x1ff8 /* control_a R/W regs */
264#define TODC_TYPE_DS1643_WATCHDOG 0x1fff
265#define TODC_TYPE_DS1643_INTERRUPTS 0x1fff
266#define TODC_TYPE_DS1643_ALARM_DATE 0x1fff
267#define TODC_TYPE_DS1643_ALARM_HOUR 0x1fff
268#define TODC_TYPE_DS1643_ALARM_MINUTES 0x1fff
269#define TODC_TYPE_DS1643_ALARM_SECONDS 0x1fff
270#define TODC_TYPE_DS1643_CENTURY 0x1ff8
271#define TODC_TYPE_DS1643_FLAGS 0x1fff
272#define TODC_TYPE_DS1643_NVRAM_ADDR_REG 0
273#define TODC_TYPE_DS1643_NVRAM_DATA_REG 0
274
275#define TODC_TYPE_DS1693_NVRAM_SIZE 0 /* Not handled yet */
276#define TODC_TYPE_DS1693_SW_FLAGS 0
277#define TODC_TYPE_DS1693_YEAR 0x09
278#define TODC_TYPE_DS1693_MONTH 0x08
279#define TODC_TYPE_DS1693_DOM 0x07 /* Day of Month */
280#define TODC_TYPE_DS1693_DOW 0x06 /* Day of Week */
281#define TODC_TYPE_DS1693_HOURS 0x04
282#define TODC_TYPE_DS1693_MINUTES 0x02
283#define TODC_TYPE_DS1693_SECONDS 0x00
284#define TODC_TYPE_DS1693_CNTL_B 0x0b
285#define TODC_TYPE_DS1693_CNTL_A 0x0a
286#define TODC_TYPE_DS1693_WATCHDOG 0xff
287#define TODC_TYPE_DS1693_INTERRUPTS 0xff
288#define TODC_TYPE_DS1693_ALARM_DATE 0x49
289#define TODC_TYPE_DS1693_ALARM_HOUR 0x05
290#define TODC_TYPE_DS1693_ALARM_MINUTES 0x03
291#define TODC_TYPE_DS1693_ALARM_SECONDS 0x01
292#define TODC_TYPE_DS1693_CENTURY 0x48
293#define TODC_TYPE_DS1693_FLAGS 0xff
294#define TODC_TYPE_DS1693_NVRAM_ADDR_REG 0
295#define TODC_TYPE_DS1693_NVRAM_DATA_REG 0
296
297#define TODC_TYPE_DS1743_NVRAM_SIZE 0x1ff8
298#define TODC_TYPE_DS1743_SW_FLAGS 0
299#define TODC_TYPE_DS1743_YEAR 0x1fff
300#define TODC_TYPE_DS1743_MONTH 0x1ffe
301#define TODC_TYPE_DS1743_DOM 0x1ffd /* Day of Month */
302#define TODC_TYPE_DS1743_DOW 0x1ffc /* Day of Week */
303#define TODC_TYPE_DS1743_HOURS 0x1ffb
304#define TODC_TYPE_DS1743_MINUTES 0x1ffa
305#define TODC_TYPE_DS1743_SECONDS 0x1ff9
306#define TODC_TYPE_DS1743_CNTL_B 0x1ff9
307#define TODC_TYPE_DS1743_CNTL_A 0x1ff8 /* control_a R/W regs */
308#define TODC_TYPE_DS1743_WATCHDOG 0x1fff
309#define TODC_TYPE_DS1743_INTERRUPTS 0x1fff
310#define TODC_TYPE_DS1743_ALARM_DATE 0x1fff
311#define TODC_TYPE_DS1743_ALARM_HOUR 0x1fff
312#define TODC_TYPE_DS1743_ALARM_MINUTES 0x1fff
313#define TODC_TYPE_DS1743_ALARM_SECONDS 0x1fff
314#define TODC_TYPE_DS1743_CENTURY 0x1ff8
315#define TODC_TYPE_DS1743_FLAGS 0x1fff
316#define TODC_TYPE_DS1743_NVRAM_ADDR_REG 0
317#define TODC_TYPE_DS1743_NVRAM_DATA_REG 0
318
319#define TODC_TYPE_DS1746_NVRAM_SIZE 0x1fff8
320#define TODC_TYPE_DS1746_SW_FLAGS 0
321#define TODC_TYPE_DS1746_YEAR 0x1ffff
322#define TODC_TYPE_DS1746_MONTH 0x1fffe
323#define TODC_TYPE_DS1746_DOM 0x1fffd /* Day of Month */
324#define TODC_TYPE_DS1746_DOW 0x1fffc /* Day of Week */
325#define TODC_TYPE_DS1746_HOURS 0x1fffb
326#define TODC_TYPE_DS1746_MINUTES 0x1fffa
327#define TODC_TYPE_DS1746_SECONDS 0x1fff9
328#define TODC_TYPE_DS1746_CNTL_B 0x1fff9
329#define TODC_TYPE_DS1746_CNTL_A 0x1fff8 /* control_a R/W regs */
330#define TODC_TYPE_DS1746_WATCHDOG 0x00000
331#define TODC_TYPE_DS1746_INTERRUPTS 0x00000
332#define TODC_TYPE_DS1746_ALARM_DATE 0x00000
333#define TODC_TYPE_DS1746_ALARM_HOUR 0x00000
334#define TODC_TYPE_DS1746_ALARM_MINUTES 0x00000
335#define TODC_TYPE_DS1746_ALARM_SECONDS 0x00000
336#define TODC_TYPE_DS1746_CENTURY 0x00000
337#define TODC_TYPE_DS1746_FLAGS 0x00000
338#define TODC_TYPE_DS1746_NVRAM_ADDR_REG 0
339#define TODC_TYPE_DS1746_NVRAM_DATA_REG 0
340
341#define TODC_TYPE_DS1747_NVRAM_SIZE 0x7fff8
342#define TODC_TYPE_DS1747_SW_FLAGS 0
343#define TODC_TYPE_DS1747_YEAR 0x7ffff
344#define TODC_TYPE_DS1747_MONTH 0x7fffe
345#define TODC_TYPE_DS1747_DOM 0x7fffd /* Day of Month */
346#define TODC_TYPE_DS1747_DOW 0x7fffc /* Day of Week */
347#define TODC_TYPE_DS1747_HOURS 0x7fffb
348#define TODC_TYPE_DS1747_MINUTES 0x7fffa
349#define TODC_TYPE_DS1747_SECONDS 0x7fff9
350#define TODC_TYPE_DS1747_CNTL_B 0x7fff9
351#define TODC_TYPE_DS1747_CNTL_A 0x7fff8 /* control_a R/W regs */
352#define TODC_TYPE_DS1747_WATCHDOG 0x00000
353#define TODC_TYPE_DS1747_INTERRUPTS 0x00000
354#define TODC_TYPE_DS1747_ALARM_DATE 0x00000
355#define TODC_TYPE_DS1747_ALARM_HOUR 0x00000
356#define TODC_TYPE_DS1747_ALARM_MINUTES 0x00000
357#define TODC_TYPE_DS1747_ALARM_SECONDS 0x00000
358#define TODC_TYPE_DS1747_CENTURY 0x00000
359#define TODC_TYPE_DS1747_FLAGS 0x00000
360#define TODC_TYPE_DS1747_NVRAM_ADDR_REG 0
361#define TODC_TYPE_DS1747_NVRAM_DATA_REG 0
362
363#define TODC_TYPE_DS17285_NVRAM_SIZE (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */
364#define TODC_TYPE_DS17285_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM
365#define TODC_TYPE_DS17285_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00)
366#define TODC_TYPE_DS17285_ALARM_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01)
367#define TODC_TYPE_DS17285_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02)
368#define TODC_TYPE_DS17285_ALARM_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03)
369#define TODC_TYPE_DS17285_HOURS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04)
370#define TODC_TYPE_DS17285_ALARM_HOUR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05)
371#define TODC_TYPE_DS17285_DOW (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06)
372#define TODC_TYPE_DS17285_DOM (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07)
373#define TODC_TYPE_DS17285_MONTH (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08)
374#define TODC_TYPE_DS17285_YEAR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09)
375#define TODC_TYPE_DS17285_CNTL_A (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A)
376#define TODC_TYPE_DS17285_CNTL_B (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B)
377#define TODC_TYPE_DS17285_CNTL_C (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C)
378#define TODC_TYPE_DS17285_CNTL_D (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D)
379#define TODC_TYPE_DS17285_WATCHDOG 0
380#define TODC_TYPE_DS17285_INTERRUPTS 0
381#define TODC_TYPE_DS17285_ALARM_DATE 0
382#define TODC_TYPE_DS17285_CENTURY 0
383#define TODC_TYPE_DS17285_FLAGS 0
384#define TODC_TYPE_DS17285_NVRAM_ADDR_REG 0x50
385#define TODC_TYPE_DS17285_NVRAM_DATA_REG 0x53
386
387#define TODC_TYPE_MC146818_NVRAM_SIZE 0 /* XXXX */
388#define TODC_TYPE_MC146818_SW_FLAGS 0
389#define TODC_TYPE_MC146818_YEAR 0x09
390#define TODC_TYPE_MC146818_MONTH 0x08
391#define TODC_TYPE_MC146818_DOM 0x07 /* Day of Month */
392#define TODC_TYPE_MC146818_DOW 0x06 /* Day of Week */
393#define TODC_TYPE_MC146818_HOURS 0x04
394#define TODC_TYPE_MC146818_MINUTES 0x02
395#define TODC_TYPE_MC146818_SECONDS 0x00
396#define TODC_TYPE_MC146818_CNTL_B 0x0a
397#define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */
398#define TODC_TYPE_MC146818_WATCHDOG 0
399#define TODC_TYPE_MC146818_INTERRUPTS 0x0c
400#define TODC_TYPE_MC146818_ALARM_DATE 0xff
401#define TODC_TYPE_MC146818_ALARM_HOUR 0x05
402#define TODC_TYPE_MC146818_ALARM_MINUTES 0x03
403#define TODC_TYPE_MC146818_ALARM_SECONDS 0x01
404#define TODC_TYPE_MC146818_CENTURY 0xff
405#define TODC_TYPE_MC146818_FLAGS 0xff
406#define TODC_TYPE_MC146818_NVRAM_ADDR_REG 0
407#define TODC_TYPE_MC146818_NVRAM_DATA_REG 0
408
409#define TODC_TYPE_PC97307_NVRAM_SIZE 0 /* No NVRAM? */
410#define TODC_TYPE_PC97307_SW_FLAGS 0
411#define TODC_TYPE_PC97307_YEAR 0x09
412#define TODC_TYPE_PC97307_MONTH 0x08
413#define TODC_TYPE_PC97307_DOM 0x07 /* Day of Month */
414#define TODC_TYPE_PC97307_DOW 0x06 /* Day of Week */
415#define TODC_TYPE_PC97307_HOURS 0x04
416#define TODC_TYPE_PC97307_MINUTES 0x02
417#define TODC_TYPE_PC97307_SECONDS 0x00
418#define TODC_TYPE_PC97307_CNTL_B 0x0a
419#define TODC_TYPE_PC97307_CNTL_A 0x0b /* control_a R/W regs */
420#define TODC_TYPE_PC97307_WATCHDOG 0x0c
421#define TODC_TYPE_PC97307_INTERRUPTS 0x0d
422#define TODC_TYPE_PC97307_ALARM_DATE 0xff
423#define TODC_TYPE_PC97307_ALARM_HOUR 0x05
424#define TODC_TYPE_PC97307_ALARM_MINUTES 0x03
425#define TODC_TYPE_PC97307_ALARM_SECONDS 0x01
426#define TODC_TYPE_PC97307_CENTURY 0xff
427#define TODC_TYPE_PC97307_FLAGS 0xff
428#define TODC_TYPE_PC97307_NVRAM_ADDR_REG 0
429#define TODC_TYPE_PC97307_NVRAM_DATA_REG 0
430
431/*
432 * Define macros to allocate and init the todc_info_t table that will
433 * be used by the todc_time.c routines.
434 */
435#define TODC_ALLOC() \
436 static todc_info_t todc_info_alloc; \
437 todc_info_t *todc_info = &todc_info_alloc;
438
439#define TODC_INIT(clock_type, as0, as1, data, bits) { \
440 todc_info->rtc_type = clock_type; \
441 \
442 todc_info->nvram_as0 = (unsigned int)(as0); \
443 todc_info->nvram_as1 = (unsigned int)(as1); \
444 todc_info->nvram_data = (unsigned int)(data); \
445 \
446 todc_info->as0_bits = (bits); \
447 \
448 todc_info->nvram_size = clock_type ##_NVRAM_SIZE; \
449 todc_info->sw_flags = clock_type ##_SW_FLAGS; \
450 \
451 todc_info->year = clock_type ##_YEAR; \
452 todc_info->month = clock_type ##_MONTH; \
453 todc_info->day_of_month = clock_type ##_DOM; \
454 todc_info->day_of_week = clock_type ##_DOW; \
455 todc_info->hours = clock_type ##_HOURS; \
456 todc_info->minutes = clock_type ##_MINUTES; \
457 todc_info->seconds = clock_type ##_SECONDS; \
458 todc_info->control_b = clock_type ##_CNTL_B; \
459 todc_info->control_a = clock_type ##_CNTL_A; \
460 todc_info->watchdog = clock_type ##_WATCHDOG; \
461 todc_info->interrupts = clock_type ##_INTERRUPTS; \
462 todc_info->alarm_date = clock_type ##_ALARM_DATE; \
463 todc_info->alarm_hour = clock_type ##_ALARM_HOUR; \
464 todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES; \
465 todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS; \
466 todc_info->century = clock_type ##_CENTURY; \
467 todc_info->flags = clock_type ##_FLAGS; \
468 \
469 todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG; \
470 todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG; \
471}
472
473extern todc_info_t *todc_info;
474
475unsigned char todc_direct_read_val(int addr);
476void todc_direct_write_val(int addr, unsigned char val);
477unsigned char todc_m48txx_read_val(int addr);
478void todc_m48txx_write_val(int addr, unsigned char val);
479unsigned char todc_mc146818_read_val(int addr);
480void todc_mc146818_write_val(int addr, unsigned char val);
481
482long todc_time_init(void);
483void todc_get_rtc_time(struct rtc_time *);
484int todc_set_rtc_time(struct rtc_time *);
485void todc_calibrate_decr(void);
486
487#endif /* __PPC_KERNEL_TODC_H */
diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h
index f1d337ed68d5..88320a05f0a8 100644
--- a/include/asm-powerpc/xmon.h
+++ b/include/asm-powerpc/xmon.h
@@ -14,8 +14,10 @@
14 14
15#ifdef CONFIG_XMON 15#ifdef CONFIG_XMON
16extern void xmon_setup(void); 16extern void xmon_setup(void);
17extern void xmon_register_spus(struct list_head *list);
17#else 18#else
18static inline void xmon_setup(void) { }; 19static inline void xmon_setup(void) { };
20static inline void xmon_register_spus(struct list_head *list) { };
19#endif 21#endif
20 22
21#endif /* __KERNEL __ */ 23#endif /* __KERNEL __ */
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index a4c411b753ef..b744baf9e206 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -26,17 +26,11 @@
26 26
27#if defined(CONFIG_4xx) 27#if defined(CONFIG_4xx)
28#include <asm/ibm4xx.h> 28#include <asm/ibm4xx.h>
29#elif defined(CONFIG_PPC_MPC52xx)
30#include <asm/mpc52xx.h>
31#elif defined(CONFIG_8xx) 29#elif defined(CONFIG_8xx)
32#include <asm/mpc8xx.h> 30#include <asm/mpc8xx.h>
33#elif defined(CONFIG_8260) 31#elif defined(CONFIG_8260)
34#include <asm/mpc8260.h> 32#include <asm/mpc8260.h>
35#elif defined(CONFIG_83xx) 33#elif defined(CONFIG_APUS) || !defined(CONFIG_PCI)
36#include <asm/mpc83xx.h>
37#elif defined(CONFIG_85xx)
38#include <asm/mpc85xx.h>
39#elif defined(CONFIG_APUS)
40#define _IO_BASE 0 34#define _IO_BASE 0
41#define _ISA_MEM_BASE 0 35#define _ISA_MEM_BASE 0
42#define PCI_DRAM_OFFSET 0 36#define PCI_DRAM_OFFSET 0
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 64c8874618dc..d9d21aa68ba3 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -29,17 +29,6 @@ struct pt_regs;
29#endif /* __ASSEMBLY__ */ 29#endif /* __ASSEMBLY__ */
30 30
31 31
32#ifdef CONFIG_PCI
33#define _IO_BASE isa_io_base
34#define _ISA_MEM_BASE isa_mem_base
35#define PCI_DRAM_OFFSET pci_dram_offset
36#else
37#define _IO_BASE 0
38#define _ISA_MEM_BASE 0
39#define PCI_DRAM_OFFSET 0
40#endif
41
42
43/* ======================================================================== */ 32/* ======================================================================== */
44/* PPC Sys devices definition */ 33/* PPC Sys devices definition */
45/* ======================================================================== */ 34/* ======================================================================== */
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
index 02ed2c325714..c3061972309b 100644
--- a/include/asm-ppc/mpc83xx.h
+++ b/include/asm-ppc/mpc83xx.h
@@ -25,14 +25,6 @@
25#include <platforms/83xx/mpc834x_sys.h> 25#include <platforms/83xx/mpc834x_sys.h>
26#endif 26#endif
27 27
28#define _IO_BASE isa_io_base
29#define _ISA_MEM_BASE isa_mem_base
30#ifdef CONFIG_PCI
31#define PCI_DRAM_OFFSET pci_dram_offset
32#else
33#define PCI_DRAM_OFFSET 0
34#endif
35
36/* 28/*
37 * The "residual" board information structure the boot loader passes 29 * The "residual" board information structure the boot loader passes
38 * into the kernel. 30 * into the kernel.
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 9b4851199c76..d7e4a79d77fb 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -44,14 +44,6 @@
44#include <platforms/85xx/tqm85xx.h> 44#include <platforms/85xx/tqm85xx.h>
45#endif 45#endif
46 46
47#define _IO_BASE isa_io_base
48#define _ISA_MEM_BASE isa_mem_base
49#ifdef CONFIG_PCI
50#define PCI_DRAM_OFFSET pci_dram_offset
51#else
52#define PCI_DRAM_OFFSET 0
53#endif
54
55/* 47/*
56 * The "residual" board information structure the boot loader passes 48 * The "residual" board information structure the boot loader passes
57 * into the kernel. 49 * into the kernel.
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 3fef7d67aedc..f02d71bf6894 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -33,6 +33,14 @@ struct cpu {
33 33
34extern int register_cpu(struct cpu *cpu, int num); 34extern int register_cpu(struct cpu *cpu, int num);
35extern struct sys_device *get_cpu_sysdev(unsigned cpu); 35extern struct sys_device *get_cpu_sysdev(unsigned cpu);
36
37extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr);
38extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr);
39
40extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs);
41extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs);
42
43
36#ifdef CONFIG_HOTPLUG_CPU 44#ifdef CONFIG_HOTPLUG_CPU
37extern void unregister_cpu(struct cpu *cpu); 45extern void unregister_cpu(struct cpu *cpu);
38#endif 46#endif