Merge branch 'linux-2.6' into for-linus
authorPaul Mackerras <paulus@samba.org>
Mon, 4 Dec 2006 04:59:07 +0000 (15:59 +1100)
committerPaul Mackerras <paulus@samba.org>
Mon, 4 Dec 2006 04:59:07 +0000 (15:59 +1100)
108 files changed:
arch/powerpc/Kconfig
arch/powerpc/boot/.gitignore
arch/powerpc/boot/Makefile
arch/powerpc/boot/flatdevtree.c [new file with mode: 0644]
arch/powerpc/boot/flatdevtree.h
arch/powerpc/boot/flatdevtree_env.h [new file with mode: 0644]
arch/powerpc/boot/flatdevtree_misc.c [new file with mode: 0644]
arch/powerpc/boot/io.h [new file with mode: 0644]
arch/powerpc/boot/main.c
arch/powerpc/boot/mktree.c [new file with mode: 0644]
arch/powerpc/boot/ns16550.c [new file with mode: 0644]
arch/powerpc/boot/of.c
arch/powerpc/boot/ops.h
arch/powerpc/boot/serial.c [new file with mode: 0644]
arch/powerpc/boot/simple_alloc.c [new file with mode: 0644]
arch/powerpc/boot/stdio.c
arch/powerpc/boot/util.S [new file with mode: 0644]
arch/powerpc/boot/wrapper
arch/powerpc/boot/zImage.coff.lds.S
arch/powerpc/configs/cell_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_ppc970.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/idle_power4.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_native_64.c
arch/powerpc/platforms/Makefile
arch/powerpc/platforms/cell/Kconfig
arch/powerpc/platforms/cell/Makefile
arch/powerpc/platforms/cell/cbe_cpufreq.c [new file with mode: 0644]
arch/powerpc/platforms/cell/cbe_regs.c
arch/powerpc/platforms/cell/cbe_regs.h
arch/powerpc/platforms/cell/cbe_thermal.c [new file with mode: 0644]
arch/powerpc/platforms/cell/pervasive.c
arch/powerpc/platforms/cell/pmu.c [new file with mode: 0644]
arch/powerpc/platforms/cell/pmu.h [new file with mode: 0644]
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/cell/spu_priv1_mmio.c
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/hw_ops.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/run.c
arch/powerpc/platforms/cell/spufs/spufs.h
arch/powerpc/platforms/cell/spufs/switch.c
arch/powerpc/platforms/efika/Makefile [new file with mode: 0644]
arch/powerpc/platforms/efika/efika.h [new file with mode: 0644]
arch/powerpc/platforms/efika/pci.c [new file with mode: 0644]
arch/powerpc/platforms/efika/setup.c [new file with mode: 0644]
arch/powerpc/platforms/iseries/dt.c
arch/powerpc/platforms/iseries/ksyms.c
arch/powerpc/platforms/iseries/misc.S
arch/powerpc/platforms/iseries/setup.c
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/mpc52xx_pic.c [new file with mode: 0644]
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/sysdev/todc.c [deleted file]
arch/powerpc/xmon/xmon.c
arch/ppc/platforms/83xx/mpc834x_sys.c
arch/ppc/platforms/85xx/mpc8540_ads.c
arch/ppc/platforms/85xx/mpc8560_ads.c
arch/ppc/platforms/85xx/mpc85xx_cds_common.c
arch/ppc/platforms/85xx/sbc8560.c
arch/ppc/platforms/85xx/stx_gp3.c
arch/ppc/platforms/85xx/tqm85xx.c
arch/ppc/platforms/mpc8272ads_setup.c
arch/ppc/platforms/mpc866ads_setup.c
drivers/ide/pci/via82cxxx.c
drivers/net/phy/fixed.c
drivers/net/tulip/de4x5.c
include/asm-powerpc/hw_irq.h
include/asm-powerpc/immap_qe.h
include/asm-powerpc/iommu.h
include/asm-powerpc/mmu.h
include/asm-powerpc/mpc52xx.h [new file with mode: 0644]
include/asm-powerpc/mpc85xx.h
include/asm-powerpc/paca.h
include/asm-powerpc/pci.h
include/asm-powerpc/processor.h
include/asm-powerpc/prom.h
include/asm-powerpc/spu.h
include/asm-powerpc/spu_csa.h
include/asm-powerpc/spu_priv1.h
include/asm-powerpc/todc.h [deleted file]
include/asm-powerpc/xmon.h
include/asm-ppc/io.h
include/asm-ppc/mpc52xx.h
include/asm-ppc/mpc83xx.h
include/asm-ppc/mpc85xx.h
include/linux/cpu.h

index 116d7d3..96316c8 100644 (file)
@@ -386,6 +386,14 @@ config PPC_CHRP
        select PPC_UDBG_16550
        default y
 
+config PPC_EFIKA
+       bool "bPlan Efika 5k2. MPC5200B based computer"
+       depends on PPC_MULTIPLATFORM && PPC32
+       select PPC_RTAS
+       select RTAS_PROC
+       select PPC_MPC52xx
+       default y
+
 config PPC_PMAC
        bool "Apple PowerMac based machines"
        depends on PPC_MULTIPLATFORM
@@ -594,12 +602,6 @@ config TAU_AVERAGE
 
          If in doubt, say N here.
 
-config PPC_TODC
-       depends on EMBEDDED6xx
-       bool "Generic Time-of-day Clock (TODC) support"
-       ---help---
-         This adds support for many TODC/RTC chips.
-
 endmenu
 
 source arch/powerpc/platforms/embedded6xx/Kconfig
index 45c9ad2..590e72f 100644 (file)
@@ -1,20 +1,27 @@
 addnote
+empty.c
+hack-coff
 infblock.c
 infblock.h
 infcodes.c
 infcodes.h
 inffast.c
 inffast.h
+inffixed.h
 inflate.c
+inflate.h
 inftrees.c
 inftrees.h
 infutil.c
 infutil.h
 kernel-vmlinux.strip.c
 kernel-vmlinux.strip.gz
+mktree
 uImage
 zImage
 zImage.vmode
+zImage.coff.lds
+zImage.lds
 zconf.h
 zlib.h
 zutil.h
index 4b2be61..4a6f0f0 100644 (file)
@@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
                $(addprefix $(obj)/,$(zlibheader))
 
-src-wlib := string.S stdio.c main.c div64.S $(zlib)
+src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
+               ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib)
 src-plat := of.c
 src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
 
@@ -74,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
        @cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
-               $(obj)/empty.c
+               empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint
 
 quiet_cmd_bootcc = BOOTCC  $@
       cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -93,13 +94,13 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
 $(obj)/wrapper.a: $(obj-wlib)
        $(call cmd,bootar)
 
-hostprogs-y    := addnote addRamDisk hack-coff
+hostprogs-y    := addnote addRamDisk hack-coff mktree
 
 extra-y                := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
                   $(obj)/zImage.lds $(obj)/zImage.coff.lds
 
 wrapper                :=$(srctree)/$(src)/wrapper
-wrapperbits    := $(extra-y) $(addprefix $(obj)/,addnote hack-coff)
+wrapperbits    := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree)
 
 #############
 # 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 (file)
index 0000000..c76c194
--- /dev/null
@@ -0,0 +1,880 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright Pantelis Antoniou 2006
+ * Copyright (C) IBM Corporation 2006
+ *
+ * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
+ *         Hollis Blanchard <hollisb@us.ibm.com>
+ *         Mark A. Greer <mgreer@mvista.com>
+ *         Paul Mackerras <paulus@samba.org>
+ */
+
+#include <string.h>
+#include <stddef.h>
+#include "flatdevtree.h"
+#include "flatdevtree_env.h"
+
+#define _ALIGN(x, al)  (((x) + (al) - 1) & ~((al) - 1))
+
+/* Routines for keeping node ptrs returned by ft_find_device current */
+/* First entry not used b/c it would return 0 and be taken as NULL/error */
+static void *ft_node_add(struct ft_cxt *cxt, char *node)
+{
+       unsigned int i;
+
+       for (i = 1; i < cxt->nodes_used; i++)   /* already there? */
+               if (cxt->node_tbl[i] == node)
+                       return (void *)i;
+
+       if (cxt->nodes_used < cxt->node_max) {
+               cxt->node_tbl[cxt->nodes_used] = node;
+               return (void *)cxt->nodes_used++;
+       }
+
+       return NULL;
+}
+
+static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
+{
+       unsigned int i = (unsigned int)phandle;
+
+       if (i < cxt->nodes_used)
+               return cxt->node_tbl[i];
+       return NULL;
+}
+
+static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
+{
+       unsigned int i;
+
+       if (shift == 0)
+               return;
+
+       for (i = 1; i < cxt->nodes_used; i++)
+               if (cxt->node_tbl[i] < addr)
+                       cxt->node_tbl[i] += shift;
+}
+
+static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
+{
+       unsigned int i;
+
+       if (shift == 0)
+               return;
+
+       for (i = 1; i < cxt->nodes_used; i++)
+               if (cxt->node_tbl[i] >= addr)
+                       cxt->node_tbl[i] += shift;
+}
+
+/* Struct used to return info from ft_next() */
+struct ft_atom {
+       u32 tag;
+       const char *name;
+       void *data;
+       u32 size;
+};
+
+/* Set ptrs to current one's info; return addr of next one */
+static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
+{
+       u32 sz;
+
+       if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
+               return NULL;
+
+       ret->tag = be32_to_cpu(*(u32 *) p);
+       p += 4;
+
+       switch (ret->tag) {     /* Tag */
+       case OF_DT_BEGIN_NODE:
+               ret->name = p;
+               ret->data = (void *)(p - 4);    /* start of node */
+               p += _ALIGN(strlen(p) + 1, 4);
+               break;
+       case OF_DT_PROP:
+               ret->size = sz = be32_to_cpu(*(u32 *) p);
+               ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
+               ret->data = (void *)(p + 8);
+               p += 8 + _ALIGN(sz, 4);
+               break;
+       case OF_DT_END_NODE:
+       case OF_DT_NOP:
+               break;
+       case OF_DT_END:
+       default:
+               p = NULL;
+               break;
+       }
+
+       return p;
+}
+
+#define HDR_SIZE       _ALIGN(sizeof(struct boot_param_header), 8)
+#define EXPAND_INCR    1024    /* alloc this much extra when expanding */
+
+/* See if the regions are in the standard order and non-overlapping */
+static int ft_ordered(struct ft_cxt *cxt)
+{
+       char *p = (char *)cxt->bph + HDR_SIZE;
+       enum ft_rgn_id r;
+
+       for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
+               if (p > cxt->rgn[r].start)
+                       return 0;
+               p = cxt->rgn[r].start + cxt->rgn[r].size;
+       }
+       return p <= (char *)cxt->bph + cxt->max_size;
+}
+
+/* Copy the tree to a newly-allocated region and put things in order */
+static int ft_reorder(struct ft_cxt *cxt, int nextra)
+{
+       unsigned long tot;
+       enum ft_rgn_id r;
+       char *p, *pend;
+       int stroff;
+
+       tot = HDR_SIZE + EXPAND_INCR;
+       for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
+               tot += cxt->rgn[r].size;
+       if (nextra > 0)
+               tot += nextra;
+       tot = _ALIGN(tot, 8);
+
+       if (!cxt->realloc)
+               return 0;
+       p = cxt->realloc(NULL, tot);
+       if (!p)
+               return 0;
+
+       memcpy(p, cxt->bph, sizeof(struct boot_param_header));
+       /* offsets get fixed up later */
+
+       cxt->bph = (struct boot_param_header *)p;
+       cxt->max_size = tot;
+       pend = p + tot;
+       p += HDR_SIZE;
+
+       memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
+       cxt->rgn[FT_RSVMAP].start = p;
+       p += cxt->rgn[FT_RSVMAP].size;
+
+       memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
+       ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
+                       p - cxt->rgn[FT_STRUCT].start);
+       cxt->p += p - cxt->rgn[FT_STRUCT].start;
+       cxt->rgn[FT_STRUCT].start = p;
+
+       p = pend - cxt->rgn[FT_STRINGS].size;
+       memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
+       stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
+       cxt->rgn[FT_STRINGS].start = p;
+       cxt->str_anchor = p + stroff;
+
+       cxt->isordered = 1;
+       return 1;
+}
+
+static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
+{
+       if (r > FT_RSVMAP)
+               return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
+       return (char *)cxt->bph + HDR_SIZE;
+}
+
+static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
+{
+       if (r < FT_STRINGS)
+               return cxt->rgn[r + 1].start;
+       return (char *)cxt->bph + cxt->max_size;
+}
+
+/*
+ * See if we can expand region rgn by nextra bytes by using up
+ * free space after or before the region.
+ */
+static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
+               int nextra)
+{
+       char *p = *pp;
+       char *rgn_start, *rgn_end;
+
+       rgn_start = cxt->rgn[rgn].start;
+       rgn_end = rgn_start + cxt->rgn[rgn].size;
+       if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
+               /* move following stuff */
+               if (p < rgn_end) {
+                       if (nextra < 0)
+                               memmove(p, p - nextra, rgn_end - p + nextra);
+                       else
+                               memmove(p + nextra, p, rgn_end - p);
+                       if (rgn == FT_STRUCT)
+                               ft_node_update_after(cxt, p, nextra);
+               }
+               cxt->rgn[rgn].size += nextra;
+               if (rgn == FT_STRINGS)
+                       /* assumes strings only added at beginning */
+                       cxt->str_anchor += nextra;
+               return 1;
+       }
+       if (prev_end(cxt, rgn) <= rgn_start - nextra) {
+               /* move preceding stuff */
+               if (p > rgn_start) {
+                       memmove(rgn_start - nextra, rgn_start, p - rgn_start);
+                       if (rgn == FT_STRUCT)
+                               ft_node_update_before(cxt, p, -nextra);
+               }
+               *p -= nextra;
+               cxt->rgn[rgn].start -= nextra;
+               cxt->rgn[rgn].size += nextra;
+               return 1;
+       }
+       return 0;
+}
+
+static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
+                        int nextra)
+{
+       unsigned long size, ssize, tot;
+       char *str, *next;
+       enum ft_rgn_id r;
+
+       if (!cxt->isordered && !ft_reorder(cxt, nextra))
+               return 0;
+       if (ft_shuffle(cxt, pp, rgn, nextra))
+               return 1;
+
+       /* See if there is space after the strings section */
+       ssize = cxt->rgn[FT_STRINGS].size;
+       if (cxt->rgn[FT_STRINGS].start + ssize
+                       < (char *)cxt->bph + cxt->max_size) {
+               /* move strings up as far as possible */
+               str = (char *)cxt->bph + cxt->max_size - ssize;
+               cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
+               memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
+               cxt->rgn[FT_STRINGS].start = str;
+               /* enough space now? */
+               if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
+                       return 1;
+       }
+
+       /* how much total free space is there following this region? */
+       tot = 0;
+       for (r = rgn; r < FT_STRINGS; ++r) {
+               char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
+               tot += next_start(cxt, rgn) - r_end;
+       }
+
+       /* cast is to shut gcc up; we know nextra >= 0 */
+       if (tot < (unsigned int)nextra) {
+               /* have to reallocate */
+               char *newp, *new_start;
+               int shift;
+
+               if (!cxt->realloc)
+                       return 0;
+               size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
+               newp = cxt->realloc(cxt->bph, size);
+               if (!newp)
+                       return 0;
+               cxt->max_size = size;
+               shift = newp - (char *)cxt->bph;
+
+               if (shift) { /* realloc can return same addr */
+                       cxt->bph = (struct boot_param_header *)newp;
+                       ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
+                                       shift);
+                       for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
+                               new_start = cxt->rgn[r].start + shift;
+                               cxt->rgn[r].start = new_start;
+                       }
+                       *pp += shift;
+                       cxt->str_anchor += shift;
+               }
+
+               /* move strings up to the end */
+               str = newp + size - ssize;
+               cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
+               memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
+               cxt->rgn[FT_STRINGS].start = str;
+
+               if (ft_shuffle(cxt, pp, rgn, nextra))
+                       return 1;
+       }
+
+       /* must be FT_RSVMAP and we need to move FT_STRUCT up */
+       if (rgn == FT_RSVMAP) {
+               next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+                       + nextra;
+               ssize = cxt->rgn[FT_STRUCT].size;
+               if (next + ssize >= cxt->rgn[FT_STRINGS].start)
+                       return 0;       /* "can't happen" */
+               memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
+               ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
+               cxt->rgn[FT_STRUCT].start = next;
+
+               if (ft_shuffle(cxt, pp, rgn, nextra))
+                       return 1;
+       }
+
+       return 0;               /* "can't happen" */
+}
+
+static void ft_put_word(struct ft_cxt *cxt, u32 v)
+{
+       *(u32 *) cxt->p = cpu_to_be32(v);
+       cxt->p += 4;
+}
+
+static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
+{
+       unsigned long sza = _ALIGN(sz, 4);
+
+       /* zero out the alignment gap if necessary */
+       if (sz < sza)
+               *(u32 *) (cxt->p + sza - 4) = 0;
+
+       /* copy in the data */
+       memcpy(cxt->p, data, sz);
+
+       cxt->p += sza;
+}
+
+int ft_begin_node(struct ft_cxt *cxt, const char *name)
+{
+       unsigned long nlen = strlen(name) + 1;
+       unsigned long len = 8 + _ALIGN(nlen, 4);
+
+       if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
+               return -1;
+       ft_put_word(cxt, OF_DT_BEGIN_NODE);
+       ft_put_bin(cxt, name, strlen(name) + 1);
+       return 0;
+}
+
+void ft_end_node(struct ft_cxt *cxt)
+{
+       ft_put_word(cxt, OF_DT_END_NODE);
+}
+
+void ft_nop(struct ft_cxt *cxt)
+{
+       if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
+               ft_put_word(cxt, OF_DT_NOP);
+}
+
+#define NO_STRING      0x7fffffff
+
+static int lookup_string(struct ft_cxt *cxt, const char *name)
+{
+       char *p, *end;
+
+       p = cxt->rgn[FT_STRINGS].start;
+       end = p + cxt->rgn[FT_STRINGS].size;
+       while (p < end) {
+               if (strcmp(p, (char *)name) == 0)
+                       return p - cxt->str_anchor;
+               p += strlen(p) + 1;
+       }
+
+       return NO_STRING;
+}
+
+/* lookup string and insert if not found */
+static int map_string(struct ft_cxt *cxt, const char *name)
+{
+       int off;
+       char *p;
+
+       off = lookup_string(cxt, name);
+       if (off != NO_STRING)
+               return off;
+       p = cxt->rgn[FT_STRINGS].start;
+       if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
+               return NO_STRING;
+       strcpy(p, name);
+       return p - cxt->str_anchor;
+}
+
+int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
+               unsigned int sz)
+{
+       int off, len;
+
+       off = lookup_string(cxt, name);
+       if (off == NO_STRING)
+               return -1;
+
+       len = 12 + _ALIGN(sz, 4);
+       if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
+               return -1;
+
+       ft_put_word(cxt, OF_DT_PROP);
+       ft_put_word(cxt, sz);
+       ft_put_word(cxt, off);
+       ft_put_bin(cxt, data, sz);
+       return 0;
+}
+
+int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
+{
+       return ft_prop(cxt, name, str, strlen(str) + 1);
+}
+
+int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
+{
+       u32 v = cpu_to_be32((u32) val);
+
+       return ft_prop(cxt, name, &v, 4);
+}
+
+/* Calculate the size of the reserved map */
+static unsigned long rsvmap_size(struct ft_cxt *cxt)
+{
+       struct ft_reserve *res;
+
+       res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
+       while (res->start || res->len)
+               ++res;
+       return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
+}
+
+/* Calculate the size of the struct region by stepping through it */
+static unsigned long struct_size(struct ft_cxt *cxt)
+{
+       char *p = cxt->rgn[FT_STRUCT].start;
+       char *next;
+       struct ft_atom atom;
+
+       /* make check in ft_next happy */
+       if (cxt->rgn[FT_STRUCT].size == 0)
+               cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
+
+       while ((next = ft_next(cxt, p, &atom)) != NULL)
+               p = next;
+       return p + 4 - cxt->rgn[FT_STRUCT].start;
+}
+
+/* add `adj' on to all string offset values in the struct area */
+static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
+{
+       char *p = cxt->rgn[FT_STRUCT].start;
+       char *next;
+       struct ft_atom atom;
+       int off;
+
+       while ((next = ft_next(cxt, p, &atom)) != NULL) {
+               if (atom.tag == OF_DT_PROP) {
+                       off = be32_to_cpu(*(u32 *) (p + 8));
+                       *(u32 *) (p + 8) = cpu_to_be32(off + adj);
+               }
+               p = next;
+       }
+}
+
+/* start construction of the flat OF tree from scratch */
+void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+               void *(*realloc_fn) (void *, unsigned long))
+{
+       struct boot_param_header *bph = blob;
+       char *p;
+       struct ft_reserve *pres;
+
+       /* clear the cxt */
+       memset(cxt, 0, sizeof(*cxt));
+
+       cxt->bph = bph;
+       cxt->max_size = max_size;
+       cxt->realloc = realloc_fn;
+       cxt->isordered = 1;
+
+       /* zero everything in the header area */
+       memset(bph, 0, sizeof(*bph));
+
+       bph->magic = cpu_to_be32(OF_DT_HEADER);
+       bph->version = cpu_to_be32(0x10);
+       bph->last_comp_version = cpu_to_be32(0x10);
+
+       /* start pointers */
+       cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
+       cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
+       pres = (struct ft_reserve *)p;
+       cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
+       cxt->rgn[FT_STRUCT].size = 4;
+       cxt->rgn[FT_STRINGS].start = blob + max_size;
+       cxt->rgn[FT_STRINGS].size = 0;
+
+       /* init rsvmap and struct */
+       pres->start = 0;
+       pres->len = 0;
+       *(u32 *) p = cpu_to_be32(OF_DT_END);
+
+       cxt->str_anchor = blob;
+}
+
+/* open up an existing blob to be examined or modified */
+int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+               unsigned int max_find_device,
+               void *(*realloc_fn) (void *, unsigned long))
+{
+       struct boot_param_header *bph = blob;
+
+       /* can't cope with version < 16 */
+       if (be32_to_cpu(bph->version) < 16)
+               return -1;
+
+       /* clear the cxt */
+       memset(cxt, 0, sizeof(*cxt));
+
+       /* alloc node_tbl to track node ptrs returned by ft_find_device */
+       ++max_find_device;
+       cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
+       if (!cxt->node_tbl)
+               return -1;
+       memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
+       cxt->node_max = max_find_device;
+       cxt->nodes_used = 1;    /* don't use idx 0 b/c looks like NULL */
+
+       cxt->bph = bph;
+       cxt->max_size = max_size;
+       cxt->realloc = realloc_fn;
+
+       cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
+       cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
+       cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
+       cxt->rgn[FT_STRUCT].size = struct_size(cxt);
+       cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
+       cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
+       /* Leave as '0' to force first ft_make_space call to do a ft_reorder
+        * and move dt to an area allocated by realloc.
+       cxt->isordered = ft_ordered(cxt);
+       */
+
+       cxt->p = cxt->rgn[FT_STRUCT].start;
+       cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
+
+       return 0;
+}
+
+/* add a reserver physical area to the rsvmap */
+int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
+{
+       char *p;
+       struct ft_reserve *pres;
+
+       p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+               - sizeof(struct ft_reserve);
+       if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
+               return -1;
+
+       pres = (struct ft_reserve *)p;
+       pres->start = cpu_to_be64(physaddr);
+       pres->len = cpu_to_be64(size);
+
+       return 0;
+}
+
+void ft_begin_tree(struct ft_cxt *cxt)
+{
+       cxt->p = cxt->rgn[FT_STRUCT].start;
+}
+
+void ft_end_tree(struct ft_cxt *cxt)
+{
+       struct boot_param_header *bph = cxt->bph;
+       char *p, *oldstr, *str, *endp;
+       unsigned long ssize;
+       int adj;
+
+       if (!cxt->isordered)
+               return;         /* we haven't touched anything */
+
+       /* adjust string offsets */
+       oldstr = cxt->rgn[FT_STRINGS].start;
+       adj = cxt->str_anchor - oldstr;
+       if (adj)
+               adjust_string_offsets(cxt, adj);
+
+       /* make strings end on 8-byte boundary */
+       ssize = cxt->rgn[FT_STRINGS].size;
+       endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
+                       + cxt->rgn[FT_STRUCT].size + ssize, 8);
+       str = endp - ssize;
+
+       /* move strings down to end of structs */
+       memmove(str, oldstr, ssize);
+       cxt->str_anchor = str;
+       cxt->rgn[FT_STRINGS].start = str;
+
+       /* fill in header fields */
+       p = (char *)bph;
+       bph->totalsize = cpu_to_be32(endp - p);
+       bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
+       bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
+       bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
+       bph->dt_strings_size = cpu_to_be32(ssize);
+}
+
+void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
+{
+       char *node;
+
+       /* require absolute path */
+       if (srch_path[0] != '/')
+               return NULL;
+       node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
+       return ft_node_add(cxt, node);
+}
+
+void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
+{
+       struct ft_atom atom;
+       char *p;
+       const char *cp, *q;
+       int cl;
+       int depth = -1;
+       int dmatch = 0;
+       const char *path_comp[FT_MAX_DEPTH];
+
+       cp = srch_path;
+       cl = 0;
+       p = top;
+
+       while ((p = ft_next(cxt, p, &atom)) != NULL) {
+               switch (atom.tag) {
+               case OF_DT_BEGIN_NODE:
+                       ++depth;
+                       if (depth != dmatch)
+                               break;
+                       cxt->genealogy[depth] = atom.data;
+                       cxt->genealogy[depth + 1] = NULL;
+                       if (depth && !(strncmp(atom.name, cp, cl) == 0
+                                       && (atom.name[cl] == '/'
+                                               || atom.name[cl] == '\0'
+                                               || atom.name[cl] == '@')))
+                               break;
+                       path_comp[dmatch] = cp;
+                       /* it matches so far, advance to next path component */
+                       cp += cl;
+                       /* skip slashes */
+                       while (*cp == '/')
+                               ++cp;
+                       /* we're done if this is the end of the string */
+                       if (*cp == 0)
+                               return atom.data;
+                       /* look for end of this component */
+                       q = strchr(cp, '/');
+                       if (q)
+                               cl = q - cp;
+                       else
+                               cl = strlen(cp);
+                       ++dmatch;
+                       break;
+               case OF_DT_END_NODE:
+                       if (depth == 0)
+                               return NULL;
+                       if (dmatch > depth) {
+                               --dmatch;
+                               cl = cp - path_comp[dmatch] - 1;
+                               cp = path_comp[dmatch];
+                               while (cl > 0 && cp[cl - 1] == '/')
+                                       --cl;
+                       }
+                       --depth;
+                       break;
+               }
+       }
+       return NULL;
+}
+
+void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
+{
+       void *node;
+       int d;
+       struct ft_atom atom;
+       char *p;
+
+       node = ft_node_ph2node(cxt, phandle);
+       if (node == NULL)
+               return NULL;
+
+       for (d = 0; cxt->genealogy[d] != NULL; ++d)
+               if (cxt->genealogy[d] == node)
+                       return cxt->genealogy[d > 0 ? d - 1 : 0];
+
+       /* have to do it the hard way... */
+       p = cxt->rgn[FT_STRUCT].start;
+       d = 0;
+       while ((p = ft_next(cxt, p, &atom)) != NULL) {
+               switch (atom.tag) {
+               case OF_DT_BEGIN_NODE:
+                       cxt->genealogy[d] = atom.data;
+                       if (node == atom.data) {
+                               /* found it */
+                               cxt->genealogy[d + 1] = NULL;
+                               return d > 0 ? cxt->genealogy[d - 1] : node;
+                       }
+                       ++d;
+                       break;
+               case OF_DT_END_NODE:
+                       --d;
+                       break;
+               }
+       }
+       return NULL;
+}
+
+int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+               void *buf, const unsigned int buflen)
+{
+       struct ft_atom atom;
+       void *node;
+       char *p;
+       int depth;
+       unsigned int size;
+
+       node = ft_node_ph2node(cxt, phandle);
+       if (node == NULL)
+               return -1;
+
+       depth = 0;
+       p = (char *)node;
+
+       while ((p = ft_next(cxt, p, &atom)) != NULL) {
+               switch (atom.tag) {
+               case OF_DT_BEGIN_NODE:
+                       ++depth;
+                       break;
+               case OF_DT_PROP:
+                       if ((depth != 1) || strcmp(atom.name, propname))
+                               break;
+                       size = min(atom.size, buflen);
+                       memcpy(buf, atom.data, size);
+                       return atom.size;
+               case OF_DT_END_NODE:
+                       if (--depth <= 0)
+                               return -1;
+               }
+       }
+       return -1;
+}
+
+int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+               const void *buf, const unsigned int buflen)
+{
+       struct ft_atom atom;
+       void *node;
+       char *p, *next;
+       int nextra, depth;
+
+       node = ft_node_ph2node(cxt, phandle);
+       if (node == NULL)
+               return -1;
+
+       depth = 0;
+       p = node;
+
+       while ((next = ft_next(cxt, p, &atom)) != NULL) {
+               switch (atom.tag) {
+               case OF_DT_BEGIN_NODE:
+                       ++depth;
+                       break;
+               case OF_DT_END_NODE:
+                       if (--depth > 0)
+                               break;
+                       /* haven't found the property, insert here */
+                       cxt->p = p;
+                       return ft_prop(cxt, propname, buf, buflen);
+               case OF_DT_PROP:
+                       if ((depth != 1) || strcmp(atom.name, propname))
+                               break;
+                       /* found an existing property, overwrite it */
+                       nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
+                       cxt->p = atom.data;
+                       if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
+                                               nextra))
+                               return -1;
+                       *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
+                       ft_put_bin(cxt, buf, buflen);
+                       return 0;
+               }
+               p = next;
+       }
+       return -1;
+}
+
+int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
+{
+       struct ft_atom atom;
+       void *node;
+       char *p, *next;
+       int size;
+
+       node = ft_node_ph2node(cxt, phandle);
+       if (node == NULL)
+               return -1;
+
+       p = node;
+       while ((next = ft_next(cxt, p, &atom)) != NULL) {
+               switch (atom.tag) {
+               case OF_DT_BEGIN_NODE:
+               case OF_DT_END_NODE:
+                       return -1;
+               case OF_DT_PROP:
+                       if (strcmp(atom.name, propname))
+                               break;
+                       /* found the property, remove it */
+                       size = 12 + -_ALIGN(atom.size, 4);
+                       cxt->p = p;
+                       if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
+                               return -1;
+                       return 0;
+               }
+               p = next;
+       }
+       return -1;
+}
+
+void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
+{
+       struct ft_atom atom;
+       char *p, *next;
+       int depth = 0;
+
+       p = cxt->rgn[FT_STRUCT].start;
+       while ((next = ft_next(cxt, p, &atom)) != NULL) {
+               switch (atom.tag) {
+               case OF_DT_BEGIN_NODE:
+                       ++depth;
+                       if (depth == 1 && strcmp(atom.name, path) == 0)
+                               /* duplicate node path, return error */
+                               return NULL;
+                       break;
+               case OF_DT_END_NODE:
+                       --depth;
+                       if (depth > 0)
+                               break;
+                       /* end of node, insert here */
+                       cxt->p = p;
+                       ft_begin_node(cxt, path);
+                       ft_end_node(cxt);
+                       return p;
+               }
+               p = next;
+       }
+       return NULL;
+}
index 761c8dc..b9cd9f6 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef FLATDEVTREE_H
 #define FLATDEVTREE_H
 
-#include "types.h"
+#include "flatdevtree_env.h"
 
 /* Definitions used by the flattened device tree */
 #define OF_DT_HEADER            0xd00dfeed      /* marker */
@@ -43,4 +43,64 @@ struct boot_param_header {
        u32 dt_strings_size;    /* size of the DT strings block */
 };
 
+struct ft_reserve {
+       u64 start;
+       u64 len;
+};
+
+struct ft_region {
+       char *start;
+       unsigned long size;
+};
+
+enum ft_rgn_id {
+       FT_RSVMAP,
+       FT_STRUCT,
+       FT_STRINGS,
+       FT_N_REGION
+};
+
+#define FT_MAX_DEPTH   50
+
+struct ft_cxt {
+       struct boot_param_header *bph;
+       int max_size;           /* maximum size of tree */
+       int isordered;          /* everything in standard order */
+       void *(*realloc)(void *, unsigned long);
+       char *str_anchor;
+       char *p;                /* current insertion point in structs */
+       struct ft_region rgn[FT_N_REGION];
+       void *genealogy[FT_MAX_DEPTH+1];
+       char **node_tbl;
+       unsigned int node_max;
+       unsigned int nodes_used;
+};
+
+int ft_begin_node(struct ft_cxt *cxt, const char *name);
+void ft_end_node(struct ft_cxt *cxt);
+
+void ft_begin_tree(struct ft_cxt *cxt);
+void ft_end_tree(struct ft_cxt *cxt);
+
+void ft_nop(struct ft_cxt *cxt);
+int ft_prop(struct ft_cxt *cxt, const char *name,
+           const void *data, unsigned int sz);
+int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
+int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
+void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+             void *(*realloc_fn)(void *, unsigned long));
+int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+               unsigned int max_find_device,
+               void *(*realloc_fn)(void *, unsigned long));
+int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
+
+void ft_dump_blob(const void *bphp);
+void ft_merge_blob(struct ft_cxt *cxt, void *blob);
+void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
+void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
+int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+               void *buf, const unsigned int buflen);
+int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+               const void *buf, const unsigned int buflen);
+
 #endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h
new file mode 100644 (file)
index 0000000..83bc1c7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file adds the header file glue so that the shared files
+ * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
+ *
+ * strncmp & strchr copied from <file:lib/strings.c>
+ * Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ */
+#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
+#define _PPC_BOOT_FLATDEVTREE_ENV_H_
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+
+#define be16_to_cpu(x)         (x)
+#define cpu_to_be16(x)         (x)
+#define be32_to_cpu(x)         (x)
+#define cpu_to_be32(x)         (x)
+#define be64_to_cpu(x)         (x)
+#define cpu_to_be64(x)         (x)
+
+static inline int strncmp(const char *cs, const char *ct, size_t count)
+{
+       signed char __res = 0;
+
+       while (count) {
+               if ((__res = *cs - *ct++) != 0 || !*cs++)
+                       break;
+               count--;
+       }
+       return __res;
+}
+
+static inline char *strchr(const char *s, int c)
+{
+       for (; *s != (char)c; ++s)
+               if (*s == '\0')
+                       return NULL;
+       return (char *)s;
+}
+
+#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 (file)
index 0000000..c7f9adb
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file does the necessary interface mapping between the bootwrapper
+ * device tree operations and the interface provided by shared source
+ * files flatdevicetree.[ch].
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stddef.h>
+#include "flatdevtree.h"
+#include "ops.h"
+
+static struct ft_cxt cxt;
+
+static void *ft_finddevice(const char *name)
+{
+       return ft_find_device(&cxt, name);
+}
+
+static int ft_getprop(const void *phandle, const char *propname, void *buf,
+               const int buflen)
+{
+       return ft_get_prop(&cxt, phandle, propname, buf, buflen);
+}
+
+static int ft_setprop(const void *phandle, const char *propname,
+               const void *buf, const int buflen)
+{
+       return ft_set_prop(&cxt, phandle, propname, buf, buflen);
+}
+
+static void ft_pack(void)
+{
+       ft_end_tree(&cxt);
+}
+
+static unsigned long ft_addr(void)
+{
+       return (unsigned long)cxt.bph;
+}
+
+int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
+{
+       dt_ops.finddevice = ft_finddevice;
+       dt_ops.getprop = ft_getprop;
+       dt_ops.setprop = ft_setprop;
+       dt_ops.ft_pack = ft_pack;
+       dt_ops.ft_addr = ft_addr;
+
+       return ft_open(&cxt, dt_blob, max_size, max_find_device,
+                       platform_ops.realloc);
+}
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644 (file)
index 0000000..32974ed
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _IO_H
+#define __IO_H
+/*
+ * Low-level I/O routines.
+ *
+ * Copied from <file:include/asm-powerpc/io.h> (which has no copyright)
+ */
+static inline int in_8(const volatile unsigned char *addr)
+{
+       int ret;
+
+       __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+                            : "=r" (ret) : "m" (*addr));
+       return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+       __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
+                            : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned in_le32(const volatile unsigned *addr)
+{
+       unsigned ret;
+
+       __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
+                            : "=r" (ret) : "r" (addr), "m" (*addr));
+       return ret;
+}
+
+static inline unsigned in_be32(const volatile unsigned *addr)
+{
+       unsigned ret;
+
+       __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+                            : "=r" (ret) : "m" (*addr));
+       return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+       __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
+                            : "r" (val), "r" (addr));
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+       __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
+                            : "=m" (*addr) : "r" (val));
+}
+
+#endif /* _IO_H */
index d719bb9..4184974 100644 (file)
@@ -27,6 +27,8 @@ extern char _vmlinux_start[];
 extern char _vmlinux_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
+extern char _dtb_start[];
+extern char _dtb_end[];
 
 struct addr_range {
        unsigned long addr;
@@ -250,10 +252,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
        flush_cache((void *)vmlinux.addr, vmlinux.size);
 }
 
-void __attribute__ ((weak)) ft_init(void *dt_blob)
-{
-}
-
 /* A buffer that may be edited by tools operating on a zImage binary so as to
  * edit the command line passed to vmlinux (by setting /chosen/bootargs).
  * 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)
                setprop(devp, "bootargs", buf, strlen(buf) + 1);
 }
 
-/* Section where ft can be tacked on after zImage is built */
-union blobspace {
-       struct boot_param_header hdr;
-       char space[8*1024];
-} dt_blob __attribute__((__section__("__builtin_ft")));
-
 struct platform_ops platform_ops;
 struct dt_ops dt_ops;
 struct console_ops console_ops;
 
 void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 {
-       int have_dt = 0;
        kernel_entry_t kentry;
        char cmdline[COMMAND_LINE_SIZE];
 
@@ -306,15 +297,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
        memset(&dt_ops, 0, sizeof(dt_ops));
        memset(&console_ops, 0, sizeof(console_ops));
 
-       /* Override the dt_ops and device tree if there was an flat dev
-        * tree attached to the zImage.
-        */
-       if (dt_blob.hdr.magic == OF_DT_HEADER) {
-               have_dt = 1;
-               ft_init(&dt_blob);
-       }
-
-       if (platform_init(promptr))
+       if (platform_init(promptr, _dtb_start, _dtb_end))
                exit();
        if (console_ops.open && (console_ops.open() < 0))
                exit();
@@ -342,8 +325,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
                console_ops.close();
 
        kentry = (kernel_entry_t) vmlinux.addr;
-       if (have_dt)
+       if (_dtb_end > _dtb_start) {
+               dt_ops.ft_pack();
                kentry(dt_ops.ft_addr(), 0, NULL);
+       }
        else
                /* XXX initrd addr/size should be passed in properties */
                kentry(a1, a2, promptr);
diff --git a/arch/powerpc/boot/mktree.c b/arch/powerpc/boot/mktree.c
new file mode 100644 (file)
index 0000000..4cb8929
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Makes a tree bootable image for IBM Evaluation boards.
+ * Basically, just take a zImage, skip the ELF header, and stuff
+ * a 32 byte header on the front.
+ *
+ * We use htonl, which is a network macro, to make sure we're doing
+ * The Right Thing on an LE machine.  It's non-obvious, but it should
+ * work on anything BSD'ish.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+/* This gets tacked on the front of the image.  There are also a few
+ * bytes allocated after the _start label used by the boot rom (see
+ * head.S for details).
+ */
+typedef struct boot_block {
+       uint32_t bb_magic;              /* 0x0052504F */
+       uint32_t bb_dest;               /* Target address of the image */
+       uint32_t bb_num_512blocks;      /* Size, rounded-up, in 512 byte blks */
+       uint32_t bb_debug_flag; /* Run debugger or image after load */
+       uint32_t bb_entry_point;        /* The image address to start */
+       uint32_t bb_checksum;   /* 32 bit checksum including header */
+       uint32_t reserved[2];
+} boot_block_t;
+
+#define IMGBLK 512
+char   tmpbuf[IMGBLK];
+
+int main(int argc, char *argv[])
+{
+       int     in_fd, out_fd;
+       int     nblks, i;
+       uint    cksum, *cp;
+       struct  stat    st;
+       boot_block_t    bt;
+
+       if (argc < 3) {
+               fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]);
+               exit(1);
+       }
+
+       if (stat(argv[1], &st) < 0) {
+               perror("stat");
+               exit(2);
+       }
+
+       nblks = (st.st_size + IMGBLK) / IMGBLK;
+
+       bt.bb_magic = htonl(0x0052504F);
+
+       /* If we have the optional entry point parameter, use it */
+       if (argc == 4)
+               bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0));
+       else
+               bt.bb_dest = bt.bb_entry_point = htonl(0x500000);
+
+       /* We know these from the linker command.
+        * ...and then move it up into memory a little more so the
+        * relocation can happen.
+        */
+       bt.bb_num_512blocks = htonl(nblks);
+       bt.bb_debug_flag = 0;
+
+       bt.bb_checksum = 0;
+
+       /* To be neat and tidy :-).
+       */
+       bt.reserved[0] = 0;
+       bt.reserved[1] = 0;
+
+       if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
+               perror("zImage open");
+               exit(3);
+       }
+
+       if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
+               perror("bootfile open");
+               exit(3);
+       }
+
+       cksum = 0;
+       cp = (void *)&bt;
+       for (i=0; i<sizeof(bt)/sizeof(uint); i++)
+               cksum += *cp++;
+
+       /* Assume zImage is an ELF file, and skip the 64K header.
+       */
+       if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) {
+               fprintf(stderr, "%s is too small to be an ELF image\n",
+                               argv[1]);
+               exit(4);
+       }
+
+       if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) {
+               fprintf(stderr, "%s is not an ELF image\n", argv[1]);
+               exit(4);
+       }
+
+       if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) {
+               fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]);
+               exit(4);
+       }
+
+       nblks -= (64 * 1024) / IMGBLK;
+
+       /* And away we go......
+       */
+       if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
+               perror("boot-image write");
+               exit(5);
+       }
+
+       while (nblks-- > 0) {
+               if (read(in_fd, tmpbuf, IMGBLK) < 0) {
+                       perror("zImage read");
+                       exit(5);
+               }
+               cp = (uint *)tmpbuf;
+               for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++)
+                       cksum += *cp++;
+               if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
+                       perror("boot-image write");
+                       exit(5);
+               }
+       }
+
+       /* rewrite the header with the computed checksum.
+       */
+       bt.bb_checksum = htonl(cksum);
+       if (lseek(out_fd, 0, SEEK_SET) < 0) {
+               perror("rewrite seek");
+               exit(1);
+       }
+       if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
+               perror("boot-image rewrite");
+               exit(1);
+       }
+
+       exit(0);
+}
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644 (file)
index 0000000..1ffe72e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 16550 serial console support.
+ *
+ * Original copied from <file:arch/ppc/boot/common/ns16550.c>
+ * (which had no copyright)
+ * Modifications: 2006 (c) MontaVista Software, Inc.
+ *
+ * Modified by: Mark A. Greer <mgreer@mvista.com>
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+#define UART_DLL       0       /* Out: Divisor Latch Low */
+#define UART_DLM       1       /* Out: Divisor Latch High */
+#define UART_FCR       2       /* Out: FIFO Control Register */
+#define UART_LCR       3       /* Out: Line Control Register */
+#define UART_MCR       4       /* Out: Modem Control Register */
+#define UART_LSR       5       /* In:  Line Status Register */
+#define UART_LSR_THRE  0x20    /* Transmit-hold-register empty */
+#define UART_LSR_DR    0x01    /* Receiver data ready */
+#define UART_MSR       6       /* In:  Modem Status Register */
+#define UART_SCR       7       /* I/O: Scratch Register */
+
+static unsigned char *reg_base;
+static u32 reg_shift;
+
+static int ns16550_open(void)
+{
+       out_8(reg_base + (UART_FCR << reg_shift), 0x06);
+       return 0;
+}
+
+static void ns16550_putc(unsigned char c)
+{
+       while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0);
+       out_8(reg_base, c);
+}
+
+static unsigned char ns16550_getc(void)
+{
+       while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0);
+       return in_8(reg_base);
+}
+
+static u8 ns16550_tstc(void)
+{
+       return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0);
+}
+
+int ns16550_console_init(void *devp, struct serial_console_data *scdp)
+{
+       int n;
+
+       n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
+       if (n != sizeof(reg_base))
+               return -1;
+
+       n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
+       if (n != sizeof(reg_shift))
+               reg_shift = 0;
+
+       scdp->open = ns16550_open;
+       scdp->putc = ns16550_putc;
+       scdp->getc = ns16550_getc;
+       scdp->tstc = ns16550_tstc;
+       scdp->close = NULL;
+
+       return 0;
+}
index 3a71845..0182f38 100644 (file)
@@ -256,24 +256,18 @@ static void of_console_write(char *buf, int len)
        call_prom("write", 3, 1, of_stdout_handle, buf, len);
 }
 
-int platform_init(void *promptr)
+int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
 {
-       platform_ops.fixups = NULL;
        platform_ops.image_hdr = of_image_hdr;
        platform_ops.malloc = of_try_claim;
-       platform_ops.free = NULL;
        platform_ops.exit = of_exit;
 
        dt_ops.finddevice = of_finddevice;
        dt_ops.getprop = of_getprop;
        dt_ops.setprop = of_setprop;
-       dt_ops.translate_addr = NULL;
 
        console_ops.open = of_console_open;
        console_ops.write = of_console_write;
-       console_ops.edit_cmdline = NULL;
-       console_ops.close = NULL;
-       console_ops.data = NULL;
 
        prom = (int (*)(void *))promptr;
        return 0;
index 135eb4b..59832fb 100644 (file)
@@ -22,7 +22,8 @@ struct platform_ops {
        void    (*fixups)(void);
        void    (*image_hdr)(const void *);
        void *  (*malloc)(u32 size);
-       void    (*free)(void *ptr, u32 size);
+       void    (*free)(void *ptr);
+       void *  (*realloc)(void *ptr, unsigned long size);
        void    (*exit)(void);
 };
 extern struct platform_ops platform_ops;
@@ -30,12 +31,11 @@ extern struct platform_ops platform_ops;
 /* Device Tree operations */
 struct dt_ops {
        void *  (*finddevice)(const char *name);
-       int     (*getprop)(const void *node, const char *name, void *buf,
+       int     (*getprop)(const void *phandle, const char *name, void *buf,
                        const int buflen);
-       int     (*setprop)(const void *node, const char *name,
+       int     (*setprop)(const void *phandle, const char *name,
                        const void *buf, const int buflen);
-       u64     (*translate_addr)(const char *path, const u32 *in_addr,
-                       const u32 addr_len);
+       void    (*ft_pack)(void);
        unsigned long (*ft_addr)(void);
 };
 extern struct dt_ops dt_ops;
@@ -59,10 +59,13 @@ struct serial_console_data {
        void            (*close)(void);
 };
 
-extern int platform_init(void *promptr);
-extern void simple_alloc_init(void);
-extern void ft_init(void *dt_blob);
-extern int serial_console_init(void);
+int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
+int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
+int serial_console_init(void);
+int ns16550_console_init(void *devp, struct serial_console_data *scdp);
+void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
+               u32 max_allocs);
+
 
 static inline void *finddevice(const char *name)
 {
@@ -84,10 +87,10 @@ static inline void *malloc(u32 size)
        return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
 }
 
-static inline void free(void *ptr, u32 size)
+static inline void free(void *ptr)
 {
        if (platform_ops.free)
-               platform_ops.free(ptr, size);
+               platform_ops.free(ptr);
 }
 
 static inline void exit(void)
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644 (file)
index 0000000..e8de4cf
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Generic serial console support
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
+ * and was written by Matt Porter <mporter@kernel.crashing.org>.
+ *
+ * 2001,2006 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+extern void udelay(long delay);
+
+static int serial_open(void)
+{
+       struct serial_console_data *scdp = console_ops.data;
+       return scdp->open();
+}
+
+static void serial_write(char *buf, int len)
+{
+       struct serial_console_data *scdp = console_ops.data;
+
+       while (*buf != '\0')
+               scdp->putc(*buf++);
+}
+
+static void serial_edit_cmdline(char *buf, int len)
+{
+       int timer = 0, count;
+       char ch, *cp;
+       struct serial_console_data *scdp = console_ops.data;
+
+       cp = buf;
+       count = strlen(buf);
+       cp = &buf[count];
+       count++;
+
+       while (timer++ < 5*1000) {
+               if (scdp->tstc()) {
+                       while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
+                               /* Test for backspace/delete */
+                               if ((ch == '\b') || (ch == '\177')) {
+                                       if (cp != buf) {
+                                               cp--;
+                                               count--;
+                                               printf("\b \b");
+                                       }
+                               /* Test for ^x/^u (and wipe the line) */
+                               } else if ((ch == '\030') || (ch == '\025')) {
+                                       while (cp != buf) {
+                                               cp--;
+                                               count--;
+                                               printf("\b \b");
+                                       }
+                               } else if (count < len) {
+                                               *cp++ = ch;
+                                               count++;
+                                               scdp->putc(ch);
+                               }
+                       }
+                       break;  /* Exit 'timer' loop */
+               }
+               udelay(1000);  /* 1 msec */
+       }
+       *cp = 0;
+}
+
+static void serial_close(void)
+{
+       struct serial_console_data *scdp = console_ops.data;
+
+       if (scdp->close)
+               scdp->close();
+}
+
+static void *serial_get_stdout_devp(void)
+{
+       void *devp;
+       char devtype[MAX_PROP_LEN];
+       char path[MAX_PATH_LEN];
+
+       devp = finddevice("/chosen");
+       if (devp == NULL)
+               goto err_out;
+
+       if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
+               devp = finddevice(path);
+               if (devp == NULL)
+                       goto err_out;
+
+               if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
+                               && !strcmp(devtype, "serial"))
+                       return devp;
+       }
+err_out:
+       return NULL;
+}
+
+static struct serial_console_data serial_cd;
+
+/* Node's "compatible" property determines which serial driver to use */
+int serial_console_init(void)
+{
+       void *devp;
+       int rc = -1;
+       char compat[MAX_PROP_LEN];
+
+       devp = serial_get_stdout_devp();
+       if (devp == NULL)
+               goto err_out;
+
+       if (getprop(devp, "compatible", compat, sizeof(compat)) < 0)
+               goto err_out;
+
+       if (!strcmp(compat, "ns16550"))
+               rc = ns16550_console_init(devp, &serial_cd);
+
+       /* Add other serial console driver calls here */
+
+       if (!rc) {
+               console_ops.open = serial_open;
+               console_ops.write = serial_write;
+               console_ops.edit_cmdline = serial_edit_cmdline;
+               console_ops.close = serial_close;
+               console_ops.data = &serial_cd;
+
+               return 0;
+       }
+err_out:
+       return -1;
+}
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
new file mode 100644 (file)
index 0000000..cfe3a75
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Implement primitive realloc(3) functionality.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stddef.h>
+#include "types.h"
+#include "page.h"
+#include "string.h"
+#include "ops.h"
+
+#define        ENTRY_BEEN_USED 0x01
+#define        ENTRY_IN_USE    0x02
+
+static struct alloc_info {
+       u32     flags;
+       u32     base;
+       u32     size;
+} *alloc_tbl;
+
+static u32 tbl_entries;
+static u32 alloc_min;
+static u32 next_base;
+static u32 space_left;
+
+/*
+ * First time an entry is used, its base and size are set.
+ * An entry can be freed and re-malloc'd but its base & size don't change.
+ * Should be smart enough for needs of bootwrapper.
+ */
+static void *simple_malloc(u32 size)
+{
+       u32 i;
+       struct alloc_info *p = alloc_tbl;
+
+       if (size == 0)
+               goto err_out;
+
+       size = _ALIGN_UP(size, alloc_min);
+
+       for (i=0; i<tbl_entries; i++, p++)
+               if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
+                       if (size <= space_left) {
+                               p->base = next_base;
+                               p->size = size;
+                               p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
+                               next_base += size;
+                               space_left -= size;
+                               return (void *)p->base;
+                       }
+                       goto err_out; /* not enough space left */
+               }
+               /* reuse an entry keeping same base & size */
+               else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) {
+                       p->flags |= ENTRY_IN_USE;
+                       return (void *)p->base;
+               }
+err_out:
+       return NULL;
+}
+
+static struct alloc_info *simple_find_entry(void *ptr)
+{
+       u32 i;
+       struct alloc_info *p = alloc_tbl;
+
+       for (i=0; i<tbl_entries; i++,p++) {
+               if (!(p->flags & ENTRY_BEEN_USED))
+                       break;
+               if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr))
+                       return p;
+       }
+       return NULL;
+}
+
+static void simple_free(void *ptr)
+{
+       struct alloc_info *p = simple_find_entry(ptr);
+
+       if (p != NULL)
+               p->flags &= ~ENTRY_IN_USE;
+}
+
+/*
+ * Change size of area pointed to by 'ptr' to 'size'.
+ * If 'ptr' is NULL, then its a malloc().  If 'size' is 0, then its a free().
+ * 'ptr' must be NULL or a pointer to a non-freed area previously returned by
+ * simple_realloc() or simple_malloc().
+ */
+static void *simple_realloc(void *ptr, unsigned long size)
+{
+       struct alloc_info *p;
+       void *new;
+
+       if (size == 0) {
+               simple_free(ptr);
+               return NULL;
+       }
+
+       if (ptr == NULL)
+               return simple_malloc(size);
+
+       p = simple_find_entry(ptr);
+       if (p == NULL) /* ptr not from simple_malloc/simple_realloc */
+               return NULL;
+       if (size <= p->size) /* fits in current block */
+               return ptr;
+
+       new = simple_malloc(size);
+       memcpy(new, ptr, p->size);
+       simple_free(ptr);
+       return new;
+}
+
+/*
+ * Returns addr of first byte after heap so caller can see if it took
+ * too much space.  If so, change args & try again.
+ */
+void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
+               u32 max_allocs)
+{
+       u32 heap_base, tbl_size;
+
+       heap_size = _ALIGN_UP(heap_size, granularity);
+       alloc_min = granularity;
+       tbl_entries = max_allocs;
+
+       tbl_size = tbl_entries * sizeof(struct alloc_info);
+
+       alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
+       memset(alloc_tbl, 0, tbl_size);
+
+       heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
+
+       next_base = heap_base;
+       space_left = heap_size;
+
+       platform_ops.malloc = simple_malloc;
+       platform_ops.free = simple_free;
+       platform_ops.realloc = simple_realloc;
+
+       return (void *)(heap_base + heap_size);
+}
index 6d5f638..0a9feeb 100644 (file)
@@ -320,6 +320,7 @@ printf(const char *fmt, ...)
        va_start(args, fmt);
        n = vsprintf(sprint_buf, fmt, args);
        va_end(args);
-       console_ops.write(sprint_buf, n);
+       if (console_ops.write)
+               console_ops.write(sprint_buf, n);
        return n;
 }
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S
new file mode 100644 (file)
index 0000000..427ddfc
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copied from <file:arch/powerpc/kernel/misc_32.S>
+ *
+ * This file contains miscellaneous low-level functions.
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * kexec bits:
+ * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#include "ppc_asm.h"
+
+#define SPRN_PVR        0x11F   /* Processor Version Register */
+
+       .text
+
+/* udelay (on non-601 processors) needs to know the period of the
+ * timebase in nanoseconds.  This used to be hardcoded to be 60ns
+ * (period of 66MHz/4).  Now a variable is used that is initialized to
+ * 60 for backward compatibility, but it can be overridden as necessary
+ * with code something like this:
+ *    extern unsigned long timebase_period_ns;
+ *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+ */
+       .data
+       .globl timebase_period_ns
+timebase_period_ns:
+       .long   60
+
+       .text
+/*
+ * Delay for a number of microseconds
+ */
+       .globl  udelay
+udelay:
+       mfspr   r4,SPRN_PVR
+       srwi    r4,r4,16
+       cmpwi   0,r4,1          /* 601 ? */
+       bne     .udelay_not_601
+00:    li      r0,86   /* Instructions / microsecond? */
+       mtctr   r0
+10:    addi    r0,r0,0 /* NOP */
+       bdnz    10b
+       subic.  r3,r3,1
+       bne     00b
+       blr
+
+.udelay_not_601:
+       mulli   r4,r3,1000      /* nanoseconds */
+       /*  Change r4 to be the number of ticks using:
+        *      (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
+        *  timebase_period_ns defaults to 60 (16.6MHz) */
+       mflr    r5
+       bl      0f
+0:     mflr    r6
+       mtlr    r5
+       lis     r5,0b@ha
+       addi    r5,r5,0b@l
+       subf    r5,r5,r6        /* In case we're relocated */
+       addis   r5,r5,timebase_period_ns@ha
+       lwz     r5,timebase_period_ns@l(r5)
+       add     r4,r4,r5
+       addi    r4,r4,-1
+       divw    r4,r4,r5        /* BUS ticks */
+1:     mftbu   r5
+       mftb    r6
+       mftbu   r7
+       cmpw    0,r5,r7
+       bne     1b              /* Get [synced] base time */
+       addc    r9,r6,r4        /* Compute end time */
+       addze   r8,r5
+2:     mftbu   r5
+       cmpw    0,r5,r8
+       blt     2b
+       bgt     3f
+       mftb    r6
+       cmpw    0,r6,r9
+       blt     2b
+3:     blr
index b5fb1fe..024e4d4 100755 (executable)
@@ -184,6 +184,9 @@ fi
 
 if [ -n "$dtb" ]; then
     addsec $tmp "$dtb" .kernel:dtb
+    if [ -n "$dts" ]; then
+       rm $dtb
+    fi
 fi
 
 if [ "$platform" != "miboot" ]; then
index 05f3238..a360905 100644 (file)
@@ -21,6 +21,10 @@ SECTIONS
     *(.got2)
     __got2_end = .;
 
+    _dtb_start = .;
+    *(.kernel:dtb)
+    _dtb_end = .;
+
     _vmlinux_start =  .;
     *(.kernel:vmlinux.strip)
     _vmlinux_end =  .;
index 0aba06d..dbcd4e3 100644 (file)
@@ -139,7 +139,19 @@ CONFIG_RTAS_FLASH=y
 CONFIG_MMIO_NVRAM=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_FREQ_PMAC64 is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 # CONFIG_MPIC is not set
 
@@ -149,6 +161,8 @@ CONFIG_MMIO_NVRAM=y
 CONFIG_SPU_FS=m
 CONFIG_SPU_BASE=y
 CONFIG_CBE_RAS=y
+CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
 
 #
 # Kernel options
index 7af23c4..d8240ce 100644 (file)
@@ -17,7 +17,7 @@ obj-y                         += vdso32/
 obj-$(CONFIG_PPC64)            += setup_64.o binfmt_elf32.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
                                   paca.o cpu_setup_ppc970.o \
-                                  firmware.o sysfs.o
+                                  firmware.o sysfs.o nvram_64.o
 obj-$(CONFIG_PPC64)            += vdso64/
 obj-$(CONFIG_ALTIVEC)          += vecemu.o vector.o
 obj-$(CONFIG_PPC_970_NAP)      += idle_power4.o
@@ -32,7 +32,6 @@ obj-$(CONFIG_LPARCFG)         += lparcfg.o
 obj-$(CONFIG_IBMVIO)           += vio.o
 obj-$(CONFIG_IBMEBUS)           += ibmebus.o
 obj-$(CONFIG_GENERIC_TBSYNC)   += smp-tbsync.o
-obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_6xx)              += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
 obj-$(CONFIG_TAU)              += tau_6xx.o
index d06f378..e965215 100644 (file)
@@ -118,7 +118,8 @@ int main(void)
        DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
        DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
        DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
-       DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled));
+       DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
+       DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
        DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
        DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
        DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
index 6525948..bf118c3 100644 (file)
@@ -83,6 +83,22 @@ _GLOBAL(__setup_cpu_ppc970)
        rldimi  r0,r11,52,8             /* set NAP and DPM */
        li      r11,0
        rldimi  r0,r11,32,31            /* clear EN_ATTN */
+       b       load_hids               /* Jump to shared code */
+
+
+_GLOBAL(__setup_cpu_ppc970MP)
+       /* Do nothing if not running in HV mode */
+       mfmsr   r0
+       rldicl. r0,r0,4,63
+       beqlr
+
+       mfspr   r0,SPRN_HID0
+       li      r11,0x15                /* clear DOZE and SLEEP */
+       rldimi  r0,r11,52,6             /* set DEEPNAP, NAP and DPM */
+       li      r11,0
+       rldimi  r0,r11,32,31            /* clear EN_ATTN */
+
+load_hids:
        mtspr   SPRN_HID0,r0
        mfspr   r0,SPRN_HID0
        mfspr   r0,SPRN_HID0
index bfd499e..1e4ed07 100644 (file)
@@ -42,6 +42,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
 #endif /* CONFIG_PPC32 */
 #ifdef CONFIG_PPC64
 extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_ppc970(void);
 #endif /* CONFIG_PPC64 */
 
@@ -222,7 +223,7 @@ static struct cpu_spec cpu_specs[] = {
                .icache_bsize           = 128,
                .dcache_bsize           = 128,
                .num_pmcs               = 8,
-               .cpu_setup              = __setup_cpu_ppc970,
+               .cpu_setup              = __setup_cpu_ppc970MP,
                .cpu_restore            = __restore_cpu_ppc970,
                .oprofile_cpu_type      = "ppc64/970",
                .oprofile_type          = PPC_OPROFILE_POWER4,
index 1af41f7..89b03c8 100644 (file)
@@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs)
        if (!cpu_online(cpu))
                return;
 
-       local_irq_disable();
+       hard_irq_disable();
        if (!cpu_isset(cpu, cpus_in_crash))
                crash_save_this_cpu(regs, cpu);
        cpu_set(cpu, cpus_in_crash);
@@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
         * an SMP system.
         * The kernel is broken so disable interrupts.
         */
-       local_irq_disable();
+       hard_irq_disable();
 
        for_each_irq(irq) {
                struct irq_desc *desc = irq_desc + irq;
index 748e74f..ec754c9 100644 (file)
@@ -87,6 +87,10 @@ system_call_common:
        addi    r9,r1,STACK_FRAME_OVERHEAD
        ld      r11,exception_marker@toc(r2)
        std     r11,-16(r9)             /* "regshere" marker */
+       li      r10,1
+       stb     r10,PACASOFTIRQEN(r13)
+       stb     r10,PACAHARDIRQEN(r13)
+       std     r10,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
        /* Hack for handling interrupts when soft-enabling on iSeries */
@@ -94,8 +98,6 @@ BEGIN_FW_FTR_SECTION
        andi.   r10,r12,MSR_PR          /* from kernel */
        crand   4*cr0+eq,4*cr1+eq,4*cr0+eq
        beq     hardware_interrupt_entry
-       lbz     r10,PACAPROCENABLED(r13)
-       std     r10,SOFTE(r1)
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
        mfmsr   r11
@@ -460,9 +462,9 @@ _GLOBAL(ret_from_except_lite)
 #endif
 
 restore:
+       ld      r5,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
-       ld      r5,SOFTE(r1)
        cmpdi   0,r5,0
        beq     4f
        /* Check for pending interrupts (iSeries) */
@@ -472,21 +474,25 @@ BEGIN_FW_FTR_SECTION
        beq+    4f                      /* skip do_IRQ if no interrupts */
 
        li      r3,0
-       stb     r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */
+       stb     r3,PACASOFTIRQEN(r13)   /* ensure we are soft-disabled */
        ori     r10,r10,MSR_EE
        mtmsrd  r10                     /* hard-enable again */
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .do_IRQ
        b       .ret_from_except_lite           /* loop back and handle more */
-
-4:     stb     r5,PACAPROCENABLED(r13)
+4:
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+       stb     r5,PACASOFTIRQEN(r13)
 
        ld      r3,_MSR(r1)
        andi.   r0,r3,MSR_RI
        beq-    unrecov_restore
 
+       /* extract EE bit and use it to restore paca->hard_enabled */
+       rldicl  r4,r3,49,63             /* r0 = (r3 >> 15) & 1 */
+       stb     r4,PACAHARDIRQEN(r13)
+
        andi.   r0,r3,MSR_PR
 
        /*
@@ -538,25 +544,15 @@ do_work:
        /* Check that preempt_count() == 0 and interrupts are enabled */
        lwz     r8,TI_PREEMPT(r9)
        cmpwi   cr1,r8,0
-#ifdef CONFIG_PPC_ISERIES
-BEGIN_FW_FTR_SECTION
        ld      r0,SOFTE(r1)
        cmpdi   r0,0
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif
-BEGIN_FW_FTR_SECTION
-       andi.   r0,r3,MSR_EE
-END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
        crandc  eq,cr1*4+eq,eq
        bne     restore
        /* here we are preempting the current task */
 1:
-#ifdef CONFIG_PPC_ISERIES
-BEGIN_FW_FTR_SECTION
        li      r0,1
-       stb     r0,PACAPROCENABLED(r13)
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif
+       stb     r0,PACASOFTIRQEN(r13)
+       stb     r0,PACAHARDIRQEN(r13)
        ori     r10,r10,MSR_EE
        mtmsrd  r10,1           /* reenable interrupts */
        bl      .preempt_schedule
@@ -639,8 +635,7 @@ _GLOBAL(enter_rtas)
        /* There is no way it is acceptable to get here with interrupts enabled,
         * check it with the asm equivalent of WARN_ON
         */
-       mfmsr   r6
-       andi.   r0,r6,MSR_EE
+       lbz     r0,PACASOFTIRQEN(r13)
 1:     tdnei   r0,0
 .section __bug_table,"a"
        .llong  1b,__LINE__ + 0x1000000, 1f, 2f
@@ -649,7 +644,13 @@ _GLOBAL(enter_rtas)
 1:     .asciz  __FILE__
 2:     .asciz "enter_rtas"
 .previous
-       
+
+       /* Hard-disable interrupts */
+       mfmsr   r6
+       rldicl  r7,r6,48,1
+       rotldi  r7,r7,16
+       mtmsrd  r7,1
+
        /* Unfortunately, the stack pointer and the MSR are also clobbered,
         * so they are saved in the PACA which allows us to restore
         * our original state after RTAS returns.
@@ -735,8 +736,6 @@ _STATIC(rtas_restore_regs)
 
 #endif /* CONFIG_PPC_RTAS */
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-
 _GLOBAL(enter_prom)
        mflr    r0
        std     r0,16(r1)
@@ -821,5 +820,3 @@ _GLOBAL(enter_prom)
        ld      r0,16(r1)
        mtlr    r0
         blr
-       
-#endif /* CONFIG_PPC_MULTIPLATFORM */
index e720729..8cdff5a 100644 (file)
@@ -35,9 +35,7 @@
 #include <asm/thread_info.h>
 #include <asm/firmware.h>
 
-#ifdef CONFIG_PPC_ISERIES
 #define DO_SOFT_DISABLE
-#endif
 
 /*
  * We layout physical memory as follows:
        .text
        .globl  _stext
 _stext:
-#ifdef CONFIG_PPC_MULTIPLATFORM
 _GLOBAL(__start)
        /* NOP this out unconditionally */
 BEGIN_FTR_SECTION
        b       .__start_initialization_multiplatform
 END_FTR_SECTION(0, 1)
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
        /* Catch branch to 0 in real mode */
        trap
@@ -308,7 +304,9 @@ exception_marker:
        std     r9,_LINK(r1);                                              \
        mfctr   r10;                    /* save CTR in stackframe       */ \
        std     r10,_CTR(r1);                                              \
+       lbz     r10,PACASOFTIRQEN(r13);                            \
        mfspr   r11,SPRN_XER;           /* save XER in stackframe       */ \
+       std     r10,SOFTE(r1);                                             \
        std     r11,_XER(r1);                                              \
        li      r9,(n)+1;                                                  \
        std     r9,_TRAP(r1);           /* set trap number              */ \
@@ -343,6 +341,34 @@ label##_pSeries:                                   \
        EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
 
 
+#define MASKABLE_EXCEPTION_PSERIES(n, label)                           \
+       . = n;                                                          \
+       .globl label##_pSeries;                                         \
+label##_pSeries:                                                       \
+       HMT_MEDIUM;                                                     \
+       mtspr   SPRN_SPRG1,r13;         /* save r13 */                  \
+       mfspr   r13,SPRN_SPRG3;         /* get paca address into r13 */ \
+       std     r9,PACA_EXGEN+EX_R9(r13);       /* save r9, r10 */      \
+       std     r10,PACA_EXGEN+EX_R10(r13);                             \
+       lbz     r10,PACASOFTIRQEN(r13);                                 \
+       mfcr    r9;                                                     \
+       cmpwi   r10,0;                                                  \
+       beq     masked_interrupt;                                       \
+       mfspr   r10,SPRN_SPRG1;                                         \
+       std     r10,PACA_EXGEN+EX_R13(r13);                             \
+       std     r11,PACA_EXGEN+EX_R11(r13);                             \
+       std     r12,PACA_EXGEN+EX_R12(r13);                             \
+       clrrdi  r12,r13,32;             /* get high part of &label */   \
+       mfmsr   r10;                                                    \
+       mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
+       LOAD_HANDLER(r12,label##_common)                                \
+       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
+       mtspr   SPRN_SRR0,r12;                                          \
+       mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
+       mtspr   SPRN_SRR1,r10;                                          \
+       rfid;                                                           \
+       b       .       /* prevent speculative execution */
+
 #define STD_EXCEPTION_ISERIES(n, label, area)          \
        .globl label##_iSeries;                         \
 label##_iSeries:                                       \
@@ -358,40 +384,32 @@ label##_iSeries:                                                  \
        HMT_MEDIUM;                                                     \
        mtspr   SPRN_SPRG1,r13;         /* save r13 */                  \
        EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);                         \
-       lbz     r10,PACAPROCENABLED(r13);                               \
+       lbz     r10,PACASOFTIRQEN(r13);                                 \
        cmpwi   0,r10,0;                                                \
        beq-    label##_iSeries_masked;                                 \
        EXCEPTION_PROLOG_ISERIES_2;                                     \
        b       label##_common;                                         \
 
-#ifdef DO_SOFT_DISABLE
+#ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS                           \
-BEGIN_FW_FTR_SECTION;                          \
-       lbz     r10,PACAPROCENABLED(r13);       \
        li      r11,0;                          \
-       std     r10,SOFTE(r1);                  \
+       stb     r11,PACASOFTIRQEN(r13);         \
+BEGIN_FW_FTR_SECTION;                          \
+       stb     r11,PACAHARDIRQEN(r13);         \
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES);  \
+BEGIN_FW_FTR_SECTION;                          \
        mfmsr   r10;                            \
-       stb     r11,PACAPROCENABLED(r13);       \
        ori     r10,r10,MSR_EE;                 \
        mtmsrd  r10,1;                          \
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 
-#define ENABLE_INTS                            \
-BEGIN_FW_FTR_SECTION;                          \
-       lbz     r10,PACAPROCENABLED(r13);       \
-       mfmsr   r11;                            \
-       std     r10,SOFTE(r1);                  \
-       ori     r11,r11,MSR_EE;                 \
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES);  \
-BEGIN_FW_FTR_SECTION;                          \
-       ld      r12,_MSR(r1);                   \
-       mfmsr   r11;                            \
-       rlwimi  r11,r12,0,MSR_EE;               \
-END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES);  \
-       mtmsrd  r11,1
+#else
+#define DISABLE_INTS                           \
+       li      r11,0;                          \
+       stb     r11,PACASOFTIRQEN(r13);         \
+       stb     r11,PACAHARDIRQEN(r13)
 
-#else  /* hard enable/disable interrupts */
-#define DISABLE_INTS
+#endif /* CONFIG_PPC_ISERIES */
 
 #define ENABLE_INTS                            \
        ld      r12,_MSR(r1);                   \
@@ -399,8 +417,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES);       \
        rlwimi  r11,r12,0,MSR_EE;               \
        mtmsrd  r11,1
 
-#endif
-
 #define STD_EXCEPTION_COMMON(trap, label, hdlr)                \
        .align  7;                                      \
        .globl label##_common;                          \
@@ -541,11 +557,11 @@ instruction_access_slb_pSeries:
        mfspr   r12,SPRN_SRR1           /* and SRR1 */
        b       .slb_miss_realmode      /* Rel. branch works in real mode */
 
-       STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)
+       MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
        STD_EXCEPTION_PSERIES(0x600, alignment)
        STD_EXCEPTION_PSERIES(0x700, program_check)
        STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
-       STD_EXCEPTION_PSERIES(0x900, decrementer)
+       MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
        STD_EXCEPTION_PSERIES(0xa00, trap_0a)
        STD_EXCEPTION_PSERIES(0xb00, trap_0b)
 
@@ -597,7 +613,24 @@ system_call_pSeries:
 /*** pSeries interrupt support ***/
 
        /* moved from 0xf00 */
-       STD_EXCEPTION_PSERIES(., performance_monitor)
+       MASKABLE_EXCEPTION_PSERIES(., performance_monitor)
+
+/*
+ * An interrupt came in while soft-disabled; clear EE in SRR1,
+ * clear paca->hard_enabled and return.
+ */
+masked_interrupt:
+       stb     r10,PACAHARDIRQEN(r13)
+       mtcrf   0x80,r9
+       ld      r9,PACA_EXGEN+EX_R9(r13)
+       mfspr   r10,SPRN_SRR1
+       rldicl  r10,r10,48,1            /* clear MSR_EE */
+       rotldi  r10,r10,16
+       mtspr   SPRN_SRR1,r10
+       ld      r10,PACA_EXGEN+EX_R10(r13)
+       mfspr   r13,SPRN_SPRG1
+       rfid
+       b       .
 
        .align  7
 do_stab_bolted_pSeries:
@@ -926,10 +959,18 @@ bad_stack:
  * any task or sent any task a signal, you should use
  * ret_from_except or ret_from_except_lite instead of this.
  */
+fast_exc_return_irq:                   /* restores irq state too */
+       ld      r3,SOFTE(r1)
+       ld      r12,_MSR(r1)
+       stb     r3,PACASOFTIRQEN(r13)   /* restore paca->soft_enabled */
+       rldicl  r4,r12,49,63            /* get MSR_EE to LSB */
+       stb     r4,PACAHARDIRQEN(r13)   /* restore paca->hard_enabled */
+       b       1f
+
        .globl  fast_exception_return
 fast_exception_return:
        ld      r12,_MSR(r1)
-       ld      r11,_NIP(r1)
+1:     ld      r11,_NIP(r1)
        andi.   r3,r12,MSR_RI           /* check if RI is set */
        beq-    unrecov_fer
 
@@ -952,7 +993,8 @@ fast_exception_return:
        REST_8GPRS(2, r1)
 
        mfmsr   r10
-       clrrdi  r10,r10,2               /* clear RI (LE is 0 already) */
+       rldicl  r10,r10,48,1            /* clear EE */
+       rldicr  r10,r10,16,61           /* clear RI (LE is 0 already) */
        mtmsrd  r10,1
 
        mtspr   SPRN_SRR1,r12
@@ -1326,6 +1368,16 @@ BEGIN_FW_FTR_SECTION
         * interrupts if necessary.
         */
        beq     13f
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+#endif
+BEGIN_FW_FTR_SECTION
+       /*
+        * Here we have interrupts hard-disabled, so it is sufficient
+        * to restore paca->{soft,hard}_enable and get out.
+        */
+       beq     fast_exc_return_irq     /* Return from exception on success */
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
+
        /* For a hash failure, we don't bother re-enabling interrupts */
        ble-    12f
 
@@ -1337,14 +1389,6 @@ BEGIN_FW_FTR_SECTION
        ld      r3,SOFTE(r1)
        bl      .local_irq_restore
        b       11f
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif
-BEGIN_FW_FTR_SECTION
-       beq     fast_exception_return   /* Return from exception on success */
-       ble-    12f                     /* Failure return from hash_page */
-
-       /* fall through */
-END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 
 /* Here we have a page fault that hash_page can't handle. */
 handle_page_fault:
@@ -1362,6 +1406,8 @@ handle_page_fault:
        bl      .bad_page_fault
        b       .ret_from_except
 
+13:    b       .ret_from_except_lite
+
 /* We have a page fault that hash_page could handle but HV refused
  * the PTE insertion
  */
@@ -1371,8 +1417,6 @@ handle_page_fault:
        bl      .low_hash_fault
        b       .ret_from_except
 
-13:    b       .ret_from_except_lite
-
        /* here we have a segment miss */
 do_ste_alloc:
        bl      .ste_allocate           /* try to insert stab entry */
@@ -1595,7 +1639,6 @@ _STATIC(__start_initialization_iSeries)
        b       .start_here_common
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 
 _STATIC(__mmu_off)
        mfmsr   r3
@@ -1621,13 +1664,11 @@ _STATIC(__mmu_off)
  *
  */
 _GLOBAL(__start_initialization_multiplatform)
-#ifdef CONFIG_PPC_MULTIPLATFORM
        /*
         * Are we booted from a PROM Of-type client-interface ?
         */
        cmpldi  cr0,r5,0
        bne     .__boot_from_prom               /* yes -> prom */
-#endif
 
        /* Save parameters */
        mr      r31,r3
@@ -1656,7 +1697,6 @@ _GLOBAL(__start_initialization_multiplatform)
        bl      .__mmu_off
        b       .__after_prom_start
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 _STATIC(__boot_from_prom)
        /* Save parameters */
        mr      r31,r3
@@ -1696,7 +1736,6 @@ _STATIC(__boot_from_prom)
        bl      .prom_init
        /* We never return */
        trap
-#endif
 
 /*
  * At this point, r3 contains the physical address we are running at,
@@ -1752,8 +1791,6 @@ _STATIC(__after_prom_start)
        bl      .copy_and_flush         /* copy the rest */
        b       .start_here_multiplatform
 
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 /*
  * Copy routine used to copy the kernel to start at physical address 0
  * and flush and invalidate the caches as needed.
@@ -1877,11 +1914,16 @@ _GLOBAL(__secondary_start)
        /* enable MMU and jump to start_secondary */
        LOAD_REG_ADDR(r3, .start_secondary_prolog)
        LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
-#ifdef DO_SOFT_DISABLE
+#ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
        ori     r4,r4,MSR_EE
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+BEGIN_FW_FTR_SECTION
+       stb     r7,PACASOFTIRQEN(r13)
+       stb     r7,PACAHARDIRQEN(r13)
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
+
        mtspr   SPRN_SRR0,r3
        mtspr   SPRN_SRR1,r4
        rfid
@@ -1913,7 +1955,6 @@ _GLOBAL(enable_64b_mode)
        isync
        blr
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 /*
  * This is where the main kernel code starts.
  */
@@ -1977,7 +2018,6 @@ _STATIC(start_here_multiplatform)
        mtspr   SPRN_SRR1,r4
        rfid
        b       .       /* prevent speculative execution */
-#endif /* CONFIG_PPC_MULTIPLATFORM */
        
        /* This is where all platforms converge execution */
 _STATIC(start_here_common)
@@ -2005,15 +2045,18 @@ _STATIC(start_here_common)
 
        /* Load up the kernel context */
 5:
-#ifdef DO_SOFT_DISABLE
-BEGIN_FW_FTR_SECTION
        li      r5,0
-       stb     r5,PACAPROCENABLED(r13) /* Soft Disabled */
+       stb     r5,PACASOFTIRQEN(r13)   /* Soft Disabled */
+#ifdef CONFIG_PPC_ISERIES
+BEGIN_FW_FTR_SECTION
        mfmsr   r5
        ori     r5,r5,MSR_EE            /* Hard Enabled */
        mtmsrd  r5
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+BEGIN_FW_FTR_SECTION
+       stb     r5,PACAHARDIRQEN(r13)
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 
        bl .start_kernel
 
index 4180c39..8994af3 100644 (file)
 #define cpu_should_die()       0
 #endif
 
+static int __init powersave_off(char *arg)
+{
+       ppc_md.power_save = NULL;
+       return 0;
+}
+__setup("powersave=off", powersave_off);
+
 /*
  * The body of the idle task.
  */
index 30de81d..ba31954 100644 (file)
@@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
        beqlr
 
        /* Go to NAP now */
+       mfmsr   r7
+       rldicl  r0,r7,48,1
+       rotldi  r0,r0,16
+       mtmsrd  r0,1                    /* hard-disable interrupts */
+       li      r0,1
+       stb     r0,PACASOFTIRQEN(r13)   /* we'll hard-enable shortly */
+       stb     r0,PACAHARDIRQEN(r13)
 BEGIN_FTR_SECTION
        DSSALL
        sync
@@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        ld      r8,TI_LOCAL_FLAGS(r9)   /* set napping bit */
        ori     r8,r8,_TLF_NAPPING      /* so when we take an exception */
        std     r8,TI_LOCAL_FLAGS(r9)   /* it will return to our caller */
-       mfmsr   r7
        ori     r7,r7,MSR_EE
        oris    r7,r7,MSR_POW@h
 1:     sync
index 5e37bf1..eb9fc62 100644 (file)
@@ -64,8 +64,9 @@
 #include <asm/ptrace.h>
 #include <asm/machdep.h>
 #include <asm/udbg.h>
-#ifdef CONFIG_PPC_ISERIES
+#ifdef CONFIG_PPC64
 #include <asm/paca.h>
+#include <asm/firmware.h>
 #endif
 
 int __irq_offset_value;
@@ -95,6 +96,27 @@ extern atomic_t ipi_sent;
 EXPORT_SYMBOL(irq_desc);
 
 int distribute_irqs = 1;
+
+void local_irq_restore(unsigned long en)
+{
+       get_paca()->soft_enabled = en;
+       if (!en)
+               return;
+
+       if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+               if (get_paca()->lppaca_ptr->int_dword.any_int)
+                       iseries_handle_interrupts();
+               return;
+       }
+
+       if (get_paca()->hard_enabled)
+               return;
+       /* need to hard-enable interrupts here */
+       get_paca()->hard_enabled = en;
+       if ((int)mfspr(SPRN_DEC) < 0)
+               mtspr(SPRN_DEC, 1);
+       hard_irq_enable();
+}
 #endif /* CONFIG_PPC64 */
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -626,10 +648,14 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
 
 void irq_dispose_mapping(unsigned int virq)
 {
-       struct irq_host *host = irq_map[virq].host;
+       struct irq_host *host;
        irq_hw_number_t hwirq;
        unsigned long flags;
 
+       if (virq == NO_IRQ)
+               return;
+
+       host = irq_map[virq].host;
        WARN_ON (host == NULL);
        if (host == NULL)
                return;
index 9bae8a5..80ae9ea 100644 (file)
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
 static void phbs_remap_io(void);
-#endif
 
 /* pci_io_base -- the base address from which io bars are offsets.
  * 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)
                pcibios_claim_one_bus(b);
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
 {
        const u32 *prop;
@@ -506,7 +503,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
                pci_scan_child_bus(bus);
 }
 EXPORT_SYMBOL(of_scan_pci_bridge);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void __devinit scan_phb(struct pci_controller *hose)
 {
@@ -540,7 +536,7 @@ void __devinit scan_phb(struct pci_controller *hose)
        }
 
        mode = PCI_PROBE_NORMAL;
-#ifdef CONFIG_PPC_MULTIPLATFORM
+
        if (node && ppc_md.pci_probe_mode)
                mode = ppc_md.pci_probe_mode(bus);
        DBG("    probe mode: %d\n", mode);
@@ -548,7 +544,7 @@ void __devinit scan_phb(struct pci_controller *hose)
                bus->subordinate = hose->last_busno;
                of_scan_bus(node, bus);
        }
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+
        if (mode == PCI_PROBE_NORMAL)
                hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
 }
@@ -592,11 +588,9 @@ static int __init pcibios_init(void)
        if (ppc64_isabridge_dev != NULL)
                printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
                /* map in PCI I/O space */
                phbs_remap_io();
-#endif
 
        printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
@@ -873,8 +867,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev)
        device_create_file(&pdev->dev, &dev_attr_devspec);
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-
 #define ISA_SPACE_MASK 0x1
 #define ISA_SPACE_IO 0x1
 
@@ -1343,8 +1335,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
        return NULL;
 }
 
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
        struct pci_controller *hose, *tmp;
index 807193a..9179f07 100644 (file)
 #include <asm/commproc.h>
 #endif
 
+#ifdef CONFIG_PPC64
+EXPORT_SYMBOL(local_irq_restore);
+#endif
+
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
 extern void do_IRQ(struct pt_regs *regs);
index bdb412d..16d29d1 100644 (file)
@@ -1674,6 +1674,7 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
        }
        return NULL;
 }
+EXPORT_SYMBOL(of_get_cpu_node);
 
 #ifdef DEBUG
 static struct debugfs_blob_wrapper flat_dt_blob;
index 603dff3..346fb7b 100644 (file)
 #define OF_CHECK_COUNTS(na, ns)        ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
                        (ns) > 0)
 
+static struct of_bus *of_match_bus(struct device_node *np);
+static int __of_address_to_resource(struct device_node *dev,
+               const u32 *addrp, u64 size, unsigned int flags,
+               struct resource *r);
+
+
 /* Debug utility */
 #ifdef DEBUG
 static 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)
 }
 
 
+#ifdef CONFIG_PCI
 /*
  * PCI bus specific translator
  */
@@ -162,6 +169,145 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
        return flags;
 }
 
+const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
+                       unsigned int *flags)
+{
+       const u32 *prop;
+       unsigned int psize;
+       struct device_node *parent;
+       struct of_bus *bus;
+       int onesize, i, na, ns;
+
+       /* Get parent & match bus type */
+       parent = of_get_parent(dev);
+       if (parent == NULL)
+               return NULL;
+       bus = of_match_bus(parent);
+       if (strcmp(bus->name, "pci")) {
+               of_node_put(parent);
+               return NULL;
+       }
+       bus->count_cells(dev, &na, &ns);
+       of_node_put(parent);
+       if (!OF_CHECK_COUNTS(na, ns))
+               return NULL;
+
+       /* Get "reg" or "assigned-addresses" property */
+       prop = get_property(dev, bus->addresses, &psize);
+       if (prop == NULL)
+               return NULL;
+       psize /= 4;
+
+       onesize = na + ns;
+       for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+               if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
+                       if (size)
+                               *size = of_read_number(prop + na, ns);
+                       if (flags)
+                               *flags = bus->get_flags(prop);
+                       return prop;
+               }
+       return NULL;
+}
+EXPORT_SYMBOL(of_get_pci_address);
+
+int of_pci_address_to_resource(struct device_node *dev, int bar,
+                              struct resource *r)
+{
+       const u32       *addrp;
+       u64             size;
+       unsigned int    flags;
+
+       addrp = of_get_pci_address(dev, bar, &size, &flags);
+       if (addrp == NULL)
+               return -EINVAL;
+       return __of_address_to_resource(dev, addrp, size, flags, r);
+}
+EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
+{
+       return (((pin - 1) + slot) % 4) + 1;
+}
+
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+       struct device_node *dn, *ppnode;
+       struct pci_dev *ppdev;
+       u32 lspec;
+       u32 laddr[3];
+       u8 pin;
+       int rc;
+
+       /* Check if we have a device node, if yes, fallback to standard OF
+        * parsing
+        */
+       dn = pci_device_to_OF_node(pdev);
+       if (dn)
+               return of_irq_map_one(dn, 0, out_irq);
+
+       /* Ok, we don't, time to have fun. Let's start by building up an
+        * interrupt spec.  we assume #interrupt-cells is 1, which is standard
+        * for PCI. If you do different, then don't use that routine.
+        */
+       rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+       if (rc != 0)
+               return rc;
+       /* No pin, exit */
+       if (pin == 0)
+               return -ENODEV;
+
+       /* Now we walk up the PCI tree */
+       lspec = pin;
+       for (;;) {
+               /* Get the pci_dev of our parent */
+               ppdev = pdev->bus->self;
+
+               /* Ouch, it's a host bridge... */
+               if (ppdev == NULL) {
+#ifdef CONFIG_PPC64
+                       ppnode = pci_bus_to_OF_node(pdev->bus);
+#else
+                       struct pci_controller *host;
+                       host = pci_bus_to_host(pdev->bus);
+                       ppnode = host ? host->arch_data : NULL;
+#endif
+                       /* No node for host bridge ? give up */
+                       if (ppnode == NULL)
+                               return -EINVAL;
+               } else
+                       /* We found a P2P bridge, check if it has a node */
+                       ppnode = pci_device_to_OF_node(ppdev);
+
+               /* Ok, we have found a parent with a device-node, hand over to
+                * the OF parsing code.
+                * We build a unit address from the linux device to be used for
+                * resolution. Note that we use the linux bus number which may
+                * not match your firmware bus numbering.
+                * Fortunately, in most cases, interrupt-map-mask doesn't include
+                * the bus number as part of the matching.
+                * You should still be careful about that though if you intend
+                * to rely on this function (you ship  a firmware that doesn't
+                * create device nodes for all PCI devices).
+                */
+               if (ppnode)
+                       break;
+
+               /* We can only get here if we hit a P2P bridge with no node,
+                * let's do standard swizzling and try again
+                */
+               lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+               pdev = ppdev;
+       }
+
+       laddr[0] = (pdev->bus->number << 16)
+               | (pdev->devfn << 8);
+       laddr[1]  = laddr[2] = 0;
+       return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
+#endif /* CONFIG_PCI */
+
 /*
  * ISA bus specific translator
  */
@@ -223,6 +369,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr)
  */
 
 static struct of_bus of_busses[] = {
+#ifdef CONFIG_PCI
        /* PCI */
        {
                .name = "pci",
@@ -233,6 +380,7 @@ static struct of_bus of_busses[] = {
                .translate = of_bus_pci_translate,
                .get_flags = of_bus_pci_get_flags,
        },
+#endif /* CONFIG_PCI */
        /* ISA */
        {
                .name = "isa",
@@ -445,48 +593,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
-const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
-                       unsigned int *flags)
-{
-       const u32 *prop;
-       unsigned int psize;
-       struct device_node *parent;
-       struct of_bus *bus;
-       int onesize, i, na, ns;
-
-       /* Get parent & match bus type */
-       parent = of_get_parent(dev);
-       if (parent == NULL)
-               return NULL;
-       bus = of_match_bus(parent);
-       if (strcmp(bus->name, "pci")) {
-               of_node_put(parent);
-               return NULL;
-       }
-       bus->count_cells(dev, &na, &ns);
-       of_node_put(parent);
-       if (!OF_CHECK_COUNTS(na, ns))
-               return NULL;
-
-       /* Get "reg" or "assigned-addresses" property */
-       prop = get_property(dev, bus->addresses, &psize);
-       if (prop == NULL)
-               return NULL;
-       psize /= 4;
-
-       onesize = na + ns;
-       for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
-               if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
-                       if (size)
-                               *size = of_read_number(prop + na, ns);
-                       if (flags)
-                               *flags = bus->get_flags(prop);
-                       return prop;
-               }
-       return NULL;
-}
-EXPORT_SYMBOL(of_get_pci_address);
-
 static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
                                    u64 size, unsigned int flags,
                                    struct resource *r)
@@ -529,20 +635,6 @@ int of_address_to_resource(struct device_node *dev, int index,
 }
 EXPORT_SYMBOL_GPL(of_address_to_resource);
 
-int of_pci_address_to_resource(struct device_node *dev, int bar,
-                              struct resource *r)
-{
-       const u32       *addrp;
-       u64             size;
-       unsigned int    flags;
-
-       addrp = of_get_pci_address(dev, bar, &size, &flags);
-       if (addrp == NULL)
-               return -EINVAL;
-       return __of_address_to_resource(dev, addrp, size, flags, r);
-}
-EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
-
 void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
                unsigned long *busno, unsigned long *phys, unsigned long *size)
 {
@@ -898,87 +990,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
        return res;
 }
 EXPORT_SYMBOL_GPL(of_irq_map_one);
-
-#ifdef CONFIG_PCI
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-       return (((pin - 1) + slot) % 4) + 1;
-}
-
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
-       struct device_node *dn, *ppnode;
-       struct pci_dev *ppdev;
-       u32 lspec;
-       u32 laddr[3];
-       u8 pin;
-       int rc;
-
-       /* Check if we have a device node, if yes, fallback to standard OF
-        * parsing
-        */
-       dn = pci_device_to_OF_node(pdev);
-       if (dn)
-               return of_irq_map_one(dn, 0, out_irq);
-
-       /* Ok, we don't, time to have fun. Let's start by building up an
-        * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-        * for PCI. If you do different, then don't use that routine.
-        */
-       rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-       if (rc != 0)
-               return rc;
-       /* No pin, exit */
-       if (pin == 0)
-               return -ENODEV;
-
-       /* Now we walk up the PCI tree */
-       lspec = pin;
-       for (;;) {
-               /* Get the pci_dev of our parent */
-               ppdev = pdev->bus->self;
-
-               /* Ouch, it's a host bridge... */
-               if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
-                       ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
-                       struct pci_controller *host;
-                       host = pci_bus_to_host(pdev->bus);
-                       ppnode = host ? host->arch_data : NULL;
-#endif
-                       /* No node for host bridge ? give up */
-                       if (ppnode == NULL)
-                               return -EINVAL;
-               } else
-                       /* We found a P2P bridge, check if it has a node */
-                       ppnode = pci_device_to_OF_node(ppdev);
-
-               /* Ok, we have found a parent with a device-node, hand over to
-                * the OF parsing code.
-                * We build a unit address from the linux device to be used for
-                * resolution. Note that we use the linux bus number which may
-                * not match your firmware bus numbering.
-                * Fortunately, in most cases, interrupt-map-mask doesn't include
-                * the bus number as part of the matching.
-                * You should still be careful about that though if you intend
-                * to rely on this function (you ship  a firmware that doesn't
-                * create device nodes for all PCI devices).
-                */
-               if (ppnode)
-                       break;
-
-               /* We can only get here if we hit a P2P bridge with no node,
-                * let's do standard swizzling and try again
-                */
-               lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
-               pdev = ppdev;
-       }
-
-       laddr[0] = (pdev->bus->number << 16)
-               | (pdev->devfn << 8);
-       laddr[1]  = laddr[2] = 0;
-       return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
index a4c2964..04df53a 100644 (file)
@@ -63,10 +63,6 @@ unsigned int DMA_MODE_WRITE;
 
 int have_of = 1;
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-dev_t boot_dev;
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 #ifdef CONFIG_VGA_CONSOLE
 unsigned long vgacon_remap_base;
 #endif
index 1627896..b0f1c82 100644 (file)
@@ -71,7 +71,6 @@
 
 int have_of = 1;
 int boot_cpuid = 0;
-dev_t boot_dev;
 u64 ppc64_pft_size;
 
 /* Pick defaults since we might want to patch instructions
@@ -226,8 +225,8 @@ void early_setup_secondary(void)
 {
        struct paca_struct *lpaca = get_paca();
 
-       /* Mark enabled in PACA */
-       lpaca->proc_enabled = 0;
+       /* Mark interrupts enabled in PACA */
+       lpaca->soft_enabled = 0;
 
        /* Initialize hash table for that CPU */
        htab_initialize_secondary();
@@ -392,7 +391,8 @@ void __init setup_system(void)
         * setting up the hash table pointers. It also sets up some interrupt-mapping
         * related options that will be used by finish_device_tree()
         */
-       ppc_md.init_early();
+       if (ppc_md.init_early)
+               ppc_md.init_early();
 
        /*
         * We can discover serial ports now since the above did setup the
index 35c6309..9b28c23 100644 (file)
@@ -65,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
 
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
+EXPORT_SYMBOL(cpu_sibling_map);
 
 /* SMP operations for this machine */
 struct smp_ops_t *smp_ops;
index d45a168..cda21a2 100644 (file)
@@ -299,6 +299,72 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
        .notifier_call  = sysfs_cpu_notify,
 };
 
+static DEFINE_MUTEX(cpu_mutex);
+
+int cpu_add_sysdev_attr(struct sysdev_attribute *attr)
+{
+       int cpu;
+
+       mutex_lock(&cpu_mutex);
+
+       for_each_possible_cpu(cpu) {
+               sysdev_create_file(get_cpu_sysdev(cpu), attr);
+       }
+
+       mutex_unlock(&cpu_mutex);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr);
+
+int cpu_add_sysdev_attr_group(struct attribute_group *attrs)
+{
+       int cpu;
+       struct sys_device *sysdev;
+
+       mutex_lock(&cpu_mutex);
+
+       for_each_possible_cpu(cpu) {
+               sysdev = get_cpu_sysdev(cpu);
+               sysfs_create_group(&sysdev->kobj, attrs);
+       }
+
+       mutex_unlock(&cpu_mutex);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group);
+
+
+void cpu_remove_sysdev_attr(struct sysdev_attribute *attr)
+{
+       int cpu;
+
+       mutex_lock(&cpu_mutex);
+
+       for_each_possible_cpu(cpu) {
+               sysdev_remove_file(get_cpu_sysdev(cpu), attr);
+       }
+
+       mutex_unlock(&cpu_mutex);
+}
+EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr);
+
+void cpu_remove_sysdev_attr_group(struct attribute_group *attrs)
+{
+       int cpu;
+       struct sys_device *sysdev;
+
+       mutex_lock(&cpu_mutex);
+
+       for_each_possible_cpu(cpu) {
+               sysdev = get_cpu_sysdev(cpu);
+               sysfs_remove_group(&sysdev->kobj, attrs);
+       }
+
+       mutex_unlock(&cpu_mutex);
+}
+EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group);
+
+
 /* NUMA stuff */
 
 #ifdef CONFIG_NUMA
index e8fa506..03aeb3a 100644 (file)
@@ -426,18 +426,21 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 
        /* kernel has accessed a bad area */
 
-       printk(KERN_ALERT "Unable to handle kernel paging request for ");
        switch (regs->trap) {
-               case 0x300:
-               case 0x380:
-                       printk("data at address 0x%08lx\n", regs->dar);
-                       break;
-               case 0x400:
-               case 0x480:
-                       printk("instruction fetch\n");
-                       break;
-               default:
-                       printk("unknown fault\n");
+       case 0x300:
+       case 0x380:
+               printk(KERN_ALERT "Unable to handle kernel paging request for "
+                       "data at address 0x%08lx\n", regs->dar);
+               break;
+       case 0x400:
+       case 0x480:
+               printk(KERN_ALERT "Unable to handle kernel paging request for "
+                       "instruction fetch\n");
+               break;
+       default:
+               printk(KERN_ALERT "Unable to handle kernel paging request for "
+                       "unknown fault\n");
+               break;
        }
        printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
                regs->nip);
index c90f124..6f1016a 100644 (file)
@@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep)
        clear_bit(HPTE_LOCK_BIT, word);
 }
 
-long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
                        unsigned long pa, unsigned long rflags,
                        unsigned long vflags, int psize)
 {
index e58fa95..7ad2673 100644 (file)
@@ -5,6 +5,7 @@ ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_PPC_PMAC)         += powermac/
 endif
 endif
+obj-$(CONFIG_PPC_EFIKA)          += efika/
 obj-$(CONFIG_PPC_CHRP)         += chrp/
 obj-$(CONFIG_4xx)              += 4xx/
 obj-$(CONFIG_PPC_83xx)         += 83xx/
index 3e430b4..06a85b7 100644 (file)
@@ -20,4 +20,18 @@ config CBE_RAS
        bool "RAS features for bare metal Cell BE"
        default y
 
+config CBE_THERM
+       tristate "CBE thermal support"
+       default m
+       depends on CBE_RAS
+
+config CBE_CPUFREQ
+       tristate "CBE frequency scaling"
+       depends on CBE_RAS && CPU_FREQ
+       default m
+       help
+         This adds the cpufreq driver for Cell BE processors.
+         For details, take a look at <file:Documentation/cpu-freq/>.
+         If you don't have such processor, say N
+
 endmenu
index c89cdd6..0f31db7 100644 (file)
@@ -1,7 +1,11 @@
 obj-$(CONFIG_PPC_CELL_NATIVE)          += interrupt.o iommu.o setup.o \
-                                          cbe_regs.o spider-pic.o pervasive.o
+                                          cbe_regs.o spider-pic.o pervasive.o \
+                                          pmu.o
 obj-$(CONFIG_CBE_RAS)                  += ras.o
 
+obj-$(CONFIG_CBE_THERM)                        += cbe_thermal.o
+obj-$(CONFIG_CBE_CPUFREQ)              += cbe_cpufreq.o
+
 ifeq ($(CONFIG_SMP),y)
 obj-$(CONFIG_PPC_CELL_NATIVE)          += smp.o
 endif
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
new file mode 100644 (file)
index 0000000..a3850fd
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * cpufreq driver for the cell processor
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/timer.h>
+
+#include <asm/hw_irq.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+
+#include "cbe_regs.h"
+
+static DEFINE_MUTEX(cbe_switch_mutex);
+
+
+/* the CBE supports an 8 step frequency scaling */
+static struct cpufreq_frequency_table cbe_freqs[] = {
+       {1,     0},
+       {2,     0},
+       {3,     0},
+       {4,     0},
+       {5,     0},
+       {6,     0},
+       {8,     0},
+       {10,    0},
+       {0,     CPUFREQ_TABLE_END},
+};
+
+/* to write to MIC register */
+static u64 MIC_Slow_Fast_Timer_table[] = {
+       [0 ... 7] = 0x007fc00000000000ull,
+};
+
+/* more values for the MIC */
+static u64 MIC_Slow_Next_Timer_table[] = {
+       0x0000240000000000ull,
+       0x0000268000000000ull,
+       0x000029C000000000ull,
+       0x00002D0000000000ull,
+       0x0000300000000000ull,
+       0x0000334000000000ull,
+       0x000039C000000000ull,
+       0x00003FC000000000ull,
+};
+
+/*
+ * hardware specific functions
+ */
+
+static int get_pmode(int cpu)
+{
+       int ret;
+       struct cbe_pmd_regs __iomem *pmd_regs;
+
+       pmd_regs = cbe_get_cpu_pmd_regs(cpu);
+       ret = in_be64(&pmd_regs->pmsr) & 0x07;
+
+       return ret;
+}
+
+static int set_pmode(int cpu, unsigned int pmode)
+{
+       struct cbe_pmd_regs __iomem *pmd_regs;
+       struct cbe_mic_tm_regs __iomem *mic_tm_regs;
+       u64 flags;
+       u64 value;
+
+       local_irq_save(flags);
+
+       mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
+       pmd_regs = cbe_get_cpu_pmd_regs(cpu);
+
+       pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr);
+       pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0);
+
+       out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
+       out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
+
+       out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
+       out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
+
+       value = in_be64(&pmd_regs->pmcr);
+       /* set bits to zero */
+       value &= 0xFFFFFFFFFFFFFFF8ull;
+       /* set bits to next pmode */
+       value |= pmode;
+
+       out_be64(&pmd_regs->pmcr, value);
+
+       /* wait until new pmode appears in status register */
+       value = in_be64(&pmd_regs->pmsr) & 0x07;
+       while(value != pmode) {
+               cpu_relax();
+               value = in_be64(&pmd_regs->pmsr) & 0x07;
+       }
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+/*
+ * cpufreq functions
+ */
+
+static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy)
+{
+       u32 *max_freq;
+       int i, cur_pmode;
+       struct device_node *cpu;
+
+       cpu = of_get_cpu_node(policy->cpu, NULL);
+
+       if(!cpu)
+               return -ENODEV;
+
+       pr_debug("init cpufreq on CPU %d\n", policy->cpu);
+
+       max_freq = (u32*) get_property(cpu, "clock-frequency", NULL);
+
+       if(!max_freq)
+               return -EINVAL;
+
+       // we need the freq in kHz
+       *max_freq /= 1000;
+
+       pr_debug("max clock-frequency is at %u kHz\n", *max_freq);
+       pr_debug("initializing frequency table\n");
+
+       // initialize frequency table
+       for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) {
+               cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index;
+               pr_debug("%d: %d\n", i, cbe_freqs[i].frequency);
+       }
+
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+       /* if DEBUG is enabled set_pmode() measures the correct latency of a transition */
+       policy->cpuinfo.transition_latency = 25000;
+
+       cur_pmode = get_pmode(policy->cpu);
+       pr_debug("current pmode is at %d\n",cur_pmode);
+
+       policy->cur = cbe_freqs[cur_pmode].frequency;
+
+#ifdef CONFIG_SMP
+       policy->cpus = cpu_sibling_map[policy->cpu];
+#endif
+
+       cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu);
+
+       /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
+       return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs);
+}
+
+static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
+
+static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, cbe_freqs);
+}
+
+
+static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq,
+                           unsigned int relation)
+{
+       int rc;
+       struct cpufreq_freqs freqs;
+       int cbe_pmode_new;
+
+       cpufreq_frequency_table_target(policy,
+                                      cbe_freqs,
+                                      target_freq,
+                                      relation,
+                                      &cbe_pmode_new);
+
+       freqs.old = policy->cur;
+       freqs.new = cbe_freqs[cbe_pmode_new].frequency;
+       freqs.cpu = policy->cpu;
+
+       mutex_lock (&cbe_switch_mutex);
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+       pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
+                policy->cpu,
+                cbe_freqs[cbe_pmode_new].frequency,
+                cbe_freqs[cbe_pmode_new].index);
+
+       rc = set_pmode(policy->cpu, cbe_pmode_new);
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       mutex_unlock(&cbe_switch_mutex);
+
+       return rc;
+}
+
+static struct cpufreq_driver cbe_cpufreq_driver = {
+       .verify         = cbe_cpufreq_verify,
+       .target         = cbe_cpufreq_target,
+       .init           = cbe_cpufreq_cpu_init,
+       .exit           = cbe_cpufreq_cpu_exit,
+       .name           = "cbe-cpufreq",
+       .owner          = THIS_MODULE,
+       .flags          = CPUFREQ_CONST_LOOPS,
+};
+
+/*
+ * module init and destoy
+ */
+
+static int __init cbe_cpufreq_init(void)
+{
+       return cpufreq_register_driver(&cbe_cpufreq_driver);
+}
+
+static void __exit cbe_cpufreq_exit(void)
+{
+       cpufreq_unregister_driver(&cbe_cpufreq_driver);
+}
+
+module_init(cbe_cpufreq_init);
+module_exit(cbe_cpufreq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
index 2f194ba..5a91b75 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/percpu.h>
 #include <linux/types.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -16,8 +17,6 @@
 
 #include "cbe_regs.h"
 
-#define MAX_CBE                2
-
 /*
  * Current implementation uses "cpu" nodes. We build our own mapping
  * array of cpu numbers to cpu nodes locally for now to allow interrupt
@@ -30,6 +29,8 @@ static struct cbe_regs_map
        struct device_node *cpu_node;
        struct cbe_pmd_regs __iomem *pmd_regs;
        struct cbe_iic_regs __iomem *iic_regs;
+       struct cbe_mic_tm_regs __iomem *mic_tm_regs;
+       struct cbe_pmd_shadow_regs pmd_shadow_regs;
 } cbe_regs_maps[MAX_CBE];
 static int cbe_regs_map_count;
 
@@ -42,6 +43,19 @@ static struct cbe_thread_map
 static struct cbe_regs_map *cbe_find_map(struct device_node *np)
 {
        int i;
+       struct device_node *tmp_np;
+
+       if (strcasecmp(np->type, "spe") == 0) {
+               if (np->data == NULL) {
+                       /* walk up path until cpu node was found */
+                       tmp_np = np->parent;
+                       while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0)
+                               tmp_np = tmp_np->parent;
+
+                       np->data = cbe_find_map(tmp_np);
+               }
+               return np->data;
+       }
 
        for (i = 0; i < cbe_regs_map_count; i++)
                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)
                return NULL;
        return map->pmd_regs;
 }
+EXPORT_SYMBOL_GPL(cbe_get_pmd_regs);
 
 struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
 {
@@ -64,7 +79,23 @@ struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
                return NULL;
        return map->pmd_regs;
 }
+EXPORT_SYMBOL_GPL(cbe_get_cpu_pmd_regs);
+
+struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np)
+{
+       struct cbe_regs_map *map = cbe_find_map(np);
+       if (map == NULL)
+               return NULL;
+       return &map->pmd_shadow_regs;
+}
 
+struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu)
+{
+       struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+       if (map == NULL)
+               return NULL;
+       return &map->pmd_shadow_regs;
+}
 
 struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
 {
@@ -73,6 +104,7 @@ struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
                return NULL;
        return map->iic_regs;
 }
+
 struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
 {
        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)
        return map->iic_regs;
 }
 
+struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np)
+{
+       struct cbe_regs_map *map = cbe_find_map(np);
+       if (map == NULL)
+               return NULL;
+       return map->mic_tm_regs;
+}
+
+struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu)
+{
+       struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+       if (map == NULL)
+               return NULL;
+       return map->mic_tm_regs;
+}
+EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs);
+
+
 void __init cbe_regs_init(void)
 {
        int i;
@@ -119,6 +169,11 @@ void __init cbe_regs_init(void)
                prop = get_property(cpu, "iic", NULL);
                if (prop != NULL)
                        map->iic_regs = ioremap(prop->address, prop->len);
+
+               prop = (struct address_prop *)get_property(cpu, "mic-tm",
+                                                          NULL);
+               if (prop != NULL)
+                       map->mic_tm_regs = ioremap(prop->address, prop->len);
        }
 }
 
index e76e4a6..91083f5 100644 (file)
@@ -4,6 +4,11 @@
  * This file is intended to hold the various register definitions for CBE
  * on-chip system devices (memory controller, IO controller, etc...)
  *
+ * (C) Copyright IBM Corporation 2001,2006
+ *
+ * Authors: Maximino Aguilar (maguilar@us.ibm.com)
+ *          David J. Erb (djerb@us.ibm.com)
+ *
  * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
  */
 
@@ -22,6 +27,7 @@
 #define HID0_CBE_THERM_INT_EN  0x0000000400000000ul
 #define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
 
+#define MAX_CBE                2
 
 /*
  *
  *
  */
 
+/* Macros for the pm_control register. */
+#define CBE_PM_16BIT_CTR(ctr)                  (1 << (24 - ((ctr) & (NR_PHYS_CTRS - 1))))
+#define CBE_PM_ENABLE_PERF_MON                 0x80000000
+
+
+union spe_reg {
+       u64 val;
+       u8 spe[8];
+};
+
+union ppe_spe_reg {
+       u64 val;
+       struct {
+               u32 ppe;
+               u32 spe;
+       };
+};
+
+
 struct cbe_pmd_regs {
-       u8 pad_0x0000_0x0800[0x0800 - 0x0000];                  /* 0x0000 */
+       /* Debug Bus Control */
+       u64     pad_0x0000;                                     /* 0x0000 */
+
+       u64     group_control;                                  /* 0x0008 */
+
+       u8      pad_0x0010_0x00a8 [0x00a8 - 0x0010];            /* 0x0010 */
+
+       u64     debug_bus_control;                              /* 0x00a8 */
+
+       u8      pad_0x00b0_0x0100 [0x0100 - 0x00b0];            /* 0x00b0 */
+
+       u64     trace_aux_data;                                 /* 0x0100 */
+       u64     trace_buffer_0_63;                              /* 0x0108 */
+       u64     trace_buffer_64_127;                            /* 0x0110 */
+       u64     trace_address;                                  /* 0x0118 */
+       u64     ext_tr_timer;                                   /* 0x0120 */
+
+       u8      pad_0x0128_0x0400 [0x0400 - 0x0128];            /* 0x0128 */
+
+       /* Performance Monitor */
+       u64     pm_status;                                      /* 0x0400 */
+       u64     pm_control;                                     /* 0x0408 */
+       u64     pm_interval;                                    /* 0x0410 */
+       u64     pm_ctr[4];                                      /* 0x0418 */
+       u64     pm_start_stop;                                  /* 0x0438 */
+       u64     pm07_control[8];                                /* 0x0440 */
+
+       u8      pad_0x0480_0x0800 [0x0800 - 0x0480];            /* 0x0480 */
 
        /* Thermal Sensor Registers */
-       u64  ts_ctsr1;                                          /* 0x0800 */
-       u64  ts_ctsr2;                                          /* 0x0808 */
-       u64  ts_mtsr1;                                          /* 0x0810 */
-       u64  ts_mtsr2;                                          /* 0x0818 */
-       u64  ts_itr1;                                           /* 0x0820 */
-       u64  ts_itr2;                                           /* 0x0828 */
-       u64  ts_gitr;                                           /* 0x0830 */
-       u64  ts_isr;                                            /* 0x0838 */
-       u64  ts_imr;                                            /* 0x0840 */
-       u64  tm_cr1;                                            /* 0x0848 */
-       u64  tm_cr2;                                            /* 0x0850 */
-       u64  tm_simr;                                           /* 0x0858 */
-       u64  tm_tpr;                                            /* 0x0860 */
-       u64  tm_str1;                                           /* 0x0868 */
-       u64  tm_str2;                                           /* 0x0870 */
-       u64  tm_tsr;                                            /* 0x0878 */
+       union   spe_reg ts_ctsr1;                               /* 0x0800 */
+       u64     ts_ctsr2;                                       /* 0x0808 */
+       union   spe_reg ts_mtsr1;                               /* 0x0810 */
+       u64     ts_mtsr2;                                       /* 0x0818 */
+       union   spe_reg ts_itr1;                                /* 0x0820 */
+       u64     ts_itr2;                                        /* 0x0828 */
+       u64     ts_gitr;                                        /* 0x0830 */
+       u64     ts_isr;                                         /* 0x0838 */
+       u64     ts_imr;                                         /* 0x0840 */
+       union   spe_reg tm_cr1;                                 /* 0x0848 */
+       u64     tm_cr2;                                         /* 0x0850 */
+       u64     tm_simr;                                        /* 0x0858 */
+       union   ppe_spe_reg tm_tpr;                             /* 0x0860 */
+       union   spe_reg tm_str1;                                /* 0x0868 */
+       u64     tm_str2;                                        /* 0x0870 */
+       union   ppe_spe_reg tm_tsr;                             /* 0x0878 */
 
        /* Power Management */
-       u64  pm_control;                                        /* 0x0880 */
-#define CBE_PMD_PAUSE_ZERO_CONTROL             0x10000
-       u64  pm_status;                                         /* 0x0888 */
+       u64     pmcr;                                           /* 0x0880 */
+#define CBE_PMD_PAUSE_ZERO_CONTROL     0x10000
+       u64     pmsr;                                           /* 0x0888 */
 
        /* Time Base Register */
-       u64  tbr;                                               /* 0x0890 */
+       u64     tbr;                                            /* 0x0890 */
 
-       u8   pad_0x0898_0x0c00 [0x0c00 - 0x0898];               /* 0x0898 */
+       u8      pad_0x0898_0x0c00 [0x0c00 - 0x0898];            /* 0x0898 */
 
        /* Fault Isolation Registers */
-       u64  checkstop_fir;                                     /* 0x0c00 */
-       u64  recoverable_fir;
-       u64  spec_att_mchk_fir;
-       u64  fir_mode_reg;
-       u64  fir_enable_mask;
+       u64     checkstop_fir;                                  /* 0x0c00 */
+       u64     recoverable_fir;                                /* 0x0c08 */
+       u64     spec_att_mchk_fir;                              /* 0x0c10 */
+       u64     fir_mode_reg;                                   /* 0x0c18 */
+       u64     fir_enable_mask;                                /* 0x0c20 */
 
-       u8   pad_0x0c28_0x1000 [0x1000 - 0x0c28];               /* 0x0c28 */
+       u8      pad_0x0c28_0x1000 [0x1000 - 0x0c28];            /* 0x0c28 */
 };
 
 extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
 extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
 
+/*
+ * PMU shadow registers
+ *
+ * Many of the registers in the performance monitoring unit are write-only,
+ * so we need to save a copy of what we write to those registers.
+ *
+ * The actual data counters are read/write. However, writing to the counters
+ * only takes effect if the PMU is enabled. Otherwise the value is stored in
+ * a hardware latch until the next time the PMU is enabled. So we save a copy
+ * of the counter values if we need to read them back while the PMU is
+ * disabled. The counter_value_in_latch field is a bitmap indicating which
+ * counters currently have a value waiting to be written.
+ */
+
+#define NR_PHYS_CTRS   4
+#define NR_CTRS                (NR_PHYS_CTRS * 2)
+
+struct cbe_pmd_shadow_regs {
+       u32 group_control;
+       u32 debug_bus_control;
+       u32 trace_address;
+       u32 ext_tr_timer;
+       u32 pm_status;
+       u32 pm_control;
+       u32 pm_interval;
+       u32 pm_start_stop;
+       u32 pm07_control[NR_CTRS];
+
+       u32 pm_ctr[NR_PHYS_CTRS];
+       u32 counter_value_in_latch;
+};
+
+extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np);
+extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu);
+
 /*
  *
  * IIC unit register definitions
@@ -102,18 +189,20 @@ struct cbe_iic_regs {
 
        /* IIC interrupt registers */
        struct  cbe_iic_thread_regs thread[2];                  /* 0x0400 */
-       u64     iic_ir;                                         /* 0x0440 */
-       u64     iic_is;                                         /* 0x0448 */
+
+       u64     iic_ir;                                         /* 0x0440 */
+       u64     iic_is;                                         /* 0x0448 */
+#define CBE_IIC_IS_PMI         0x2
 
        u8      pad_0x0450_0x0500[0x0500 - 0x0450];             /* 0x0450 */
 
        /* IOC FIR */
        u64     ioc_fir_reset;                                  /* 0x0500 */
-       u64     ioc_fir_set;
-       u64     ioc_checkstop_enable;
-       u64     ioc_fir_error_mask;
-       u64     ioc_syserr_enable;
-       u64     ioc_fir;
+       u64     ioc_fir_set;                                    /* 0x0508 */
+       u64     ioc_checkstop_enable;                           /* 0x0510 */
+       u64     ioc_fir_error_mask;                             /* 0x0518 */
+       u64     ioc_syserr_enable;                              /* 0x0520 */
+       u64     ioc_fir;                                        /* 0x0528 */
 
        u8      pad_0x0530_0x1000[0x1000 - 0x0530];             /* 0x0530 */
 };
@@ -122,6 +211,48 @@ extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
 extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
 
 
+struct cbe_mic_tm_regs {
+       u8      pad_0x0000_0x0040[0x0040 - 0x0000];             /* 0x0000 */
+
+       u64     mic_ctl_cnfg2;                                  /* 0x0040 */
+#define CBE_MIC_ENABLE_AUX_TRC         0x8000000000000000LL
+#define CBE_MIC_DISABLE_PWR_SAV_2      0x0200000000000000LL
+#define CBE_MIC_DISABLE_AUX_TRC_WRAP   0x0100000000000000LL
+#define CBE_MIC_ENABLE_AUX_TRC_INT     0x0080000000000000LL
+
+       u64     pad_0x0048;                                     /* 0x0048 */
+
+       u64     mic_aux_trc_base;                               /* 0x0050 */
+       u64     mic_aux_trc_max_addr;                           /* 0x0058 */
+       u64     mic_aux_trc_cur_addr;                           /* 0x0060 */
+       u64     mic_aux_trc_grf_addr;                           /* 0x0068 */
+       u64     mic_aux_trc_grf_data;                           /* 0x0070 */
+
+       u64     pad_0x0078;                                     /* 0x0078 */
+
+       u64     mic_ctl_cnfg_0;                                 /* 0x0080 */
+#define CBE_MIC_DISABLE_PWR_SAV_0      0x8000000000000000LL
+
+       u64     pad_0x0088;                                     /* 0x0088 */
+
+       u64     slow_fast_timer_0;                              /* 0x0090 */
+       u64     slow_next_timer_0;                              /* 0x0098 */
+
+       u8      pad_0x00a0_0x01c0[0x01c0 - 0x0a0];              /* 0x00a0 */
+
+       u64     mic_ctl_cnfg_1;                                 /* 0x01c0 */
+#define CBE_MIC_DISABLE_PWR_SAV_1      0x8000000000000000LL
+       u64     pad_0x01c8;                                     /* 0x01c8 */
+
+       u64     slow_fast_timer_1;                              /* 0x01d0 */
+       u64     slow_next_timer_1;                              /* 0x01d8 */
+
+       u8      pad_0x01e0_0x1000[0x1000 - 0x01e0];             /* 0x01e0 */
+};
+
+extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
+extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
+
 /* Init this module early */
 extern void cbe_regs_init(void);
 
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
new file mode 100644 (file)
index 0000000..17831a9
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * thermal support for the cell processor
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/sysdev.h>
+#include <linux/kernel.h>
+#include <linux/cpu.h>
+#include <asm/spu.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+
+#include "cbe_regs.h"
+
+static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
+{
+       struct spu *spu;
+
+       spu = container_of(sysdev, struct spu, sysdev);
+
+       return cbe_get_pmd_regs(spu->devnode);
+}
+
+/* returns the value for a given spu in a given register */
+static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg)
+{
+       unsigned int *id;
+       union spe_reg value;
+       struct spu *spu;
+
+       /* getting the id from the reg attribute will not work on future device-tree layouts
+        * in future we should store the id to the spu struct and use it here */
+       spu = container_of(sysdev, struct spu, sysdev);
+       id = (unsigned int *)get_property(spu->devnode, "reg", NULL);
+       value.val = in_be64(&reg->val);
+
+       return value.spe[*id];
+}
+
+static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
+{
+       int value;
+       struct cbe_pmd_regs __iomem *pmd_regs;
+
+       pmd_regs = get_pmd_regs(sysdev);
+
+       value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1);
+       /* clear all other bits */
+       value &= 0x3F;
+       /* temp is stored in steps of 2 degrees */
+       value *= 2;
+       /* base temp is 65 degrees */
+       value += 65;
+
+       return sprintf(buf, "%d\n", (int) value);
+}
+
+static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
+{
+       struct cbe_pmd_regs __iomem *pmd_regs;
+       u64 value;
+
+       pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
+       value = in_be64(&pmd_regs->ts_ctsr2);
+
+       /* access the corresponding byte */
+       value >>= pos;
+       /* clear all other bits */
+       value &= 0x3F;
+       /* temp is stored in steps of 2 degrees */
+       value *= 2;
+       /* base temp is 65 degrees */
+       value += 65;
+
+       return sprintf(buf, "%d\n", (int) value);
+}
+
+
+/* shows the temperature of the DTS on the PPE,
+ * located near the linear thermal sensor */
+static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf)
+{
+       return ppe_show_temp(sysdev, buf, 32);
+}
+
+/* shows the temperature of the second DTS on the PPE */
+static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf)
+{
+       return ppe_show_temp(sysdev, buf, 0);
+}
+
+static struct sysdev_attribute attr_spu_temperature = {
+       .attr = {.name = "temperature", .mode = 0400 },
+       .show = spu_show_temp,
+};
+
+static struct attribute *spu_attributes[] = {
+       &attr_spu_temperature.attr,
+};
+
+static struct attribute_group spu_attribute_group = {
+       .name   = "thermal",
+       .attrs  = spu_attributes,
+};
+
+static struct sysdev_attribute attr_ppe_temperature0 = {
+       .attr = {.name = "temperature0", .mode = 0400 },
+       .show = ppe_show_temp0,
+};
+
+static struct sysdev_attribute attr_ppe_temperature1 = {
+       .attr = {.name = "temperature1", .mode = 0400 },
+       .show = ppe_show_temp1,
+};
+
+static struct attribute *ppe_attributes[] = {
+       &attr_ppe_temperature0.attr,
+       &attr_ppe_temperature1.attr,
+};
+
+static struct attribute_group ppe_attribute_group = {
+       .name   = "thermal",
+       .attrs  = ppe_attributes,
+};
+
+/*
+ * initialize throttling with default values
+ */
+static void __init init_default_values(void)
+{
+       int cpu;
+       struct cbe_pmd_regs __iomem *pmd_regs;
+       struct sys_device *sysdev;
+       union ppe_spe_reg tpr;
+       union spe_reg str1;
+       u64 str2;
+       union spe_reg cr1;
+       u64 cr2;
+
+       /* TPR defaults */
+       /* ppe
+        *      1F - no full stop
+        *      08 - dynamic throttling starts if over 80 degrees
+        *      03 - dynamic throttling ceases if below 70 degrees */
+       tpr.ppe = 0x1F0803;
+       /* spe
+        *      10 - full stopped when over 96 degrees
+        *      08 - dynamic throttling starts if over 80 degrees
+        *      03 - dynamic throttling ceases if below 70 degrees
+        */
+       tpr.spe = 0x100803;
+
+       /* STR defaults */
+       /* str1
+        *      10 - stop 16 of 32 cycles
+        */
+       str1.val = 0x1010101010101010ull;
+       /* str2
+        *      10 - stop 16 of 32 cycles
+        */
+       str2 = 0x10;
+
+       /* CR defaults */
+       /* cr1
+        *      4 - normal operation
+        */
+       cr1.val = 0x0404040404040404ull;
+       /* cr2
+        *      4 - normal operation
+        */
+       cr2 = 0x04;
+
+       for_each_possible_cpu (cpu) {
+               pr_debug("processing cpu %d\n", cpu);
+               sysdev = get_cpu_sysdev(cpu);
+               pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
+
+               out_be64(&pmd_regs->tm_str2, str2);
+               out_be64(&pmd_regs->tm_str1.val, str1.val);
+               out_be64(&pmd_regs->tm_tpr.val, tpr.val);
+               out_be64(&pmd_regs->tm_cr1.val, cr1.val);
+               out_be64(&pmd_regs->tm_cr2, cr2);
+       }
+}
+
+
+static int __init thermal_init(void)
+{
+       init_default_values();
+
+       spu_add_sysdev_attr_group(&spu_attribute_group);
+       cpu_add_sysdev_attr_group(&ppe_attribute_group);
+
+       return 0;
+}
+module_init(thermal_init);
+
+static void __exit thermal_exit(void)
+{
+       spu_remove_sysdev_attr_group(&spu_attribute_group);
+       cpu_remove_sysdev_attr_group(&ppe_attribute_group);
+}
+module_exit(thermal_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+
index 9f2e4ed..c68fabd 100644 (file)
 #include "pervasive.h"
 #include "cbe_regs.h"
 
-static DEFINE_SPINLOCK(cbe_pervasive_lock);
-
-static void __init cbe_enable_pause_zero(void)
+static void cbe_power_save(void)
 {
-       unsigned long thread_switch_control;
-       unsigned long temp_register;
-       struct cbe_pmd_regs __iomem *pregs;
-
-       spin_lock_irq(&cbe_pervasive_lock);
-       pregs = cbe_get_cpu_pmd_regs(smp_processor_id());
-       if (pregs == NULL)
-               goto out;
-
-       pr_debug("Power Management: CPU %d\n", smp_processor_id());
-
-        /* Enable Pause(0) control bit */
-       temp_register = in_be64(&pregs->pm_control);
-
-       out_be64(&pregs->pm_control,
-                temp_register | CBE_PMD_PAUSE_ZERO_CONTROL);
+       unsigned long ctrl, thread_switch_control;
+       ctrl = mfspr(SPRN_CTRLF);
 
        /* Enable DEC and EE interrupt request */
        thread_switch_control  = mfspr(SPRN_TSC_CELL);
        thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
 
-       switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) {
+       switch (ctrl & CTRL_CT) {
        case CTRL_CT0:
                thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
                break;
@@ -75,58 +59,21 @@ static void __init cbe_enable_pause_zero(void)
                        __FUNCTION__);
                break;
        }
-
        mtspr(SPRN_TSC_CELL, thread_switch_control);
 
-out:
-       spin_unlock_irq(&cbe_pervasive_lock);
-}
-
-static void cbe_idle(void)
-{
-       unsigned long ctrl;
-
-       /* Why do we do that on every idle ? Couldn't that be done once for
-        * all or do we lose the state some way ? Also, the pm_control
-        * register setting, that can't be set once at boot ? We really want
-        * to move that away in order to implement a simple powersave
+       /*
+        * go into low thread priority, medium priority will be
+        * restored for us after wake-up.
         */
-       cbe_enable_pause_zero();
-
-       while (1) {
-               if (!need_resched()) {
-                       local_irq_disable();
-                       while (!need_resched()) {
-                               /* go into low thread priority */
-                               HMT_low();
-
-                               /*
-                                * atomically disable thread execution
-                                * and runlatch.
-                                * External and Decrementer exceptions
-                                * are still handled when the thread
-                                * is disabled but now enter in
-                                * cbe_system_reset_exception()
-                                */
-                               ctrl = mfspr(SPRN_CTRLF);
-                               ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
-                               mtspr(SPRN_CTRLT, ctrl);
-                       }
-                       /* restore thread prio */
-                       HMT_medium();
-                       local_irq_enable();
-               }
+       HMT_low();
 
-               /*
-                * turn runlatch on again before scheduling the
-                * process we just woke up
-                */
-               ppc64_runlatch_on();
-
-               preempt_enable_no_resched();
-               schedule();
-               preempt_disable();
-       }
+       /*
+        * atomically disable thread execution and runlatch.
+        * External and Decrementer exceptions are still handled when the
+        * thread is disabled but now enter in cbe_system_reset_exception()
+        */
+       ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
+       mtspr(SPRN_CTRLT, ctrl);
 }
 
 static int cbe_system_reset_exception(struct pt_regs *regs)
@@ -158,9 +105,20 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
 
 void __init cbe_pervasive_init(void)
 {
+       int cpu;
        if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
                return;
 
-       ppc_md.idle_loop = cbe_idle;
+       for_each_possible_cpu(cpu) {
+               struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
+               if (!regs)
+                       continue;
+
+                /* Enable Pause(0) control bit */
+               out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
+                                           CBE_PMD_PAUSE_ZERO_CONTROL);
+       }
+
+       ppc_md.power_save = cbe_power_save;
        ppc_md.system_reset_exception = cbe_system_reset_exception;
 }
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
new file mode 100644 (file)
index 0000000..30d17ce
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Cell Broadband Engine Performance Monitor
+ *
+ * (C) Copyright IBM Corporation 2001,2006
+ *
+ * Author:
+ *    David Erb (djerb@us.ibm.com)
+ *    Kevin Corry (kevcorry@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/reg.h>
+#include <asm/spu.h>
+
+#include "cbe_regs.h"
+#include "interrupt.h"
+#include "pmu.h"
+
+/*
+ * When writing to write-only mmio addresses, save a shadow copy. All of the
+ * registers are 32-bit, but stored in the upper-half of a 64-bit field in
+ * pmd_regs.
+ */
+
+#define WRITE_WO_MMIO(reg, x)                                  \
+       do {                                                    \
+               u32 _x = (x);                                   \
+               struct cbe_pmd_regs __iomem *pmd_regs;          \
+               struct cbe_pmd_shadow_regs *shadow_regs;        \
+               pmd_regs = cbe_get_cpu_pmd_regs(cpu);           \
+               shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
+               out_be64(&(pmd_regs->reg), (((u64)_x) << 32));  \
+               shadow_regs->reg = _x;                          \
+       } while (0)
+
+#define READ_SHADOW_REG(val, reg)                              \
+       do {                                                    \
+               struct cbe_pmd_shadow_regs *shadow_regs;        \
+               shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
+               (val) = shadow_regs->reg;                       \
+       } while (0)
+
+#define READ_MMIO_UPPER32(val, reg)                            \
+       do {                                                    \
+               struct cbe_pmd_regs __iomem *pmd_regs;          \
+               pmd_regs = cbe_get_cpu_pmd_regs(cpu);           \
+               (val) = (u32)(in_be64(&pmd_regs->reg) >> 32);   \
+       } while (0)
+
+/*
+ * Physical counter registers.
+ * Each physical counter can act as one 32-bit counter or two 16-bit counters.
+ */
+
+u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr)
+{
+       u32 val_in_latch, val = 0;
+
+       if (phys_ctr < NR_PHYS_CTRS) {
+               READ_SHADOW_REG(val_in_latch, counter_value_in_latch);
+
+               /* Read the latch or the actual counter, whichever is newer. */
+               if (val_in_latch & (1 << phys_ctr)) {
+                       READ_SHADOW_REG(val, pm_ctr[phys_ctr]);
+               } else {
+                       READ_MMIO_UPPER32(val, pm_ctr[phys_ctr]);
+               }
+       }
+
+       return val;
+}
+
+void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
+{
+       struct cbe_pmd_shadow_regs *shadow_regs;
+       u32 pm_ctrl;
+
+       if (phys_ctr < NR_PHYS_CTRS) {
+               /* Writing to a counter only writes to a hardware latch.
+                * The new value is not propagated to the actual counter
+                * until the performance monitor is enabled.
+                */
+               WRITE_WO_MMIO(pm_ctr[phys_ctr], val);
+
+               pm_ctrl = cbe_read_pm(cpu, pm_control);
+               if (pm_ctrl & CBE_PM_ENABLE_PERF_MON) {
+                       /* The counters are already active, so we need to
+                        * rewrite the pm_control register to "re-enable"
+                        * the PMU.
+                        */
+                       cbe_write_pm(cpu, pm_control, pm_ctrl);
+               } else {
+                       shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
+                       shadow_regs->counter_value_in_latch |= (1 << phys_ctr);
+               }
+       }
+}
+
+/*
+ * "Logical" counter registers.
+ * These will read/write 16-bits or 32-bits depending on the
+ * current size of the counter. Counters 4 - 7 are always 16-bit.
+ */
+
+u32 cbe_read_ctr(u32 cpu, u32 ctr)
+{
+       u32 val;
+       u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
+
+       val = cbe_read_phys_ctr(cpu, phys_ctr);
+
+       if (cbe_get_ctr_size(cpu, phys_ctr) == 16)
+               val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
+
+       return val;
+}
+
+void cbe_write_ctr(u32 cpu, u32 ctr, u32 val)
+{
+       u32 phys_ctr;
+       u32 phys_val;
+
+       phys_ctr = ctr & (NR_PHYS_CTRS - 1);
+
+       if (cbe_get_ctr_size(cpu, phys_ctr) == 16) {
+               phys_val = cbe_read_phys_ctr(cpu, phys_ctr);
+
+               if (ctr < NR_PHYS_CTRS)
+                       val = (val << 16) | (phys_val & 0xffff);
+               else
+                       val = (val & 0xffff) | (phys_val & 0xffff0000);
+       }
+
+       cbe_write_phys_ctr(cpu, phys_ctr, val);
+}
+
+/*
+ * Counter-control registers.
+ * Each "logical" counter has a corresponding control register.
+ */
+
+u32 cbe_read_pm07_control(u32 cpu, u32 ctr)
+{
+       u32 pm07_control = 0;
+
+       if (ctr < NR_CTRS)
+               READ_SHADOW_REG(pm07_control, pm07_control[ctr]);
+
+       return pm07_control;
+}
+
+void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val)
+{
+       if (ctr < NR_CTRS)
+               WRITE_WO_MMIO(pm07_control[ctr], val);
+}
+
+/*
+ * Other PMU control registers. Most of these are write-only.
+ */
+
+u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg)
+{
+       u32 val = 0;
+
+       switch (reg) {
+       case group_control:
+               READ_SHADOW_REG(val, group_control);
+               break;
+
+       case debug_bus_control:
+               READ_SHADOW_REG(val, debug_bus_control);
+               break;
+
+       case trace_address:
+               READ_MMIO_UPPER32(val, trace_address);
+               break;
+
+       case ext_tr_timer:
+               READ_SHADOW_REG(val, ext_tr_timer);
+               break;
+
+       case pm_status:
+               READ_MMIO_UPPER32(val, pm_status);
+               break;
+
+       case pm_control:
+               READ_SHADOW_REG(val, pm_control);
+               break;
+
+       case pm_interval:
+               READ_SHADOW_REG(val, pm_interval);
+               break;
+
+       case pm_start_stop:
+               READ_SHADOW_REG(val, pm_start_stop);
+               break;
+       }
+
+       return val;
+}
+
+void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
+{
+       switch (reg) {
+       case group_control:
+               WRITE_WO_MMIO(group_control, val);
+               break;
+
+       case debug_bus_control:
+               WRITE_WO_MMIO(debug_bus_control, val);
+               break;
+
+       case trace_address:
+               WRITE_WO_MMIO(trace_address, val);
+               break;
+
+       case ext_tr_timer:
+               WRITE_WO_MMIO(ext_tr_timer, val);
+               break;
+
+       case pm_status:
+               WRITE_WO_MMIO(pm_status, val);
+               break;
+
+       case pm_control:
+               WRITE_WO_MMIO(pm_control, val);
+               break;
+
+       case pm_interval:
+               WRITE_WO_MMIO(pm_interval, val);
+               break;
+
+       case pm_start_stop:
+               WRITE_WO_MMIO(pm_start_stop, val);
+               break;
+       }
+}
+
+/*
+ * Get/set the size of a physical counter to either 16 or 32 bits.
+ */
+
+u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr)
+{
+       u32 pm_ctrl, size = 0;
+
+       if (phys_ctr < NR_PHYS_CTRS) {
+               pm_ctrl = cbe_read_pm(cpu, pm_control);
+               size = (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
+       }
+
+       return size;
+}
+
+void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
+{
+       u32 pm_ctrl;
+
+       if (phys_ctr < NR_PHYS_CTRS) {
+               pm_ctrl = cbe_read_pm(cpu, pm_control);
+               switch (ctr_size) {
+               case 16:
+                       pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
+                       break;
+
+               case 32:
+                       pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
+                       break;
+               }
+               cbe_write_pm(cpu, pm_control, pm_ctrl);
+       }
+}
+
+/*
+ * Enable/disable the entire performance monitoring unit.
+ * When we enable the PMU, all pending writes to counters get committed.
+ */
+
+void cbe_enable_pm(u32 cpu)
+{
+       struct cbe_pmd_shadow_regs *shadow_regs;
+       u32 pm_ctrl;
+
+       shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
+       shadow_regs->counter_value_in_latch = 0;
+
+       pm_ctrl = cbe_read_pm(cpu, pm_control) | CBE_PM_ENABLE_PERF_MON;
+       cbe_write_pm(cpu, pm_control, pm_ctrl);
+}
+
+void cbe_disable_pm(u32 cpu)
+{
+       u32 pm_ctrl;
+       pm_ctrl = cbe_read_pm(cpu, pm_control) & ~CBE_PM_ENABLE_PERF_MON;
+       cbe_write_pm(cpu, pm_control, pm_ctrl);
+}
+
+/*
+ * Reading from the trace_buffer.
+ * The trace buffer is two 64-bit registers. Reading from
+ * the second half automatically increments the trace_address.
+ */
+
+void cbe_read_trace_buffer(u32 cpu, u64 *buf)
+{
+       struct cbe_pmd_regs __iomem *pmd_regs = cbe_get_cpu_pmd_regs(cpu);
+
+       *buf++ = in_be64(&pmd_regs->trace_buffer_0_63);
+       *buf++ = in_be64(&pmd_regs->trace_buffer_64_127);
+}
+
diff --git a/arch/powerpc/platforms/cell/pmu.h b/arch/powerpc/platforms/cell/pmu.h
new file mode 100644 (file)
index 0000000..eb1e8e0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Cell Broadband Engine Performance Monitor
+ *
+ * (C) Copyright IBM Corporation 2001,2006
+ *
+ * Author:
+ *   David Erb (djerb@us.ibm.com)
+ *   Kevin Corry (kevcorry@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PERFMON_H__
+#define __PERFMON_H__
+
+enum pm_reg_name {
+       group_control,
+       debug_bus_control,
+       trace_address,
+       ext_tr_timer,
+       pm_status,
+       pm_control,
+       pm_interval,
+       pm_start_stop,
+};
+
+extern u32  cbe_read_phys_ctr(u32 cpu, u32 phys_ctr);
+extern void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val);
+extern u32  cbe_read_ctr(u32 cpu, u32 ctr);
+extern void cbe_write_ctr(u32 cpu, u32 ctr, u32 val);
+
+extern u32  cbe_read_pm07_control(u32 cpu, u32 ctr);
+extern void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val);
+extern u32  cbe_read_pm (u32 cpu, enum pm_reg_name reg);
+extern void cbe_write_pm (u32 cpu, enum pm_reg_name reg, u32 val);
+
+extern u32  cbe_get_ctr_size(u32 cpu, u32 phys_ctr);
+extern void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size);
+
+extern void cbe_enable_pm(u32 cpu);
+extern void cbe_disable_pm(u32 cpu);
+
+extern void cbe_read_trace_buffer(u32 cpu, u64 *buf);
+
+#endif
index 7aa809d..d5aeb3c 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
 #include <asm/mmu_context.h>
+#include <asm/xmon.h>
 
 #include "interrupt.h"
 
@@ -89,7 +90,30 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
                printk("%s: invalid access during switch!\n", __func__);
                return 1;
        }
-       if (!mm || (REGION_ID(ea) != USER_REGION_ID)) {
+       esid = (ea & ESID_MASK) | SLB_ESID_V;
+
+       switch(REGION_ID(ea)) {
+       case USER_REGION_ID:
+#ifdef CONFIG_HUGETLB_PAGE
+               if (in_hugepage_area(mm->context, ea))
+                       llp = mmu_psize_defs[mmu_huge_psize].sllp;
+               else
+#endif
+                       llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+               vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
+                               SLB_VSID_USER | llp;
+               break;
+       case VMALLOC_REGION_ID:
+               llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+               vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
+                       SLB_VSID_KERNEL | llp;
+               break;
+       case KERNEL_REGION_ID:
+               llp = mmu_psize_defs[mmu_linear_psize].sllp;
+               vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
+                       SLB_VSID_KERNEL | llp;
+               break;
+       default:
                /* Future: support kernel segments so that drivers
                 * can use SPUs.
                 */
@@ -97,16 +121,6 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
                return 1;
        }
 
-       esid = (ea & ESID_MASK) | SLB_ESID_V;
-#ifdef CONFIG_HUGETLB_PAGE
-       if (in_hugepage_area(mm->context, ea))
-               llp = mmu_psize_defs[mmu_huge_psize].sllp;
-       else
-#endif
-               llp = mmu_psize_defs[mmu_virtual_psize].sllp;
-       vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
-                       SLB_VSID_USER | llp;
-
        out_be64(&priv2->slb_index_W, spu->slb_replace);
        out_be64(&priv2->slb_vsid_RW, vsid);
        out_be64(&priv2->slb_esid_RW, esid);
@@ -320,6 +334,7 @@ static void spu_free_irqs(struct spu *spu)
 }
 
 static struct list_head spu_list[MAX_NUMNODES];
+static LIST_HEAD(spu_full_list);
 static DEFINE_MUTEX(spu_mutex);
 
 static void spu_init_channels(struct spu *spu)
@@ -364,8 +379,7 @@ struct spu *spu_alloc_node(int node)
        if (!list_empty(&spu_list[node])) {
                spu = list_entry(spu_list[node].next, struct spu, list);
                list_del_init(&spu->list);
-               pr_debug("Got SPU %x %d %d\n",
-                        spu->isrc, spu->number, spu->node);
+               pr_debug("Got SPU %d %d\n", spu->number, spu->node);
                spu_init_channels(spu);
        }
        mutex_unlock(&spu_mutex);
@@ -591,7 +605,6 @@ static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np
 
        /* Add the node number */
        isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
-       spu->isrc = isrc;
 
        /* Now map interrupts of all 3 classes */
        spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
@@ -758,15 +771,56 @@ struct sysdev_class spu_sysdev_class = {
        set_kset_name("spu")
 };
 
-static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf)
+int spu_add_sysdev_attr(struct sysdev_attribute *attr)
 {
-       struct spu *spu = container_of(sysdev, struct spu, sysdev);
-       return sprintf(buf, "%d\n", spu->isrc);
+       struct spu *spu;
+       mutex_lock(&spu_mutex);
+
+       list_for_each_entry(spu, &spu_full_list, full_list)
+               sysdev_create_file(&spu->sysdev, attr);
 
+       mutex_unlock(&spu_mutex);
+       return 0;
 }
-static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL);
+EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
+
+int spu_add_sysdev_attr_group(struct attribute_group *attrs)
+{
+       struct spu *spu;
+       mutex_lock(&spu_mutex);
 
-extern int attach_sysdev_to_node(struct sys_device *dev, int nid);
+       list_for_each_entry(spu, &spu_full_list, full_list)
+               sysfs_create_group(&spu->sysdev.kobj, attrs);
+
+       mutex_unlock(&spu_mutex);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
+
+
+void spu_remove_sysdev_attr(struct sysdev_attribute *attr)
+{
+       struct spu *spu;
+       mutex_lock(&spu_mutex);
+
+       list_for_each_entry(spu, &spu_full_list, full_list)
+               sysdev_remove_file(&spu->sysdev, attr);
+
+       mutex_unlock(&spu_mutex);
+}
+EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);
+
+void spu_remove_sysdev_attr_group(struct attribute_group *attrs)
+{
+       struct spu *spu;
+       mutex_lock(&spu_mutex);
+
+       list_for_each_entry(spu, &spu_full_list, full_list)
+               sysfs_remove_group(&spu->sysdev.kobj, attrs);
+
+       mutex_unlock(&spu_mutex);
+}
+EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);
 
 static int spu_create_sysdev(struct spu *spu)
 {
@@ -781,8 +835,6 @@ static int spu_create_sysdev(struct spu *spu)
                return ret;
        }
 
-       if (spu->isrc != 0)
-               sysdev_create_file(&spu->sysdev, &attr_isrc);
        sysfs_add_device_to_node(&spu->sysdev, spu->nid);
 
        return 0;
@@ -790,7 +842,6 @@ static int spu_create_sysdev(struct spu *spu)
 
 static void spu_destroy_sysdev(struct spu *spu)
 {
-       sysdev_remove_file(&spu->sysdev, &attr_isrc);
        sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
        sysdev_unregister(&spu->sysdev);
 }
@@ -830,7 +881,7 @@ static int __init create_spu(struct device_node *spe)
        if (ret)
                goto out_unmap;
        spin_lock_init(&spu->register_lock);
-       spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
+       spu_mfc_sdr_setup(spu);
        spu_mfc_sr1_set(spu, 0x33);
        mutex_lock(&spu_mutex);
 
@@ -844,10 +895,13 @@ static int __init create_spu(struct device_node *spe)
                goto out_free_irqs;
 
        list_add(&spu->list, &spu_list[spu->node]);
+       list_add(&spu->full_list, &spu_full_list);
+       spu->devnode = of_node_get(spe);
+
        mutex_unlock(&spu_mutex);
 
-       pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
-               spu->name, spu->isrc, spu->local_store,
+       pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n",
+               spu->name, spu->local_store,
                spu->problem, spu->priv1, spu->priv2, spu->number);
        goto out;
 
@@ -866,6 +920,9 @@ out:
 static void destroy_spu(struct spu *spu)
 {
        list_del_init(&spu->list);
+       list_del_init(&spu->full_list);
+
+       of_node_put(spu->devnode);
 
        spu_destroy_sysdev(spu);
        spu_free_irqs(spu);
@@ -912,6 +969,9 @@ static int __init init_spu_base(void)
                        break;
                }
        }
+
+       xmon_register_spus(&spu_full_list);
+
        return ret;
 }
 module_init(init_spu_base);
index 71b69f0..90011f9 100644 (file)
@@ -84,9 +84,9 @@ static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
        out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
 }
 
-static void mfc_sdr_set(struct spu *spu, u64 sdr)
+static void mfc_sdr_setup(struct spu *spu)
 {
-       out_be64(&spu->priv1->mfc_sdr_RW, sdr);
+       out_be64(&spu->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1));
 }
 
 static void mfc_sr1_set(struct spu *spu, u64 sr1)
@@ -146,7 +146,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops =
        .mfc_dar_get = mfc_dar_get,
        .mfc_dsisr_get = mfc_dsisr_get,
        .mfc_dsisr_set = mfc_dsisr_set,
-       .mfc_sdr_set = mfc_sdr_set,
+       .mfc_sdr_setup = mfc_sdr_setup,
        .mfc_sr1_set = mfc_sr1_set,
        .mfc_sr1_get = mfc_sr1_get,
        .mfc_tclass_id_set = mfc_tclass_id_set,
index 034cf6a..48eb050 100644 (file)
@@ -120,6 +120,33 @@ void spu_unmap_mappings(struct spu_context *ctx)
                unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
 }
 
+int spu_acquire_exclusive(struct spu_context *ctx)
+{
+       int ret = 0;
+
+       down_write(&ctx->state_sema);
+       /* ctx is about to be freed, can't acquire any more */
+       if (!ctx->owner) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (ctx->state == SPU_STATE_SAVED) {
+               ret = spu_activate(ctx, 0);
+               if (ret)
+                       goto out;
+               ctx->state = SPU_STATE_RUNNABLE;
+       } else {
+               /* We need to exclude userspace access to the context. */
+               spu_unmap_mappings(ctx);
+       }
+
+out:
+       if (ret)
+               up_write(&ctx->state_sema);
+       return ret;
+}
+
 int spu_acquire_runnable(struct spu_context *ctx)
 {
        int ret = 0;
index 533e272..0ea2361 100644 (file)
@@ -1343,6 +1343,37 @@ static struct file_operations spufs_mfc_fops = {
        .mmap    = spufs_mfc_mmap,
 };
 
+
+static int spufs_recycle_open(struct inode *inode, struct file *file)
+{
+       file->private_data = SPUFS_I(inode)->i_ctx;
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t spufs_recycle_write(struct file *file,
+               const char __user *buffer, size_t size, loff_t *pos)
+{
+       struct spu_context *ctx = file->private_data;
+       int ret;
+
+       if (!(ctx->flags & SPU_CREATE_ISOLATE))
+               return -EINVAL;
+
+       if (size < 1)
+               return -EINVAL;
+
+       ret = spu_recycle_isolated(ctx);
+
+       if (ret)
+               return ret;
+       return size;
+}
+
+static struct file_operations spufs_recycle_fops = {
+       .open    = spufs_recycle_open,
+       .write   = spufs_recycle_write,
+};
+
 static void spufs_npc_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
@@ -1531,3 +1562,26 @@ struct tree_descr spufs_dir_contents[] = {
        { "object-id", &spufs_object_id_ops, 0666, },
        {},
 };
+
+struct tree_descr spufs_dir_nosched_contents[] = {
+       { "mem",  &spufs_mem_fops,  0666, },
+       { "mbox", &spufs_mbox_fops, 0444, },
+       { "ibox", &spufs_ibox_fops, 0444, },
+       { "wbox", &spufs_wbox_fops, 0222, },
+       { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
+       { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
+       { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
+       { "signal1", &spufs_signal1_fops, 0666, },
+       { "signal2", &spufs_signal2_fops, 0666, },
+       { "signal1_type", &spufs_signal1_type, 0666, },
+       { "signal2_type", &spufs_signal2_type, 0666, },
+       { "mss", &spufs_mss_fops, 0666, },
+       { "mfc", &spufs_mfc_fops, 0666, },
+       { "cntl", &spufs_cntl_fops,  0666, },
+       { "npc", &spufs_npc_ops, 0666, },
+       { "psmap", &spufs_psmap_fops, 0666, },
+       { "phys-id", &spufs_id_ops, 0666, },
+       { "object-id", &spufs_object_id_ops, 0666, },
+       { "recycle", &spufs_recycle_fops, 0222, },
+       {},
+};
index d805ffe..59c87f1 100644 (file)
@@ -219,8 +219,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx)
 
 static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
 {
-       eieio();
+       spin_lock_irq(&ctx->spu->register_lock);
+       if (val & SPU_RUNCNTL_ISOLATE)
+               out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL);
        out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
+       spin_unlock_irq(&ctx->spu->register_lock);
 }
 
 static void spu_hw_runcntl_stop(struct spu_context *ctx)
index 427d00a..9e457be 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/slab.h>
 #include <linux/parser.h>
 
+#include <asm/prom.h>
+#include <asm/spu_priv1.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/spu.h>
@@ -41,6 +43,7 @@
 #include "spufs.h"
 
 static kmem_cache_t *spufs_inode_cache;
+static char *isolated_loader;
 
 static struct inode *
 spufs_alloc_inode(struct super_block *sb)
@@ -232,6 +235,95 @@ struct file_operations spufs_context_fops = {
        .fsync          = simple_sync_file,
 };
 
+static int spu_setup_isolated(struct spu_context *ctx)
+{
+       int ret;
+       u64 __iomem *mfc_cntl;
+       u64 sr1;
+       u32 status;
+       unsigned long timeout;
+       const u32 status_loading = SPU_STATUS_RUNNING
+               | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
+
+       if (!isolated_loader)
+               return -ENODEV;
+
+       if ((ret = spu_acquire_exclusive(ctx)) != 0)
+               return ret;
+
+       mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
+
+       /* purge the MFC DMA queue to ensure no spurious accesses before we
+        * enter kernel mode */
+       timeout = jiffies + HZ;
+       out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
+       while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
+                       != MFC_CNTL_PURGE_DMA_COMPLETE) {
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
+                                       __FUNCTION__);
+                       ret = -EIO;
+                       goto out_unlock;
+               }
+               cond_resched();
+       }
+
+       /* put the SPE in kernel mode to allow access to the loader */
+       sr1 = spu_mfc_sr1_get(ctx->spu);
+       sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
+       spu_mfc_sr1_set(ctx->spu, sr1);
+
+       /* start the loader */
+       ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
+       ctx->ops->signal2_write(ctx,
+                       (unsigned long)isolated_loader & 0xffffffff);
+
+       ctx->ops->runcntl_write(ctx,
+                       SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
+
+       ret = 0;
+       timeout = jiffies + HZ;
+       while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
+                               status_loading) {
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "%s: timeout waiting for loader\n",
+                                       __FUNCTION__);
+                       ret = -EIO;
+                       goto out_drop_priv;
+               }
+               cond_resched();
+       }
+
+       if (!(status & SPU_STATUS_RUNNING)) {
+               /* If isolated LOAD has failed: run SPU, we will get a stop-and
+                * signal later. */
+               pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
+               ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+               ret = -EACCES;
+
+       } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
+               /* This isn't allowed by the CBEA, but check anyway */
+               pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
+               ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
+               ret = -EINVAL;
+       }
+
+out_drop_priv:
+       /* Finished accessing the loader. Drop kernel mode */
+       sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
+       spu_mfc_sr1_set(ctx->spu, sr1);
+
+out_unlock:
+       spu_release_exclusive(ctx);
+       return ret;
+}
+
+int spu_recycle_isolated(struct spu_context *ctx)
+{
+       ctx->ops->runcntl_stop(ctx);
+       return spu_setup_isolated(ctx);
+}
+
 static int
 spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
                int mode)
@@ -255,10 +347,14 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
                goto out_iput;
 
        ctx->flags = flags;
-
        inode->i_op = &spufs_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
-       ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
+       if (flags & SPU_CREATE_NOSCHED)
+               ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
+                                        mode, ctx);
+       else
+               ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
+
        if (ret)
                goto out_free_ctx;
 
@@ -307,6 +403,16 @@ static int spufs_create_context(struct inode *inode,
 {
        int ret;
 
+       ret = -EPERM;
+       if ((flags & SPU_CREATE_NOSCHED) &&
+           !capable(CAP_SYS_NICE))
+               goto out_unlock;
+
+       ret = -EINVAL;
+       if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
+           == SPU_CREATE_ISOLATE)
+               goto out_unlock;
+
        ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
        if (ret)
                goto out_unlock;
@@ -326,6 +432,13 @@ static int spufs_create_context(struct inode *inode,
 out_unlock:
        mutex_unlock(&inode->i_mutex);
 out:
+       if (ret >= 0 && (flags & SPU_CREATE_ISOLATE)) {
+               int setup_err = spu_setup_isolated(
+                               SPUFS_I(dentry->d_inode)->i_ctx);
+               if (setup_err)
+                       ret = setup_err;
+       }
+
        dput(dentry);
        return ret;
 }
@@ -540,6 +653,30 @@ spufs_parse_options(char *options, struct inode *root)
        return 1;
 }
 
+static void
+spufs_init_isolated_loader(void)
+{
+       struct device_node *dn;
+       const char *loader;
+       int size;
+
+       dn = of_find_node_by_path("/spu-isolation");
+       if (!dn)
+               return;
+
+       loader = get_property(dn, "loader", &size);
+       if (!loader)
+               return;
+
+       /* kmalloc should align on a 16 byte boundary..* */
+       isolated_loader = kmalloc(size, GFP_KERNEL);
+       if (!isolated_loader)
+               return;
+
+       memcpy(isolated_loader, loader, size);
+       printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
+}
+
 static int
 spufs_create_root(struct super_block *sb, void *data)
 {
@@ -625,6 +762,8 @@ static int __init spufs_init(void)
        ret = register_spu_syscalls(&spufs_calls);
        if (ret)
                goto out_fs;
+
+       spufs_init_isolated_loader();
        return 0;
 out_fs:
        unregister_filesystem(&spufs_type);
index 63df8cf..a4a0080 100644 (file)
@@ -1,3 +1,5 @@
+#define DEBUG
+
 #include <linux/wait.h>
 #include <linux/ptrace.h>
 
@@ -51,11 +53,17 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
 static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
 {
        int ret;
+       unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
 
        if ((ret = spu_acquire_runnable(ctx)) != 0)
                return ret;
-       ctx->ops->npc_write(ctx, *npc);
-       ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+
+       /* if we're in isolated mode, we would have started the SPU
+        * earlier, so don't do it again now. */
+       if (!(ctx->flags & SPU_CREATE_ISOLATE)) {
+               ctx->ops->npc_write(ctx, *npc);
+               ctx->ops->runcntl_write(ctx, runcntl);
+       }
        return 0;
 }
 
index a0f55ca..f438f0b 100644 (file)
@@ -135,6 +135,7 @@ struct spufs_inode_info {
        container_of(inode, struct spufs_inode_info, vfs_inode)
 
 extern struct tree_descr spufs_dir_contents[];
+extern struct tree_descr spufs_dir_nosched_contents[];
 
 /* system call implementation */
 long spufs_run_spu(struct file *file,
@@ -162,6 +163,12 @@ void spu_acquire(struct spu_context *ctx);
 void spu_release(struct spu_context *ctx);
 int spu_acquire_runnable(struct spu_context *ctx);
 void spu_acquire_saved(struct spu_context *ctx);
+int spu_acquire_exclusive(struct spu_context *ctx);
+
+static inline void spu_release_exclusive(struct spu_context *ctx)
+{
+       up_write(&ctx->state_sema);
+}
 
 int spu_activate(struct spu_context *ctx, u64 flags);
 void spu_deactivate(struct spu_context *ctx);
@@ -169,6 +176,7 @@ void spu_yield(struct spu_context *ctx);
 int __init spu_sched_init(void);
 void __exit spu_sched_exit(void);
 
+int spu_recycle_isolated(struct spu_context *ctx);
 /*
  * spufs_wait
  *     Same as wait_event_interruptible(), except that here
index 0f782ca..c08981f 100644 (file)
@@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu)
         *     saved at this time.
         */
        isolate_state = SPU_STATUS_ISOLATED_STATE |
-           SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS;
+           SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS;
        return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0;
 }
 
@@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu)
         */
        if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) {
                if (in_be32(&prob->spu_status_R) &
-                   SPU_STATUS_ISOLATED_EXIT_STAUTUS) {
+                   SPU_STATUS_ISOLATED_EXIT_STATUS) {
                        POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
                                        SPU_STATUS_RUNNING);
                }
                if ((in_be32(&prob->spu_status_R) &
-                    SPU_STATUS_ISOLATED_LOAD_STAUTUS)
+                    SPU_STATUS_ISOLATED_LOAD_STATUS)
                    || (in_be32(&prob->spu_status_R) &
                        SPU_STATUS_ISOLATED_STATE)) {
                        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)
         */
        if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) {
                if (in_be32(&prob->spu_status_R) &
-                   SPU_STATUS_ISOLATED_EXIT_STAUTUS) {
+                   SPU_STATUS_ISOLATED_EXIT_STATUS) {
                        spu_mfc_sr1_set(spu,
                                        MFC_STATE1_MASTER_RUN_CONTROL_MASK);
                        eieio();
@@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
                                        SPU_STATUS_RUNNING);
                }
                if ((in_be32(&prob->spu_status_R) &
-                    SPU_STATUS_ISOLATED_LOAD_STAUTUS)
+                    SPU_STATUS_ISOLATED_LOAD_STATUS)
                    || (in_be32(&prob->spu_status_R) &
                        SPU_STATUS_ISOLATED_STATE)) {
                        spu_mfc_sr1_set(spu,
@@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu)
        wait_spu_stopped(prev, spu);    /* Step 57. */
 }
 
+static void force_spu_isolate_exit(struct spu *spu)
+{
+       struct spu_problem __iomem *prob = spu->problem;
+       struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+       /* Stop SPE execution and wait for completion. */
+       out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+       iobarrier_rw();
+       POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
+
+       /* Restart SPE master runcntl. */
+       spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK);
+       iobarrier_w();
+
+       /* Initiate isolate exit request and wait for completion. */
+       out_be64(&priv2->spu_privcntl_RW, 4LL);
+       iobarrier_w();
+       out_be32(&prob->spu_runcntl_RW, 2);
+       iobarrier_rw();
+       POLL_WHILE_FALSE((in_be32(&prob->spu_status_R)
+                               & SPU_STATUS_STOPPED_BY_STOP));
+
+       /* Reset load request to normal. */
+       out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL);
+       iobarrier_w();
+}
+
+/**
+ * stop_spu_isolate
+ *     Check SPU run-control state and force isolated
+ *     exit function as necessary.
+ */
+static void stop_spu_isolate(struct spu *spu)
+{
+       struct spu_problem __iomem *prob = spu->problem;
+
+       if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) {
+               /* The SPU is in isolated state; the only way
+                * to get it out is to perform an isolated
+                * exit (clean) operation.
+                */
+               force_spu_isolate_exit(spu);
+       }
+}
+
 static void harvest(struct spu_state *prev, struct spu *spu)
 {
        /*
@@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu)
        inhibit_user_access(prev, spu);         /* Step 3.  */
        terminate_spu_app(prev, spu);           /* Step 4.  */
        set_switch_pending(prev, spu);          /* Step 5.  */
+       stop_spu_isolate(spu);                  /* NEW.     */
        remove_other_spu_access(prev, spu);     /* Step 6.  */
        suspend_mfc(prev, spu);                 /* Step 7.  */
        wait_suspend_mfc_complete(prev, spu);   /* Step 8.  */
@@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu)
        acquire_spu_lock(spu);          /* Step 1.     */
        rc = __do_spu_save(prev, spu);  /* Steps 2-53. */
        release_spu_lock(spu);
-       if (rc) {
+       if (rc != 0 && rc != 2 && rc != 6) {
                panic("%s failed on SPU[%d], rc=%d.\n",
                      __func__, spu->number, rc);
        }
-       return rc;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(spu_save);
 
@@ -2165,9 +2211,6 @@ static void init_priv1(struct spu_state *csa)
            MFC_STATE1_PROBLEM_STATE_MASK |
            MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK;
 
-       /* Set storage description.  */
-       csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1);
-
        /* Enable OS-specific set of interrupts. */
        csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR |
            CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR |
diff --git a/arch/powerpc/platforms/efika/Makefile b/arch/powerpc/platforms/efika/Makefile
new file mode 100644 (file)
index 0000000..17b2a78
--- /dev/null
@@ -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 (file)
index 0000000..2f060fd
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Efika 5K2 platform setup - Header file
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef __ARCH_POWERPC_EFIKA__
+#define __ARCH_POWERPC_EFIKA__
+
+#define EFIKA_PLATFORM_NAME "Efika"
+
+extern void __init efika_pcisetup(void);
+
+#endif
diff --git a/arch/powerpc/platforms/efika/pci.c b/arch/powerpc/platforms/efika/pci.c
new file mode 100644 (file)
index 0000000..62e05b2
--- /dev/null
@@ -0,0 +1,119 @@
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/rtas.h>
+
+#include "efika.h"
+
+#ifdef CONFIG_PCI
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+                           int len, u32 * val)
+{
+       struct pci_controller *hose = bus->sysdata;
+       unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+           | (((bus->number - hose->first_busno) & 0xff) << 16)
+           | (hose->index << 24);
+       int ret = -1;
+       int rval;
+
+       rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
+       *val = ret;
+       return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
+                            int offset, int len, u32 val)
+{
+       struct pci_controller *hose = bus->sysdata;
+       unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+           | (((bus->number - hose->first_busno) & 0xff) << 16)
+           | (hose->index << 24);
+       int rval;
+
+       rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
+                        addr, len, val);
+       return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops rtas_pci_ops = {
+       rtas_read_config,
+       rtas_write_config
+};
+
+void __init efika_pcisetup(void)
+{
+       const int *bus_range;
+       int len;
+       struct pci_controller *hose;
+       struct device_node *root;
+       struct device_node *pcictrl;
+
+       root = of_find_node_by_path("/");
+       if (root == NULL) {
+               printk(KERN_WARNING EFIKA_PLATFORM_NAME
+                      ": Unable to find the root node\n");
+               return;
+       }
+
+       for (pcictrl = NULL;;) {
+               pcictrl = of_get_next_child(root, pcictrl);
+               if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
+                       break;
+       }
+
+       of_node_put(root);
+
+       if (pcictrl == NULL) {
+               printk(KERN_WARNING EFIKA_PLATFORM_NAME
+                      ": Unable to find the PCI bridge node\n");
+               return;
+       }
+
+       bus_range = get_property(pcictrl, "bus-range", &len);
+       if (bus_range == NULL || len < 2 * sizeof(int)) {
+               printk(KERN_WARNING EFIKA_PLATFORM_NAME
+                      ": Can't get bus-range for %s\n", pcictrl->full_name);
+               return;
+       }
+
+       if (bus_range[1] == bus_range[0])
+               printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
+                      bus_range[0]);
+       else
+               printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
+                      bus_range[0], bus_range[1]);
+       printk(" controlled by %s\n", pcictrl->full_name);
+       printk("\n");
+
+       hose = pcibios_alloc_controller();
+       if (!hose) {
+               printk(KERN_WARNING EFIKA_PLATFORM_NAME
+                      ": Can't allocate PCI controller structure for %s\n",
+                      pcictrl->full_name);
+               return;
+       }
+
+       hose->arch_data = of_node_get(pcictrl);
+       hose->first_busno = bus_range[0];
+       hose->last_busno = bus_range[1];
+       hose->ops = &rtas_pci_ops;
+
+       pci_process_bridge_OF_ranges(hose, pcictrl, 0);
+}
+
+#else
+void __init efika_pcisetup(void)
+{}
+#endif
diff --git a/arch/powerpc/platforms/efika/setup.c b/arch/powerpc/platforms/efika/setup.c
new file mode 100644 (file)
index 0000000..3bc1b5f
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *
+ * Efika 5K2 platform setup
+ * Some code really inspired from the lite5200b platform.
+ * 
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/utsrelease.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/rtas.h>
+#include <asm/of_device.h>
+#include <asm/mpc52xx.h>
+
+#include "efika.h"
+
+static void efika_show_cpuinfo(struct seq_file *m)
+{
+       struct device_node *root;
+       const char *revision = NULL;
+       const char *codegendescription = NULL;
+       const char *codegenvendor = NULL;
+
+       root = of_find_node_by_path("/");
+       if (root) {
+               revision = get_property(root, "revision", NULL);
+               codegendescription =
+                   get_property(root, "CODEGEN,description", NULL);
+               codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
+
+               of_node_put(root);
+       }
+
+       if (codegendescription)
+               seq_printf(m, "machine\t\t: %s\n", codegendescription);
+       else
+               seq_printf(m, "machine\t\t: Efika\n");
+
+       if (revision)
+               seq_printf(m, "revision\t: %s\n", revision);
+
+       if (codegenvendor)
+               seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
+
+       of_node_put(root);
+}
+
+static void __init efika_setup_arch(void)
+{
+       rtas_initialize();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       initrd_below_start_ok = 1;
+
+       if (initrd_start)
+               ROOT_DEV = Root_RAM0;
+       else
+#endif
+               ROOT_DEV = Root_SDA2;   /* sda2 (sda1 is for the kernel) */
+
+       efika_pcisetup();
+
+       if (ppc_md.progress)
+               ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
+}
+
+static void __init efika_init(void)
+{
+       struct device_node *np;
+       struct device_node *cnp = NULL;
+       const u32 *base;
+
+       /* Find every child of the SOC node and add it to of_platform */
+       np = of_find_node_by_name(NULL, "builtin");
+       if (np) {
+               char name[BUS_ID_SIZE];
+               while ((cnp = of_get_next_child(np, cnp))) {
+                       strcpy(name, cnp->name);
+
+                       base = get_property(cnp, "reg", NULL);
+                       if (base == NULL)
+                               continue;
+
+                       snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
+                       of_platform_device_create(cnp, name, NULL);
+
+                       printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
+               }
+       }
+
+       if (ppc_md.progress)
+               ppc_md.progress("  Have fun with your Efika!    ", 0x7777);
+}
+
+static int __init efika_probe(void)
+{
+       char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+                                         "model", NULL);
+
+       if (model == NULL)
+               return 0;
+       if (strcmp(model, "EFIKA5K2"))
+               return 0;
+
+       ISA_DMA_THRESHOLD = ~0L;
+       DMA_MODE_READ = 0x44;
+       DMA_MODE_WRITE = 0x48;
+
+       return 1;
+}
+
+define_machine(efika)
+{
+       .name = EFIKA_PLATFORM_NAME,
+       .probe = efika_probe,
+       .setup_arch = efika_setup_arch,
+       .init = efika_init,
+       .show_cpuinfo = efika_show_cpuinfo,
+       .init_IRQ = mpc52xx_init_irq,
+       .get_irq = mpc52xx_get_irq,
+       .restart = rtas_restart,
+       .power_off = rtas_power_off,
+       .halt = rtas_halt,
+       .set_rtc_time = rtas_set_rtc_time,
+       .get_rtc_time = rtas_get_rtc_time,
+       .progress = rtas_progress,
+       .get_boot_time = rtas_get_boot_time,
+       .calibrate_decr = generic_calibrate_decr,
+       .phys_mem_access_prot = pci_phys_mem_access_prot,
+};
index e305dee..9e8a334 100644 (file)
@@ -41,6 +41,7 @@
 #include "call_pci.h"
 #include "pci.h"
 #include "it_exp_vpd_panel.h"
+#include "naca.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -205,13 +206,11 @@ static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
        dt_prop(dt, name, &data, sizeof(u32));
 }
 
-#ifdef notyet
 static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
                u64 data)
 {
        dt_prop(dt, name, &data, sizeof(u64));
 }
-#endif
 
 static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
                const char *name, u64 *data, int n)
@@ -306,6 +305,17 @@ static void __init dt_model(struct iseries_flat_dt *dt)
        dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
 }
 
+static void __init dt_initrd(struct iseries_flat_dt *dt)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (naca.xRamDisk) {
+               dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk);
+               dt_prop_u64(dt, "linux,initrd-end",
+                       (u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE);
+       }
+#endif
+}
+
 static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
                const char *name, u32 reg, int unit,
                const char *type, const char *compat, int end)
@@ -641,6 +651,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size)
        /* /chosen */
        dt_start_node(iseries_dt, "chosen");
        dt_prop_str(iseries_dt, "bootargs", cmd_line);
+       dt_initrd(iseries_dt);
        dt_end_node(iseries_dt);
 
        dt_cpus(iseries_dt);
index a220084..2430848 100644 (file)
@@ -19,9 +19,3 @@ EXPORT_SYMBOL(HvCall4);
 EXPORT_SYMBOL(HvCall5);
 EXPORT_SYMBOL(HvCall6);
 EXPORT_SYMBOL(HvCall7);
-
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(local_get_flags);
-EXPORT_SYMBOL(local_irq_disable);
-EXPORT_SYMBOL(local_irq_restore);
-#endif
index 7641fc7..2c6ff0f 100644 (file)
 
        .text
 
-/* unsigned long local_save_flags(void) */
-_GLOBAL(local_get_flags)
-       lbz     r3,PACAPROCENABLED(r13)
-       blr
-
-/* unsigned long local_irq_disable(void) */
-_GLOBAL(local_irq_disable)
-       lbz     r3,PACAPROCENABLED(r13)
-       li      r4,0
-       stb     r4,PACAPROCENABLED(r13)
-       blr                     /* Done */
-
-/* void local_irq_restore(unsigned long flags) */
-_GLOBAL(local_irq_restore)
-       lbz     r5,PACAPROCENABLED(r13)
-        /* Check if things are setup the way we want _already_. */
-       cmpw    0,r3,r5
-       beqlr
-       /* are we enabling interrupts? */
-       cmpdi   0,r3,0
-       stb     r3,PACAPROCENABLED(r13)
-       beqlr
-       /* Check pending interrupts */
-       /*   A decrementer, IPI or PMC interrupt may have occurred
-        *   while we were in the hypervisor (which enables) */
-       ld      r4,PACALPPACAPTR(r13)
-       ld      r4,LPPACAANYINT(r4)
-       cmpdi   r4,0
-       beqlr
-
-       /*
-        * Handle pending interrupts in interrupt context
-        */
+/* Handle pending interrupts in interrupt context */
+_GLOBAL(iseries_handle_interrupts)
        li      r0,0x5555
        sc
        blr
index 6f73469..cd8965e 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/smp.h>
 #include <linux/param.h>
 #include <linux/string.h>
-#include <linux/initrd.h>
 #include <linux/seq_file.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
@@ -80,8 +79,6 @@ extern void iSeries_pci_final_fixup(void);
 static void iSeries_pci_final_fixup(void) { }
 #endif
 
-extern int rd_size;            /* Defined in drivers/block/rd.c */
-
 extern unsigned long iSeries_recal_tb;
 extern unsigned long iSeries_recal_titan;
 
@@ -295,24 +292,6 @@ static void __init iSeries_init_early(void)
 {
        DBG(" -> iSeries_init_early()\n");
 
-#if defined(CONFIG_BLK_DEV_INITRD)
-       /*
-        * If the init RAM disk has been configured and there is
-        * a non-zero starting address for it, set it up
-        */
-       if (naca.xRamDisk) {
-               initrd_start = (unsigned long)__va(naca.xRamDisk);
-               initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE;
-               initrd_below_start_ok = 1;      // ramdisk in kernel space
-               ROOT_DEV = Root_RAM0;
-               if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize)
-                       rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024;
-       } else
-#endif /* CONFIG_BLK_DEV_INITRD */
-       {
-           /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
-       }
-
        iSeries_recal_tb = get_tb();
        iSeries_recal_titan = HvCallXm_loadTod();
 
@@ -331,17 +310,6 @@ static void __init iSeries_init_early(void)
 
        mf_init();
 
-       /* If we were passed an initrd, set the ROOT_DEV properly if the values
-        * look sensible. If not, clear initrd reference.
-        */
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
-           initrd_end > initrd_start)
-               ROOT_DEV = Root_RAM0;
-       else
-               initrd_start = initrd_end = 0;
-#endif /* CONFIG_BLK_DEV_INITRD */
-
        DBG(" <- iSeries_init_early()\n");
 }
 
index e49621b..c29a6a0 100644 (file)
@@ -486,10 +486,6 @@ static long heathrow_sound_enable(struct device_node *node, long param,
 
 static u32 save_fcr[6];
 static u32 save_mbcr;
-static u32 save_gpio_levels[2];
-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
-static u32 save_unin_clock_ctl;
 static struct dbdma_regs save_dbdma[13];
 static struct dbdma_regs save_alt_dbdma[13];
 
@@ -1548,6 +1544,10 @@ void g5_phy_disable_cpu1(void)
 
 
 #ifdef CONFIG_PM
+static u32 save_gpio_levels[2];
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
+static u32 save_unin_clock_ctl;
 
 static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
 {
index 824a618..cb1c342 100644 (file)
@@ -361,7 +361,7 @@ char *bootdevice;
 void *boot_host;
 int boot_target;
 int boot_part;
-extern dev_t boot_dev;
+static dev_t boot_dev;
 
 #ifdef CONFIG_SCSI
 void __init note_scsi_host(struct device_node *node, void *host)
index 1820a0b..721436d 100644 (file)
@@ -282,7 +282,7 @@ void vpa_init(int cpu)
        }
 }
 
-long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
                              unsigned long va, unsigned long pa,
                              unsigned long rflags, unsigned long vflags,
                              int psize)
@@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
  * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
  * lock.
  */
-void pSeries_lpar_flush_hash_range(unsigned long number, int local)
+static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 {
        int i;
        unsigned long flags = 0;
index 91f052d..5b87f7b 100644 (file)
@@ -10,9 +10,9 @@ obj-$(CONFIG_40x)             += dcr.o
 obj-$(CONFIG_U3_DART)          += dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)       += mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)          += fsl_soc.o
-obj-$(CONFIG_PPC_TODC)         += todc.o
 obj-$(CONFIG_TSI108_BRIDGE)    += tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)     += qe_lib/
+obj-$(CONFIG_PPC_MPC52xx)      += mpc52xx_pic.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)                += i8259.o
index dbe92ae..ad31e56 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 #include <linux/fsl_devices.h>
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
@@ -146,7 +147,7 @@ static int __init gfar_mdio_of_init(void)
                }
 
                for (k = 0; k < 32; k++)
-                       mdio_data.irq[k] = -1;
+                       mdio_data.irq[k] = PHY_POLL;
 
                while ((child = of_get_next_child(np, child)) != NULL) {
                        int irq = irq_of_parse_and_map(child, 0);
@@ -177,6 +178,7 @@ static const char *gfar_tx_intr = "tx";
 static const char *gfar_rx_intr = "rx";
 static const char *gfar_err_intr = "error";
 
+
 static int __init gfar_of_init(void)
 {
        struct device_node *np;
@@ -204,8 +206,7 @@ static int __init gfar_of_init(void)
                if (ret)
                        goto err;
 
-               r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
-               r[1].flags = IORESOURCE_IRQ;
+               of_irq_to_resource(np, 0, &r[1]);
 
                model = get_property(np, "model", NULL);
 
@@ -214,12 +215,10 @@ static int __init gfar_of_init(void)
                        r[1].name = gfar_tx_intr;
 
                        r[2].name = gfar_rx_intr;
-                       r[2].start = r[2].end = irq_of_parse_and_map(np, 1);
-                       r[2].flags = IORESOURCE_IRQ;
+                       of_irq_to_resource(np, 1, &r[2]);
 
                        r[3].name = gfar_err_intr;
-                       r[3].start = r[3].end = irq_of_parse_and_map(np, 2);
-                       r[3].flags = IORESOURCE_IRQ;
+                       of_irq_to_resource(np, 2, &r[3]);
 
                        n_res += 2;
                }
@@ -323,8 +322,7 @@ static int __init fsl_i2c_of_init(void)
                if (ret)
                        goto err;
 
-               r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
-               r[1].flags = IORESOURCE_IRQ;
+               of_irq_to_resource(np, 0, &r[1]);
 
                i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
                if (IS_ERR(i2c_dev)) {
@@ -459,8 +457,7 @@ static int __init fsl_usb_of_init(void)
                if (ret)
                        goto err;
 
-               r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
-               r[1].flags = IORESOURCE_IRQ;
+               of_irq_to_resource(np, 0, &r[1]);
 
                usb_dev_mph =
                    platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -507,8 +504,7 @@ static int __init fsl_usb_of_init(void)
                if (ret)
                        goto unreg_mph;
 
-               r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
-               r[1].flags = IORESOURCE_IRQ;
+               of_irq_to_resource(np, 0, &r[1]);
 
                usb_dev_dr =
                    platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -591,8 +587,7 @@ static int __init fs_enet_of_init(void)
                r[2].name = fcc_regs_c;
                fs_enet_data.fcc_regs_c = r[2].start;
 
-               r[3].start = r[3].end = irq_of_parse_and_map(np, 0);
-               r[3].flags = IORESOURCE_IRQ;
+               of_irq_to_resource(np, 0, &r[3]);
 
                fs_enet_dev =
                    platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
@@ -754,8 +749,7 @@ static int __init cpm_uart_of_init(void)
                        goto err;
                r[1].name = scc_pram;
 
-               r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
-               r[2].flags = IORESOURCE_IRQ;
+               of_irq_to_resource(np, 0, &r[2]);
 
                cpm_uart_dev =
                    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 (file)
index 0000000..6df51f0
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * Based on the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost = NULL;
+
+static unsigned char mpc52xx_map_senses[4] = {
+       IRQ_TYPE_LEVEL_HIGH,
+       IRQ_TYPE_EDGE_RISING,
+       IRQ_TYPE_EDGE_FALLING,
+       IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem * addr, int bitno)
+{
+       out_be32(addr, in_be32(addr) | (1 << bitno));
+}
+
+static inline void io_be_clrbit(u32 __iomem * addr, int bitno)
+{
+       out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+/*
+ * IRQ[0-3] interrupt irq_chip
+*/
+
+static void mpc52xx_extirq_mask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_unmask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_ack(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_setbit(&intr->ctrl, 27 - l2irq);
+}
+
+static struct irq_chip mpc52xx_extirq_irqchip = {
+       .typename = " MPC52xx IRQ[0-3] ",
+       .mask = mpc52xx_extirq_mask,
+       .unmask = mpc52xx_extirq_unmask,
+       .ack = mpc52xx_extirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip = {
+       .typename = "MPC52xx Main",
+       .mask = mpc52xx_main_mask,
+       .mask_ack = mpc52xx_main_mask,
+       .unmask = mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip = {
+       .typename = "MPC52xx Peripherals",
+       .mask = mpc52xx_periph_mask,
+       .mask_ack = mpc52xx_periph_mask,
+       .unmask = mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+       int irq;
+       int l2irq;
+
+       irq = irq_map[virq].hwirq;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+       out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip = {
+       .typename = "MPC52xx SDMA",
+       .mask = mpc52xx_sdma_mask,
+       .unmask = mpc52xx_sdma_unmask,
+       .ack = mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+       pr_debug("%s: node=%p\n", __func__, node);
+       return mpc52xx_irqhost->host_data == node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
+                                u32 * intspec, unsigned int intsize,
+                                irq_hw_number_t * out_hwirq,
+                                unsigned int *out_flags)
+{
+       int intrvect_l1;
+       int intrvect_l2;
+       int intrvect_type;
+       int intrvect_linux;
+
+       if (intsize != 3)
+               return -1;
+
+       intrvect_l1 = (int)intspec[0];
+       intrvect_l2 = (int)intspec[1];
+       intrvect_type = (int)intspec[2];
+
+       intrvect_linux =
+           (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+       intrvect_linux |=
+           (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+       pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
+                intrvect_l2);
+
+       *out_hwirq = intrvect_linux;
+       *out_flags = mpc52xx_map_senses[intrvect_type];
+
+       return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+       int type;
+       u32 ctrl_reg;
+
+       ctrl_reg = in_be32(&intr->ctrl);
+       type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+       return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+                              irq_hw_number_t irq)
+{
+       int l1irq;
+       int l2irq;
+       struct irq_chip *good_irqchip;
+       void *good_handle;
+       int type;
+
+       l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+       /*
+        * Most of ours IRQs will be level low
+        * Only external IRQs on some platform may be others
+        */
+       type = IRQ_TYPE_LEVEL_LOW;
+
+       switch (l1irq) {
+       case MPC52xx_IRQ_L1_CRIT:
+               pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
+
+               BUG_ON(l2irq != 0);
+
+               type = mpc52xx_irqx_gettype(l2irq);
+               good_irqchip = &mpc52xx_extirq_irqchip;
+               break;
+
+       case MPC52xx_IRQ_L1_MAIN:
+               pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
+
+               if ((l2irq >= 1) && (l2irq <= 3)) {
+                       type = mpc52xx_irqx_gettype(l2irq);
+                       good_irqchip = &mpc52xx_extirq_irqchip;
+               } else {
+                       good_irqchip = &mpc52xx_main_irqchip;
+               }
+               break;
+
+       case MPC52xx_IRQ_L1_PERP:
+               pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
+               good_irqchip = &mpc52xx_periph_irqchip;
+               break;
+
+       case MPC52xx_IRQ_L1_SDMA:
+               pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
+               good_irqchip = &mpc52xx_sdma_irqchip;
+               break;
+
+       default:
+               pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
+               printk(KERN_ERR "Unknow IRQ!\n");
+               return -EINVAL;
+       }
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_EDGE_RISING:
+               good_handle = handle_edge_irq;
+               break;
+       default:
+               good_handle = handle_level_irq;
+       }
+
+       set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+       pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
+                (int)irq, type);
+
+       return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+       .match = mpc52xx_irqhost_match,
+       .xlate = mpc52xx_irqhost_xlate,
+       .map = mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+       struct device_node *picnode = NULL;
+       int picnode_regsize;
+       u32 picnode_regoffset;
+
+       struct device_node *sdmanode = NULL;
+       int sdmanode_regsize;
+       u32 sdmanode_regoffset;
+
+       u64 size64;
+       int flags;
+
+       u32 intr_ctrl;
+
+       picnode = of_find_compatible_node(NULL, "interrupt-controller",
+                                               "mpc5200-pic");
+       if (picnode == NULL) {
+               printk(KERN_ERR "MPC52xx PIC: "
+                       "Unable to find the interrupt controller "
+                       "in the OpenFirmware device tree\n");
+               goto end;
+       }
+
+       sdmanode = of_find_compatible_node(NULL, "dma-controller",
+                                                "mpc5200-bestcomm");
+       if (sdmanode == NULL) {
+               printk(KERN_ERR "MPC52xx PIC"
+                       "Unable to find the Bestcomm DMA controller device "
+                       "in the OpenFirmware device tree\n");
+               goto end;
+       }
+
+       /* Retrieve PIC ressources */
+       picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
+       if (picnode_regoffset == 0) {
+               printk(KERN_ERR "MPC52xx PIC"
+                       "Unable to get the interrupt controller address\n");
+               goto end;
+       }
+
+       picnode_regoffset =
+               of_translate_address(picnode, (u32 *) picnode_regoffset);
+       picnode_regsize = (int)size64;
+
+       /* Retrieve SDMA ressources */
+       sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
+       if (sdmanode_regoffset == 0) {
+               printk(KERN_ERR "MPC52xx PIC: "
+                       "Unable to get the Bestcomm DMA controller address\n");
+               goto end;
+       }
+
+       sdmanode_regoffset =
+           of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
+       sdmanode_regsize = (int)size64;
+
+       /* Remap the necessary zones */
+       intr = ioremap(picnode_regoffset, picnode_regsize);
+       if (intr == NULL) {
+               printk(KERN_ERR "MPC52xx PIC: "
+                       "Unable to ioremap interrupt controller registers!\n");
+               goto end;
+       }
+
+       sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
+       if (sdma == NULL) {
+               iounmap(intr);
+               printk(KERN_ERR "MPC52xx PIC: "
+                       "Unable to ioremap Bestcomm DMA registers!\n");
+               goto end;
+       }
+
+       printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n",
+               picnode_regoffset);
+       printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n",
+               sdmanode_regoffset);
+
+       /* Disable all interrupt sources. */
+       out_be32(&sdma->IntPend, 0xffffffff);   /* 1 means clear pending */
+       out_be32(&sdma->IntMask, 0xffffffff);   /* 1 means disabled */
+       out_be32(&intr->per_mask, 0x7ffffc00);  /* 1 means disabled */
+       out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
+       intr_ctrl = in_be32(&intr->ctrl);
+       intr_ctrl &= 0x00ff0000;        /* Keeps IRQ[0-3] config */
+       intr_ctrl |=    0x0f000000 |    /* clear IRQ 0-3 */
+                       0x00001000 |    /* MEE master external enable */
+                       0x00000000 |    /* 0 means disable IRQ 0-3 */
+                       0x00000001;     /* CEb route critical normally */
+       out_be32(&intr->ctrl, intr_ctrl);
+
+       /* Zero a bunch of the priority settings. */
+       out_be32(&intr->per_pri1, 0);
+       out_be32(&intr->per_pri2, 0);
+       out_be32(&intr->per_pri3, 0);
+       out_be32(&intr->main_pri1, 0);
+       out_be32(&intr->main_pri2, 0);
+
+       /*
+        * As last step, add an irq host to translate the real
+        * hw irq information provided by the ofw to linux virq
+        */
+
+       mpc52xx_irqhost =
+           irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ,
+                          &mpc52xx_irqhost_ops, -1);
+
+       if (mpc52xx_irqhost) {
+               mpc52xx_irqhost->host_data = picnode;
+               printk(KERN_INFO "MPC52xx PIC is up and running!\n");
+       } else {
+               printk(KERN_ERR
+                       "MPC52xx PIC: Unable to allocate the IRQ host\n");
+       }
+
+end:
+       of_node_put(picnode);
+       of_node_put(sdmanode);
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+       u32 status;
+       int irq = NO_IRQ_IGNORE;
+
+       status = in_be32(&intr->enc_status);
+       if (status & 0x00000400) {      /* critical */
+               irq = (status >> 8) & 0x3;
+               if (irq == 2)   /* high priority peripheral */
+                       goto peripheral;
+               irq |=  (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+                       MPC52xx_IRQ_L1_MASK;
+       } else if (status & 0x00200000) {       /* main */
+               irq = (status >> 16) & 0x1f;
+               if (irq == 4)   /* low priority peripheral */
+                       goto peripheral;
+               irq |=  (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+                       MPC52xx_IRQ_L1_MASK;
+       } else if (status & 0x20000000) {       /* peripheral */
+             peripheral:
+               irq = (status >> 24) & 0x1f;
+               if (irq == 0) { /* bestcomm */
+                       status = in_be32(&sdma->IntPend);
+                       irq = ffs(status) - 1;
+                       irq |=  (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+                               MPC52xx_IRQ_L1_MASK;
+               } else
+                       irq |=  (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+                               MPC52xx_IRQ_L1_MASK;
+       }
+
+       pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
+                irq_linear_revmap(mpc52xx_irqhost, irq));
+
+       return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
+
index e422322..e3d71e0 100644 (file)
@@ -174,8 +174,7 @@ void qe_setbrg(u32 brg, u32 rate)
        u32 divisor, tempval;
        int div16 = 0;
 
-       bp = &qe_immr->brg.brgc1;
-       bp += brg;
+       bp = &qe_immr->brg.brgc[brg];
 
        divisor = (get_brg_clk() / rate);
        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 (file)
index 0a65980..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
- * Real Time Clocks/Timekeepers.
- *
- * Author: Mark A. Greer <mgreer@mvista.com>
- *
- * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/bcd.h>
-#include <linux/mc146818rtc.h>
-
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/todc.h>
-
-/*
- * Depending on the hardware on your board and your board design, the
- * RTC/NVRAM may be accessed either directly (like normal memory) or via
- * address/data registers.  If your board uses the direct method, set
- * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
- * 'nvram_as1' NULL.  If your board uses address/data regs to access nvram,
- * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
- * address of the upper byte (leave NULL if using mc146818), and set
- * 'nvram_data' to the address of the 8-bit data register.
- *
- * Note: Even though the documentation for the various RTC chips say that it
- *      take up to a second before it starts updating once the 'R' bit is
- *      cleared, they always seem to update even though we bang on it many
- *      times a second.  This is true, except for the Dallas Semi 1746/1747
- *      (possibly others).  Those chips seem to have a real problem whenever
- *      we set the 'R' bit before reading them, they basically stop counting.
- *                                             --MAG
- */
-
-/*
- * 'todc_info' should be initialized in your *_setup.c file to
- * point to a fully initialized 'todc_info_t' structure.
- * This structure holds all the register offsets for your particular
- * TODC/RTC chip.
- * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you.
- */
-
-#ifdef RTC_FREQ_SELECT
-#undef RTC_FREQ_SELECT
-#define        RTC_FREQ_SELECT         control_b       /* Register A */
-#endif
-
-#ifdef RTC_CONTROL
-#undef RTC_CONTROL
-#define        RTC_CONTROL             control_a       /* Register B */
-#endif
-
-#ifdef RTC_INTR_FLAGS
-#undef RTC_INTR_FLAGS
-#define        RTC_INTR_FLAGS          watchdog        /* Register C */
-#endif
-
-#ifdef RTC_VALID
-#undef RTC_VALID
-#define        RTC_VALID               interrupts      /* Register D */
-#endif
-
-/* Access routines when RTC accessed directly (like normal memory) */
-u_char
-todc_direct_read_val(int addr)
-{
-       return readb((void __iomem *)(todc_info->nvram_data + addr));
-}
-
-void
-todc_direct_write_val(int addr, unsigned char val)
-{
-       writeb(val, (void __iomem *)(todc_info->nvram_data + addr));
-       return;
-}
-
-/* Access routines for accessing m48txx type chips via addr/data regs */
-u_char
-todc_m48txx_read_val(int addr)
-{
-       outb(addr, todc_info->nvram_as0);
-       outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
-       return inb(todc_info->nvram_data);
-}
-
-void
-todc_m48txx_write_val(int addr, unsigned char val)
-{
-       outb(addr, todc_info->nvram_as0);
-       outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
-       outb(val, todc_info->nvram_data);
-       return;
-}
-
-/* Access routines for accessing mc146818 type chips via addr/data regs */
-u_char
-todc_mc146818_read_val(int addr)
-{
-       outb_p(addr, todc_info->nvram_as0);
-       return inb_p(todc_info->nvram_data);
-}
-
-void
-todc_mc146818_write_val(int addr, unsigned char val)
-{
-       outb_p(addr, todc_info->nvram_as0);
-       outb_p(val, todc_info->nvram_data);
-}
-
-
-/*
- * Routines to make RTC chips with NVRAM buried behind an addr/data pair
- * have the NVRAM and clock regs appear at the same level.
- * The NVRAM will appear to start at addr 0 and the clock regs will appear
- * to start immediately after the NVRAM (actually, start at offset
- * todc_info->nvram_size).
- */
-static inline u_char
-todc_read_val(int addr)
-{
-       u_char  val;
-
-       if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
-               if (addr < todc_info->nvram_size) { /* NVRAM */
-                       ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
-                       val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
-               } else { /* Clock Reg */
-                       addr -= todc_info->nvram_size;
-                       val = ppc_md.rtc_read_val(addr);
-               }
-       } else
-               val = ppc_md.rtc_read_val(addr);
-
-       return val;
-}
-
-static inline void
-todc_write_val(int addr, u_char val)
-{
-       if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
-               if (addr < todc_info->nvram_size) { /* NVRAM */
-                       ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
-                       ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
-               } else { /* Clock Reg */
-                       addr -= todc_info->nvram_size;
-                       ppc_md.rtc_write_val(addr, val);
-               }
-       } else
-               ppc_md.rtc_write_val(addr, val);
-}
-
-/*
- * TODC routines
- *
- * There is some ugly stuff in that there are assumptions for the mc146818.
- *
- * Assumptions:
- *     - todc_info->control_a has the offset as mc146818 Register B reg
- *     - todc_info->control_b has the offset as mc146818 Register A reg
- *     - m48txx control reg's write enable or 'W' bit is same as
- *       mc146818 Register B 'SET' bit (i.e., 0x80)
- *
- * These assumptions were made to make the code simpler.
- */
-long __init
-todc_time_init(void)
-{
-       u_char  cntl_b;
-
-       if (!ppc_md.rtc_read_val)
-               ppc_md.rtc_read_val = ppc_md.nvram_read_val;
-       if (!ppc_md.rtc_write_val)
-               ppc_md.rtc_write_val = ppc_md.nvram_write_val;
-
-       cntl_b = todc_read_val(todc_info->control_b);
-
-       if (todc_info->rtc_type == TODC_TYPE_MC146818) {
-               if ((cntl_b & 0x70) != 0x20) {
-                       printk(KERN_INFO "TODC real-time-clock was stopped."
-                               "  Now starting...");
-                       cntl_b &= ~0x70;
-                       cntl_b |= 0x20;
-               }
-
-               todc_write_val(todc_info->control_b, cntl_b);
-       } else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
-               u_char mode;
-
-               mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
-               /* Make sure countdown clear is not set */
-               mode &= ~0x40;
-               /* Enable oscillator, extended register set */
-               mode |= 0x30;
-               todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
-
-       } else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
-               u_char  month;
-
-               todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
-               todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
-
-               month = todc_read_val(todc_info->month);
-
-               if ((month & 0x80) == 0x80) {
-                       printk(KERN_INFO "TODC %s %s\n",
-                               "real-time-clock was stopped.",
-                               "Now starting...");
-                       month &= ~0x80;
-                       todc_write_val(todc_info->month, month);
-               }
-
-               cntl_b &= ~TODC_DS1501_CNTL_B_TE;
-               todc_write_val(todc_info->control_b, cntl_b);
-       } else { /* must be a m48txx type */
-               u_char  cntl_a;
-
-               todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
-               todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
-
-               cntl_a = todc_read_val(todc_info->control_a);
-
-               /* Check & clear STOP bit in control B register */
-               if (cntl_b & TODC_MK48TXX_DAY_CB) {
-                       printk(KERN_INFO "TODC %s %s\n",
-                               "real-time-clock was stopped.",
-                               "Now starting...");
-
-                       cntl_a |= todc_info->enable_write;
-                       cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
-
-                       todc_write_val(todc_info->control_a, cntl_a);
-                       todc_write_val(todc_info->control_b, cntl_b);
-               }
-
-               /* Make sure READ & WRITE bits are cleared. */
-               cntl_a &= ~(todc_info->enable_write | todc_info->enable_read);
-               todc_write_val(todc_info->control_a, cntl_a);
-       }
-
-       return 0;
-}
-
-/*
- * There is some ugly stuff in that there are assumptions that for a mc146818,
- * the todc_info->control_a has the offset of the mc146818 Register B reg and
- * that the register'ss 'SET' bit is the same as the m48txx's write enable
- * bit in the control register of the m48txx (i.e., 0x80).
- *
- * It was done to make the code look simpler.
- */
-void
-todc_get_rtc_time(struct rtc_time *tm)
-{
-       uint    year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0;
-       uint    limit, i;
-       u_char  save_control, uip = 0;
-       extern void GregorianDay(struct rtc_time *);
-
-       spin_lock(&rtc_lock);
-       save_control = todc_read_val(todc_info->control_a);
-
-       if (todc_info->rtc_type != TODC_TYPE_MC146818) {
-               limit = 1;
-
-               switch (todc_info->rtc_type) {
-               case TODC_TYPE_DS1553:
-               case TODC_TYPE_DS1557:
-               case TODC_TYPE_DS1743:
-               case TODC_TYPE_DS1746:  /* XXXX BAD HACK -> FIX */
-               case TODC_TYPE_DS1747:
-               case TODC_TYPE_DS17285:
-                       break;
-               default:
-                       todc_write_val(todc_info->control_a,
-                               (save_control | todc_info->enable_read));
-               }
-       } else
-               limit = 100000000;
-
-       for (i=0; i<limit; i++) {
-               if (todc_info->rtc_type == TODC_TYPE_MC146818)
-                       uip = todc_read_val(todc_info->RTC_FREQ_SELECT);
-
-               sec = todc_read_val(todc_info->seconds) & 0x7f;
-               min = todc_read_val(todc_info->minutes) & 0x7f;
-               hour = todc_read_val(todc_info->hours) & 0x3f;
-               mday = todc_read_val(todc_info->day_of_month) & 0x3f;
-               mon = todc_read_val(todc_info->month) & 0x1f;
-               year = todc_read_val(todc_info->year) & 0xff;
-
-               if (todc_info->rtc_type == TODC_TYPE_MC146818) {
-                       uip |= todc_read_val(todc_info->RTC_FREQ_SELECT);
-                       if ((uip & RTC_UIP) == 0)
-                               break;
-               }
-       }
-
-       if (todc_info->rtc_type != TODC_TYPE_MC146818) {
-               switch (todc_info->rtc_type) {
-               case TODC_TYPE_DS1553:
-               case TODC_TYPE_DS1557:
-               case TODC_TYPE_DS1743:
-               case TODC_TYPE_DS1746:  /* XXXX BAD HACK -> FIX */
-               case TODC_TYPE_DS1747:
-               case TODC_TYPE_DS17285:
-                       break;
-               default:
-                       save_control &= ~(todc_info->enable_read);
-                       todc_write_val(todc_info->control_a, save_control);
-               }
-       }
-       spin_unlock(&rtc_lock);
-
-       if ((todc_info->rtc_type != TODC_TYPE_MC146818)
-                       || ((save_control & RTC_DM_BINARY) == 0)
-                       || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hour);
-               BCD_TO_BIN(mday);
-               BCD_TO_BIN(mon);
-               BCD_TO_BIN(year);
-       }
-
-       if ((year + 1900) < 1970) {
-               year += 100;
-       }
-
-       tm->tm_sec = sec;
-       tm->tm_min = min;
-       tm->tm_hour = hour;
-       tm->tm_mday = mday;
-       tm->tm_mon = mon;
-       tm->tm_year = year;
-
-       GregorianDay(tm);
-}
-
-int
-todc_set_rtc_time(struct rtc_time *tm)
-{
-       u_char save_control, save_freq_select = 0;
-
-       spin_lock(&rtc_lock);
-       save_control = todc_read_val(todc_info->control_a);
-
-       /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
-       todc_write_val(todc_info->control_a,
-               (save_control | todc_info->enable_write));
-       save_control &= ~(todc_info->enable_write); /* in case it was set */
-
-       if (todc_info->rtc_type == TODC_TYPE_MC146818) {
-               save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT);
-               todc_write_val(todc_info->RTC_FREQ_SELECT,
-                       save_freq_select | RTC_DIV_RESET2);
-       }
-
-       if ((todc_info->rtc_type != TODC_TYPE_MC146818)
-                       || ((save_control & RTC_DM_BINARY) == 0)
-                       || RTC_ALWAYS_BCD) {
-               BIN_TO_BCD(tm->tm_sec);
-               BIN_TO_BCD(tm->tm_min);
-               BIN_TO_BCD(tm->tm_hour);
-               BIN_TO_BCD(tm->tm_mon);
-               BIN_TO_BCD(tm->tm_mday);
-               BIN_TO_BCD(tm->tm_year);
-       }
-
-       todc_write_val(todc_info->seconds, tm->tm_sec);
-       todc_write_val(todc_info->minutes, tm->tm_min);
-       todc_write_val(todc_info->hours, tm->tm_hour);
-       todc_write_val(todc_info->month, tm->tm_mon);
-       todc_write_val(todc_info->day_of_month, tm->tm_mday);
-       todc_write_val(todc_info->year, tm->tm_year);
-
-       todc_write_val(todc_info->control_a, save_control);
-
-       if (todc_info->rtc_type == TODC_TYPE_MC146818)
-               todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select);
-
-       spin_unlock(&rtc_lock);
-       return 0;
-}
index f56ffef..0689c08 100644 (file)
@@ -37,6 +37,8 @@
 #include <asm/sstep.h>
 #include <asm/bug.h>
 #include <asm/irq_regs.h>
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
@@ -147,6 +149,8 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
                              const char *after);
 static const char *getvecname(unsigned long vec);
 
+static int do_spu_cmd(void);
+
 int xmon_no_auto_backtrace;
 
 extern int print_insn_powerpc(unsigned long, unsigned long, int);
@@ -209,8 +213,13 @@ Commands:\n\
   mi   show information about memory allocation\n\
   p    call a procedure\n\
   r    print registers\n\
-  s    single step\n\
-  S    print special registers\n\
+  s    single step\n"
+#ifdef CONFIG_PPC_CELL
+"  ss  stop execution on all spus\n\
+  sr   restore execution on stopped spus\n\
+  sf # dump spu fields for spu # (in hex)\n"
+#endif
+"  S   print special registers\n\
   t    print backtrace\n\
   x    exit monitor and recover\n\
   X    exit monitor and dont recover\n"
@@ -518,6 +527,7 @@ int xmon(struct pt_regs *excp)
                xmon_save_regs(&regs);
                excp = &regs;
        }
+
        return xmon_core(excp, 0);
 }
 EXPORT_SYMBOL(xmon);
@@ -809,6 +819,8 @@ cmds(struct pt_regs *excp)
                        cacheflush();
                        break;
                case 's':
+                       if (do_spu_cmd() == 0)
+                               break;
                        if (do_step(excp))
                                return cmd;
                        break;
@@ -2630,3 +2642,194 @@ void __init xmon_setup(void)
        if (xmon_early)
                debugger(NULL);
 }
+
+#ifdef CONFIG_PPC_CELL
+
+struct spu_info {
+       struct spu *spu;
+       u64 saved_mfc_sr1_RW;
+       u32 saved_spu_runcntl_RW;
+       u8 stopped_ok;
+};
+
+#define XMON_NUM_SPUS  16      /* Enough for current hardware */
+
+static struct spu_info spu_info[XMON_NUM_SPUS];
+
+void xmon_register_spus(struct list_head *list)
+{
+       struct spu *spu;
+
+       list_for_each_entry(spu, list, full_list) {
+               if (spu->number >= XMON_NUM_SPUS) {
+                       WARN_ON(1);
+                       continue;
+               }
+
+               spu_info[spu->number].spu = spu;
+               spu_info[spu->number].stopped_ok = 0;
+       }
+}
+
+static void stop_spus(void)
+{
+       struct spu *spu;
+       int i;
+       u64 tmp;
+
+       for (i = 0; i < XMON_NUM_SPUS; i++) {
+               if (!spu_info[i].spu)
+                       continue;
+
+               if (setjmp(bus_error_jmp) == 0) {
+                       catch_memory_errors = 1;
+                       sync();
+
+                       spu = spu_info[i].spu;
+
+                       spu_info[i].saved_spu_runcntl_RW =
+                               in_be32(&spu->problem->spu_runcntl_RW);
+
+                       tmp = spu_mfc_sr1_get(spu);
+                       spu_info[i].saved_mfc_sr1_RW = tmp;
+
+                       tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
+                       spu_mfc_sr1_set(spu, tmp);
+
+                       sync();
+                       __delay(200);
+
+                       spu_info[i].stopped_ok = 1;
+                       printf("Stopped spu %.2d\n", i);
+               } else {
+                       catch_memory_errors = 0;
+                       printf("*** Error stopping spu %.2d\n", i);
+               }
+               catch_memory_errors = 0;
+       }
+}
+
+static void restart_spus(void)
+{
+       struct spu *spu;
+       int i;
+
+       for (i = 0; i < XMON_NUM_SPUS; i++) {
+               if (!spu_info[i].spu)
+                       continue;
+
+               if (!spu_info[i].stopped_ok) {
+                       printf("*** Error, spu %d was not successfully stopped"
+                                       ", not restarting\n", i);
+                       continue;
+               }
+
+               if (setjmp(bus_error_jmp) == 0) {
+                       catch_memory_errors = 1;
+                       sync();
+
+                       spu = spu_info[i].spu;
+                       spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
+                       out_be32(&spu->problem->spu_runcntl_RW,
+                                       spu_info[i].saved_spu_runcntl_RW);
+
+                       sync();
+                       __delay(200);
+
+                       printf("Restarted spu %.2d\n", i);
+               } else {
+                       catch_memory_errors = 0;
+                       printf("*** Error restarting spu %.2d\n", i);
+               }
+               catch_memory_errors = 0;
+       }
+}
+
+#define DUMP_WIDTH     23
+#define DUMP_FIELD(obj, format, field)                                 \
+do {                                                                   \
+       if (setjmp(bus_error_jmp) == 0) {                               \
+               catch_memory_errors = 1;                                \
+               sync();                                                 \
+               printf("  %-*s = "format"\n", DUMP_WIDTH,               \
+                               #field, obj->field);                    \
+               sync();                                                 \
+               __delay(200);                                           \
+       } else {                                                        \
+               catch_memory_errors = 0;                                \
+               printf("  %-*s = *** Error reading field.\n",           \
+                                       DUMP_WIDTH, #field);            \
+       }                                                               \
+       catch_memory_errors = 0;                                        \
+} while (0)
+
+static void dump_spu_fields(struct spu *spu)
+{
+       printf("Dumping spu fields at address %p:\n", spu);
+
+       DUMP_FIELD(spu, "0x%x", number);
+       DUMP_FIELD(spu, "%s", name);
+       DUMP_FIELD(spu, "%s", devnode->full_name);
+       DUMP_FIELD(spu, "0x%x", nid);
+       DUMP_FIELD(spu, "0x%lx", local_store_phys);
+       DUMP_FIELD(spu, "0x%p", local_store);
+       DUMP_FIELD(spu, "0x%lx", ls_size);
+       DUMP_FIELD(spu, "0x%x", node);
+       DUMP_FIELD(spu, "0x%lx", flags);
+       DUMP_FIELD(spu, "0x%lx", dar);
+       DUMP_FIELD(spu, "0x%lx", dsisr);
+       DUMP_FIELD(spu, "%d", class_0_pending);
+       DUMP_FIELD(spu, "0x%lx", irqs[0]);
+       DUMP_FIELD(spu, "0x%lx", irqs[1]);
+       DUMP_FIELD(spu, "0x%lx", irqs[2]);
+       DUMP_FIELD(spu, "0x%x", slb_replace);
+       DUMP_FIELD(spu, "%d", pid);
+       DUMP_FIELD(spu, "%d", prio);
+       DUMP_FIELD(spu, "0x%p", mm);
+       DUMP_FIELD(spu, "0x%p", ctx);
+       DUMP_FIELD(spu, "0x%p", rq);
+       DUMP_FIELD(spu, "0x%p", timestamp);
+       DUMP_FIELD(spu, "0x%lx", problem_phys);
+       DUMP_FIELD(spu, "0x%p", problem);
+       DUMP_FIELD(spu, "0x%x", problem->spu_runcntl_RW);
+       DUMP_FIELD(spu, "0x%x", problem->spu_status_R);
+       DUMP_FIELD(spu, "0x%x", problem->spu_npc_RW);
+       DUMP_FIELD(spu, "0x%p", priv1);
+
+       if (spu->priv1)
+               DUMP_FIELD(spu, "0x%lx", priv1->mfc_sr1_RW);
+
+       DUMP_FIELD(spu, "0x%p", priv2);
+}
+
+static int do_spu_cmd(void)
+{
+       unsigned long num = 0;
+       int cmd;
+
+       cmd = inchar();
+       switch (cmd) {
+       case 's':
+               stop_spus();
+               break;
+       case 'r':
+               restart_spus();
+               break;
+       case 'f':
+               if (scanhex(&num) && num < XMON_NUM_SPUS && spu_info[num].spu)
+                       dump_spu_fields(spu_info[num].spu);
+               else
+                       printf("*** Error: invalid spu number\n");
+               break;
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+#else /* ! CONFIG_PPC_CELL */
+static int do_spu_cmd(void)
+{
+       return -1;
+}
+#endif
index 3397f0d..b84f8df 100644 (file)
@@ -121,8 +121,8 @@ mpc834x_sys_setup_arch(void)
 
        mdata->irq[0] = MPC83xx_IRQ_EXT1;
        mdata->irq[1] = MPC83xx_IRQ_EXT2;
-       mdata->irq[2] = -1;
-       mdata->irq[31] = -1;
+       mdata->irq[2] = PHY_POLL;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
index 4f839da..00a3ba5 100644 (file)
@@ -92,9 +92,9 @@ mpc8540ads_setup_arch(void)
 
        mdata->irq[0] = MPC85xx_IRQ_EXT5;
        mdata->irq[1] = MPC85xx_IRQ_EXT5;
-       mdata->irq[2] = -1;
+       mdata->irq[2] = PHY_POLL;
        mdata->irq[3] = MPC85xx_IRQ_EXT5;
-       mdata->irq[31] = -1;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
index 14ecec7..3a06046 100644 (file)
@@ -156,9 +156,9 @@ mpc8560ads_setup_arch(void)
 
        mdata->irq[0] = MPC85xx_IRQ_EXT5;
        mdata->irq[1] = MPC85xx_IRQ_EXT5;
-       mdata->irq[2] = -1;
+       mdata->irq[2] = PHY_POLL;
        mdata->irq[3] = MPC85xx_IRQ_EXT5;
-       mdata->irq[31] = -1;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
index 5ce0f69..2d59eb7 100644 (file)
@@ -451,9 +451,9 @@ mpc85xx_cds_setup_arch(void)
 
        mdata->irq[0] = MPC85xx_IRQ_EXT5;
        mdata->irq[1] = MPC85xx_IRQ_EXT5;
-       mdata->irq[2] = -1;
-       mdata->irq[3] = -1;
-       mdata->irq[31] = -1;
+       mdata->irq[2] = PHY_POLL;
+       mdata->irq[3] = PHY_POLL;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
index 764d580..1d10ab9 100644 (file)
@@ -129,7 +129,7 @@ sbc8560_setup_arch(void)
 
        mdata->irq[25] = MPC85xx_IRQ_EXT6;
        mdata->irq[26] = MPC85xx_IRQ_EXT7;
-       mdata->irq[31] = -1;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
index 4bb18ab..b1f5b73 100644 (file)
@@ -123,7 +123,7 @@ gp3_setup_arch(void)
 
        mdata->irq[2] = MPC85xx_IRQ_EXT5;
        mdata->irq[4] = MPC85xx_IRQ_EXT5;
-       mdata->irq[31] = -1;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
index dd45f2e..4ee2bd1 100644 (file)
@@ -137,9 +137,9 @@ tqm85xx_setup_arch(void)
 
        mdata->irq[0] = MPC85xx_IRQ_EXT8;
        mdata->irq[1] = MPC85xx_IRQ_EXT8;
-       mdata->irq[2] = -1;
+       mdata->irq[2] = PHY_POLL;
        mdata->irq[3] = MPC85xx_IRQ_EXT8;
-       mdata->irq[31] = -1;
+       mdata->irq[31] = PHY_POLL;
 
        /* setup the board related information for the enet controllers */
        pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
index 1f9ea36..0bc0676 100644 (file)
@@ -266,10 +266,10 @@ static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
                                              int idx)
 {
        m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
-       m82xx_mii_bb_pdata.irq[1] = -1;
-       m82xx_mii_bb_pdata.irq[2] = -1;
+       m82xx_mii_bb_pdata.irq[1] = PHY_POLL;
+       m82xx_mii_bb_pdata.irq[2] = PHY_POLL;
        m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
-       m82xx_mii_bb_pdata.irq[31] = -1;
+       m82xx_mii_bb_pdata.irq[31] = PHY_POLL;
 
 
        m82xx_mii_bb_pdata.mdio_dat.offset =
index e95d2c1..8a0c07e 100644 (file)
@@ -361,7 +361,7 @@ int __init mpc866ads_init(void)
 
        fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
        /* No PHY interrupt line here */
-       fmpi->irq[0xf] = -1;
+       fmpi->irq[0xf] = PHY_POLL;
 
 /* Since either of the uarts could be used as console, they need to ready */
 #ifdef CONFIG_SERIAL_CPM_SMC1
@@ -380,7 +380,7 @@ int __init mpc866ads_init(void)
 
        fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
        /* No PHY interrupt line here */
-       fmpi->irq[0xf] = -1;
+       fmpi->irq[0xf] = PHY_POLL;
 
        return 0;
 }
index 2af634d..eb7ab11 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/ide.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_CHRP
 #include <asm/processor.h>
 #endif
 
@@ -442,7 +442,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
        hwif->speedproc = &via_set_drive;
 
 
-#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
+#ifdef CONFIG_PPC_CHRP
        if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
                hwif->irq = hwif->channel ? 15 : 14;
        }
index f14e992..096d4a1 100644 (file)
@@ -254,7 +254,7 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)
                goto device_create_fail;
        }
 
-       phydev->irq = -1;
+       phydev->irq = PHY_IGNORE_INTERRUPT;
        phydev->dev.bus = &mdio_bus_type;
 
        if(number)
index 3f4b640..4b3cd3d 100644 (file)
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 #include <asm/uaccess.h>
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PMAC
 #include <asm/machdep.h>
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC_PMAC */
 
 #include "de4x5.h"
 
@@ -4151,7 +4151,7 @@ get_hw_addr(struct net_device *dev)
     /* If possible, try to fix a broken card - SMC only so far */
     srom_repair(dev, broken);
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PMAC
     /*
     ** If the address starts with 00 a0, we have to bit-reverse
     ** each byte of the address.
@@ -4168,7 +4168,7 @@ get_hw_addr(struct net_device *dev)
                    dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
            }
     }
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC_PMAC */
 
     /* Test for a bad enet address */
     status = test_bad_enet(dev, status);
index d403592..c4a1ab6 100644 (file)
@@ -7,16 +7,30 @@
 #ifdef __KERNEL__
 
 #include <linux/errno.h>
+#include <linux/compiler.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
 extern void timer_interrupt(struct pt_regs *);
 
-#ifdef CONFIG_PPC_ISERIES
+#ifdef CONFIG_PPC64
+#include <asm/paca.h>
+
+static inline unsigned long local_get_flags(void)
+{
+       return get_paca()->soft_enabled;
+}
+
+static inline unsigned long local_irq_disable(void)
+{
+       unsigned long flag = get_paca()->soft_enabled;
+       get_paca()->soft_enabled = 0;
+       barrier();
+       return flag;
+}
 
-extern unsigned long local_get_flags(void);
-extern unsigned long local_irq_disable(void);
 extern void local_irq_restore(unsigned long);
+extern void iseries_handle_interrupts(void);
 
 #define local_irq_enable()     local_irq_restore(1)
 #define local_save_flags(flags)        ((flags) = local_get_flags())
@@ -24,17 +38,14 @@ extern void local_irq_restore(unsigned long);
 
 #define irqs_disabled()                (local_get_flags() == 0)
 
+#define hard_irq_enable()      __mtmsrd(mfmsr() | MSR_EE, 1)
+#define hard_irq_disable()     __mtmsrd(mfmsr() & ~MSR_EE, 1)
+
 #else
 
 #if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)  mtmsr(x)
 #define local_irq_restore(flags)       __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
-#elif defined(__powerpc64__)
-#define SET_MSR_EE(x)  __mtmsrd(x, 1)
-#define local_irq_restore(flags) do { \
-       __asm__ __volatile__("": : :"memory"); \
-       __mtmsrd((flags), 1); \
-} while(0)
 #else
 #define SET_MSR_EE(x)  mtmsr(x)
 #define local_irq_restore(flags)       mtmsr(flags)
@@ -81,7 +92,7 @@ static inline void local_irq_save_ptr(unsigned long *flags)
 #define local_irq_save(flags)  local_irq_save_ptr(&flags)
 #define irqs_disabled()                ((mfmsr() & MSR_EE) == 0)
 
-#endif /* CONFIG_PPC_ISERIES */
+#endif /* CONFIG_PPC64 */
 
 #define mask_irq(irq)                                          \
        ({                                                      \
index ce12f85..9fdd049 100644 (file)
@@ -136,22 +136,7 @@ struct qe_timers {
 
 /* BRG */
 struct qe_brg {
-       __be32  brgc1;          /* BRG1 configuration register */
-       __be32  brgc2;          /* BRG2 configuration register */
-       __be32  brgc3;          /* BRG3 configuration register */
-       __be32  brgc4;          /* BRG4 configuration register */
-       __be32  brgc5;          /* BRG5 configuration register */
-       __be32  brgc6;          /* BRG6 configuration register */
-       __be32  brgc7;          /* BRG7 configuration register */
-       __be32  brgc8;          /* BRG8 configuration register */
-       __be32  brgc9;          /* BRG9 configuration register */
-       __be32  brgc10;         /* BRG10 configuration register */
-       __be32  brgc11;         /* BRG11 configuration register */
-       __be32  brgc12;         /* BRG12 configuration register */
-       __be32  brgc13;         /* BRG13 configuration register */
-       __be32  brgc14;         /* BRG14 configuration register */
-       __be32  brgc15;         /* BRG15 configuration register */
-       __be32  brgc16;         /* BRG16 configuration register */
+       __be32  brgc[16];       /* BRG configuration registers */
        u8      res0[0x40];
 } __attribute__ ((packed));
 
index 39fad68..19e6f7e 100644 (file)
@@ -70,17 +70,9 @@ struct iommu_table {
 struct scatterlist;
 struct device_node;
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-
-/* Walks all buses and creates iommu tables */
-extern void iommu_setup_pSeries(void);
-extern void iommu_setup_dart(void);
-
 /* Frees table for an individual device node */
 extern void iommu_free_table(struct device_node *dn);
 
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 /* Initializes an iommu_table based in values set in the passed-in
  * structure
  */
index c3fc7a2..41c8c9c 100644 (file)
@@ -248,21 +248,6 @@ extern void hpte_init_native(void);
 extern void hpte_init_lpar(void);
 extern void hpte_init_iSeries(void);
 
-extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
-                                    unsigned long va, unsigned long prpn,
-                                    unsigned long rflags,
-                                    unsigned long vflags, int psize);
-
-extern long native_hpte_insert(unsigned long hpte_group,
-                              unsigned long va, unsigned long prpn,
-                              unsigned long rflags,
-                              unsigned long vflags, int psize);
-
-extern long iSeries_hpte_insert(unsigned long hpte_group,
-                               unsigned long va, unsigned long prpn,
-                               unsigned long rflags,
-                               unsigned long vflags, int psize);
-
 extern void stabs_alloc(void);
 extern void slb_initialize(void);
 extern void slb_flush_and_rebolt(void);
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
new file mode 100644 (file)
index 0000000..e9aa622
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+#endif /* __ASSEMBLY__ */
+
+
+/* ======================================================================== */
+/* HW IRQ mapping                                                           */
+/* ======================================================================== */
+
+#define MPC52xx_IRQ_L1_CRIT            (0)
+#define MPC52xx_IRQ_L1_MAIN            (1)
+#define MPC52xx_IRQ_L1_PERP            (2)
+#define MPC52xx_IRQ_L1_SDMA            (3)
+
+#define MPC52xx_IRQ_L1_OFFSET          (6)
+#define MPC52xx_IRQ_L1_MASK            (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET          (0)
+#define MPC52xx_IRQ_L2_MASK            (0x3f)
+
+#define MPC52xx_IRQ_HIGHTESTHWIRQ      (0xd0)
+
+
+/* ======================================================================== */
+/* Structures mapping of some unit register set                             */
+/* ======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Interrupt controller Register set */
+struct mpc52xx_intr {
+       u32 per_mask;           /* INTR + 0x00 */
+       u32 per_pri1;           /* INTR + 0x04 */
+       u32 per_pri2;           /* INTR + 0x08 */
+       u32 per_pri3;           /* INTR + 0x0c */
+       u32 ctrl;               /* INTR + 0x10 */
+       u32 main_mask;          /* INTR + 0x14 */
+       u32 main_pri1;          /* INTR + 0x18 */
+       u32 main_pri2;          /* INTR + 0x1c */
+       u32 reserved1;          /* INTR + 0x20 */
+       u32 enc_status;         /* INTR + 0x24 */
+       u32 crit_status;        /* INTR + 0x28 */
+       u32 main_status;        /* INTR + 0x2c */
+       u32 per_status;         /* INTR + 0x30 */
+       u32 reserved2;          /* INTR + 0x34 */
+       u32 per_error;          /* INTR + 0x38 */
+};
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+       u32 mbar;               /* MMAP_CTRL + 0x00 */
+
+       u32 cs0_start;          /* MMAP_CTRL + 0x04 */
+       u32 cs0_stop;           /* MMAP_CTRL + 0x08 */
+       u32 cs1_start;          /* MMAP_CTRL + 0x0c */
+       u32 cs1_stop;           /* MMAP_CTRL + 0x10 */
+       u32 cs2_start;          /* MMAP_CTRL + 0x14 */
+       u32 cs2_stop;           /* MMAP_CTRL + 0x18 */
+       u32 cs3_start;          /* MMAP_CTRL + 0x1c */
+       u32 cs3_stop;           /* MMAP_CTRL + 0x20 */
+       u32 cs4_start;          /* MMAP_CTRL + 0x24 */
+       u32 cs4_stop;           /* MMAP_CTRL + 0x28 */
+       u32 cs5_start;          /* MMAP_CTRL + 0x2c */
+       u32 cs5_stop;           /* MMAP_CTRL + 0x30 */
+
+       u32 sdram0;             /* MMAP_CTRL + 0x34 */
+       u32 sdram1;             /* MMAP_CTRL + 0X38 */
+
+       u32 reserved[4];        /* MMAP_CTRL + 0x3c .. 0x48 */
+
+       u32 boot_start;         /* MMAP_CTRL + 0x4c */
+       u32 boot_stop;          /* MMAP_CTRL + 0x50 */
+
+       u32 ipbi_ws_ctrl;       /* MMAP_CTRL + 0x54 */
+
+       u32 cs6_start;          /* MMAP_CTRL + 0x58 */
+       u32 cs6_stop;           /* MMAP_CTRL + 0x5c */
+       u32 cs7_start;          /* MMAP_CTRL + 0x60 */
+       u32 cs7_stop;           /* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+       u32 mode;               /* SDRAM + 0x00 */
+       u32 ctrl;               /* SDRAM + 0x04 */
+       u32 config1;            /* SDRAM + 0x08 */
+       u32 config2;            /* SDRAM + 0x0c */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+       u32 taskBar;            /* SDMA + 0x00 */
+       u32 currentPointer;     /* SDMA + 0x04 */
+       u32 endPointer;         /* SDMA + 0x08 */
+       u32 variablePointer;    /* SDMA + 0x0c */
+
+       u8 IntVect1;            /* SDMA + 0x10 */
+       u8 IntVect2;            /* SDMA + 0x11 */
+       u16 PtdCntrl;           /* SDMA + 0x12 */
+
+       u32 IntPend;            /* SDMA + 0x14 */
+       u32 IntMask;            /* SDMA + 0x18 */
+
+       u16 tcr[16];            /* SDMA + 0x1c .. 0x3a */
+
+       u8 ipr[32];             /* SDMA + 0x3c .. 0x5b */
+
+       u32 cReqSelect;         /* SDMA + 0x5c */
+       u32 task_size0;         /* SDMA + 0x60 */
+       u32 task_size1;         /* SDMA + 0x64 */
+       u32 MDEDebug;           /* SDMA + 0x68 */
+       u32 ADSDebug;           /* SDMA + 0x6c */
+       u32 Value1;             /* SDMA + 0x70 */
+       u32 Value2;             /* SDMA + 0x74 */
+       u32 Control;            /* SDMA + 0x78 */
+       u32 Status;             /* SDMA + 0x7c */
+       u32 PTDDebug;           /* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+       u32 mode;               /* GPTx + 0x00 */
+       u32 count;              /* GPTx + 0x04 */
+       u32 pwm;                /* GPTx + 0x08 */
+       u32 status;             /* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+       u32 port_config;        /* GPIO + 0x00 */
+       u32 simple_gpioe;       /* GPIO + 0x04 */
+       u32 simple_ode;         /* GPIO + 0x08 */
+       u32 simple_ddr;         /* GPIO + 0x0c */
+       u32 simple_dvo;         /* GPIO + 0x10 */
+       u32 simple_ival;        /* GPIO + 0x14 */
+       u8 outo_gpioe;          /* GPIO + 0x18 */
+       u8 reserved1[3];        /* GPIO + 0x19 */
+       u8 outo_dvo;            /* GPIO + 0x1c */
+       u8 reserved2[3];        /* GPIO + 0x1d */
+       u8 sint_gpioe;          /* GPIO + 0x20 */
+       u8 reserved3[3];        /* GPIO + 0x21 */
+       u8 sint_ode;            /* GPIO + 0x24 */
+       u8 reserved4[3];        /* GPIO + 0x25 */
+       u8 sint_ddr;            /* GPIO + 0x28 */
+       u8 reserved5[3];        /* GPIO + 0x29 */
+       u8 sint_dvo;            /* GPIO + 0x2c */
+       u8 reserved6[3];        /* GPIO + 0x2d */
+       u8 sint_inten;          /* GPIO + 0x30 */
+       u8 reserved7[3];        /* GPIO + 0x31 */
+       u16 sint_itype;         /* GPIO + 0x34 */
+       u16 reserved8;          /* GPIO + 0x36 */
+       u8 gpio_control;        /* GPIO + 0x38 */
+       u8 reserved9[3];        /* GPIO + 0x39 */
+       u8 sint_istat;          /* GPIO + 0x3c */
+       u8 sint_ival;           /* GPIO + 0x3d */
+       u8 bus_errs;            /* GPIO + 0x3e */
+       u8 reserved10;          /* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD        4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD   5
+#define MPC52xx_GPIO_PCI_DIS                   (1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+       u8 wkup_gpioe;          /* GPIO_WKUP + 0x00 */
+       u8 reserved1[3];        /* GPIO_WKUP + 0x03 */
+       u8 wkup_ode;            /* GPIO_WKUP + 0x04 */
+       u8 reserved2[3];        /* GPIO_WKUP + 0x05 */
+       u8 wkup_ddr;            /* GPIO_WKUP + 0x08 */
+       u8 reserved3[3];        /* GPIO_WKUP + 0x09 */
+       u8 wkup_dvo;            /* GPIO_WKUP + 0x0C */
+       u8 reserved4[3];        /* GPIO_WKUP + 0x0D */
+       u8 wkup_inten;          /* GPIO_WKUP + 0x10 */
+       u8 reserved5[3];        /* GPIO_WKUP + 0x11 */
+       u8 wkup_iinten;         /* GPIO_WKUP + 0x14 */
+       u8 reserved6[3];        /* GPIO_WKUP + 0x15 */
+       u16 wkup_itype;         /* GPIO_WKUP + 0x18 */
+       u8 reserved7[2];        /* GPIO_WKUP + 0x1A */
+       u8 wkup_maste;          /* GPIO_WKUP + 0x1C */
+       u8 reserved8[3];        /* GPIO_WKUP + 0x1D */
+       u8 wkup_ival;           /* GPIO_WKUP + 0x20 */
+       u8 reserved9[3];        /* GPIO_WKUP + 0x21 */
+       u8 wkup_istat;          /* GPIO_WKUP + 0x24 */
+       u8 reserved10[3];       /* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+       u8 reserved[0x40];
+       u32 config;             /* XLB + 0x40 */
+       u32 version;            /* XLB + 0x44 */
+       u32 status;             /* XLB + 0x48 */
+       u32 int_enable;         /* XLB + 0x4c */
+       u32 addr_capture;       /* XLB + 0x50 */
+       u32 bus_sig_capture;    /* XLB + 0x54 */
+       u32 addr_timeout;       /* XLB + 0x58 */
+       u32 data_timeout;       /* XLB + 0x5c */
+       u32 bus_act_timeout;    /* XLB + 0x60 */
+       u32 master_pri_enable;  /* XLB + 0x64 */
+       u32 master_priority;    /* XLB + 0x68 */
+       u32 base_address;       /* XLB + 0x6c */
+       u32 snoop_window;       /* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS          (1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP          (1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+       u32 jtag_id;            /* CDM + 0x00  reg0 read only */
+       u32 rstcfg;             /* CDM + 0x04  reg1 read only */
+       u32 breadcrumb;         /* CDM + 0x08  reg2 */
+
+       u8 mem_clk_sel;         /* CDM + 0x0c  reg3 byte0 */
+       u8 xlb_clk_sel;         /* CDM + 0x0d  reg3 byte1 read only */
+       u8 ipb_clk_sel;         /* CDM + 0x0e  reg3 byte2 */
+       u8 pci_clk_sel;         /* CDM + 0x0f  reg3 byte3 */
+
+       u8 ext_48mhz_en;        /* CDM + 0x10  reg4 byte0 */
+       u8 fd_enable;           /* CDM + 0x11  reg4 byte1 */
+       u16 fd_counters;        /* CDM + 0x12  reg4 byte2,3 */
+
+       u32 clk_enables;        /* CDM + 0x14  reg5 */
+
+       u8 osc_disable;         /* CDM + 0x18  reg6 byte0 */
+       u8 reserved0[3];        /* CDM + 0x19  reg6 byte1,2,3 */
+
+       u8 ccs_sleep_enable;    /* CDM + 0x1c  reg7 byte0 */
+       u8 osc_sleep_enable;    /* CDM + 0x1d  reg7 byte1 */
+       u8 reserved1;           /* CDM + 0x1e  reg7 byte2 */
+       u8 ccs_qreq_test;       /* CDM + 0x1f  reg7 byte3 */
+
+       u8 soft_reset;          /* CDM + 0x20  u8 byte0 */
+       u8 no_ckstp;            /* CDM + 0x21  u8 byte0 */
+       u8 reserved2[2];        /* CDM + 0x22  u8 byte1,2,3 */
+
+       u8 pll_lock;            /* CDM + 0x24  reg9 byte0 */
+       u8 pll_looselock;       /* CDM + 0x25  reg9 byte1 */
+       u8 pll_sm_lockwin;      /* CDM + 0x26  reg9 byte2 */
+       u8 reserved3;           /* CDM + 0x27  reg9 byte3 */
+
+       u16 reserved4;          /* CDM + 0x28  reg10 byte0,1 */
+       u16 mclken_div_psc1;    /* CDM + 0x2a  reg10 byte2,3 */
+
+       u16 reserved5;          /* CDM + 0x2c  reg11 byte0,1 */
+       u16 mclken_div_psc2;    /* CDM + 0x2e  reg11 byte2,3 */
+
+       u16 reserved6;          /* CDM + 0x30  reg12 byte0,1 */
+       u16 mclken_div_psc3;    /* CDM + 0x32  reg12 byte2,3 */
+
+       u16 reserved7;          /* CDM + 0x34  reg13 byte0,1 */
+       u16 mclken_div_psc6;    /* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+/* ========================================================================= */
+/* Prototypes for MPC52xx sysdev                                             */
+/* ========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_POWERPC_MPC52xx_H__ */
+
index ccdb8a2..5414299 100644 (file)
 #include <platforms/85xx/mpc85xx_cds.h>
 #endif
 
-#define _IO_BASE        isa_io_base
-#define _ISA_MEM_BASE   isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#else
-#define PCI_DRAM_OFFSET 0
-#endif
-
 /* Let modules/drivers get at CCSRBAR */
 extern phys_addr_t get_ccsrbar(void);
 
index 0a4e5c9..0d3adc0 100644 (file)
@@ -93,7 +93,8 @@ struct paca_struct {
        u64 stab_rr;                    /* stab/slb round-robin counter */
        u64 saved_r1;                   /* r1 save for RTAS calls */
        u64 saved_msr;                  /* MSR saved here by enter_rtas */
-       u8 proc_enabled;                /* irq soft-enable flag */
+       u8 soft_enabled;                /* irq soft-enable flag */
+       u8 hard_enabled;                /* set if irqs are enabled in MSR */
        u8 io_sync;                     /* writel() needs spin_unlock sync */
 
        /* Stuff for accurate time accounting */
index 721c97f..c772860 100644 (file)
@@ -232,12 +232,10 @@ extern pgprot_t   pci_phys_mem_access_prot(struct file *file,
                                         unsigned long size,
                                         pgprot_t prot);
 
-#if defined(CONFIG_PPC_MULTIPLATFORM) || defined(CONFIG_PPC32)
 #define HAVE_ARCH_PCI_RESOURCE_TO_USER
 extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
                                 const struct resource *rsrc,
                                 resource_size_t *start, resource_size_t *end);
-#endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */
index 6cb6fb1..a26c32e 100644 (file)
@@ -53,10 +53,6 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin;
 
 #endif /* CONFIG_PPC_PREP */
 
-#ifndef CONFIG_PPC_MULTIPLATFORM
-#define _machine 0
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
 
 /*
index ec11d44..0afee17 100644 (file)
@@ -17,6 +17,7 @@
  */
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/platform_device.h>
 #include <asm/atomic.h>
 
 /* Definitions used by the flattened device tree */
@@ -333,6 +334,20 @@ extern int of_irq_map_one(struct device_node *device, int index,
 struct pci_dev;
 extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
 
+static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
+{
+       int irq = irq_of_parse_and_map(dev, index);
+
+       /* Only dereference the resource if both the
+        * resource and the irq are valid. */
+       if (r && irq != NO_IRQ) {
+               r->start = r->end = irq;
+               r->flags = IORESOURCE_IRQ;
+       }
+
+       return irq;
+}
+
 
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
index e73ea00..ffa4df0 100644 (file)
@@ -115,10 +115,10 @@ struct spu {
        struct spu_priv2 __iomem *priv2;
        struct list_head list;
        struct list_head sched_list;
+       struct list_head full_list;
        int number;
        int nid;
        unsigned int irqs[3];
-       u32 isrc;
        u32 node;
        u64 flags;
        u64 dar;
@@ -144,6 +144,8 @@ struct spu {
        char irq_c1[8];
        char irq_c2[8];
 
+       struct device_node *devnode;
+
        struct sys_device sysdev;
 };
 
@@ -182,8 +184,10 @@ extern struct spufs_calls {
  */
 #define SPU_CREATE_EVENTS_ENABLED      0x0001
 #define SPU_CREATE_GANG                        0x0002
+#define SPU_CREATE_NOSCHED             0x0004
+#define SPU_CREATE_ISOLATE             0x0008
 
-#define SPU_CREATE_FLAG_ALL            0x0003 /* mask of all valid flags */
+#define SPU_CREATE_FLAG_ALL            0x000f /* mask of all valid flags */
 
 
 #ifdef CONFIG_SPU_FS_MODULE
@@ -199,6 +203,12 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls)
 }
 #endif /* MODULE */
 
+int spu_add_sysdev_attr(struct sysdev_attribute *attr);
+void spu_remove_sysdev_attr(struct sysdev_attribute *attr);
+
+int spu_add_sysdev_attr_group(struct attribute_group *attrs);
+void spu_remove_sysdev_attr_group(struct attribute_group *attrs);
+
 
 /*
  * Notifier blocks:
@@ -277,6 +287,7 @@ struct spu_problem {
        u32 spu_runcntl_RW;                                     /* 0x401c */
 #define SPU_RUNCNTL_STOP       0L
 #define SPU_RUNCNTL_RUNNABLE   1L
+#define SPU_RUNCNTL_ISOLATE    2L
        u8  pad_0x4020_0x4024[0x4];                             /* 0x4020 */
        u32 spu_status_R;                                       /* 0x4024 */
 #define SPU_STOP_STATUS_SHIFT           16
@@ -289,8 +300,8 @@ struct spu_problem {
 #define SPU_STATUS_INVALID_INSTR        0x20
 #define SPU_STATUS_INVALID_CH           0x40
 #define SPU_STATUS_ISOLATED_STATE       0x80
-#define SPU_STATUS_ISOLATED_LOAD_STAUTUS 0x200
-#define SPU_STATUS_ISOLATED_EXIT_STAUTUS 0x400
+#define SPU_STATUS_ISOLATED_LOAD_STATUS 0x200
+#define SPU_STATUS_ISOLATED_EXIT_STATUS 0x400
        u8  pad_0x4028_0x402c[0x4];                             /* 0x4028 */
        u32 spu_spe_R;                                          /* 0x402c */
        u8  pad_0x4030_0x4034[0x4];                             /* 0x4030 */
index 964c2d3..bdbf906 100644 (file)
@@ -151,7 +151,6 @@ struct spu_priv1_collapsed {
        u64 mfc_fir_chkstp_enable_RW;
        u64 smf_sbi_signal_sel;
        u64 smf_ato_signal_sel;
-       u64 mfc_sdr_RW;
        u64 tlb_index_hint_RO;
        u64 tlb_index_W;
        u64 tlb_vpn_RW;
index 300c458..4f9a04d 100644 (file)
@@ -37,7 +37,7 @@ struct spu_priv1_ops
        u64 (*mfc_dar_get) (struct spu *spu);
        u64 (*mfc_dsisr_get) (struct spu *spu);
        void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr);
-       void (*mfc_sdr_set) (struct spu *spu, u64 sdr);
+       void (*mfc_sdr_setup) (struct spu *spu);
        void (*mfc_sr1_set) (struct spu *spu, u64 sr1);
        u64 (*mfc_sr1_get) (struct spu *spu);
        void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id);
@@ -112,9 +112,9 @@ spu_mfc_dsisr_set (struct spu *spu, u64 dsisr)
 }
 
 static inline void
-spu_mfc_sdr_set (struct spu *spu, u64 sdr)
+spu_mfc_sdr_setup (struct spu *spu)
 {
-       spu_priv1_ops->mfc_sdr_set(spu, sdr);
+       spu_priv1_ops->mfc_sdr_setup(spu);
 }
 
 static inline void
diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h
deleted file mode 100644 (file)
index 60a8c39..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Definitions for the M48Txx and mc146818 series of Time of day/Real Time
- * Clock chips.
- *
- * Author: Mark A. Greer <mgreer@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/*
- * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips.
- * Purpose is to make one generic file that handles all of these chips instead
- * of every platform implementing the same code over & over again.
- */
-
-#ifndef __PPC_KERNEL_TODC_H
-#define __PPC_KERNEL_TODC_H
-
-typedef struct {
-       uint rtc_type;          /* your particular chip */
-
-       /*
-        * Following are the addresses of the AS0, AS1, and DATA registers
-        * of these chips.  Note that these are board-specific.
-        */
-       unsigned int nvram_as0;
-       unsigned int nvram_as1;
-       unsigned int nvram_data;
-
-       /*
-        * Define bits to stop external set of regs from changing so
-        * the chip can be read/written reliably.
-        */
-       unsigned char enable_read;
-       unsigned char enable_write;
-
-       /*
-        * Following is the number of AS0 address bits.  This is normally
-        * 8 but some bad hardware routes address lines incorrectly.
-        */
-       int as0_bits;
-
-       int nvram_size; /* Size of NVRAM on chip */
-       int sw_flags;   /* Software control flags */
-
-       /* Following are the register offsets for the particular chip */
-       int year;
-       int month;
-       int day_of_month;
-       int day_of_week;
-       int hours;
-       int minutes;
-       int seconds;
-       int control_b;
-       int control_a;
-       int watchdog;
-       int interrupts;
-       int alarm_date;
-       int alarm_hour;
-       int alarm_minutes;
-       int alarm_seconds;
-       int century;
-       int flags;
-
-       /*
-        * Some RTC chips have their NVRAM buried behind a addr/data pair of
-        * regs on the first level/clock registers.  The following fields
-        * are the addresses for those addr/data regs.
-        */
-       int nvram_addr_reg;
-       int nvram_data_reg;
-} todc_info_t;
-
-/*
- * Define the types of TODC/RTC variants that are supported in
- * arch/ppc/kernel/todc_time.c
- * Make a new one of these for any chip somehow differs from what's already
- * defined.  That way, if you ever need to put in code to touch those
- * bits/registers in todc_time.c, you can put it inside an
- * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break
- * anyone else.
- */
-#define TODC_TYPE_MK48T35              1
-#define TODC_TYPE_MK48T37              2
-#define TODC_TYPE_MK48T59              3
-#define TODC_TYPE_DS1693               4       /* Dallas DS1693 RTC */
-#define TODC_TYPE_DS1743               5       /* Dallas DS1743 RTC */
-#define TODC_TYPE_DS1746               6       /* Dallas DS1746 RTC */
-#define TODC_TYPE_DS1747               7       /* Dallas DS1747 RTC */
-#define TODC_TYPE_DS1501               8       /* Dallas DS1501 RTC */
-#define TODC_TYPE_DS1643               9       /* Dallas DS1643 RTC */
-#define TODC_TYPE_PC97307              10      /* PC97307 internal RTC */
-#define TODC_TYPE_DS1557               11      /* Dallas DS1557 RTC */
-#define TODC_TYPE_DS17285              12      /* Dallas DS17285 RTC */
-#define TODC_TYPE_DS1553               13      /* Dallas DS1553 RTC */
-#define TODC_TYPE_MC146818             100     /* Leave room for m48txx's */
-
-/*
- * Bit to clear/set to enable reads/writes to the chip
- */
-#define TODC_MK48TXX_CNTL_A_R          0x40
-#define TODC_MK48TXX_CNTL_A_W          0x80
-#define TODC_MK48TXX_DAY_CB            0x80
-
-#define TODC_DS1501_CNTL_B_TE          0x80
-
-/*
- * Define flag bits used by todc routines.
- */
-#define TODC_FLAG_2_LEVEL_NVRAM                0x00000001
-
-/*
- * Define the values for the various RTC's that should to into the todc_info
- * table.
- * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only
- * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set.
- */
-#define TODC_TYPE_MK48T35_NVRAM_SIZE           0x7ff8
-#define TODC_TYPE_MK48T35_SW_FLAGS             0
-#define TODC_TYPE_MK48T35_YEAR                 0x7fff
-#define TODC_TYPE_MK48T35_MONTH                        0x7ffe
-#define TODC_TYPE_MK48T35_DOM                  0x7ffd  /* Day of Month */
-#define TODC_TYPE_MK48T35_DOW                  0x7ffc  /* Day of Week */
-#define TODC_TYPE_MK48T35_HOURS                        0x7ffb
-#define TODC_TYPE_MK48T35_MINUTES              0x7ffa
-#define TODC_TYPE_MK48T35_SECONDS              0x7ff9
-#define TODC_TYPE_MK48T35_CNTL_B               0x7ff9
-#define TODC_TYPE_MK48T35_CNTL_A               0x7ff8
-#define TODC_TYPE_MK48T35_WATCHDOG             0x0000
-#define TODC_TYPE_MK48T35_INTERRUPTS           0x0000
-#define TODC_TYPE_MK48T35_ALARM_DATE           0x0000
-#define TODC_TYPE_MK48T35_ALARM_HOUR           0x0000
-#define TODC_TYPE_MK48T35_ALARM_MINUTES                0x0000
-#define TODC_TYPE_MK48T35_ALARM_SECONDS                0x0000
-#define TODC_TYPE_MK48T35_CENTURY              0x0000
-#define TODC_TYPE_MK48T35_FLAGS                        0x0000
-#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG       0
-#define TODC_TYPE_MK48T35_NVRAM_DATA_REG       0
-
-#define TODC_TYPE_MK48T37_NVRAM_SIZE           0x7ff0
-#define TODC_TYPE_MK48T37_SW_FLAGS             0
-#define TODC_TYPE_MK48T37_YEAR                 0x7fff
-#define TODC_TYPE_MK48T37_MONTH                        0x7ffe
-#define TODC_TYPE_MK48T37_DOM                  0x7ffd  /* Day of Month */
-#define TODC_TYPE_MK48T37_DOW                  0x7ffc  /* Day of Week */
-#define TODC_TYPE_MK48T37_HOURS                        0x7ffb
-#define TODC_TYPE_MK48T37_MINUTES              0x7ffa
-#define TODC_TYPE_MK48T37_SECONDS              0x7ff9
-#define TODC_TYPE_MK48T37_CNTL_B               0x7ff9
-#define TODC_TYPE_MK48T37_CNTL_A               0x7ff8
-#define TODC_TYPE_MK48T37_WATCHDOG             0x7ff7
-#define TODC_TYPE_MK48T37_INTERRUPTS           0x7ff6
-#define TODC_TYPE_MK48T37_ALARM_DATE           0x7ff5
-#define TODC_TYPE_MK48T37_ALARM_HOUR           0x7ff4
-#define TODC_TYPE_MK48T37_ALARM_MINUTES                0x7ff3
-#define TODC_TYPE_MK48T37_ALARM_SECONDS                0x7ff2
-#define TODC_TYPE_MK48T37_CENTURY              0x7ff1
-#define TODC_TYPE_MK48T37_FLAGS                        0x7ff0
-#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG       0
-#define TODC_TYPE_MK48T37_NVRAM_DATA_REG       0
-
-#define TODC_TYPE_MK48T59_NVRAM_SIZE           0x1ff0
-#define TODC_TYPE_MK48T59_SW_FLAGS             0
-#define TODC_TYPE_MK48T59_YEAR                 0x1fff
-#define TODC_TYPE_MK48T59_MONTH                        0x1ffe
-#define TODC_TYPE_MK48T59_DOM                  0x1ffd  /* Day of Month */
-#define TODC_TYPE_MK48T59_DOW                  0x1ffc  /* Day of Week */
-#define TODC_TYPE_MK48T59_HOURS                        0x1ffb
-#define TODC_TYPE_MK48T59_MINUTES              0x1ffa
-#define TODC_TYPE_MK48T59_SECONDS              0x1ff9
-#define TODC_TYPE_MK48T59_CNTL_B               0x1ff9
-#define TODC_TYPE_MK48T59_CNTL_A               0x1ff8
-#define TODC_TYPE_MK48T59_WATCHDOG             0x1fff
-#define TODC_TYPE_MK48T59_INTERRUPTS           0x1fff
-#define TODC_TYPE_MK48T59_ALARM_DATE           0x1fff
-#define TODC_TYPE_MK48T59_ALARM_HOUR           0x1fff
-#define TODC_TYPE_MK48T59_ALARM_MINUTES                0x1fff
-#define TODC_TYPE_MK48T59_ALARM_SECONDS                0x1fff
-#define TODC_TYPE_MK48T59_CENTURY              0x1fff
-#define TODC_TYPE_MK48T59_FLAGS                        0x1fff
-#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG       0
-#define TODC_TYPE_MK48T59_NVRAM_DATA_REG       0
-
-#define TODC_TYPE_DS1501_NVRAM_SIZE    0x100
-#define TODC_TYPE_DS1501_SW_FLAGS      TODC_FLAG_2_LEVEL_NVRAM
-#define TODC_TYPE_DS1501_YEAR          (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06)
-#define TODC_TYPE_DS1501_MONTH         (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05)
-#define TODC_TYPE_DS1501_DOM           (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04)
-#define TODC_TYPE_DS1501_DOW           (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03)
-#define TODC_TYPE_DS1501_HOURS         (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02)
-#define TODC_TYPE_DS1501_MINUTES       (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01)
-#define TODC_TYPE_DS1501_SECONDS       (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00)
-#define TODC_TYPE_DS1501_CNTL_B                (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
-#define TODC_TYPE_DS1501_CNTL_A                (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
-#define TODC_TYPE_DS1501_WATCHDOG      (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
-#define TODC_TYPE_DS1501_INTERRUPTS    (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
-#define TODC_TYPE_DS1501_ALARM_DATE    (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b)
-#define TODC_TYPE_DS1501_ALARM_HOUR    (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a)
-#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09)
-#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08)
-#define TODC_TYPE_DS1501_CENTURY       (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07)
-#define TODC_TYPE_DS1501_FLAGS         (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
-#define TODC_TYPE_DS1501_NVRAM_ADDR_REG        0x10
-#define TODC_TYPE_DS1501_NVRAM_DATA_REG        0x13
-
-#define TODC_TYPE_DS1553_NVRAM_SIZE            0x1ff0
-#define TODC_TYPE_DS1553_SW_FLAGS              0
-#define TODC_TYPE_DS1553_YEAR                  0x1fff
-#define TODC_TYPE_DS1553_MONTH                 0x1ffe
-#define TODC_TYPE_DS1553_DOM                   0x1ffd  /* Day of Month */
-#define TODC_TYPE_DS1553_DOW                   0x1ffc  /* Day of Week */
-#define TODC_TYPE_DS1553_HOURS                 0x1ffb
-#define TODC_TYPE_DS1553_MINUTES               0x1ffa
-#define TODC_TYPE_DS1553_SECONDS               0x1ff9
-#define TODC_TYPE_DS1553_CNTL_B                        0x1ff9
-#define TODC_TYPE_DS1553_CNTL_A                        0x1ff8  /* control_a R/W regs */
-#define TODC_TYPE_DS1553_WATCHDOG              0x1ff7
-#define TODC_TYPE_DS1553_INTERRUPTS            0x1ff6
-#define TODC_TYPE_DS1553_ALARM_DATE            0x1ff5
-#define TODC_TYPE_DS1553_ALARM_HOUR            0x1ff4
-#define TODC_TYPE_DS1553_ALARM_MINUTES         0x1ff3
-#define TODC_TYPE_DS1553_ALARM_SECONDS         0x1ff2
-#define TODC_TYPE_DS1553_CENTURY               0x1ff8
-#define TODC_TYPE_DS1553_FLAGS                 0x1ff0
-#define TODC_TYPE_DS1553_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1553_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS1557_NVRAM_SIZE            0x7fff0
-#define TODC_TYPE_DS1557_SW_FLAGS              0
-#define TODC_TYPE_DS1557_YEAR                  0x7ffff
-#define TODC_TYPE_DS1557_MONTH                 0x7fffe
-#define TODC_TYPE_DS1557_DOM                   0x7fffd /* Day of Month */
-#define TODC_TYPE_DS1557_DOW                   0x7fffc /* Day of Week */
-#define TODC_TYPE_DS1557_HOURS                 0x7fffb
-#define TODC_TYPE_DS1557_MINUTES               0x7fffa
-#define TODC_TYPE_DS1557_SECONDS               0x7fff9
-#define TODC_TYPE_DS1557_CNTL_B                        0x7fff9
-#define TODC_TYPE_DS1557_CNTL_A                        0x7fff8 /* control_a R/W regs */
-#define TODC_TYPE_DS1557_WATCHDOG              0x7fff7
-#define TODC_TYPE_DS1557_INTERRUPTS            0x7fff6
-#define TODC_TYPE_DS1557_ALARM_DATE            0x7fff5
-#define TODC_TYPE_DS1557_ALARM_HOUR            0x7fff4
-#define TODC_TYPE_DS1557_ALARM_MINUTES         0x7fff3
-#define TODC_TYPE_DS1557_ALARM_SECONDS         0x7fff2
-#define TODC_TYPE_DS1557_CENTURY               0x7fff8
-#define TODC_TYPE_DS1557_FLAGS                 0x7fff0
-#define TODC_TYPE_DS1557_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1557_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS1643_NVRAM_SIZE            0x1ff8
-#define TODC_TYPE_DS1643_SW_FLAGS              0
-#define TODC_TYPE_DS1643_YEAR                  0x1fff
-#define TODC_TYPE_DS1643_MONTH                 0x1ffe
-#define TODC_TYPE_DS1643_DOM                   0x1ffd  /* Day of Month */
-#define TODC_TYPE_DS1643_DOW                   0x1ffc  /* Day of Week */
-#define TODC_TYPE_DS1643_HOURS                 0x1ffb
-#define TODC_TYPE_DS1643_MINUTES               0x1ffa
-#define TODC_TYPE_DS1643_SECONDS               0x1ff9
-#define TODC_TYPE_DS1643_CNTL_B                        0x1ff9
-#define TODC_TYPE_DS1643_CNTL_A                        0x1ff8  /* control_a R/W regs */
-#define TODC_TYPE_DS1643_WATCHDOG              0x1fff
-#define TODC_TYPE_DS1643_INTERRUPTS            0x1fff
-#define TODC_TYPE_DS1643_ALARM_DATE            0x1fff
-#define TODC_TYPE_DS1643_ALARM_HOUR            0x1fff
-#define TODC_TYPE_DS1643_ALARM_MINUTES         0x1fff
-#define TODC_TYPE_DS1643_ALARM_SECONDS         0x1fff
-#define TODC_TYPE_DS1643_CENTURY               0x1ff8
-#define TODC_TYPE_DS1643_FLAGS                 0x1fff
-#define TODC_TYPE_DS1643_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1643_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS1693_NVRAM_SIZE            0 /* Not handled yet */
-#define TODC_TYPE_DS1693_SW_FLAGS              0
-#define TODC_TYPE_DS1693_YEAR                  0x09
-#define TODC_TYPE_DS1693_MONTH                 0x08
-#define TODC_TYPE_DS1693_DOM                   0x07    /* Day of Month */
-#define TODC_TYPE_DS1693_DOW                   0x06    /* Day of Week */
-#define TODC_TYPE_DS1693_HOURS                 0x04
-#define TODC_TYPE_DS1693_MINUTES               0x02
-#define TODC_TYPE_DS1693_SECONDS               0x00
-#define TODC_TYPE_DS1693_CNTL_B                        0x0b
-#define TODC_TYPE_DS1693_CNTL_A                        0x0a
-#define TODC_TYPE_DS1693_WATCHDOG              0xff
-#define TODC_TYPE_DS1693_INTERRUPTS            0xff
-#define TODC_TYPE_DS1693_ALARM_DATE            0x49
-#define TODC_TYPE_DS1693_ALARM_HOUR            0x05
-#define TODC_TYPE_DS1693_ALARM_MINUTES         0x03
-#define TODC_TYPE_DS1693_ALARM_SECONDS         0x01
-#define TODC_TYPE_DS1693_CENTURY               0x48
-#define TODC_TYPE_DS1693_FLAGS                 0xff
-#define TODC_TYPE_DS1693_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1693_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS1743_NVRAM_SIZE            0x1ff8
-#define TODC_TYPE_DS1743_SW_FLAGS              0
-#define TODC_TYPE_DS1743_YEAR                  0x1fff
-#define TODC_TYPE_DS1743_MONTH                 0x1ffe
-#define TODC_TYPE_DS1743_DOM                   0x1ffd  /* Day of Month */
-#define TODC_TYPE_DS1743_DOW                   0x1ffc  /* Day of Week */
-#define TODC_TYPE_DS1743_HOURS                 0x1ffb
-#define TODC_TYPE_DS1743_MINUTES               0x1ffa
-#define TODC_TYPE_DS1743_SECONDS               0x1ff9
-#define TODC_TYPE_DS1743_CNTL_B                        0x1ff9
-#define TODC_TYPE_DS1743_CNTL_A                        0x1ff8  /* control_a R/W regs */
-#define TODC_TYPE_DS1743_WATCHDOG              0x1fff
-#define TODC_TYPE_DS1743_INTERRUPTS            0x1fff
-#define TODC_TYPE_DS1743_ALARM_DATE            0x1fff
-#define TODC_TYPE_DS1743_ALARM_HOUR            0x1fff
-#define TODC_TYPE_DS1743_ALARM_MINUTES         0x1fff
-#define TODC_TYPE_DS1743_ALARM_SECONDS         0x1fff
-#define TODC_TYPE_DS1743_CENTURY               0x1ff8
-#define TODC_TYPE_DS1743_FLAGS                 0x1fff
-#define TODC_TYPE_DS1743_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1743_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS1746_NVRAM_SIZE            0x1fff8
-#define TODC_TYPE_DS1746_SW_FLAGS              0
-#define TODC_TYPE_DS1746_YEAR                  0x1ffff
-#define TODC_TYPE_DS1746_MONTH                 0x1fffe
-#define TODC_TYPE_DS1746_DOM                   0x1fffd /* Day of Month */
-#define TODC_TYPE_DS1746_DOW                   0x1fffc /* Day of Week */
-#define TODC_TYPE_DS1746_HOURS                 0x1fffb
-#define TODC_TYPE_DS1746_MINUTES               0x1fffa
-#define TODC_TYPE_DS1746_SECONDS               0x1fff9
-#define TODC_TYPE_DS1746_CNTL_B                        0x1fff9
-#define TODC_TYPE_DS1746_CNTL_A                        0x1fff8 /* control_a R/W regs */
-#define TODC_TYPE_DS1746_WATCHDOG              0x00000
-#define TODC_TYPE_DS1746_INTERRUPTS            0x00000
-#define TODC_TYPE_DS1746_ALARM_DATE            0x00000
-#define TODC_TYPE_DS1746_ALARM_HOUR            0x00000
-#define TODC_TYPE_DS1746_ALARM_MINUTES         0x00000
-#define TODC_TYPE_DS1746_ALARM_SECONDS         0x00000
-#define TODC_TYPE_DS1746_CENTURY               0x00000
-#define TODC_TYPE_DS1746_FLAGS                 0x00000
-#define TODC_TYPE_DS1746_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1746_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS1747_NVRAM_SIZE            0x7fff8
-#define TODC_TYPE_DS1747_SW_FLAGS              0
-#define TODC_TYPE_DS1747_YEAR                  0x7ffff
-#define TODC_TYPE_DS1747_MONTH                 0x7fffe
-#define TODC_TYPE_DS1747_DOM                   0x7fffd /* Day of Month */
-#define TODC_TYPE_DS1747_DOW                   0x7fffc /* Day of Week */
-#define TODC_TYPE_DS1747_HOURS                 0x7fffb
-#define TODC_TYPE_DS1747_MINUTES               0x7fffa
-#define TODC_TYPE_DS1747_SECONDS               0x7fff9
-#define TODC_TYPE_DS1747_CNTL_B                        0x7fff9
-#define TODC_TYPE_DS1747_CNTL_A                        0x7fff8 /* control_a R/W regs */
-#define TODC_TYPE_DS1747_WATCHDOG              0x00000
-#define TODC_TYPE_DS1747_INTERRUPTS            0x00000
-#define TODC_TYPE_DS1747_ALARM_DATE            0x00000
-#define TODC_TYPE_DS1747_ALARM_HOUR            0x00000
-#define TODC_TYPE_DS1747_ALARM_MINUTES         0x00000
-#define TODC_TYPE_DS1747_ALARM_SECONDS         0x00000
-#define TODC_TYPE_DS1747_CENTURY               0x00000
-#define TODC_TYPE_DS1747_FLAGS                 0x00000
-#define TODC_TYPE_DS1747_NVRAM_ADDR_REG                0
-#define TODC_TYPE_DS1747_NVRAM_DATA_REG                0
-
-#define TODC_TYPE_DS17285_NVRAM_SIZE           (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */
-#define TODC_TYPE_DS17285_SW_FLAGS             TODC_FLAG_2_LEVEL_NVRAM
-#define TODC_TYPE_DS17285_SECONDS              (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00)
-#define TODC_TYPE_DS17285_ALARM_SECONDS                (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01)
-#define TODC_TYPE_DS17285_MINUTES              (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02)
-#define TODC_TYPE_DS17285_ALARM_MINUTES                (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03)
-#define TODC_TYPE_DS17285_HOURS                        (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04)
-#define TODC_TYPE_DS17285_ALARM_HOUR           (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05)
-#define TODC_TYPE_DS17285_DOW                  (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06)
-#define TODC_TYPE_DS17285_DOM                  (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07)
-#define TODC_TYPE_DS17285_MONTH                        (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08)
-#define TODC_TYPE_DS17285_YEAR                 (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09)
-#define TODC_TYPE_DS17285_CNTL_A               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A)
-#define TODC_TYPE_DS17285_CNTL_B               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B)
-#define TODC_TYPE_DS17285_CNTL_C               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C)
-#define TODC_TYPE_DS17285_CNTL_D               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D)
-#define TODC_TYPE_DS17285_WATCHDOG             0
-#define TODC_TYPE_DS17285_INTERRUPTS           0
-#define TODC_TYPE_DS17285_ALARM_DATE           0
-#define TODC_TYPE_DS17285_CENTURY              0
-#define TODC_TYPE_DS17285_FLAGS                        0
-#define TODC_TYPE_DS17285_NVRAM_ADDR_REG       0x50
-#define TODC_TYPE_DS17285_NVRAM_DATA_REG       0x53
-
-#define TODC_TYPE_MC146818_NVRAM_SIZE          0       /* XXXX */
-#define TODC_TYPE_MC146818_SW_FLAGS            0
-#define TODC_TYPE_MC146818_YEAR                        0x09
-#define TODC_TYPE_MC146818_MONTH               0x08
-#define TODC_TYPE_MC146818_DOM                 0x07    /* Day of Month */
-#define TODC_TYPE_MC146818_DOW                 0x06    /* Day of Week */
-#define TODC_TYPE_MC146818_HOURS               0x04
-#define TODC_TYPE_MC146818_MINUTES             0x02
-#define TODC_TYPE_MC146818_SECONDS             0x00
-#define TODC_TYPE_MC146818_CNTL_B              0x0a
-#define TODC_TYPE_MC146818_CNTL_A              0x0b    /* control_a R/W regs */
-#define TODC_TYPE_MC146818_WATCHDOG            0
-#define TODC_TYPE_MC146818_INTERRUPTS          0x0c
-#define TODC_TYPE_MC146818_ALARM_DATE          0xff
-#define TODC_TYPE_MC146818_ALARM_HOUR          0x05
-#define TODC_TYPE_MC146818_ALARM_MINUTES       0x03
-#define TODC_TYPE_MC146818_ALARM_SECONDS       0x01
-#define TODC_TYPE_MC146818_CENTURY             0xff
-#define TODC_TYPE_MC146818_FLAGS               0xff
-#define TODC_TYPE_MC146818_NVRAM_ADDR_REG      0
-#define TODC_TYPE_MC146818_NVRAM_DATA_REG      0
-
-#define TODC_TYPE_PC97307_NVRAM_SIZE           0       /* No NVRAM? */
-#define TODC_TYPE_PC97307_SW_FLAGS             0
-#define TODC_TYPE_PC97307_YEAR                 0x09
-#define TODC_TYPE_PC97307_MONTH                        0x08
-#define TODC_TYPE_PC97307_DOM                  0x07    /* Day of Month */
-#define TODC_TYPE_PC97307_DOW                  0x06    /* Day of Week */
-#define TODC_TYPE_PC97307_HOURS                        0x04
-#define TODC_TYPE_PC97307_MINUTES              0x02
-#define TODC_TYPE_PC97307_SECONDS              0x00
-#define TODC_TYPE_PC97307_CNTL_B               0x0a
-#define TODC_TYPE_PC97307_CNTL_A               0x0b    /* control_a R/W regs */
-#define TODC_TYPE_PC97307_WATCHDOG             0x0c
-#define TODC_TYPE_PC97307_INTERRUPTS           0x0d
-#define TODC_TYPE_PC97307_ALARM_DATE           0xff
-#define TODC_TYPE_PC97307_ALARM_HOUR           0x05
-#define TODC_TYPE_PC97307_ALARM_MINUTES                0x03
-#define TODC_TYPE_PC97307_ALARM_SECONDS                0x01
-#define TODC_TYPE_PC97307_CENTURY              0xff
-#define TODC_TYPE_PC97307_FLAGS                        0xff
-#define TODC_TYPE_PC97307_NVRAM_ADDR_REG       0
-#define TODC_TYPE_PC97307_NVRAM_DATA_REG       0
-
-/*
- * Define macros to allocate and init the todc_info_t table that will
- * be used by the todc_time.c routines.
- */
-#define TODC_ALLOC()                                                   \
-       static todc_info_t todc_info_alloc;                             \
-       todc_info_t *todc_info = &todc_info_alloc;
-
-#define TODC_INIT(clock_type, as0, as1, data, bits) {                  \
-       todc_info->rtc_type = clock_type;                               \
-                                                                       \
-       todc_info->nvram_as0 = (unsigned int)(as0);                     \
-       todc_info->nvram_as1 = (unsigned int)(as1);                     \
-       todc_info->nvram_data = (unsigned int)(data);                   \
-                                                                       \
-       todc_info->as0_bits = (bits);                                   \
-                                                                       \
-       todc_info->nvram_size = clock_type ##_NVRAM_SIZE;               \
-       todc_info->sw_flags = clock_type ##_SW_FLAGS;                   \
-                                                                       \
-       todc_info->year = clock_type ##_YEAR;                           \
-       todc_info->month = clock_type ##_MONTH;                         \
-       todc_info->day_of_month = clock_type ##_DOM;                    \
-       todc_info->day_of_week = clock_type ##_DOW;                     \
-       todc_info->hours = clock_type ##_HOURS;                         \
-       todc_info->minutes = clock_type ##_MINUTES;                     \
-       todc_info->seconds = clock_type ##_SECONDS;                     \
-       todc_info->control_b = clock_type ##_CNTL_B;                    \
-       todc_info->control_a = clock_type ##_CNTL_A;                    \
-       todc_info->watchdog = clock_type ##_WATCHDOG;                   \
-       todc_info->interrupts = clock_type ##_INTERRUPTS;               \
-       todc_info->alarm_date = clock_type ##_ALARM_DATE;               \
-       todc_info->alarm_hour = clock_type ##_ALARM_HOUR;               \
-       todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES;         \
-       todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS;         \
-       todc_info->century = clock_type ##_CENTURY;                     \
-       todc_info->flags = clock_type ##_FLAGS;                         \
-                                                                       \
-       todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG;       \
-       todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG;       \
-}
-
-extern todc_info_t *todc_info;
-
-unsigned char todc_direct_read_val(int addr);
-void todc_direct_write_val(int addr, unsigned char val);
-unsigned char todc_m48txx_read_val(int addr);
-void todc_m48txx_write_val(int addr, unsigned char val);
-unsigned char todc_mc146818_read_val(int addr);
-void todc_mc146818_write_val(int addr, unsigned char val);
-
-long todc_time_init(void);
-void todc_get_rtc_time(struct rtc_time *);
-int todc_set_rtc_time(struct rtc_time *);
-void todc_calibrate_decr(void);
-
-#endif                         /* __PPC_KERNEL_TODC_H */
index f1d337e..88320a0 100644 (file)
 
 #ifdef CONFIG_XMON
 extern void xmon_setup(void);
+extern void xmon_register_spus(struct list_head *list);
 #else
 static inline void xmon_setup(void) { };
+static inline void xmon_register_spus(struct list_head *list) { };
 #endif
 
 #endif /* __KERNEL __ */
index a4c411b..b744baf 100644 (file)
 
 #if defined(CONFIG_4xx)
 #include <asm/ibm4xx.h>
-#elif defined(CONFIG_PPC_MPC52xx)
-#include <asm/mpc52xx.h>
 #elif defined(CONFIG_8xx)
 #include <asm/mpc8xx.h>
 #elif defined(CONFIG_8260)
 #include <asm/mpc8260.h>
-#elif defined(CONFIG_83xx)
-#include <asm/mpc83xx.h>
-#elif defined(CONFIG_85xx)
-#include <asm/mpc85xx.h>
-#elif defined(CONFIG_APUS)
+#elif defined(CONFIG_APUS) || !defined(CONFIG_PCI)
 #define _IO_BASE       0
 #define _ISA_MEM_BASE  0
 #define PCI_DRAM_OFFSET 0
index 64c8874..d9d21aa 100644 (file)
@@ -29,17 +29,6 @@ struct pt_regs;
 #endif /* __ASSEMBLY__ */
 
 
-#ifdef CONFIG_PCI
-#define _IO_BASE       isa_io_base
-#define _ISA_MEM_BASE  isa_mem_base
-#define PCI_DRAM_OFFSET        pci_dram_offset
-#else
-#define _IO_BASE       0
-#define _ISA_MEM_BASE  0
-#define PCI_DRAM_OFFSET        0
-#endif
-
-
 /* ======================================================================== */
 /* PPC Sys devices definition                                               */
 /* ======================================================================== */
index 02ed2c3..c306197 100644 (file)
 #include <platforms/83xx/mpc834x_sys.h>
 #endif
 
-#define _IO_BASE        isa_io_base
-#define _ISA_MEM_BASE   isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#else
-#define PCI_DRAM_OFFSET 0
-#endif
-
 /*
  * The "residual" board information structure the boot loader passes
  * into the kernel.
index 9b48511..d7e4a79 100644 (file)
 #include <platforms/85xx/tqm85xx.h>
 #endif
 
-#define _IO_BASE        isa_io_base
-#define _ISA_MEM_BASE   isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#else
-#define PCI_DRAM_OFFSET 0
-#endif
-
 /*
  * The "residual" board information structure the boot loader passes
  * into the kernel.
index 3fef7d6..f02d71b 100644 (file)
@@ -33,6 +33,14 @@ struct cpu {
 
 extern int register_cpu(struct cpu *cpu, int num);
 extern struct sys_device *get_cpu_sysdev(unsigned cpu);
+
+extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr);
+extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr);
+
+extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs);
+extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs);
+
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern void unregister_cpu(struct cpu *cpu);
 #endif