summaryrefslogtreecommitdiff
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@tango.paulus.ozlabs.org>2002-02-11 20:41:44 +1100
committerPaul Mackerras <paulus@tango.paulus.ozlabs.org>2002-02-11 20:41:44 +1100
commitdb7bfdb0276574b29618179004ced1de8dcf40c0 (patch)
treef65179bd228616f902065bc92a96ad394f4b0097 /arch/ppc/kernel
parent0dc68d77428413d0f417df3a378f857a2e798ebf (diff)
Import arch/ppc and include/asm-ppc changes from linuxppc_2_5 tree
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile86
-rw-r--r--arch/ppc/kernel/align.c10
-rw-r--r--arch/ppc/kernel/apus_pci.c187
-rw-r--r--arch/ppc/kernel/apus_pci.h40
-rw-r--r--arch/ppc/kernel/apus_setup.c1113
-rw-r--r--arch/ppc/kernel/bitops.c32
-rw-r--r--arch/ppc/kernel/btext.c205
-rw-r--r--arch/ppc/kernel/chrp_pci.c330
-rw-r--r--arch/ppc/kernel/chrp_setup.c634
-rw-r--r--arch/ppc/kernel/chrp_smp.c149
-rw-r--r--arch/ppc/kernel/chrp_time.c195
-rw-r--r--arch/ppc/kernel/cputable.c75
-rw-r--r--arch/ppc/kernel/entry.S175
-rw-r--r--arch/ppc/kernel/error_log.c186
-rw-r--r--arch/ppc/kernel/error_log.h98
-rw-r--r--arch/ppc/kernel/feature.c1300
-rw-r--r--arch/ppc/kernel/galaxy_pci.c5
-rw-r--r--arch/ppc/kernel/gemini_pci.c124
-rw-r--r--arch/ppc/kernel/gemini_prom.S99
-rw-r--r--arch/ppc/kernel/gemini_setup.c584
-rw-r--r--arch/ppc/kernel/gt64260_common.c1666
-rw-r--r--arch/ppc/kernel/gt64260_pic.c245
-rw-r--r--arch/ppc/kernel/harrier.c214
-rw-r--r--arch/ppc/kernel/head.S263
-rw-r--r--arch/ppc/kernel/head_4xx.S1200
-rw-r--r--arch/ppc/kernel/head_8xx.S96
-rw-r--r--arch/ppc/kernel/i8259.c222
-rw-r--r--arch/ppc/kernel/i8259.h15
-rw-r--r--arch/ppc/kernel/iSeries_asm.h62
-rw-r--r--arch/ppc/kernel/iSeries_head.S1512
-rw-r--r--arch/ppc/kernel/iSeries_misc.S469
-rw-r--r--arch/ppc/kernel/idle.c114
-rw-r--r--arch/ppc/kernel/indirect_pci.c10
-rw-r--r--arch/ppc/kernel/irq.c93
-rw-r--r--arch/ppc/kernel/l2cr.S30
-rw-r--r--arch/ppc/kernel/local_irq.h22
-rw-r--r--arch/ppc/kernel/m8260_setup.c37
-rw-r--r--arch/ppc/kernel/m8xx_setup.c41
-rw-r--r--arch/ppc/kernel/misc.S183
-rw-r--r--arch/ppc/kernel/mk_defs.c51
-rw-r--r--arch/ppc/kernel/mpc10x_common.c378
-rw-r--r--arch/ppc/kernel/oak_setup.c297
-rw-r--r--arch/ppc/kernel/oak_setup.h53
-rw-r--r--arch/ppc/kernel/open_pic.c196
-rw-r--r--arch/ppc/kernel/open_pic.h68
-rw-r--r--arch/ppc/kernel/open_pic_defs.h10
-rw-r--r--arch/ppc/kernel/pci-dma.c10
-rw-r--r--arch/ppc/kernel/pci.c427
-rw-r--r--arch/ppc/kernel/pci.h27
-rw-r--r--arch/ppc/kernel/pci_auto.c519
-rw-r--r--arch/ppc/kernel/pmac_backlight.c150
-rw-r--r--arch/ppc/kernel/pmac_nvram.c402
-rw-r--r--arch/ppc/kernel/pmac_pci.c626
-rw-r--r--arch/ppc/kernel/pmac_pic.c496
-rw-r--r--arch/ppc/kernel/pmac_pic.h14
-rw-r--r--arch/ppc/kernel/pmac_setup.c838
-rw-r--r--arch/ppc/kernel/pmac_smp.c489
-rw-r--r--arch/ppc/kernel/pmac_time.c286
-rw-r--r--arch/ppc/kernel/ppc-stub.c248
-rwxr-xr-xarch/ppc/kernel/ppc405_dma.c511
-rwxr-xr-xarch/ppc/kernel/ppc405_pci.c207
-rw-r--r--arch/ppc/kernel/ppc4xx_kgdb.c124
-rw-r--r--arch/ppc/kernel/ppc4xx_pic.c221
-rw-r--r--arch/ppc/kernel/ppc4xx_pic.h30
-rw-r--r--arch/ppc/kernel/ppc4xx_pm.c75
-rwxr-xr-xarch/ppc/kernel/ppc4xx_serial.c190
-rwxr-xr-xarch/ppc/kernel/ppc4xx_setup.c415
-rw-r--r--arch/ppc/kernel/ppc8260_pic.c22
-rw-r--r--arch/ppc/kernel/ppc8260_pic.h4
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.c41
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.h6
-rw-r--r--arch/ppc/kernel/ppc_asm.h158
-rw-r--r--arch/ppc/kernel/ppc_asm.tmpl115
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c73
-rw-r--r--arch/ppc/kernel/pplus_common.c317
-rw-r--r--arch/ppc/kernel/prep_nvram.c143
-rw-r--r--arch/ppc/kernel/prep_pci.c1249
-rw-r--r--arch/ppc/kernel/prep_setup.c927
-rw-r--r--arch/ppc/kernel/prep_time.c228
-rw-r--r--arch/ppc/kernel/proc_rtas.c787
-rw-r--r--arch/ppc/kernel/process.c67
-rw-r--r--arch/ppc/kernel/prom.c1167
-rw-r--r--arch/ppc/kernel/prom_init.c899
-rw-r--r--arch/ppc/kernel/ptrace.c115
-rw-r--r--arch/ppc/kernel/qspan_pci.c5
-rw-r--r--arch/ppc/kernel/residual.c878
-rw-r--r--arch/ppc/kernel/semaphore.c3
-rw-r--r--arch/ppc/kernel/setup.c142
-rw-r--r--arch/ppc/kernel/signal.c21
-rw-r--r--arch/ppc/kernel/sleep.S366
-rw-r--r--arch/ppc/kernel/smp.c39
-rw-r--r--arch/ppc/kernel/softemu8xx.c9
-rw-r--r--arch/ppc/kernel/time.c78
-rw-r--r--arch/ppc/kernel/todc_time.c456
-rw-r--r--arch/ppc/kernel/traps.c157
-rw-r--r--arch/ppc/kernel/walnut_setup.c292
-rw-r--r--arch/ppc/kernel/walnut_setup.h53
-rw-r--r--arch/ppc/kernel/xics.c217
-rw-r--r--arch/ppc/kernel/xics.h26
99 files changed, 11750 insertions, 16789 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 59236099d7a9..d00aacf316d8 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.34 10/16/01 15:58:42 trini
+# BK Id: %F% %I% %G% %U% %#%
#
#
# Makefile for the linux kernel.
@@ -14,17 +14,24 @@ USE_STANDARD_AS_RULE := true
ifdef CONFIG_PPC64BRIDGE
EXTRA_AFLAGS := -Wa,-mppc64bridge
endif
+ifdef CONFIG_4xx
+EXTRA_AFLAGS := -Wa,-m405
+endif
+
+CFLAGS_prom_init.o += -mrelocatable-lib
+CFLAGS_btext.o += -mrelocatable-lib
# Start off with 'head.o', change as needed.
HEAD-y := head.o
HEAD-$(CONFIG_4xx) := head_4xx.o
HEAD-$(CONFIG_8xx) := head_8xx.o
+HEAD-$(CONFIG_PPC_ISERIES) := iSeries_head.o
all: $(HEAD-y) kernel.o
O_TARGET := kernel.o
-export-objs := ppc_ksyms.o prep_setup.o time.o
+export-objs := ppc_ksyms.o time.o ppc405_dma.o
obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
process.o signal.o ptrace.o align.o \
@@ -32,16 +39,20 @@ obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
cputable.o ppc_htab.o
obj-$(CONFIG_6xx) += l2cr.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
-obj-$(CONFIG_POWER4) += xics.o
-obj-$(CONFIG_PCI) += pci.o pci-dma.o
+obj-$(CONFIG_PCI) += pci.o
+ifneq ($(CONFIG_PPC_ISERIES),y)
+obj-$(CONFIG_PCI) += pci-dma.o
+endif
obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_4xx) += ppc4xx_pic.o
-obj-$(CONFIG_OAK) += oak_setup.o
-obj-$(CONFIG_WALNUT) += walnut_setup.o
obj-$(CONFIG_TAU) += temp.o
-ifeq ($(CONFIG_WALNUT),y)
-obj-$(CONFIG_PCI) += galaxy_pci.o
+ifeq ($(CONFIG_4xx),y)
+obj-$(CONFIG_4xx) += ppc4xx_setup.o ppc4xx_pic.o ppc4xx_serial.o
+obj-$(CONFIG_PPC_RTC) += todc_time.o
+obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o
+obj-$(CONFIG_405_DMA) += ppc405_dma.o
+obj-$(CONFIG_PCI) += ppc405_pci.o indirect_pci.o pci_auto.o
+obj-$(CONFIG_PM) += ppc4xx_pm.o
endif
obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o
ifeq ($(CONFIG_8xx),y)
@@ -51,28 +62,41 @@ obj-y += softemu8xx.o
endif
endif
obj-$(CONFIG_MBX) += i8259.o
-obj-$(CONFIG_APUS) += apus_setup.o
-ifeq ($(CONFIG_APUS),y)
-obj-$(CONFIG_PCI) += apus_pci.o
-endif
-obj-$(CONFIG_ALL_PPC) += pmac_pic.o pmac_setup.o pmac_time.o prom.o \
- feature.o pmac_pci.o chrp_setup.o \
- chrp_time.o chrp_pci.o open_pic.o \
- indirect_pci.o i8259.o prep_pci.o \
- prep_time.o prep_nvram.o prep_setup.o
-obj-$(CONFIG_NVRAM) += pmac_nvram.o
-obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
-obj-$(CONFIG_PMAC_PBOOK) += sleep.o
-obj-$(CONFIG_PREP_RESIDUAL) += residual.o
-obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o
-obj-$(CONFIG_GEMINI) += gemini_prom.o gemini_pci.o gemini_setup.o \
- open_pic.o
+obj-$(CONFIG_ALL_PPC) += prom_init.o prom.o open_pic.o \
+ indirect_pci.o i8259.o
+obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
+ todc_time.o
+obj-$(CONFIG_EV64260) += gt64260_common.o gt64260_pic.o \
+ indirect_pci.o todc_time.o pci_auto.o
+obj-$(CONFIG_GEMINI) += open_pic.o
+obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
+ pci_auto.o
+obj-$(CONFIG_LOPEC) += mpc10x_common.o indirect_pci.o pci_auto.o \
+ open_pic.o i8259.o todc_time.o
+obj-$(CONFIG_MCPN765) += todc_time.o indirect_pci.o pci_auto.o \
+ open_pic.o i8259.o pplus_common.o
+obj-$(CONFIG_MENF1) += todc_time.o i8259.o mpc10x_common.o \
+ pci_auto.o indirect_pci.o
+obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \
+ i8259.o pci_auto.o pplus_common.o
+obj-$(CONFIG_PCORE) += mpc10x_common.o todc_time.o i8259.o \
+ indirect_pci.o pci_auto.o
+obj-$(CONFIG_POWERPMC250) += open_pic.o mpc10x_common.o \
+ indirect_pci.o pci_auto.o
+obj-$(CONFIG_PPLUS) += pplus_common.o open_pic.o i8259.o \
+ indirect_pci.o todc_time.o pci_auto.o
+obj-$(CONFIG_PRPMC750) += open_pic.o indirect_pci.o pci_auto.o \
+ pplus_common.o
+obj-$(CONFIG_PRPMC800) += open_pic.o indirect_pci.o pci_auto.o \
+ pplus_common.o harrier.o
+obj-$(CONFIG_SANDPOINT) += i8259.o open_pic.o mpc10x_common.o \
+ pci_auto.o indirect_pci.o todc_time.o
+obj-$(CONFIG_SPRUCE) += indirect_pci.o pci_auto.o todc_time.o
+obj-$(CONFIG_ZX4500) += indirect_pci.o pci_auto.o mpc10x_common.o \
+ i8259.o open_pic.o
obj-$(CONFIG_8260) += m8260_setup.o ppc8260_pic.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
-
-ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_ALL_PPC) += pmac_smp.o chrp_smp.o
-endif
+obj-$(CONFIG_PPC_ISERIES) += iSeries_misc.o
include $(TOPDIR)/Rules.make
@@ -82,7 +106,8 @@ l2cr.o: l2cr.S ppc_defs.h
head.o: head.S ppc_defs.h
head_4xx.o: head_4xx.S ppc_defs.h
head_8xx.o: head_8xx.S ppc_defs.h
-gemini_prom.o: gemini_prom.S ppc_defs.h
+iSeries_head.o: iSeries_head.S ppc_defs.h
+iSeries_misc.o: iSeries_misc.S ppc_defs.h
ppc_defs.h: mk_defs.c ppc_defs.head \
$(TOPDIR)/include/asm/mmu.h \
@@ -102,4 +127,3 @@ find_name : find_name.c
checks: checks.c
$(HOSTCC) -I$(HPATH) $(HOSTCFLAGS) -D__KERNEL__ -fno-builtin -o checks checks.c
./checks
-
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 4edb4616848c..0f8dbd1cb585 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.align.c 1.5 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* align.c - handle alignment exceptions for the Power PC.
@@ -24,7 +24,7 @@ struct aligninfo {
unsigned char flags;
};
-#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
+#if defined(CONFIG_4xx)
#define OPCD(inst) (((inst) & 0xFC000000) >> 26)
#define RS(inst) (((inst) & 0x03E00000) >> 21)
#define RA(inst) (((inst) & 0x001F0000) >> 16)
@@ -187,7 +187,7 @@ int
fix_alignment(struct pt_regs *regs)
{
int instr, nb, flags;
-#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
+#if defined(CONFIG_4xx)
int opcode, f1, f2, f3;
#endif
int i, t;
@@ -200,11 +200,9 @@ fix_alignment(struct pt_regs *regs)
unsigned char v[8];
} data;
-#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
+#if defined(CONFIG_4xx)
/* The 4xx-family processors have no DSISR register,
* so we emulate it.
- * The POWER4 has a DSISR register but doesn't set it on
- * an alignment fault. -- paulus
*/
instr = *((unsigned int *)regs->nip);
diff --git a/arch/ppc/kernel/apus_pci.c b/arch/ppc/kernel/apus_pci.c
deleted file mode 100644
index 95367ff771f5..000000000000
--- a/arch/ppc/kernel/apus_pci.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * BK Id: SCCS/s.apus_pci.c 1.5 09/08/01 15:47:42 paulus
- */
-/*
- * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
- *
- * APUS PCI routines.
- *
- * Currently, only B/CVisionPPC cards (Permedia2) are supported.
- *
- * Thanks to Geert Uytterhoeven for the idea:
- * Read values from given config space(s) for the first devices, -1 otherwise
- *
- */
-
-#include <linux/config.h>
-#ifdef CONFIG_AMIGA
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#include "apus_pci.h"
-
-
-/* These definitions are mostly adapted from pm2fb.c */
-
-#undef APUS_PCI_MASTER_DEBUG
-#ifdef APUS_PCI_MASTER_DEBUG
-#define DPRINTK(a,b...) printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b)
-#else
-#define DPRINTK(a,b...)
-#endif
-
-/*
- * The _DEFINITIVE_ memory mapping/unmapping functions.
- * This is due to the fact that they're changing soooo often...
- */
-#define DEFW() wmb()
-#define DEFR() rmb()
-#define DEFRW() mb()
-
-#define DEVNO(d) ((d)>>3)
-#define FNNO(d) ((d)&7)
-
-
-extern unsigned long powerup_PCI_present;
-
-static struct pci_controller *apus_hose;
-
-
-void *pci_io_base(unsigned int bus)
-{
- return 0;
-}
-
-
-#define cfg_read(val, addr, type, op) *val = op((type)(addr))
-#define cfg_write(val, addr, type, op) op((val), (type *)(addr)); DEFW()
-#define cfg_read_bad *val = ~0;
-#define cfg_write_bad ;
-#define cfg_read_val(val) *val
-#define cfg_write_val(val) val
-
-#define APUS_PCI_OP(rw, size, type, op, mask) \
-int \
-apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- int fnno = FNNO(dev->devfn); \
- int devno = DEVNO(dev->devfn); \
- \
- if (dev->bus->number > 0 || devno != 1) { \
- cfg_##rw##_bad; \
- return PCIBIOS_DEVICE_NOT_FOUND; \
- } \
- /* base address + function offset + offset ^ endianness conversion */ \
- cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask), \
- type, op); \
- \
- DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n", \
- dev->bus->number, dev->devfn>>3, dev->devfn&7, \
- offset, cfg_##rw##_val(val)); \
- return PCIBIOS_SUCCESSFUL; \
-}
-
-APUS_PCI_OP(read, byte, u8 *, readb, 3)
-APUS_PCI_OP(read, word, u16 *, readw, 2)
-APUS_PCI_OP(read, dword, u32 *, readl, 0)
-APUS_PCI_OP(write, byte, u8, writeb, 3)
-APUS_PCI_OP(write, word, u16, writew, 2)
-APUS_PCI_OP(write, dword, u32, writel, 0)
-
-
-static struct pci_ops apus_pci_ops = {
- apus_pcibios_read_config_byte,
- apus_pcibios_read_config_word,
- apus_pcibios_read_config_dword,
- apus_pcibios_write_config_byte,
- apus_pcibios_write_config_word,
- apus_pcibios_write_config_dword
-};
-
-static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
-
-void __init
-apus_pcibios_fixup(void)
-{
-/* struct pci_dev *dev = pci_find_slot(0, 1<<3);
- unsigned int reg, val, offset;*/
-
- /* FIXME: interrupt? */
- /*dev->interrupt = xxx;*/
-
- request_resource(&iomem_resource, &pci_mem);
- printk("%s: PCI mem resource requested\n", __FUNCTION__);
-}
-
-static void __init apus_pcibios_fixup_bus(struct pci_bus *bus)
-{
- bus->resource[1] = &pci_mem;
-}
-
-
-/*
- * This is from pm2fb.c again
- *
- * Check if PCI (B/CVisionPPC) is available, initialize it and set up
- * the pcibios_* pointers
- */
-
-
-void __init
-apus_setup_pci_ptrs(void)
-{
- if (!powerup_PCI_present) {
- DPRINTK("no PCI bridge detected\n");
- return;
- }
- DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n");
-
- apus_hose = pcibios_alloc_controller();
- if (!apus_hose) {
- printk("apus_pci: Can't allocate PCI controller structure\n");
- return;
- }
-
- if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) {
- printk("apus_pci: unable to map PCI config region\n");
- return;
- }
-
- if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) {
- printk("apus_pci: unable to map PCI bridge\n");
- return;
- }
-
- writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN);
- DEFW();
-
- writel(CVPPC_REGS_REGION, apus_hose->cfg_data+ PCI_BASE_ADDRESS_0);
- DEFW();
- writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1);
- DEFW();
- writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2);
- DEFW();
- writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS);
- DEFW();
-
- writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND);
- DEFW();
-
- apus_hose->first_busno = 0;
- apus_hose->last_busno = 0;
- apus_hose->ops = &apus_pci_ops;
- ppc_md.pcibios_fixup = apus_pcibios_fixup;
- ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus;
-
- return;
-}
-
-#endif /* CONFIG_AMIGA */
diff --git a/arch/ppc/kernel/apus_pci.h b/arch/ppc/kernel/apus_pci.h
deleted file mode 100644
index c245dcfce835..000000000000
--- a/arch/ppc/kernel/apus_pci.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * BK Id: SCCS/s.apus_pci.h 1.4 05/17/01 18:14:21 cort
- */
-/*
- * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
- * driver.
- *
- * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- * --------------------------------------------------------------------------
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
- */
-
-#ifndef APUS_PCI_H
-#define APUS_PCI_H
-
-
-#include "pci.h"
-
-
-#define CSPPC_PCI_BRIDGE 0xfffe0000
-#define CSPPC_BRIDGE_ENDIAN 0x0000
-#define CSPPC_BRIDGE_INT 0x0010
-
-#define CVPPC_PCI_CONFIG 0xfffc0000
-#define CVPPC_ROM_ADDRESS 0xe2000001
-#define CVPPC_REGS_REGION 0xef000000
-#define CVPPC_FB_APERTURE_ONE 0xe0000000
-#define CVPPC_FB_APERTURE_TWO 0xe1000000
-#define CVPPC_FB_SIZE 0x00800000
-
-/* CVPPC_BRIDGE_ENDIAN */
-#define CSPPCF_BRIDGE_BIG_ENDIAN 0x02
-
-/* CVPPC_BRIDGE_INT */
-#define CSPPCF_BRIDGE_ACTIVE_INT2 0x01
-
-
-#endif /* APUS_PCI_H */
diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c
deleted file mode 100644
index c3fe77cde972..000000000000
--- a/arch/ppc/kernel/apus_setup.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
- * BK Id: SCCS/s.apus_setup.c 1.24 11/13/01 21:26:07 paulus
- */
-/*
- * linux/arch/ppc/kernel/apus_setup.c
- *
- * Copyright (C) 1998, 1999 Jesper Skov
- *
- * Basically what is needed to replace functionality found in
- * arch/m68k allowing Amiga drivers to work under APUS.
- * Bits of code and/or ideas from arch/m68k and arch/ppc files.
- *
- * TODO:
- * This file needs a *really* good cleanup. Restructure and optimize.
- * Make sure it can be compiled for non-APUS configs. Begin to move
- * Amiga specific stuff into mach/amiga.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kd.h>
-#include <linux/init.h>
-#include <linux/hdreg.h>
-#include <linux/blk.h>
-#include <linux/pci.h>
-#include <linux/seq_file.h>
-
-#ifdef CONFIG_APUS
-#include <asm/logging.h>
-#endif
-
-/* Needs INITSERIAL call in head.S! */
-#undef APUS_DEBUG
-
-
-#include <linux/ide.h>
-#define T_CHAR (0x0000) /* char: don't touch */
-#define T_SHORT (0x4000) /* short: 12 -> 21 */
-#define T_INT (0x8000) /* int: 1234 -> 4321 */
-#define T_TEXT (0xc000) /* text: 12 -> 21 */
-
-#define T_MASK_TYPE (0xc000)
-#define T_MASK_COUNT (0x3fff)
-
-#define D_CHAR(cnt) (T_CHAR | (cnt))
-#define D_SHORT(cnt) (T_SHORT | (cnt))
-#define D_INT(cnt) (T_INT | (cnt))
-#define D_TEXT(cnt) (T_TEXT | (cnt))
-
-static u_short driveid_types[] = {
- D_SHORT(10), /* config - vendor2 */
- D_TEXT(20), /* serial_no */
- D_SHORT(3), /* buf_type, buf_size - ecc_bytes */
- D_TEXT(48), /* fw_rev - model */
- D_CHAR(2), /* max_multsect - vendor3 */
- D_SHORT(1), /* dword_io */
- D_CHAR(2), /* vendor4 - capability */
- D_SHORT(1), /* reserved50 */
- D_CHAR(4), /* vendor5 - tDMA */
- D_SHORT(4), /* field_valid - cur_sectors */
- D_INT(1), /* cur_capacity */
- D_CHAR(2), /* multsect - multsect_valid */
- D_INT(1), /* lba_capacity */
- D_SHORT(194) /* dma_1word - reservedyy */
-};
-
-#define num_driveid_types (sizeof(driveid_types)/sizeof(*driveid_types))
-
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/amigappc.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-
-#include "local_irq.h"
-
-unsigned long m68k_machtype;
-char debug_device[6] = "";
-
-extern void amiga_init_IRQ(void);
-
-void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
-/* machine dependent keyboard functions */
-int (*mach_keyb_init) (void) __initdata = NULL;
-int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
-void (*mach_kbd_leds) (unsigned int) = NULL;
-/* machine dependent irq functions */
-void (*mach_init_IRQ) (void) __initdata = NULL;
-void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-void (*mach_get_model) (char *model) = NULL;
-int (*mach_get_hardware_list) (char *buffer) = NULL;
-int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
-void (*mach_process_int) (int, struct pt_regs *) = NULL;
-/* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
-void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
-int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
-int (*mach_set_clock_mmss) (unsigned long) = NULL;
-void (*mach_reset)( void );
-long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#if defined(CONFIG_AMIGA_FLOPPY)
-void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
-#endif
-#ifdef CONFIG_HEARTBEAT
-void (*mach_heartbeat) (int) = NULL;
-extern void apus_heartbeat (void);
-#endif
-
-extern unsigned long amiga_model;
-extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
-extern unsigned count_period_num; /* 1 decrementer count equals */
-extern unsigned count_period_den; /* count_period_num / count_period_den us */
-
-int num_memory = 0;
-struct mem_info memory[NUM_MEMINFO];/* memory description */
-/* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
-int m68k_realnum_memory = 0;
-struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
-
-struct mem_info ramdisk;
-
-extern void amiga_floppy_setup(char *, int *);
-extern void config_amiga(void);
-
-static int __60nsram = 0;
-
-/* for cpuinfo */
-static int __bus_speed = 0;
-static int __speed_test_failed = 0;
-
-/********************************************** COMPILE PROTECTION */
-/* Provide some stubs that links to Amiga specific functions.
- * This allows CONFIG_APUS to be removed from generic PPC files while
- * preventing link errors for other PPC targets.
- */
-unsigned long apus_get_rtc_time(void)
-{
-#ifdef CONFIG_APUS
- extern unsigned long m68k_get_rtc_time(void);
-
- return m68k_get_rtc_time ();
-#else
- return 0;
-#endif
-}
-
-int apus_set_rtc_time(unsigned long nowtime)
-{
-#ifdef CONFIG_APUS
- extern int m68k_set_rtc_time(unsigned long nowtime);
-
- return m68k_set_rtc_time (nowtime);
-#else
- return 0;
-#endif
-}
-
-
-
-/* Here some functions we don't support, but which the other ports reference */
-int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
- return 0;
-}
-int pckbd_getkeycode(unsigned int scancode)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
- return 0;
-}
-int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
- return 0;
-}
-char pckbd_unexpected_up(unsigned char keycode)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
- return 0;
-}
-void pckbd_leds(unsigned char leds)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-}
-void pckbd_init_hw(void)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-}
-unsigned char pckbd_sysrq_xlate[128];
-
-struct pci_bus * __init pci_scan_peer_bridge(int bus)
-{
- printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
- return NULL;
-}
-
-/*********************************************************** SETUP */
-/* From arch/m68k/kernel/setup.c. */
-void __init apus_setup_arch(void)
-{
-#ifdef CONFIG_APUS
- extern char cmd_line[];
- int i;
- char *p, *q;
-
- /* Let m68k-shared code know it should do the Amiga thing. */
- m68k_machtype = MACH_AMIGA;
-
- /* Parse the command line for arch-specific options.
- * For the m68k, this is currently only "debug=xxx" to enable printing
- * certain kernel messages to some machine-specific device. */
- for( p = cmd_line; p && *p; ) {
- i = 0;
- if (!strncmp( p, "debug=", 6 )) {
- strncpy( debug_device, p+6, sizeof(debug_device)-1 );
- debug_device[sizeof(debug_device)-1] = 0;
- if ((q = strchr( debug_device, ' ' ))) *q = 0;
- i = 1;
- } else if (!strncmp( p, "60nsram", 7 )) {
- APUS_WRITE (APUS_REG_WAITSTATE,
- REGWAITSTATE_SETRESET
- |REGWAITSTATE_PPCR
- |REGWAITSTATE_PPCW);
- __60nsram = 1;
- i = 1;
- }
-
- if (i) {
- /* option processed, delete it */
- if ((q = strchr( p, ' ' )))
- strcpy( p, q+1 );
- else
- *p = 0;
- } else {
- if ((p = strchr( p, ' ' ))) ++p;
- }
- }
-
- config_amiga();
-
-#if 0 /* Enable for logging - also include logging.o in Makefile rule */
- {
-#define LOG_SIZE 4096
- void* base;
-
- /* Throw away some memory - the P5 firmare stomps on top
- * of CHIP memory during bootup.
- */
- amiga_chip_alloc(0x1000);
-
- base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
- LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
- }
-#endif
-#endif
-}
-
-int
-apus_show_cpuinfo(struct seq_file *m)
-{
- extern int __map_without_bats;
- extern unsigned long powerup_PCI_present;
-
- seq_printf(m, "machine\t\t: Amiga\n");
- seq_printf(m, "bus speed\t: %d%s", __bus_speed,
- (__speed_test_failed) ? " [failed]\n" : "\n");
- seq_printf(m, "using BATs\t: %s\n",
- (__map_without_bats) ? "No" : "Yes");
- seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70);
- seq_printf(m, "PCI bridge\t: %s\n",
- (powerup_PCI_present) ? "Yes" : "No");
- return 0;
-}
-
-static void get_current_tb(unsigned long long *time)
-{
- __asm __volatile ("1:mftbu 4 \n\t"
- " mftb 5 \n\t"
- " mftbu 6 \n\t"
- " cmpw 4,6 \n\t"
- " bne 1b \n\t"
- " stw 4,0(%0)\n\t"
- " stw 5,4(%0)\n\t"
- :
- : "r" (time)
- : "r4", "r5", "r6");
-}
-
-
-void apus_calibrate_decr(void)
-{
-#ifdef CONFIG_APUS
- unsigned long freq;
-
- /* This algorithm for determining the bus speed was
- contributed by Ralph Schmidt. */
- unsigned long long start, stop;
- int bus_speed;
- int speed_test_failed = 0;
-
- {
- unsigned long loop = amiga_eclock / 10;
-
- get_current_tb (&start);
- while (loop--) {
- unsigned char tmp;
-
- tmp = ciaa.pra;
- }
- get_current_tb (&stop);
- }
-
- bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
- if (AMI_1200 == amiga_model)
- bus_speed /= 2;
-
- if ((bus_speed >= 47) && (bus_speed < 53)) {
- bus_speed = 50;
- freq = 12500000;
- } else if ((bus_speed >= 57) && (bus_speed < 63)) {
- bus_speed = 60;
- freq = 15000000;
- } else if ((bus_speed >= 63) && (bus_speed < 69)) {
- bus_speed = 67;
- freq = 16666667;
- } else {
- printk ("APUS: Unable to determine bus speed (%d). "
- "Defaulting to 50MHz", bus_speed);
- bus_speed = 50;
- freq = 12500000;
- speed_test_failed = 1;
- }
-
- /* Ease diagnostics... */
- {
- extern int __map_without_bats;
- extern unsigned long powerup_PCI_present;
-
- printk ("APUS: BATs=%d, BUS=%dMHz",
- (__map_without_bats) ? 0 : 1,
- bus_speed);
- if (speed_test_failed)
- printk ("[FAILED - please report]");
-
- printk (", RAM=%dns, PCI bridge=%d\n",
- (__60nsram) ? 60 : 70,
- (powerup_PCI_present) ? 1 : 0);
-
- /* print a bit more if asked politely... */
- if (!(ciaa.pra & 0x40)){
- extern unsigned int bat_addrs[4][3];
- int b;
- for (b = 0; b < 4; ++b) {
- printk ("APUS: BAT%d ", b);
- printk ("%08x-%08x -> %08x\n",
- bat_addrs[b][0],
- bat_addrs[b][1],
- bat_addrs[b][2]);
- }
- }
-
- }
-
- printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
- __bus_speed = bus_speed;
- __speed_test_failed = speed_test_failed;
-#endif
-}
-
-void arch_gettod(int *year, int *mon, int *day, int *hour,
- int *min, int *sec)
-{
-#ifdef CONFIG_APUS
- if (mach_gettod)
- mach_gettod(year, mon, day, hour, min, sec);
- else
- *year = *mon = *day = *hour = *min = *sec = 0;
-#endif
-}
-
-/* for "kbd-reset" cmdline param */
-__init
-void kbd_reset_setup(char *str, int *ints)
-{
-}
-
-/*********************************************************** FLOPPY */
-#if defined(CONFIG_AMIGA_FLOPPY)
-__init
-void floppy_setup(char *str, int *ints)
-{
- if (mach_floppy_setup)
- mach_floppy_setup (str, ints);
-}
-#endif
-
-/*********************************************************** MEMORY */
-#define KMAP_MAX 32
-unsigned long kmap_chunks[KMAP_MAX*3];
-int kmap_chunk_count = 0;
-
-/* From pgtable.h */
-static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
-{
- pgd_t *dir = 0;
- pmd_t *pmd = 0;
- pte_t *pte = 0;
-
- va &= PAGE_MASK;
-
- dir = pgd_offset( mm, va );
- if (dir)
- {
- pmd = pmd_offset(dir, va & PAGE_MASK);
- if (pmd && pmd_present(*pmd))
- {
- pte = pte_offset(pmd, va);
- }
- }
- return pte;
-}
-
-
-/* Again simulating an m68k/mm/kmap.c function. */
-void kernel_set_cachemode( unsigned long address, unsigned long size,
- unsigned int cmode )
-{
- unsigned long mask, flags;
-
- switch (cmode)
- {
- case IOMAP_FULL_CACHING:
- mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
- flags = 0;
- break;
- case IOMAP_NOCACHE_SER:
- mask = ~0;
- flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
- break;
- default:
- panic ("kernel_set_cachemode() doesn't support mode %d\n",
- cmode);
- break;
- }
-
- size /= PAGE_SIZE;
- address &= PAGE_MASK;
- while (size--)
- {
- pte_t *pte;
-
- pte = my_find_pte(&init_mm, address);
- if ( !pte )
- {
- printk("pte NULL in kernel_set_cachemode()\n");
- return;
- }
-
- pte_val (*pte) &= mask;
- pte_val (*pte) |= flags;
- flush_tlb_page(find_vma(&init_mm,address),address);
-
- address += PAGE_SIZE;
- }
-}
-
-unsigned long mm_ptov (unsigned long paddr)
-{
- unsigned long ret;
- if (paddr < 16*1024*1024)
- ret = ZTWO_VADDR(paddr);
- else {
- int i;
-
- for (i = 0; i < kmap_chunk_count;){
- unsigned long phys = kmap_chunks[i++];
- unsigned long size = kmap_chunks[i++];
- unsigned long virt = kmap_chunks[i++];
- if (paddr >= phys
- && paddr < (phys + size)){
- ret = virt + paddr - phys;
- goto exit;
- }
- }
-
- ret = (unsigned long) __va(paddr);
- }
-exit:
-#ifdef DEBUGPV
- printk ("PTOV(%lx)=%lx\n", paddr, ret);
-#endif
- return ret;
-}
-
-int mm_end_of_chunk (unsigned long addr, int len)
-{
- if (memory[0].addr + memory[0].size == addr + len)
- return 1;
- return 0;
-}
-
-/*********************************************************** CACHE */
-
-#define L1_CACHE_BYTES 32
-#define MAX_CACHE_SIZE 8192
-void cache_push(__u32 addr, int length)
-{
- addr = mm_ptov(addr);
-
- if (MAX_CACHE_SIZE < length)
- length = MAX_CACHE_SIZE;
-
- while(length > 0){
- __asm ("dcbf 0,%0\n\t"
- : : "r" (addr));
- addr += L1_CACHE_BYTES;
- length -= L1_CACHE_BYTES;
- }
- /* Also flush trailing block */
- __asm ("dcbf 0,%0\n\t"
- "sync \n\t"
- : : "r" (addr));
-}
-
-void cache_clear(__u32 addr, int length)
-{
- if (MAX_CACHE_SIZE < length)
- length = MAX_CACHE_SIZE;
-
- addr = mm_ptov(addr);
-
- __asm ("dcbf 0,%0\n\t"
- "sync \n\t"
- "icbi 0,%0 \n\t"
- "isync \n\t"
- : : "r" (addr));
-
- addr += L1_CACHE_BYTES;
- length -= L1_CACHE_BYTES;
-
- while(length > 0){
- __asm ("dcbf 0,%0\n\t"
- "sync \n\t"
- "icbi 0,%0 \n\t"
- "isync \n\t"
- : : "r" (addr));
- addr += L1_CACHE_BYTES;
- length -= L1_CACHE_BYTES;
- }
-
- __asm ("dcbf 0,%0\n\t"
- "sync \n\t"
- "icbi 0,%0 \n\t"
- "isync \n\t"
- : : "r" (addr));
-}
-
-/****************************************************** from setup.c */
-void
-apus_restart(char *cmd)
-{
- cli();
-
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
- APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
- APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
- for(;;);
-}
-
-void
-apus_power_off(void)
-{
- for (;;);
-}
-
-void
-apus_halt(void)
-{
- apus_restart(NULL);
-}
-
-/****************************************************** from setup.c/IDE */
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-
-#if 0 /* no longer used -- paulus */
-void
-apus_ide_fix_driveid(struct hd_driveid *id)
-{
- u_char *p = (u_char *)id;
- int i, j, cnt;
- u_char t;
-
- if (!MACH_IS_AMIGA && !MACH_IS_MAC)
- return;
- for (i = 0; i < num_driveid_types; i++) {
- cnt = driveid_types[i] & T_MASK_COUNT;
- switch (driveid_types[i] & T_MASK_TYPE) {
- case T_CHAR:
- p += cnt;
- break;
- case T_SHORT:
- for (j = 0; j < cnt; j++) {
- t = p[0];
- p[0] = p[1];
- p[1] = t;
- p += 2;
- }
- break;
- case T_INT:
- for (j = 0; j < cnt; j++) {
- t = p[0];
- p[0] = p[3];
- p[3] = t;
- t = p[1];
- p[1] = p[2];
- p[2] = t;
- p += 4;
- }
- break;
- case T_TEXT:
- for (j = 0; j < cnt; j += 2) {
- t = p[0];
- p[0] = p[1];
- p[1] = t;
- p += 2;
- }
- break;
- }
- }
-}
-#endif /* 0 */
-
-__init
-void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port,
- ide_ioreg_t ctrl_port, int *irq)
-{
- if (data_port || ctrl_port)
- printk("apus_ide_init_hwif_ports: must not be called\n");
-}
-#endif
-/****************************************************** IRQ stuff */
-
-static unsigned int apus_irq_cannonicalize(unsigned int irq)
-{
- return irq;
-}
-
-int show_apus_interrupts(struct seq_file *p, void *v)
-{
-#ifdef CONFIG_APUS
- extern int show_amiga_interrupts(struct seq_file *p, void *v)
-
- return show_amiga_interrupts(p, v);
-#else
- return 0;
-#endif
-}
-
-/* IPL must be between 0 and 7 */
-static inline void apus_set_IPL(unsigned long ipl)
-{
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | ((~ipl) & IPLEMU_IPLMASK));
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
-}
-
-static inline unsigned long apus_get_IPL(void)
-{
- /* This returns the present IPL emulation level. */
- unsigned long __f;
- APUS_READ(APUS_IPL_EMU, __f);
- return ((~__f) & IPLEMU_IPLMASK);
-}
-
-static inline unsigned long apus_get_prev_IPL(struct pt_regs* regs)
-{
- /* The value saved in mq is the IPL_EMU value at the time of
- interrupt. The lower bits are the current interrupt level,
- the upper bits the requested level. Thus, to restore the
- IPL level to the post-interrupt state, we will need to use
- the lower bits. */
- unsigned long __f = regs->mq;
- return ((~__f) & IPLEMU_IPLMASK);
-}
-
-
-#ifdef CONFIG_APUS
-void free_irq(unsigned int irq, void *dev_id)
-{
- extern void amiga_free_irq(unsigned int irq, void *dev_id);
-
- amiga_free_irq (irq, dev_id);
-}
-
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
-{
- extern int amiga_request_irq(unsigned int irq,
- void (*handler)(int, void *,
- struct pt_regs *),
- unsigned long flags,
- const char *devname,
- void *dev_id);
-
- return amiga_request_irq (irq, handler, irqflags, devname, dev_id);
-}
-
-/* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what
- callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO
- vectors (24-31), so we put this dummy function in between to adjust
- the vector argument (rather have cruft here than in the generic irq.c). */
-int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
-{
- extern int request_sysirq(unsigned int irq,
- void (*handler)(int, void *,
- struct pt_regs *),
- unsigned long irqflags,
- const char * devname, void *dev_id);
- return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags,
- devname, dev_id);
-}
-#endif
-
-int apus_get_irq(struct pt_regs* regs)
-{
-#ifdef CONFIG_APUS
- int level = apus_get_IPL();
-
-#ifdef __INTERRUPT_DEBUG
- printk("<%d:%d>", level, apus_get_prev_IPL(regs));
-#endif
-
- if (0 == level)
- return -8;
- if (7 == level)
- return -9;
-
- return level + IRQ_AMIGA_AUTO;
-#else
- return 0;
-#endif
-}
-
-void apus_post_irq(struct pt_regs* regs, int level)
-{
-#ifdef __INTERRUPT_DEBUG
- printk("{%d}", apus_get_prev_IPL(regs));
-#endif
- /* Restore IPL to the previous value */
- apus_set_IPL(apus_get_prev_IPL(regs));
-}
-
-/****************************************************** keyboard */
-static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
- return -EOPNOTSUPP;
-}
-
-static int apus_kbd_getkeycode(unsigned int scancode)
-{
- return scancode > 127 ? -EINVAL : scancode;
-}
-
-static int apus_kbd_translate(unsigned char keycode, unsigned char *keycodep,
- char raw_mode)
-{
- *keycodep = keycode;
- return 1;
-}
-
-static char apus_kbd_unexpected_up(unsigned char keycode)
-{
- return 0200;
-}
-
-static void apus_kbd_leds(unsigned char leds)
-{
-}
-
-static void apus_kbd_init_hw(void)
-{
-#ifdef CONFIG_APUS
- extern int amiga_keyb_init(void);
-
- amiga_keyb_init();
-#endif
-}
-
-
-/****************************************************** debugging */
-
-/* some serial hardware definitions */
-#define SDR_OVRUN (1<<15)
-#define SDR_RBF (1<<14)
-#define SDR_TBE (1<<13)
-#define SDR_TSRE (1<<12)
-
-#define AC_SETCLR (1<<15)
-#define AC_UARTBRK (1<<11)
-
-#define SER_DTR (1<<7)
-#define SER_RTS (1<<6)
-#define SER_DCD (1<<5)
-#define SER_CTS (1<<4)
-#define SER_DSR (1<<3)
-
-static __inline__ void ser_RTSon(void)
-{
- ciab.pra &= ~SER_RTS; /* active low */
-}
-
-int __debug_ser_out( unsigned char c )
-{
- custom.serdat = c | 0x100;
- mb();
- while (!(custom.serdatr & 0x2000))
- barrier();
- return 1;
-}
-
-unsigned char __debug_ser_in( void )
-{
- unsigned char c;
-
- /* XXX: is that ok?? derived from amiga_ser.c... */
- while( !(custom.intreqr & IF_RBF) )
- barrier();
- c = custom.serdatr;
- /* clear the interrupt, so that another character can be read */
- custom.intreq = IF_RBF;
- return c;
-}
-
-int __debug_serinit( void )
-{
- unsigned long flags;
-
- save_flags (flags);
- cli();
-
- /* turn off Rx and Tx interrupts */
- custom.intena = IF_RBF | IF_TBE;
-
- /* clear any pending interrupt */
- custom.intreq = IF_RBF | IF_TBE;
-
- restore_flags (flags);
-
- /*
- * set the appropriate directions for the modem control flags,
- * and clear RTS and DTR
- */
- ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */
- ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
-
-#ifdef CONFIG_KGDB
- /* turn Rx interrupts on for GDB */
- custom.intena = IF_SETCLR | IF_RBF;
- ser_RTSon();
-#endif
-
- return 0;
-}
-
-void __debug_print_hex(unsigned long x)
-{
- int i;
- char hexchars[] = "0123456789ABCDEF";
-
- for (i = 0; i < 8; i++) {
- __debug_ser_out(hexchars[(x >> 28) & 15]);
- x <<= 4;
- }
- __debug_ser_out('\n');
- __debug_ser_out('\r');
-}
-
-void __debug_print_string(char* s)
-{
- unsigned char c;
- while((c = *s++))
- __debug_ser_out(c);
- __debug_ser_out('\n');
- __debug_ser_out('\r');
-}
-
-static void apus_progress(char *s, unsigned short value)
-{
- __debug_print_string(s);
-}
-
-/****************************************************** init */
-
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
-extern void (*amiga_default_handler[AUTO_IRQS])(int, void *, struct pt_regs *);
-
-static const char *default_names[SYS_IRQS] = {
- "spurious int", "int1 handler", "int2 handler", "int3 handler",
- "int4 handler", "int5 handler", "int6 handler", "int7 handler"
-};
-
-irq_node_t *new_irq_node(void)
-{
- irq_node_t *node;
- short i;
-
- for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
- if (!node->handler)
- return node;
-
- printk ("new_irq_node: out of nodes\n");
- return NULL;
-}
-
-extern void amiga_enable_irq(unsigned int irq);
-extern void amiga_disable_irq(unsigned int irq);
-
-struct hw_interrupt_type amiga_irqctrl = {
- " Amiga ",
- NULL,
- NULL,
- amiga_enable_irq,
- amiga_disable_irq,
- 0,
- 0
-};
-
-#define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long __init apus_find_end_of_memory(void)
-{
- int shadow = 0;
- unsigned long total;
-
- /* The memory size reported by ADOS excludes the 512KB
- reserved for PPC exception registers and possibly 512KB
- containing a shadow of the ADOS ROM. */
- {
- unsigned long size = memory[0].size;
-
- /* If 2MB aligned, size was probably user
- specified. We can't tell anything about shadowing
- in this case so skip shadow assignment. */
- if (0 != (size & 0x1fffff)){
- /* Align to 512KB to ensure correct handling
- of both memfile and system specified
- sizes. */
- size = ((size+0x0007ffff) & 0xfff80000);
- /* If memory is 1MB aligned, assume
- shadowing. */
- shadow = !(size & 0x80000);
- }
-
- /* Add the chunk that ADOS does not see. by aligning
- the size to the nearest 2MB limit upwards. */
- memory[0].size = ((size+0x001fffff) & 0xffe00000);
- }
-
- total = memory[0].size;
-
- /* Remove the memory chunks that are controlled by special
- Phase5 hardware. */
-
- /* Remove the upper 512KB if it contains a shadow of
- the ADOS ROM. FIXME: It might be possible to
- disable this shadow HW. Check the booter
- (ppc_boot.c) */
- if (shadow)
- total -= HARDWARE_MAPPED_SIZE;
-
- /* Remove the upper 512KB where the PPC exception
- vectors are mapped. */
- total -= HARDWARE_MAPPED_SIZE;
-
- /* Linux/APUS only handles one block of memory -- the one on
- the PowerUP board. Other system memory is horrible slow in
- comparison. The user can use other memory for swapping
- using the z2ram device. */
- ram_phys_base = memory[0].addr;
- return total;
-}
-
-static void __init
-apus_map_io(void)
-{
- /* Map PPC exception vectors. */
- io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
- /* Map chip and ZorroII memory */
- io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO);
-}
-
-__init
-void apus_init_IRQ(void)
-{
- int i;
-
- for ( i = 0 ; i < NR_IRQS ; i++ )
- irq_desc[i].handler = &amiga_irqctrl;
-
- for (i = 0; i < NUM_IRQ_NODES; i++)
- nodes[i].handler = NULL;
-
- for (i = 0; i < AUTO_IRQS; i++) {
- if (amiga_default_handler[i] != NULL)
- sys_request_irq(i, amiga_default_handler[i],
- 0, default_names[i], NULL);
- }
-
- amiga_init_IRQ();
-
-}
-
-__init
-void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- extern int parse_bootinfo(const struct bi_record *);
- extern char _end[];
-
- /* Parse bootinfo. The bootinfo is located right after
- the kernel bss */
- parse_bootinfo((const struct bi_record *)&_end);
-#ifdef CONFIG_BLK_DEV_INITRD
- /* Take care of initrd if we have one. Use data from
- bootinfo to avoid the need to initialize PPC
- registers when kernel is booted via a PPC reset. */
- if ( ramdisk.addr ) {
- initrd_start = (unsigned long) __va(ramdisk.addr);
- initrd_end = (unsigned long)
- __va(ramdisk.size + ramdisk.addr);
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- ISA_DMA_THRESHOLD = 0x00ffffff;
-
- ppc_md.setup_arch = apus_setup_arch;
- ppc_md.show_cpuinfo = apus_show_cpuinfo;
- ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
- ppc_md.init_IRQ = apus_init_IRQ;
- ppc_md.get_irq = apus_get_irq;
-
-#error Should use the ->end() member of irq_desc[x]. -- Cort
- /*ppc_md.post_irq = apus_post_irq;*/
-
-#ifdef CONFIG_HEARTBEAT
- ppc_md.heartbeat = apus_heartbeat;
- ppc_md.heartbeat_count = 1;
-#endif
-#ifdef APUS_DEBUG
- __debug_serinit();
- ppc_md.progress = apus_progress;
-#endif
- ppc_md.init = NULL;
-
- ppc_md.restart = apus_restart;
- ppc_md.power_off = apus_power_off;
- ppc_md.halt = apus_halt;
-
- ppc_md.time_init = NULL;
- ppc_md.set_rtc_time = apus_set_rtc_time;
- ppc_md.get_rtc_time = apus_get_rtc_time;
- ppc_md.calibrate_decr = apus_calibrate_decr;
-
- ppc_md.find_end_of_memory = apus_find_end_of_memory;
- ppc_md.setup_io_mappings = apus_map_io;
-
- ppc_md.nvram_read_val = NULL;
- ppc_md.nvram_write_val = NULL;
-
- /* These should not be used for the APUS yet, since it uses
- the M68K keyboard now. */
- ppc_md.kbd_setkeycode = apus_kbd_setkeycode;
- ppc_md.kbd_getkeycode = apus_kbd_getkeycode;
- ppc_md.kbd_translate = apus_kbd_translate;
- ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up;
- ppc_md.kbd_leds = apus_kbd_leds;
- ppc_md.kbd_init_hw = apus_kbd_init_hw;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
- ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
-#endif
-}
-
-
-/*************************************************** coexistence */
-void __init adbdev_init(void)
-{
-}
diff --git a/arch/ppc/kernel/bitops.c b/arch/ppc/kernel/bitops.c
index eebbab590e0e..e61da0d1e978 100644
--- a/arch/ppc/kernel/bitops.c
+++ b/arch/ppc/kernel/bitops.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.bitops.c 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Copyright (C) 1996 Paul Mackerras.
@@ -21,8 +21,9 @@ void set_bit(int nr, volatile void * addr)
__asm__ __volatile__(SMP_WMB "\n\
1: lwarx %0,0,%3 \n\
- or %0,%0,%2 \n\
- stwcx. %0,0,%3 \n\
+ or %0,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+" stwcx. %0,0,%3 \n\
bne 1b"
SMP_MB
: "=&r" (old), "=m" (*p)
@@ -38,8 +39,9 @@ void clear_bit(int nr, volatile void *addr)
__asm__ __volatile__(SMP_WMB "\n\
1: lwarx %0,0,%3 \n\
- andc %0,%0,%2 \n\
- stwcx. %0,0,%3 \n\
+ andc %0,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+" stwcx. %0,0,%3 \n\
bne 1b"
SMP_MB
: "=&r" (old), "=m" (*p)
@@ -55,8 +57,9 @@ void change_bit(int nr, volatile void *addr)
__asm__ __volatile__(SMP_WMB "\n\
1: lwarx %0,0,%3 \n\
- xor %0,%0,%2 \n\
- stwcx. %0,0,%3 \n\
+ xor %0,%0,%2 \n"
+ PPC405_ERR77(0,%3)
+" stwcx. %0,0,%3 \n\
bne 1b"
SMP_MB
: "=&r" (old), "=m" (*p)
@@ -72,8 +75,9 @@ int test_and_set_bit(int nr, volatile void *addr)
__asm__ __volatile__(SMP_WMB "\n\
1: lwarx %0,0,%4 \n\
- or %1,%0,%3 \n\
- stwcx. %1,0,%4 \n\
+ or %1,%0,%3 \n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4 \n\
bne 1b"
SMP_MB
: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -91,8 +95,9 @@ int test_and_clear_bit(int nr, volatile void *addr)
__asm__ __volatile__(SMP_WMB "\n\
1: lwarx %0,0,%4 \n\
- andc %1,%0,%3 \n\
- stwcx. %1,0,%4 \n\
+ andc %1,%0,%3 \n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4 \n\
bne 1b"
SMP_MB
: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -110,8 +115,9 @@ int test_and_change_bit(int nr, volatile void *addr)
__asm__ __volatile__(SMP_WMB "\n\
1: lwarx %0,0,%4 \n\
- xor %1,%0,%3 \n\
- stwcx. %1,0,%4 \n\
+ xor %1,%0,%3 \n"
+ PPC405_ERR77(0,%4)
+" stwcx. %1,0,%4 \n\
bne 1b"
SMP_MB
: "=&r" (old), "=&r" (t), "=m" (*p)
diff --git a/arch/ppc/kernel/btext.c b/arch/ppc/kernel/btext.c
index 7cd47d953cf8..ec2befee7d33 100644
--- a/arch/ppc/kernel/btext.c
+++ b/arch/ppc/kernel/btext.c
@@ -44,10 +44,10 @@ unsigned long disp_BAT[2] __initdata = {0, 0};
static unsigned char vga_font[cmapsz];
-int boot_text_mapped = 1;
+int boot_text_mapped;
+int force_printk_to_btext = 0;
-boot_infos_t *disp_bi;
-boot_infos_t fake_bi;
+boot_infos_t disp_bi;
extern char *klimit;
@@ -69,48 +69,47 @@ extern char *klimit;
void __init
btext_init(boot_infos_t *bi)
{
- unsigned long offset = reloc_offset();
-
- RELOC(g_loc_X) = 0;
- RELOC(g_loc_Y) = 0;
- RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8;
- RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16;
- RELOC(disp_bi) = PTRUNRELOC(bi);
+ g_loc_X = 0;
+ g_loc_Y = 0;
+ g_max_loc_X = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8;
+ g_max_loc_Y = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16;
+ disp_bi = *bi;
+ boot_text_mapped = 1;
}
void __init
-btext_welcome(boot_infos_t* bi)
+btext_welcome(void)
{
- unsigned long offset = reloc_offset();
unsigned long flags;
unsigned long pvr;
-
- btext_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n"));
- btext_drawstring(RELOC("\nlinked at : 0x"));
+ boot_infos_t* bi = &disp_bi;
+
+ btext_drawstring("Welcome to Linux, kernel " UTS_RELEASE "\n");
+ btext_drawstring("\nlinked at : 0x");
btext_drawhex(KERNELBASE);
- btext_drawstring(RELOC("\nframe buffer at : 0x"));
+ btext_drawstring("\nframe buffer at : 0x");
btext_drawhex((unsigned long)bi->dispDeviceBase);
- btext_drawstring(RELOC(" (phys), 0x"));
+ btext_drawstring(" (phys), 0x");
btext_drawhex((unsigned long)bi->logicalDisplayBase);
- btext_drawstring(RELOC(" (log)"));
- btext_drawstring(RELOC("\nklimit : 0x"));
- btext_drawhex((unsigned long)RELOC(klimit));
- btext_drawstring(RELOC("\nMSR : 0x"));
+ btext_drawstring(" (log)");
+ btext_drawstring("\nklimit : 0x");
+ btext_drawhex((unsigned long)klimit);
+ btext_drawstring("\nMSR : 0x");
__asm__ __volatile__ ("mfmsr %0" : "=r" (flags));
btext_drawhex(flags);
__asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr));
pvr >>= 16;
if (pvr > 1) {
- btext_drawstring(RELOC("\nHID0 : 0x"));
+ btext_drawstring("\nHID0 : 0x");
__asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags));
btext_drawhex(flags);
}
if (pvr == 8 || pvr == 12 || pvr == 0x800c) {
- btext_drawstring(RELOC("\nICTC : 0x"));
+ btext_drawstring("\nICTC : 0x");
__asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags));
btext_drawhex(flags);
}
- btext_drawstring(RELOC("\n\n"));
+ btext_drawstring("\n\n");
}
/* Calc BAT values for mapping the display and store them
@@ -131,28 +130,28 @@ btext_welcome(boot_infos_t* bi)
void __init
btext_prepare_BAT(void)
{
- unsigned long offset = reloc_offset();
- boot_infos_t* bi = PTRRELOC(RELOC(disp_bi));
- unsigned long addr = (unsigned long)bi->dispDeviceBase;
+ boot_infos_t* bi = &disp_bi;
unsigned long vaddr = KERNELBASE + 0x10000000;
+ unsigned long addr;
unsigned long lowbits;
- if (!RELOC(disp_bi)) {
- RELOC(boot_text_mapped) = 0;
+ addr = (unsigned long)bi->dispDeviceBase;
+ if (!addr) {
+ boot_text_mapped = 0;
return;
}
if (PVR_VER(mfspr(PVR)) != 1) {
/* 603, 604, G3, G4, ... */
lowbits = addr & ~0xFF000000UL;
addr &= 0xFF000000UL;
- RELOC(disp_BAT[0]) = vaddr | (BL_16M<<2) | 2;
- RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);
+ disp_BAT[0] = vaddr | (BL_16M<<2) | 2;
+ disp_BAT[1] = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);
} else {
/* 601 */
lowbits = addr & ~0xFF800000UL;
addr &= 0xFF800000UL;
- RELOC(disp_BAT[0]) = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
- RELOC(disp_BAT[1]) = addr | BL_8M | 0x40;
+ disp_BAT[0] = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
+ disp_BAT[1] = addr | BL_8M | 0x40;
}
bi->logicalDisplayBase = (void *) (vaddr + lowbits);
}
@@ -164,15 +163,12 @@ void __init
btext_setup_display(int width, int height, int depth, int pitch,
unsigned long address)
{
- unsigned long offset = reloc_offset();
- boot_infos_t* bi;
-
- RELOC(disp_bi) = &fake_bi;
- bi = PTRRELOC((&fake_bi));
- RELOC(g_loc_X) = 0;
- RELOC(g_loc_Y) = 0;
- RELOC(g_max_loc_X) = width / 8;
- RELOC(g_max_loc_Y) = height / 16;
+ boot_infos_t* bi = &disp_bi;
+
+ g_loc_X = 0;
+ g_loc_Y = 0;
+ g_max_loc_X = width / 8;
+ g_max_loc_Y = height / 16;
bi->logicalDisplayBase = (unsigned char *)address;
bi->dispDeviceBase = (unsigned char *)address;
bi->dispDeviceRowBytes = pitch;
@@ -180,6 +176,7 @@ btext_setup_display(int width, int height, int depth, int pitch,
bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
bi->dispDeviceRect[2] = width;
bi->dispDeviceRect[3] = height;
+ boot_text_mapped = 1;
}
/* Here's a small text engine to use during early boot
@@ -197,16 +194,18 @@ void __openfirmware
map_boot_text(void)
{
unsigned long base, offset, size;
- if (disp_bi == 0)
+ boot_infos_t *bi = &disp_bi;
+
+ if (bi->dispDeviceBase == 0)
return;
- base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL;
- offset = ((unsigned long) disp_bi->dispDeviceBase) - base;
- size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset
- + disp_bi->dispDeviceRect[0];
- disp_bi->logicalDisplayBase = ioremap(base, size);
- if (disp_bi->logicalDisplayBase == 0)
+ base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL;
+ offset = ((unsigned long) bi->dispDeviceBase) - base;
+ size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset
+ + bi->dispDeviceRect[0];
+ bi->logicalDisplayBase = ioremap(base, size);
+ if (bi->logicalDisplayBase == 0)
return;
- disp_bi->logicalDisplayBase += offset;
+ bi->logicalDisplayBase += offset;
boot_text_mapped = 1;
}
@@ -229,22 +228,24 @@ void
btext_update_display(unsigned long phys, int width, int height,
int depth, int pitch)
{
- if (disp_bi == 0)
+ boot_infos_t *bi = &disp_bi;
+
+ if (bi->dispDeviceBase == 0)
return;
- /* check it's the same frame buffer (within 64MB) */
- if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) {
+
+ /* check it's the same frame buffer (within 256MB) */
+ if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
return;
- }
- disp_bi->dispDeviceBase = (__u8 *) phys;
- disp_bi->dispDeviceRect[0] = 0;
- disp_bi->dispDeviceRect[1] = 0;
- disp_bi->dispDeviceRect[2] = width;
- disp_bi->dispDeviceRect[3] = height;
- disp_bi->dispDeviceDepth = depth;
- disp_bi->dispDeviceRowBytes = pitch;
+ bi->dispDeviceBase = (__u8 *) phys;
+ bi->dispDeviceRect[0] = 0;
+ bi->dispDeviceRect[1] = 0;
+ bi->dispDeviceRect[2] = width;
+ bi->dispDeviceRect[3] = height;
+ bi->dispDeviceDepth = depth;
+ bi->dispDeviceRowBytes = pitch;
if (boot_text_mapped) {
- iounmap(disp_bi->logicalDisplayBase);
+ iounmap(bi->logicalDisplayBase);
boot_text_mapped = 0;
}
map_boot_text();
@@ -256,8 +257,7 @@ btext_update_display(unsigned long phys, int width, int height,
void BTEXT btext_clearscreen(void)
{
- unsigned long offset = reloc_offset();
- boot_infos_t* bi = PTRRELOC(RELOC(disp_bi));
+ boot_infos_t* bi = &disp_bi;
unsigned long *base = (unsigned long *)calc_base(bi, 0, 0);
unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
@@ -279,8 +279,7 @@ __inline__ void dcbst(const void* addr)
void BTEXT btext_flushscreen(void)
{
- unsigned long offset = reloc_offset();
- boot_infos_t* bi = PTRRELOC(RELOC(disp_bi));
+ boot_infos_t* bi = &disp_bi;
unsigned long *base = (unsigned long *)calc_base(bi, 0, 0);
unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
@@ -301,8 +300,7 @@ void BTEXT btext_flushscreen(void)
static BTEXT void
scrollscreen(void)
{
- unsigned long offset = reloc_offset();
- boot_infos_t* bi = PTRRELOC(RELOC(disp_bi));
+ boot_infos_t* bi = &disp_bi;
unsigned long *src = (unsigned long *)calc_base(bi,0,16);
unsigned long *dst = (unsigned long *)calc_base(bi,0,0);
unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
@@ -336,49 +334,48 @@ scrollscreen(void)
void BTEXT btext_drawchar(char c)
{
- unsigned long offset = reloc_offset();
int cline = 0, x;
- if (!RELOC(boot_text_mapped))
+ if (!boot_text_mapped)
return;
switch (c) {
case '\b':
- if (RELOC(g_loc_X) > 0)
- --RELOC(g_loc_X);
+ if (g_loc_X > 0)
+ --g_loc_X;
break;
case '\t':
- RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8;
+ g_loc_X = (g_loc_X & -8) + 8;
break;
case '\r':
- RELOC(g_loc_X) = 0;
+ g_loc_X = 0;
break;
case '\n':
- RELOC(g_loc_X) = 0;
- RELOC(g_loc_Y)++;
+ g_loc_X = 0;
+ g_loc_Y++;
cline = 1;
break;
default:
- draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+ draw_byte(c, g_loc_X++, g_loc_Y);
}
- if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) {
- RELOC(g_loc_X) = 0;
- RELOC(g_loc_Y)++;
+ if (g_loc_X >= g_max_loc_X) {
+ g_loc_X = 0;
+ g_loc_Y++;
cline = 1;
}
#ifndef NO_SCROLL
- while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) {
+ while (g_loc_Y >= g_max_loc_Y) {
scrollscreen();
- RELOC(g_loc_Y)--;
+ g_loc_Y--;
}
#else
/* wrap around from bottom to top of screen so we don't
waste time scrolling each line. -- paulus. */
- if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y))
- RELOC(g_loc_Y) = 0;
+ if (g_loc_Y >= g_max_loc_Y)
+ g_loc_Y = 0;
if (cline) {
- for (x = 0; x < RELOC(g_max_loc_X); ++x)
- draw_byte(' ', x, RELOC(g_loc_Y));
+ for (x = 0; x < g_max_loc_X; ++x)
+ draw_byte(' ', x, g_loc_Y);
}
#endif
}
@@ -386,9 +383,7 @@ void BTEXT btext_drawchar(char c)
void BTEXT
btext_drawstring(const char *c)
{
- unsigned long offset = reloc_offset();
-
- if (!RELOC(boot_text_mapped))
+ if (!boot_text_mapped)
return;
while (*c)
btext_drawchar(*c++);
@@ -398,34 +393,34 @@ void BTEXT
btext_drawhex(unsigned long v)
{
static char hex_table[] = "0123456789abcdef";
- unsigned long offset = reloc_offset();
- if (!RELOC(boot_text_mapped))
+ if (!boot_text_mapped)
return;
- btext_drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]);
- btext_drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]);
+ btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]);
btext_drawchar(' ');
}
static void BTEXT
draw_byte(unsigned char c, long locX, long locY)
{
- unsigned long offset = reloc_offset();
- boot_infos_t* bi = PTRRELOC(RELOC(disp_bi));
+ boot_infos_t* bi = &disp_bi;
unsigned char *base = calc_base(bi, locX << 3, locY << 4);
- unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16];
+ unsigned char *font = &vga_font[((unsigned long)c) * 16];
int rb = bi->dispDeviceRowBytes;
switch(bi->dispDeviceDepth) {
+ case 24:
case 32:
draw_byte_32(font, (unsigned long *)base, rb);
break;
+ case 15:
case 16:
draw_byte_16(font, (unsigned long *)base, rb);
break;
@@ -490,8 +485,7 @@ draw_byte_16(unsigned char *font, unsigned long *base, int rb)
int l, bits;
int fg = 0xFFFFFFFFUL;
int bg = 0x00000000UL;
- unsigned long offset = reloc_offset();
- unsigned long *eb = RELOC(expand_bits_16);
+ unsigned long *eb = expand_bits_16;
for (l = 0; l < 16; ++l)
{
@@ -510,8 +504,7 @@ draw_byte_8(unsigned char *font, unsigned long *base, int rb)
int l, bits;
int fg = 0x0F0F0F0FUL;
int bg = 0x00000000UL;
- unsigned long offset = reloc_offset();
- unsigned long *eb = RELOC(expand_bits_8);
+ unsigned long *eb = expand_bits_8;
for (l = 0; l < 16; ++l)
{
diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c
deleted file mode 100644
index fae4a2351bf5..000000000000
--- a/arch/ppc/kernel/chrp_pci.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * BK Id: SCCS/s.chrp_pci.c 1.22 09/08/01 15:47:42 paulus
- */
-/*
- * CHRP pci routines.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/bootmem.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/machdep.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-
-#include "open_pic.h"
-#include "pci.h"
-
-/* LongTrail */
-unsigned long gg2_pci_config_base;
-
-#define pci_config_addr(dev, offset) \
-(gg2_pci_config_base | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
-
-volatile struct Hydra *Hydra = NULL;
-
-/*
- * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
- * limit the bus number to 3 bits
- */
-
-#define cfg_read(val, addr, type, op) *val = op((type)(addr))
-#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
-
-#define cfg_read_bad(val, size) *val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte 0xff
-#define bad_word 0xffff
-#define bad_dword 0xffffffffU
-
-#define GG2_PCI_OP(rw, size, type, op) \
-int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
-{ \
- if (dev->bus->number > 7) { \
- cfg_##rw##_bad(val, size) \
- return PCIBIOS_DEVICE_NOT_FOUND; \
- } \
- cfg_##rw(val, pci_config_addr(dev, off), type, op); \
- return PCIBIOS_SUCCESSFUL; \
-}
-
-GG2_PCI_OP(read, byte, u8 *, in_8)
-GG2_PCI_OP(read, word, u16 *, in_le16)
-GG2_PCI_OP(read, dword, u32 *, in_le32)
-GG2_PCI_OP(write, byte, u8, out_8)
-GG2_PCI_OP(write, word, u16, out_le16)
-GG2_PCI_OP(write, dword, u32, out_le32)
-
-static struct pci_ops gg2_pci_ops =
-{
- gg2_read_config_byte,
- gg2_read_config_word,
- gg2_read_config_dword,
- gg2_write_config_byte,
- gg2_write_config_word,
- gg2_write_config_dword
-};
-
-/*
- * Access functions for PCI config space on IBM "python" host bridges.
- */
-#define PYTHON_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
- | (((o) & ~3) << 24))
-
-#define PYTHON_PCI_OP(rw, size, type, op, mask) \
-int __chrp \
-python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- struct pci_controller *hose = dev->sysdata; \
- \
- out_be32(hose->cfg_addr, \
- PYTHON_CFA(dev->bus->number, dev->devfn, offset)); \
- cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
- return PCIBIOS_SUCCESSFUL; \
-}
-
-PYTHON_PCI_OP(read, byte, u8 *, in_8, 3)
-PYTHON_PCI_OP(read, word, u16 *, in_le16, 2)
-PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0)
-PYTHON_PCI_OP(write, byte, u8, out_8, 3)
-PYTHON_PCI_OP(write, word, u16, out_le16, 2)
-PYTHON_PCI_OP(write, dword, u32, out_le32, 0)
-
-static struct pci_ops python_pci_ops =
-{
- python_read_config_byte,
- python_read_config_word,
- python_read_config_dword,
- python_write_config_byte,
- python_write_config_word,
- python_write_config_dword
-};
-
-/*
- * Access functions for PCI config space using RTAS calls.
- */
-#define RTAS_PCI_READ_OP(size, type, nbytes) \
-int __chrp \
-rtas_read_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
- | ((dev->bus->number & 0xff) << 16); \
- unsigned long ret = ~0UL; \
- int rval; \
- \
- rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes); \
- *val = ret; \
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
-}
-
-#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
-int __chrp \
-rtas_write_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
- | ((dev->bus->number & 0xff) << 16); \
- int rval; \
- \
- rval = call_rtas("write-pci-config", 3, 1, NULL, \
- addr, nbytes, (ulong)val); \
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
-}
-
-RTAS_PCI_READ_OP(byte, u8 *, 1)
-RTAS_PCI_READ_OP(word, u16 *, 2)
-RTAS_PCI_READ_OP(dword, u32 *, 4)
-RTAS_PCI_WRITE_OP(byte, u8, 1)
-RTAS_PCI_WRITE_OP(word, u16, 2)
-RTAS_PCI_WRITE_OP(dword, u32, 4)
-
-static struct pci_ops rtas_pci_ops =
-{
- rtas_read_config_byte,
- rtas_read_config_word,
- rtas_read_config_dword,
- rtas_write_config_byte,
- rtas_write_config_word,
- rtas_write_config_dword
-};
-
- /*
- * Temporary fixes for PCI devices. These should be replaced by OF query
- * code -- Geert
- */
-
-static u_char hydra_openpic_initsenses[] __initdata = {
- 1, /* HYDRA_INT_SIO */
- 0, /* HYDRA_INT_SCSI_DMA */
- 0, /* HYDRA_INT_SCCA_TX_DMA */
- 0, /* HYDRA_INT_SCCA_RX_DMA */
- 0, /* HYDRA_INT_SCCB_TX_DMA */
- 0, /* HYDRA_INT_SCCB_RX_DMA */
- 1, /* HYDRA_INT_SCSI */
- 1, /* HYDRA_INT_SCCA */
- 1, /* HYDRA_INT_SCCB */
- 1, /* HYDRA_INT_VIA */
- 1, /* HYDRA_INT_ADB */
- 0, /* HYDRA_INT_ADB_NMI */
- /* all others are 1 (= default) */
-};
-
-int __init
-hydra_init(void)
-{
- struct device_node *np;
-
- np = find_devices("mac-io");
- if (np == NULL || np->n_addrs == 0) {
- printk(KERN_WARNING "Warning: no mac-io found\n");
- return 0;
- }
- Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
- printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
- out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
- HYDRA_FC_SCSI_CELL_EN |
- HYDRA_FC_SCCA_ENABLE |
- HYDRA_FC_SCCB_ENABLE |
- HYDRA_FC_ARB_BYPASS |
- HYDRA_FC_MPIC_ENABLE |
- HYDRA_FC_SLOW_SCC_PCLK |
- HYDRA_FC_MPIC_IS_MASTER));
- OpenPIC_Addr = &Hydra->OpenPIC;
- OpenPIC_InitSenses = hydra_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof(hydra_openpic_initsenses);
- return 1;
-}
-
-void __init
-chrp_pcibios_fixup(void)
-{
- struct pci_dev *dev;
- struct device_node *np;
-
- /* PCI interrupts are controlled by the OpenPIC */
- pci_for_each_dev(dev) {
- np = pci_device_to_OF_node(dev);
- if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
- dev->irq = np->intrs[0].line;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
-void __init
-chrp_find_bridges(void)
-{
- struct device_node *dev;
- int *bus_range;
- int len, index = -1;
- struct pci_controller *hose;
- volatile unsigned char *cfg;
- unsigned int *dma;
- char *model, *machine;
- int is_longtrail = 0, is_mot = 0;
- struct device_node *root = find_path_device("/");
-#ifdef CONFIG_POWER3
- unsigned int *opprop = (unsigned int *)
- get_property(root, "platform-open-pic", NULL);
- int i;
-#endif
-
- /*
- * The PCI host bridge nodes on some machines don't have
- * properties to adequately identify them, so we have to
- * look at what sort of machine this is as well.
- */
- machine = get_property(root, "model", NULL);
- if (machine != NULL) {
- is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
- is_mot = strncmp(machine, "MOT", 3) == 0;
- }
- for (dev = root->child; dev != NULL; dev = dev->sibling) {
- if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
- continue;
- ++index;
- /* The GG2 bridge on the LongTrail doesn't have an address */
- if (dev->n_addrs < 1 && !is_longtrail) {
- printk(KERN_WARNING "Can't use %s: no address\n",
- dev->full_name);
- continue;
- }
- bus_range = (int *) get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s\n",
- dev->full_name);
- continue;
- }
- if (bus_range[1] == bus_range[0])
- printk(KERN_INFO "PCI bus %d", bus_range[0]);
- else
- printk(KERN_INFO "PCI buses %d..%d",
- bus_range[0], bus_range[1]);
- printk(" controlled by %s", dev->type);
- if (dev->n_addrs > 0)
- printk(" at %x", dev->addrs[0].address);
- printk("\n");
-
- hose = pcibios_alloc_controller();
- if (!hose) {
- printk("Can't allocate PCI controller structure for %s\n",
- dev->full_name);
- continue;
- }
- hose->arch_data = dev;
- hose->first_busno = bus_range[0];
- hose->last_busno = bus_range[1];
-
- model = get_property(dev, "model", NULL);
- if (model == NULL)
- model = "<none>";
- if (device_is_compatible(dev, "IBM,python")) {
- hose->ops = &python_pci_ops;
- cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20);
- hose->cfg_addr = (volatile unsigned int *) cfg;
- hose->cfg_data = cfg + 0x10;
- } else if (is_mot
- || strncmp(model, "Motorola, Grackle", 17) == 0) {
- setup_grackle(hose);
- } else if (is_longtrail) {
- hose->ops = &gg2_pci_ops;
- gg2_pci_config_base = (unsigned long)
- ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
- } else {
- printk("No methods for %s (model %s), using RTAS\n",
- dev->full_name, model);
- hose->ops = &rtas_pci_ops;
- }
-
- pci_process_bridge_OF_ranges(hose, dev, index == 0);
-
-#ifdef CONFIG_POWER3
- if (opprop != NULL) {
- i = prom_n_addr_cells(root) * (index + 2) - 1;
- openpic_setup_ISU(index, opprop[i]);
- }
-#endif /* CONFIG_POWER3 */
-
- /* check the first bridge for a property that we can
- use to set pci_dram_offset */
- dma = (unsigned int *)
- get_property(dev, "ibm,dma-ranges", &len);
- if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
- pci_dram_offset = dma[2] - dma[3];
- printk("pci_dram_offset = %lx\n", pci_dram_offset);
- }
- }
-
- ppc_md.pcibios_fixup = chrp_pcibios_fixup;
-}
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
deleted file mode 100644
index 6fd574cbae84..000000000000
--- a/arch/ppc/kernel/chrp_setup.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * BK Id: SCCS/s.chrp_setup.c 1.38 11/13/01 21:26:07 paulus
- */
-/*
- * linux/arch/ppc/kernel/setup.c
- *
- * Copyright (C) 1995 Linus Torvalds
- * Adapted from 'alpha' version by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/blk.h>
-#include <linux/ioport.h>
-#include <linux/console.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/adb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/pci-bridge.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/keyboard.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-#include <asm/btext.h>
-
-#include "local_irq.h"
-#include "i8259.h"
-#include "open_pic.h"
-#include "xics.h"
-
-unsigned long chrp_get_rtc_time(void);
-int chrp_set_rtc_time(unsigned long nowtime);
-void chrp_calibrate_decr(void);
-long chrp_time_init(void);
-
-void chrp_find_bridges(void);
-void chrp_event_scan(void);
-void rtas_display_progress(char *, unsigned short);
-void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
-
-extern unsigned long pmac_find_end_of_memory(void);
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[128];
-extern void select_adb_keyboard(void);
-extern int of_show_percpuinfo(struct seq_file *, int);
-
-extern kdev_t boot_dev;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-static int max_width;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t chrp_smp_ops;
-extern struct smp_ops_t xics_smp_ops;
-#endif
-
-static const char *gg2_memtypes[4] = {
- "FPM", "SDRAM", "EDO", "BEDO"
-};
-static const char *gg2_cachesizes[4] = {
- "256 KB", "512 KB", "1 MB", "Reserved"
-};
-static const char *gg2_cachetypes[4] = {
- "Asynchronous", "Reserved", "Flow-Through Synchronous",
- "Pipelined Synchronous"
-};
-static const char *gg2_cachemodes[4] = {
- "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
-};
-
-int __chrp
-chrp_show_cpuinfo(struct seq_file *m)
-{
- int i, sdramen;
- unsigned int t;
- struct device_node *root;
- const char *model = "";
-
- root = find_path_device("/");
- if (root)
- model = get_property(root, "model", NULL);
- seq_printf(m, "machine\t\t: CHRP %s\n", model);
-
- /* longtrail (goldengate) stuff */
- if (!strncmp(model, "IBM,LongTrail", 13)) {
- /* VLSI VAS96011/12 `Golden Gate 2' */
- /* Memory banks */
- sdramen = (in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
- GG2_PCI_DRAM_CTRL))
- >>31) & 1;
- for (i = 0; i < (sdramen ? 4 : 6); i++) {
- t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
- GG2_PCI_DRAM_BANK0+
- i*4));
- if (!(t & 1))
- continue;
- switch ((t>>8) & 0x1f) {
- case 0x1f:
- model = "4 MB";
- break;
- case 0x1e:
- model = "8 MB";
- break;
- case 0x1c:
- model = "16 MB";
- break;
- case 0x18:
- model = "32 MB";
- break;
- case 0x10:
- model = "64 MB";
- break;
- case 0x00:
- model = "128 MB";
- break;
- default:
- model = "Reserved";
- break;
- }
- seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
- gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
- }
- /* L2 cache */
- t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_CC_CTRL));
- seq_printf(m, "board l2\t: %s %s (%s)\n",
- gg2_cachesizes[(t>>7) & 3],
- gg2_cachetypes[(t>>2) & 3],
- gg2_cachemodes[t & 3]);
- }
- return 0;
-}
-
-/*
- * Fixes for the National Semiconductor PC78308VUL SuperI/O
- *
- * Some versions of Open Firmware incorrectly initialize the IRQ settings
- * for keyboard and mouse
- */
-static inline void __init sio_write(u8 val, u8 index)
-{
- outb(index, 0x15c);
- outb(val, 0x15d);
-}
-
-static inline u8 __init sio_read(u8 index)
-{
- outb(index, 0x15c);
- return inb(0x15d);
-}
-
-static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
- u8 type)
-{
- u8 level0, type0, active;
-
- /* select logical device */
- sio_write(device, 0x07);
- active = sio_read(0x30);
- level0 = sio_read(0x70);
- type0 = sio_read(0x71);
- if (level0 != level || type0 != type || !active) {
- printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
- "remapping to level %d, type %d, active\n",
- name, level0, type0, !active ? "in" : "", level, type);
- sio_write(0x01, 0x30);
- sio_write(level, 0x70);
- sio_write(type, 0x71);
- }
-}
-
-static void __init sio_init(void)
-{
- struct device_node *root;
-
- if ((root = find_path_device("/")) &&
- !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
- /* logical device 0 (KBC/Keyboard) */
- sio_fixup_irq("keyboard", 0, 1, 2);
- /* select logical device 1 (KBC/Mouse) */
- sio_fixup_irq("mouse", 1, 12, 2);
- }
-}
-
-
-void __init
-chrp_setup_arch(void)
-{
- struct device_node *device;
-
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* this is fine for chrp */
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- else
-#endif
- ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
-
- /* Lookup PCI host bridges */
- chrp_find_bridges();
-
-#ifndef CONFIG_PPC64BRIDGE
- /*
- * Temporary fixes for PCI devices.
- * -- Geert
- */
- hydra_init(); /* Mac I/O */
-
-#endif /* CONFIG_PPC64BRIDGE */
-
- /* Some IBM machines don't have the hydra -- Cort */
- if (!OpenPIC_Addr) {
- struct device_node *root;
- unsigned long *opprop;
- int n;
-
- root = find_path_device("/");
- opprop = (unsigned long *) get_property
- (root, "platform-open-pic", NULL);
- n = prom_n_addr_cells(root);
- if (opprop != 0) {
- printk("OpenPIC addrs: %lx %lx %lx\n",
- opprop[n-1], opprop[2*n-1], opprop[3*n-1]);
- OpenPIC_Addr = ioremap(opprop[n-1], 0x40000);
- }
- }
-
- /*
- * Fix the Super I/O configuration
- */
- sio_init();
-
- /*
- * Setup the console operations
- */
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
- /* Get the event scan rate for the rtas so we know how
- * often it expects a heartbeat. -- Cort
- */
- if ( rtas_data ) {
- struct property *p;
- device = find_devices("rtas");
- for ( p = device->properties;
- p && strncmp(p->name, "rtas-event-scan-rate", 20);
- p = p->next )
- /* nothing */ ;
- if ( p && *(unsigned long *)p->value ) {
- ppc_md.heartbeat = chrp_event_scan;
- ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
- ppc_md.heartbeat_count = 1;
- printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
- *(unsigned long *)p->value, ppc_md.heartbeat_reset );
- }
- }
-}
-
-void __chrp
-chrp_event_scan(void)
-{
- unsigned char log[1024];
- unsigned long ret = 0;
- /* XXX: we should loop until the hardware says no more error logs -- Cort */
- call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
- __pa(log), 1024 );
- ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void __chrp
-chrp_restart(char *cmd)
-{
- printk("RTAS system-reboot returned %d\n",
- call_rtas("system-reboot", 0, 1, NULL));
- for (;;);
-}
-
-void __chrp
-chrp_power_off(void)
-{
- /* allow power on only with power button press */
- printk("RTAS power-off returned %d\n",
- call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
- for (;;);
-}
-
-void __chrp
-chrp_halt(void)
-{
- chrp_power_off();
-}
-
-u_int __chrp
-chrp_irq_cannonicalize(u_int irq)
-{
- if (irq == 2)
- return 9;
- return irq;
-}
-
-void __init chrp_init_IRQ(void)
-{
- struct device_node *np;
- int i;
- unsigned int *addrp;
- unsigned char* chrp_int_ack_special = 0;
- unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
- int nmi_irq = -1;
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
- struct device_node *kbd;
-#endif
-
- if (!(np = find_devices("pci"))
- || !(addrp = (unsigned int *)
- get_property(np, "8259-interrupt-acknowledge", NULL)))
- printk("Cannot find pci to get ack address\n");
- else
- chrp_int_ack_special = (unsigned char *)
- ioremap(addrp[prom_n_addr_cells(np)-1], 1);
- /* hydra still sets OpenPIC_InitSenses to a static set of values */
- if (OpenPIC_InitSenses == NULL) {
- prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
- OpenPIC_InitSenses = init_senses;
- OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
- }
- openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq);
- for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
- irq_desc[i].handler = &i8259_pic;
- i8259_init();
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
- /* see if there is a keyboard in the device tree
- with a parent of type "adb" */
- for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
- if (kbd->parent && kbd->parent->type
- && strcmp(kbd->parent->type, "adb") == 0)
- break;
- if (kbd)
- request_irq( HYDRA_INT_ADB_NMI, xmon_irq, 0, "XMON break", 0);
-#endif
-}
-
-void __init
-chrp_init2(void)
-{
-#ifdef CONFIG_NVRAM
- pmac_nvram_init();
-#endif
-
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
-
- if (ppc_md.progress)
- ppc_md.progress(" Have fun! ", 0x7777);
-
-#if defined(CONFIG_VT) && (defined(CONFIG_ADB_KEYBOARD) || defined(CONFIG_INPUT))
- /* see if there is a keyboard in the device tree
- with a parent of type "adb" */
- {
- struct device_node *kbd;
-
- for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) {
- if (kbd->parent && kbd->parent->type
- && strcmp(kbd->parent->type, "adb") == 0) {
- select_adb_keyboard();
- break;
- }
- }
- }
-#endif /* CONFIG_VT && (CONFIG_ADB_KEYBOARD || CONFIG_INPUT) */
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-
-static int __chrp
-chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
- return check_region(from, extent);
-}
-
-static void __chrp
-chrp_ide_request_region(ide_ioreg_t from,
- unsigned int extent,
- const char *name)
-{
- request_region(from, extent, name);
-}
-
-static void __chrp
-chrp_ide_release_region(ide_ioreg_t from,
- unsigned int extent)
-{
- release_region(from, extent);
-}
-
-static void __chrp
-chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
-{
- ide_ioreg_t reg = data_port;
- int i;
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
- }
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-}
-#endif
-
-/*
- * One of the main thing these mappings are needed for is so that
- * xmon can get to the serial port early on. We probably should
- * handle the machines with the mpc106 as well as the python (F50)
- * and the GG2 (longtrail). Actually we should look in the device
- * tree and do the right thing.
- */
-static void __init
-chrp_map_io(void)
-{
- char *name;
-
- /*
- * The code below tends to get removed, please don't take it out.
- * The F50 needs this mapping and it you take it out I'll track you
- * down and slap your hands. If it causes problems please email me.
- * -- Cort <cort@fsmlabs.com>
- */
- name = get_property(find_path_device("/"), "name", NULL);
- if (name && strncmp(name, "IBM-70", 6) == 0
- && strstr(name, "-F50")) {
- io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
- io_block_mapping(0x90000000, 0x90000000, 0x10000000, _PAGE_IO);
- return;
- } else {
- io_block_mapping(0xf8000000, 0xf8000000, 0x04000000, _PAGE_IO);
- }
-}
-
-void __init
-chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r6 )
- {
- initrd_start = r6 + KERNELBASE;
- initrd_end = r6 + r7 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
- isa_io_base = CHRP_ISA_IO_BASE; /* default value */
-
- ppc_md.setup_arch = chrp_setup_arch;
- ppc_md.show_percpuinfo = of_show_percpuinfo;
- ppc_md.show_cpuinfo = chrp_show_cpuinfo;
- ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
-#ifndef CONFIG_POWER4
- ppc_md.init_IRQ = chrp_init_IRQ;
- ppc_md.get_irq = openpic_get_irq;
-#else
- ppc_md.init_IRQ = xics_init_IRQ;
- ppc_md.get_irq = xics_get_irq;
-#endif /* CONFIG_POWER4 */
-
- ppc_md.init = chrp_init2;
-
- ppc_md.restart = chrp_restart;
- ppc_md.power_off = chrp_power_off;
- ppc_md.halt = chrp_halt;
-
- ppc_md.time_init = chrp_time_init;
- ppc_md.set_rtc_time = chrp_set_rtc_time;
- ppc_md.get_rtc_time = chrp_get_rtc_time;
- ppc_md.calibrate_decr = chrp_calibrate_decr;
-
- ppc_md.find_end_of_memory = pmac_find_end_of_memory;
- ppc_md.setup_io_mappings = chrp_map_io;
-
-#ifdef CONFIG_VT
- /* these are adjusted in chrp_init2 if we have an ADB keyboard */
- ppc_md.kbd_setkeycode = pckbd_setkeycode;
- ppc_md.kbd_getkeycode = pckbd_getkeycode;
- ppc_md.kbd_translate = pckbd_translate;
- ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
- ppc_md.kbd_leds = pckbd_leds;
- ppc_md.kbd_init_hw = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
- SYSRQ_KEY = 0x54;
-#endif /* CONFIG_MAGIC_SYSRQ */
-#endif /* CONFIG_VT */
-
- if (rtas_data) {
- struct device_node *rtas;
- unsigned int *p;
-
- rtas = find_devices("rtas");
- if (rtas != NULL) {
- if (get_property(rtas, "display-character", NULL)) {
- ppc_md.progress = rtas_display_progress;
- p = (unsigned int *) get_property
- (rtas, "ibm,display-line-length", NULL);
- if (p)
- max_width = *p;
- } else if (get_property(rtas, "set-indicator", NULL))
- ppc_md.progress = rtas_indicator_progress;
- }
- }
-#ifdef CONFIG_BOOTX_TEXT
- if (ppc_md.progress == NULL && boot_text_mapped)
- ppc_md.progress = btext_progress;
-#endif
-
-#ifdef CONFIG_SMP
-#ifndef CONFIG_POWER4
- ppc_md.smp_ops = &chrp_smp_ops;
-#else
- ppc_md.smp_ops = &xics_smp_ops;
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_SMP */
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
- ppc_ide_md.ide_check_region = chrp_ide_check_region;
- ppc_ide_md.ide_request_region = chrp_ide_request_region;
- ppc_ide_md.ide_release_region = chrp_ide_release_region;
- ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
-#endif
-
- /*
- * Print the banner, then scroll down so boot progress
- * can be printed. -- Cort
- */
- if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
-}
-
-void __chrp
-rtas_display_progress(char *s, unsigned short hex)
-{
- int width;
- char *os = s;
-
- if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
- return;
-
- width = max_width;
- while ( *os )
- {
- if ( (*os == '\n') || (*os == '\r') )
- width = max_width;
- else
- width--;
- call_rtas( "display-character", 1, 1, NULL, *os++ );
- /* if we overwrite the screen length */
- if ( width == 0 )
- while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
- os++;
- }
-
- /*while ( width-- > 0 )*/
- call_rtas( "display-character", 1, 1, NULL, ' ' );
-}
-
-void __chrp
-rtas_indicator_progress(char *s, unsigned short hex)
-{
- call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
- prom_print(s);
- prom_print("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/kernel/chrp_smp.c b/arch/ppc/kernel/chrp_smp.c
deleted file mode 100644
index 505e8587d341..000000000000
--- a/arch/ppc/kernel/chrp_smp.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- * Smp support for CHRP machines.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
- * deal of code from the sparc and intel versions.
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/hardirq.h>
-#include <asm/softirq.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/feature.h>
-#include <asm/time.h>
-
-#include "open_pic.h"
-
-extern unsigned long smp_chrp_cpu_nr;
-
-static int __init
-smp_chrp_probe(void)
-{
- if (smp_chrp_cpu_nr > 1)
- openpic_request_IPIs();
-
- return smp_chrp_cpu_nr;
-}
-
-static void __init
-smp_chrp_kick_cpu(int nr)
-{
- *(unsigned long *)KERNELBASE = nr;
- asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-}
-
-static void __init
-smp_chrp_setup_cpu(int cpu_nr)
-{
- static atomic_t ready = ATOMIC_INIT(1);
- static volatile int frozen = 0;
-
- if (cpu_nr == 0) {
- /* wait for all the others */
- while (atomic_read(&ready) < smp_num_cpus)
- barrier();
- atomic_set(&ready, 1);
- /* freeze the timebase */
- call_rtas("freeze-time-base", 0, 1, NULL);
- mb();
- frozen = 1;
- /* XXX assumes this is not a 601 */
- set_tb(0, 0);
- last_jiffy_stamp(0) = 0;
- while (atomic_read(&ready) < smp_num_cpus)
- barrier();
- /* thaw the timebase again */
- call_rtas("thaw-time-base", 0, 1, NULL);
- mb();
- frozen = 0;
- smp_tb_synchronized = 1;
- } else {
- atomic_inc(&ready);
- while (!frozen)
- barrier();
- set_tb(0, 0);
- last_jiffy_stamp(0) = 0;
- mb();
- atomic_inc(&ready);
- while (frozen)
- barrier();
- }
-
- if (OpenPIC_Addr)
- do_openpic_setup_cpu();
-}
-
-#ifdef CONFIG_POWER4
-static void __chrp
-smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
-{
- /* for now, only do reschedule messages
- since we only have one IPI */
- if (msg != PPC_MSG_RESCHEDULE)
- return;
- for (i = 0; i < smp_num_cpus; ++i) {
- if (target == MSG_ALL || target == i
- || (target == MSG_ALL_BUT_SELF
- && i != smp_processor_id()))
- xics_cause_IPI(i);
- }
-}
-
-static int __chrp
-smp_xics_probe(void)
-{
- return smp_chrp_cpu_nr;
-}
-
-static void __chrp
-smp_xics_setup_cpu(int cpu_nr)
-{
- if (cpu_nr > 0)
- xics_setup_cpu();
-}
-#endif /* CONFIG_POWER4 */
-
-/* CHRP with openpic */
-struct smp_ops_t chrp_smp_ops __chrpdata = {
- smp_openpic_message_pass,
- smp_chrp_probe,
- smp_chrp_kick_cpu,
- smp_chrp_setup_cpu,
-};
-
-#ifdef CONFIG_POWER4
-/* CHRP with new XICS interrupt controller */
-struct smp_ops_t xics_smp_ops __chrpdata = {
- smp_xics_message_pass,
- smp_xics_probe,
- smp_chrp_kick_cpu,
- smp_xics_setup_cpu,
-};
-#endif /* CONFIG_POWER4 */
diff --git a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c
deleted file mode 100644
index cb0d96071969..000000000000
--- a/arch/ppc/kernel/chrp_time.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * BK Id: SCCS/s.chrp_time.c 1.10 09/08/01 15:47:42 paulus
- */
-/*
- * linux/arch/i386/kernel/time.c
- *
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * Adapted for PowerPC (PreP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- * copied and modified from intel version
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/nvram.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-static int nvram_as1 = NVRAM_AS1;
-static int nvram_as0 = NVRAM_AS0;
-static int nvram_data = NVRAM_DATA;
-
-long __init chrp_time_init(void)
-{
- struct device_node *rtcs;
- int base;
-
- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
- if (rtcs == NULL || rtcs->addrs == NULL)
- return 0;
- base = rtcs->addrs[0].address;
- nvram_as1 = 0;
- nvram_as0 = base;
- nvram_data = base + 1;
-
- return 0;
-}
-
-int __chrp chrp_cmos_clock_read(int addr)
-{
- if (nvram_as1 != 0)
- outb(addr>>8, nvram_as1);
- outb(addr, nvram_as0);
- return (inb(nvram_data));
-}
-
-void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
-{
- if (nvram_as1 != 0)
- outb(addr>>8, nvram_as1);
- outb(addr, nvram_as0);
- outb(val, nvram_data);
- return;
-}
-
-/*
- * Set the hardware clock. -- Cort
- */
-int __chrp chrp_set_rtc_time(unsigned long nowtime)
-{
- unsigned char save_control, save_freq_select;
- struct rtc_time tm;
-
- spin_lock(&rtc_lock);
- to_tm(nowtime, &tm);
-
- save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
-
- chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year -= 1900;
- if (!(save_control & RTC_DM_BINARY) || 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);
- }
- chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
- chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
- chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
- chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
- chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
- chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- chrp_cmos_clock_write(save_control, RTC_CONTROL);
- chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
-
- if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
- time_state = TIME_OK;
- spin_unlock(&rtc_lock);
- return 0;
-}
-
-unsigned long __chrp chrp_get_rtc_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- int uip, i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for ( i = 0; i<1000000; i++) {
- uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
- sec = chrp_cmos_clock_read(RTC_SECONDS);
- min = chrp_cmos_clock_read(RTC_MINUTES);
- hour = chrp_cmos_clock_read(RTC_HOURS);
- day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
- mon = chrp_cmos_clock_read(RTC_MONTH);
- year = chrp_cmos_clock_read(RTC_YEAR);
- uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0) break;
- }
-
- if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-
-void __init chrp_calibrate_decr(void)
-{
- struct device_node *cpu;
- unsigned int freq, *fp;
-
- if (via_calibrate_decr())
- return;
-
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- freq = 16666000; /* hardcoded default */
- cpu = find_type_devices("cpu");
- if (cpu != 0) {
- fp = (unsigned int *)
- get_property(cpu, "timebase-frequency", NULL);
- if (fp != 0)
- freq = *fp;
- }
- printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
index f718c1a91667..d6f8eccb3d76 100644
--- a/arch/ppc/kernel/cputable.c
+++ b/arch/ppc/kernel/cputable.c
@@ -26,15 +26,14 @@ extern void __setup_cpu_603(int cpu_nr);
extern void __setup_cpu_604(int cpu_nr);
extern void __setup_cpu_750(int cpu_nr);
extern void __setup_cpu_7400(int cpu_nr);
+extern void __setup_cpu_7410(int cpu_nr);
extern void __setup_cpu_7450(int cpu_nr);
extern void __setup_cpu_power3(int cpu_nr);
-extern void __setup_cpu_power4(int cpu_nr);
extern void __setup_cpu_8xx(int cpu_nr);
extern void __setup_cpu_generic(int cpu_nr);
-#define CLASSIC_PPC (!defined(CONFIG_8xx) && \
- !defined(CONFIG_4xx) && !defined(CONFIG_POWER3) && \
- !defined(CONFIG_POWER4) && !defined(CONFIG_PPC_ISERIES))
+#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
+ !defined(CONFIG_POWER3) && !defined(CONFIG_PPC_ISERIES))
/* This table only contains "desktop" CPUs, it need to be filled with embedded
* ones as well...
@@ -113,16 +112,40 @@ struct cpu_spec cpu_specs[] = {
32, 32,
__setup_cpu_604
},
- { /* 750 (0x4202, don't support TAU ?) */
- 0xffffffff, 0x00084202, "750",
+ { /* 740/750 (0x4202, don't support TAU ?) */
+ 0xffffffff, 0x00084202, "740/750",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE,
COMMON_PPC,
32, 32,
__setup_cpu_750
},
- { /* 750CX */
- 0xffffff00, 0x00082200, "750CX",
+ { /* 745/755 */
+ 0xfffff000, 0x00083000, "745/755",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
+ COMMON_PPC,
+ 32, 32,
+ __setup_cpu_750
+ },
+ { /* 750CX (80100 and 8010x?) */
+ 0xfffffff0, 0x00080100, "750CX",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
+ COMMON_PPC,
+ 32, 32,
+ __setup_cpu_750
+ },
+ { /* 750CX (82201 and 82202) */
+ 0xfffffff0, 0x00082200, "750CX",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
+ COMMON_PPC,
+ 32, 32,
+ __setup_cpu_750
+ },
+ { /* 750CXe (82214) */
+ 0xfffffff0, 0x00082210, "750CXe",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
COMMON_PPC,
@@ -159,9 +182,18 @@ struct cpu_spec cpu_specs[] = {
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
- __setup_cpu_7400
+ __setup_cpu_7410
},
- { /* 7450 */
+ { /* 7450 2.0 - no doze/nap */
+ 0xffffffff, 0x80000200, "7450",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
+ COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
+ 32, 32,
+ __setup_cpu_7450
+ },
+ { /* 7450 others */
0xffff0000, 0x80000000, "7450",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP |
@@ -215,15 +247,6 @@ struct cpu_spec cpu_specs[] = {
__setup_cpu_power3
},
#endif /* CONFIG_PPC64BRIDGE */
-#ifdef CONFIG_POWER4
- { /* Power4 */
- 0xffff0000, 0x00350000, "Power4",
- CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
- COMMON_PPC | PPC_FEATURE_64,
- 128, 128,
- __setup_cpu_power4
- },
-#endif /* CONFIG_POWER4 */
#ifdef CONFIG_8xx
{ /* 8xx */
0xffff0000, 0x00500000, "8xx",
@@ -270,6 +293,20 @@ struct cpu_spec cpu_specs[] = {
32, 32,
0, /*__setup_cpu_405 */
},
+ { /* STB 04xxx */
+ 0xffff0000, 0x41810000, "STB04xxx",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+ PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ 32, 32,
+ 0, /*__setup_cpu_405 */
+ },
+ { /* NP405L */
+ 0xffff0000, 0x41610000, "NP405L",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+ PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ 16, 8,
+ 0, /*__setup_cpu_405 */
+ },
#endif /* CONFIG_4xx */
#if !CLASSIC_PPC
{ /* default match */
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index cb4ff46032f5..70fae23e5ffd 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.entry.S 1.22 08/15/01 22:43:06 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* PowerPC version
@@ -11,6 +11,7 @@
* rewritten by Paul Mackerras.
* Copyright (C) 1996 Paul Mackerras.
* MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ * Adaptations for iSeries Lpar by Mike Corrigan & Dave Boutcher
*
* This file contains the system call entry code, context switch
* code, and exception/interrupt return code for PowerPC.
@@ -22,7 +23,6 @@
*
*/
-#include "ppc_asm.h"
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sys.h>
@@ -31,6 +31,11 @@
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
+#ifdef CONFIG_PPC_ISERIES
+#include "iSeries_asm.h"
+#endif /* CONFIG_PPC_ISERIES */
#undef SHOW_SYSCALLS
#undef SHOW_SYSCALLS_TASK
@@ -45,6 +50,10 @@ show_syscalls_task:
* Handle a system call.
*/
.text
+ .stabs "arch/ppc/kernel/",N_SO,0,0,0f
+ .stabs "entry.S",N_SO,0,0,0f
+0:
+
_GLOBAL(DoSyscall)
stw r0,THREAD+LAST_SYSCALL(r2)
lwz r11,_CCR(r1) /* Clear SO bit in CR */
@@ -86,8 +95,8 @@ _GLOBAL(DoSyscall)
beq- 10f
cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */
beq- 16f
- lwz r10,TASK_PTRACE(r2)
- andi. r10,r10,PT_TRACESYS
+ lbz r10,SYSCALL_TRACE(r2)
+ cmpwi r10,0
bne- 50f
cmpli 0,r0,NR_syscalls
bge- 66f
@@ -142,7 +151,7 @@ ret_from_syscall_1:
bge ret_from_except
b 20b
/* Traced system call support */
-50: bl syscall_trace
+50: bl do_syscall_trace
lwz r0,GPR0(r1) /* Restore original registers */
lwz r3,GPR3(r1)
lwz r4,GPR4(r1)
@@ -177,7 +186,7 @@ ret_from_syscall_2:
oris r10,r10,0x1000
stw r10,_CCR(r1)
60: stw r3,GPR3(r1) /* Update return value */
- bl syscall_trace
+ bl do_syscall_trace
b ret_from_except
66: li r3,ENOSYS
b 52b
@@ -197,6 +206,9 @@ ret_from_syscall_2:
* On entry, r3 points to the THREAD for the current task, r4
* points to the THREAD for the new task.
*
+ * This routine is always called with interrupts disabled
+ * (soft disabled for iSeries).
+ *
* Note: there are two ways to get to the "going out" portion
* of this code; either by coming in via the entry (_switch)
* or via "fork" which must set up an environment equivalent
@@ -216,6 +228,7 @@ _GLOBAL(_switch)
SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1)
mflr r20 /* Return to switch caller */
+ stw r20,INT_FRAME_SIZE+4(r1)
mfmsr r22
li r0,MSR_FP /* Disable floating-point */
#ifdef CONFIG_ALTIVEC
@@ -223,10 +236,12 @@ BEGIN_FTR_SECTION
oris r0,r0,MSR_VEC@h /* Disable altivec */
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif /* CONFIG_ALTIVEC */
+ and. r0,r0,r22 /* FP or altivec enabled? */
+ beq+ 1f
andc r22,r22,r0
mtmsr r22
isync
- stw r20,_NIP(r1)
+1: stw r20,_NIP(r1)
stw r22,_MSR(r1)
stw r20,_LINK(r1)
mfcr r20
@@ -261,9 +276,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
.globl ret_from_fork
ret_from_fork:
bl schedule_tail
-#error lwz r0,TASK_PTRACE(r2)
- andi. r0,r0,PT_TRACESYS
-#error bnel- syscall_trace
+ lbz r0,SYSCALL_TRACE(r2)
+ cmpwi r0,0
+ bnel- do_syscall_trace
b ret_from_except
.globl ret_from_intercept
@@ -276,94 +291,115 @@ ret_from_intercept:
beq restore
.globl ret_from_except
ret_from_except:
- lwz r3,_MSR(r1) /* Returning to user mode? */
- andi. r3,r3,MSR_PR
- beq+ do_signal_ret /* if so, check need_resched and signals */
-#error lwz r3,NEED_RESCHED(r2)
- cmpi 0,r3,0 /* check need_resched flag */
- beq+ 7f
- bl schedule
-#error 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */
- cmpwi 0,r5,0
- beq+ do_signal_ret
- li r3,0
- addi r4,r1,STACK_FRAME_OVERHEAD
-#error bl do_signal
- .globl do_signal_ret
-do_signal_ret:
- .globl ret_to_user_hook
-ret_to_user_hook:
- nop
-restore:
- lwz r3,_XER(r1)
- mtspr XER,r3
- REST_10GPRS(9,r1)
- REST_10GPRS(19,r1)
- REST_2GPRS(29,r1)
+ REST_10GPRS(13,r1)
+ REST_8GPRS(23,r1)
REST_GPR(31,r1)
- /* make sure we hard disable here, even if rtl is active, to protect
- * SRR[01] and SPRG2 -- Cort
- */
- mfmsr r0 /* Get current interrupt state */
- rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
+ /* Hard-disable interrupts so that current->work can't change
+ * between when we test it and when we return from the interrupt. */
+recheck:
+ mfmsr r10
+ rlwinm r0,r10,0,17,15 /* clear MSR_EE in r0 */
+#ifdef CONFIG_4xx
+ rlwinm r0,r0,0,23,21 /* clear MSR_DE in r0 */
+#endif
SYNC /* Some chip revs have problems here... */
mtmsr r0 /* Update machine state */
- stwcx. r0,0,r1 /* to clear the reservation */
+ lwz r3,_MSR(r1) /* Returning to user mode? */
+ andi. r3,r3,MSR_PR
+ beq+ restore /* if not, just restore regs and return */
+
+ /* Check current->work */
+ lwz r3,TASK_WORK(r2)
+ rlwinm. r0,r3,0,16,7 /* need_resched, sigpending, notify_resume */
+ bne do_work
+
+ .globl ret_to_user_hook
+ret_to_user_hook:
+ nop
- /* if returning to user mode, set new sprg2 and save kernel SP */
- lwz r0,_MSR(r1)
- andi. r0,r0,MSR_PR
- beq+ 1f
#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
lwz r0,THREAD+THREAD_VRSAVE(r2)
mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif /* CONFIG_ALTIVEC */
+
addi r0,r1,INT_FRAME_SIZE /* size of frame */
stw r0,THREAD+KSP(r2) /* save kernel stack pointer */
+
+#ifndef CONFIG_PPC_ISERIES
tophys(r8,r1)
CLR_TOP32(r8)
mtspr SPRG2,r8 /* phys exception stack pointer */
-1:
+#else /* CONFIG_PPC_ISERIES */
+ mfspr r2,SPRG1 /* Get Paca address */
+ stw r1,PACAKSAVE(r2) /* save exception stack pointer */
+#endif /* CONFIG_PPC_ISERIES */
+
+ /* interrupts are hard-disabled at this point */
+restore:
+ REST_8GPRS(4, r1)
+ REST_GPR(12, r1)
+ lwz r3,_XER(r1)
+ mtspr XER,r3
+
+ PPC405_ERR77(0,r1)
+ stwcx. r0,0,r1 /* to clear the reservation */
+
lwz r3,_CTR(r1)
lwz r0,_LINK(r1)
mtctr r3
mtlr r0
- REST_4GPRS(3, r1)
- REST_2GPRS(7, r1)
- /* We have to "dummy" load from the context save area in case
- * these instructions cause an MMU fault. If this happens
- * after we load SRR0/SRR1, our return context is hosed. -- Dan
- */
- lwz r0,GPR0(r1)
- lwz r0,GPR2(r1)
- lwz r0,GPR1(r1)
+ lwz r0,_MSR(r1)
+ lwz r3,_CCR(r1)
+ FIX_SRR1(r0,r2)
+ lwz r2,_NIP(r1)
+ mtcrf 0xFF,r3
- /* We re-use r3,r4 here (the load above was to cause the MMU
- * fault if necessary). Using r3,r4 removes the need to "dummy"
- * load the CCR and NIP. Since we load them we may as well
- * use them.
+ /*
+ * We can't afford to take an exception between setting SRR0/1
+ * and the rfi. Since GPR0(r1) .. GPR3(r1) are in the same cache
+ * line, loading r3 here should mean that we should have a HPTE
+ * (for classic PPC) or TLB entry (for 4xx/8xx) for that cache
+ * line, even if it isn't covered by a BAT register.
+ * In addition, the cache line itself will be in L1 cache.
+ * There is still the possibility of the HPTE getting evicted
+ * on SMP systems.
*/
- lwz r3,_CCR(r1)
- lwz r4,_NIP(r1)
+ lwz r3,GPR3(r1)
- lwz r0,_MSR(r1)
- FIX_SRR1(r0,r2)
mtspr SRR1,r0
- mtcrf 0xFF,r3
- mtspr SRR0,r4
+ mtspr SRR0,r2
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
- lwz r3,GPR3(r1)
- lwz r4,GPR4(r1)
lwz r1,GPR1(r1)
SYNC
+ PPC405_ERR77_SYNC
RFI
+do_work:
+ ori r10,r10,MSR_EE
+ SYNC
+ mtmsr r10 /* hard-enable interrupts */
+ rlwinm. r0,r3,0,0,7 /* test need_resched */
+ beq 1f
+ bl schedule
+ b recheck
+1:
+ rlwinm. r0,r3,0,16,23 /* test sigpending */
+ beq 2f
+ li r3,0
+ addi r4,r1,STACK_FRAME_OVERHEAD
+ bl do_signal
+ b recheck
+2:
+ /* nobody uses work.notify_resume yet */
+ li r0,0
+ stb r0,NOTIFY_RESUME(r2)
+ b recheck
/*
* PROM code for specific machines follows. Put it
@@ -375,8 +411,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
* On CHRP, the Run-Time Abstraction Services (RTAS) have to be
* called with the MMU off.
*/
- .globl enter_rtas
-enter_rtas:
+_GLOBAL(enter_rtas)
mflr r0
stw r0,20(r1)
lis r4,rtas_data@ha
@@ -391,9 +426,9 @@ enter_rtas:
mfmsr r9
stw r9,8(r1)
li r0,0
- ori r0,r0,MSR_EE|MSR_SE|MSR_BE
+ ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_FE0|MSR_FE1
andc r0,r9,r0
- li r10,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP
+ li r10,MSR_IR|MSR_DR|MSR_FP
andc r9,r0,r10
SYNC /* disable interrupts so SRR0/1 */
mtmsr r0 /* don't get trashed */
diff --git a/arch/ppc/kernel/error_log.c b/arch/ppc/kernel/error_log.c
deleted file mode 100644
index b414b27fb174..000000000000
--- a/arch/ppc/kernel/error_log.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * BK Id: SCCS/s.error_log.c 1.6 05/17/01 18:14:21 cort
- */
-/*
- * arch/ppc/kernel/error_log.c
- *
- * Copyright (c) 2000 Tilmann Bitterberg
- * (tilmann@bitterberg.de)
- *
- * Error processing of errors found by rtas even-scan routine
- * which is done with every heartbeat. (chrp_setup.c)
- */
-
-#include <linux/sched.h>
-
-#include <asm/prom.h>
-
-#include "error_log.h"
-
-/* ****************************************************************** */
-/*
- * EVENT-SCAN
- * The whole stuff below here doesn't take any action when it found
- * an error, it just prints as much information as possible and
- * then its up to the user to decide what to do.
- *
- * Returns 0 if no errors were found
- * Returns 1 if there may be more errors
- */
-int ppc_rtas_errorlog_scan(void)
-{
-const char *_errlog_severity[] = {
-#ifdef VERBOSE_ERRORS
- "No Error\n\t\
-Should require no further information",
- "Event\n\t\
-This is not really an error, it is an event. I use events\n\t\
-to communicate with RTAS back and forth.",
- "Warning\n\t\
-Indicates a non-state-losing error, either fully recovered\n\t\
-by RTAS or not needing recovery. Ignore it.",
- "Error sync\n\t\
-May only be fatal to a certain program or thread. Recovery\n\t\
-and continuation is possible, if I only had a handler for\n\t\
-this. Less serious",
- "Error\n\t\
-Less serious, but still causing a loss of data and state.\n\t\
-I can't tell you exactly what to do, You have to decide\n\t\
-with help from the target and initiator field, what kind\n\t\
-of further actions may take place.",
- "Fatal\n\t\
-Represent a permanent hardware failure and I believe this\n\t\
-affects my overall performance and behaviour. I would not\n\t\
-attempt to continue normal operation."
-#else
- "No Error",
- "Event",
- "Warning",
- "Error sync",
- "Error",
- "Fatal"
-#endif /* VERBOSE_ERRORS */
-};
-
-#if 0 /* unused?? */
-const char *_errlog_disposition[] = {
-#ifdef VERBOSE_ERRORS
- "Fully recovered\n\t\
-There was an error, but it is fully recovered by RTAS.",
- "Limited recovery\n\t\
-RTAS was able to recover the state of the machine, but some\n\t\
-feature of the machine has been disabled or lost (for example\n\t\
-error checking) or performance may suffer.",
- "Not recovered\n\t\
-Whether RTAS did not try to recover anything or recovery failed:\n\t\
-HOUSTON, WE HAVE A PROBLEM!"
-#else
- "Fully recovered",
- "Limited recovery",
- "Not recovered"
-#endif /* VERBOSE_ERRORS */
-};
-#endif
-
-const char *_errlog_extended[] = {
-#ifdef VERBOSE_ERRORS
- "Not present\n\t\
-Sad, the RTAS call didn't return an extended error log.",
- "Present\n\t\
-The extended log is present and hopefully it contains a lot of\n\t\
-useful information, which leads to the solution of the problem."
-#else
- "Not present",
- "Present"
-#endif /* VERBOSE_ERRORS */
-};
-
-const char *_errlog_initiator[] = {
- "Unknown or not applicable",
- "CPU",
- "PCI",
- "ISA",
- "Memory",
- "Power management"
-};
-
-const char *_errlog_target[] = {
- "Unknown or not applicable",
- "CPU",
- "PCI",
- "ISA",
- "Memory",
- "Power management"
-};
- rtas_error_log error_log;
- char logdata[1024];
- int error;
-#if 0 /* unused?? */
- int retries = 0; /* if HW error, try 10 times */
-#endif
-
- error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log,
- INTERNAL_ERROR | EPOW_WARNING,
- 0, __pa(logdata), 1024);
-
- if (error == 1) /* no errors found */
- return 0;
-
- if (error == -1) {
- printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n");
- return 0;
- }
- if (error_log.version != 1)
- printk(KERN_WARNING "Unknown version (%d), please implement me\n",
- error_log.version);
-
- switch (error_log.disposition) {
- case DISP_FULLY_RECOVERED:
- /* there was an error, but everything is fine now */
- return 0;
- case DISP_NOT_RECOVERED:
- printk("We have a really serious Problem!\n");
- case DISP_LIMITED_RECOVERY:
- printk("Error classification\n");
- printk("Severity : %s\n",
- ppc_rtas_errorlog_check_severity (error_log));
- printk("Initiator : %s\n",
- ppc_rtas_errorlog_check_initiator (error_log));
- printk("Target : %s\n",
- ppc_rtas_errorlog_check_target (error_log));
- printk("Type : %s\n",
- ppc_rtas_errorlog_check_type (error_log));
- printk("Ext. log : %s\n",
- ppc_rtas_errorlog_check_extended (error_log));
- if (error_log.extended)
- ppc_rtas_errorlog_disect_extended (logdata);
- return 1;
- default:
- /* nothing */
- break;
- }
- return 0;
-}
-/* ****************************************************************** */
-const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log)
-{
- const char *_errlog_type[] = {
- "unknown type",
- "too many tries failed",
- "TCE error",
- "RTAS device failed",
- "target timed out",
- "parity error on data", /* 5 */
- "parity error on address",
- "parity error on external cache",
- "access to invalid address",
- "uncorrectable ECC error",
- "corrected ECC error" /* 10 */
- };
- if (error_log.type == TYPE_EPOW)
- return "EPOW";
- if (error_log.type >= TYPE_PMGM_POWER_SW_ON)
- return "PowerMGM Event (not handled right now)";
- return _errlog_type[error_log.type];
-}
-
diff --git a/arch/ppc/kernel/error_log.h b/arch/ppc/kernel/error_log.h
deleted file mode 100644
index bb162a592e3a..000000000000
--- a/arch/ppc/kernel/error_log.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * BK Id: SCCS/s.error_log.h 1.5 05/17/01 18:14:21 cort
- */
-#ifndef __ERROR_LOG_H__
-#define __ERROR_LOG_H__
-
-#define VERBOSE_ERRORS 1 /* Maybe I enlarge the kernel too much */
-#undef VERBOSE_ERRORS
-
-/* Event classes */
-/* XXX: Endianess correct? NOW*/
-#define INTERNAL_ERROR 0x80000000 /* set bit 0 */
-#define EPOW_WARNING 0x40000000 /* set bit 1 */
-#define POWERMGM_EVENTS 0x20000000 /* set bit 2 */
-
-/* event-scan returns */
-#define SEVERITY_FATAL 0x5
-#define SEVERITY_ERROR 0x4
-#define SEVERITY_ERROR_SYNC 0x3
-#define SEVERITY_WARNING 0x2
-#define SEVERITY_EVENT 0x1
-#define SEVERITY_NO_ERROR 0x0
-#define DISP_FULLY_RECOVERED 0x0
-#define DISP_LIMITED_RECOVERY 0x1
-#define DISP_NOT_RECOVERED 0x2
-#define PART_PRESENT 0x0
-#define PART_NOT_PRESENT 0x1
-#define INITIATOR_UNKNOWN 0x0
-#define INITIATOR_CPU 0x1
-#define INITIATOR_PCI 0x2
-#define INITIATOR_ISA 0x3
-#define INITIATOR_MEMORY 0x4
-#define INITIATOR_POWERMGM 0x5
-#define TARGET_UNKNOWN 0x0
-#define TARGET_CPU 0x1
-#define TARGET_PCI 0x2
-#define TARGET_ISA 0x3
-#define TARGET_MEMORY 0x4
-#define TARGET_POWERMGM 0x5
-#define TYPE_RETRY 0x01
-#define TYPE_TCE_ERR 0x02
-#define TYPE_INTERN_DEV_FAIL 0x03
-#define TYPE_TIMEOUT 0x04
-#define TYPE_DATA_PARITY 0x05
-#define TYPE_ADDR_PARITY 0x06
-#define TYPE_CACHE_PARITY 0x07
-#define TYPE_ADDR_INVALID 0x08
-#define TYPE_ECC_UNCORR 0x09
-#define TYPE_ECC_CORR 0x0a
-#define TYPE_EPOW 0x40
-/* I don't add PowerMGM events right now, this is a different topic */
-#define TYPE_PMGM_POWER_SW_ON 0x60
-#define TYPE_PMGM_POWER_SW_OFF 0x61
-#define TYPE_PMGM_LID_OPEN 0x62
-#define TYPE_PMGM_LID_CLOSE 0x63
-#define TYPE_PMGM_SLEEP_BTN 0x64
-#define TYPE_PMGM_WAKE_BTN 0x65
-#define TYPE_PMGM_BATTERY_WARN 0x66
-#define TYPE_PMGM_BATTERY_CRIT 0x67
-#define TYPE_PMGM_SWITCH_TO_BAT 0x68
-#define TYPE_PMGM_SWITCH_TO_AC 0x69
-#define TYPE_PMGM_KBD_OR_MOUSE 0x6a
-#define TYPE_PMGM_ENCLOS_OPEN 0x6b
-#define TYPE_PMGM_ENCLOS_CLOSED 0x6c
-#define TYPE_PMGM_RING_INDICATE 0x6d
-#define TYPE_PMGM_LAN_ATTENTION 0x6e
-#define TYPE_PMGM_TIME_ALARM 0x6f
-#define TYPE_PMGM_CONFIG_CHANGE 0x70
-#define TYPE_PMGM_SERVICE_PROC 0x71
-
-typedef struct _rtas_error_log {
- unsigned long version:8; /* Architectural version */
- unsigned long severity:3; /* Severity level of error */
- unsigned long disposition:2; /* Degree of recovery */
- unsigned long extended:1; /* extended log present? */
- unsigned long /* reserved */ :2; /* Reserved for future use */
- unsigned long initiator:4; /* Initiator of event */
- unsigned long target:4; /* Target of failed operation */
- unsigned long type:8; /* General event or error*/
- unsigned long extended_log_length:32; /* length in bytes */
-} rtas_error_log;
-
-/* ****************************************************************** */
-#define ppc_rtas_errorlog_check_severity(x) \
- (_errlog_severity[x.severity])
-#define ppc_rtas_errorlog_check_target(x) \
- (_errlog_target[x.target])
-#define ppc_rtas_errorlog_check_initiator(x) \
- (_errlog_initiator[x.initiator])
-#define ppc_rtas_errorlog_check_extended(x) \
- (_errlog_extended[x.extended])
-#define ppc_rtas_errorlog_disect_extended(x) \
- do { /* implement me */ } while(0)
-extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log);
-extern int ppc_rtas_errorlog_scan(void);
-
-
-#endif /* __ERROR_LOG_H__ */
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
deleted file mode 100644
index 21c1d9e20f2f..000000000000
--- a/arch/ppc/kernel/feature.c
+++ /dev/null
@@ -1,1300 +0,0 @@
-/*
- * BK Id: SCCS/s.feature.c 1.21 09/08/01 15:47:42 paulus
- */
-/*
- * arch/ppc/kernel/feature.c
- *
- * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- * Ben. Herrenschmidt (benh@kernel.crashing.org)
- *
- * 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 <linux/config.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/sections.h>
-#include <asm/errno.h>
-#include <asm/ohare.h>
-#include <asm/heathrow.h>
-#include <asm/keylargo.h>
-#include <asm/uninorth.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/feature.h>
-#include <asm/dbdma.h>
-#include <asm/machdep.h>
-
-#undef DEBUG_FEATURE
-
-#define MAX_FEATURE_CONTROLLERS 2
-#define FREG(c,r) (&(((c)->reg)[(r)>>2]))
-
-/* Keylargo reg. access. */
-#define KL_FCR(r) (keylargo_base + ((r) >> 2))
-#define KL_IN(r) (in_le32(KL_FCR(r)))
-#define KL_OUT(r,v) (out_le32(KL_FCR(r), (v)))
-#define KL_BIS(r,v) (KL_OUT((r), KL_IN(r) | (v)))
-#define KL_BIC(r,v) (KL_OUT((r), KL_IN(r) & ~(v)))
-#define KL_GPIO_IN(r) (in_8(((volatile u8 *)keylargo_base)+(r)))
-#define KL_GPIO_OUT(r,v) (out_8(((volatile u8 *)keylargo_base)+(r), (v)))
-#define KL_LOCK() spin_lock_irqsave(&keylargo->lock, flags)
-#define KL_UNLOCK() spin_unlock_irqrestore(&keylargo->lock, flags)
-
-/* Uni-N reg. access. Note that Uni-N regs are big endian */
-#define UN_REG(r) (uninorth_base + ((r) >> 2))
-#define UN_IN(r) (in_be32(UN_REG(r)))
-#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
-#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
-#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
-
-typedef struct feature_bit {
- int reg; /* reg. offset from mac-io base */
- unsigned int polarity; /* 0 = normal, 1 = inverse */
- unsigned int mask; /* bit mask */
-} fbit;
-
-/* Those features concern for OHare-based PowerBooks (2400, 3400, 3500)
- */
-static fbit feature_bits_ohare_pbook[] __pmacdata = {
- {0x38,0,0}, /* FEATURE_null */
- {0x38,0,OH_SCC_RESET}, /* FEATURE_Serial_reset */
- {0x38,0,OH_SCC_ENABLE}, /* FEATURE_Serial_enable */
- {0x38,0,OH_SCCA_IO}, /* FEATURE_Serial_IO_A */
- {0x38,0,OH_SCCB_IO}, /* FEATURE_Serial_IO_B */
- {0x38,0,OH_FLOPPY_ENABLE}, /* FEATURE_SWIM3_enable */
- {0x38,0,OH_MESH_ENABLE}, /* FEATURE_MESH_enable */
- {0x38,0,OH_IDE0_ENABLE}, /* FEATURE_IDE0_enable */
- {0x38,1,OH_IDE0_RESET_N}, /* FEATURE_IDE0_reset */
- {0x38,0,OH_IOBUS_ENABLE}, /* FEATURE_IOBUS_enable */
- {0x38,1,OH_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
- {0x38,1,OH_BAY_POWER_N}, /* FEATURE_Mediabay_power */
- {0x38,0,OH_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,OH_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
- {0x38,1,OH_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
- {0x38,0,OH_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
- {0x38,0,0}, /* FEATURE_BMac_reset */
- {0x38,0,0}, /* FEATURE_BMac_IO_enable */
- {0x38,0,0}, /* FEATURE_Modem_power */
- {0x38,0,0}, /* FEATURE_Slow_SCC_PCLK */
- {0x38,0,0}, /* FEATURE_Sound_Power */
- {0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
- {0x38,0,0}, /* FEATURE_IDE2_enable */
- {0x38,0,0}, /* FEATURE_IDE2_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
- {0x38,0,0}, /* FEATURE_Mediabay_content */
- {0x38,0,0}, /* FEATURE_Airport_reset */
-};
-
-/* Those bits concern heathrow-based desktop machines (Beige G3s). We have removed
- * the SCC related bits and init them once. They have proven to occasionally cause
- * problems with the desktop units.
- */
-static fbit feature_bits_heathrow[] __pmacdata = {
- {0x38,0,0}, /* FEATURE_null */
- {0x38,0,0}, /* FEATURE_Serial_reset */
- {0x38,0,0}, /* FEATURE_Serial_enable */
- {0x38,0,0}, /* FEATURE_Serial_IO_A */
- {0x38,0,0}, /* FEATURE_Serial_IO_B */
- {0x38,0,HRW_SWIM_ENABLE}, /* FEATURE_SWIM3_enable */
- {0x38,0,HRW_MESH_ENABLE}, /* FEATURE_MESH_enable */
- {0x38,0,HRW_IDE0_ENABLE}, /* FEATURE_IDE0_enable */
- {0x38,1,HRW_IDE0_RESET_N}, /* FEATURE_IDE0_reset */
- {0x38,0,HRW_IOBUS_ENABLE}, /* FEATURE_IOBUS_enable */
- {0x38,1,0}, /* FEATURE_Mediabay_reset */
- {0x38,1,0}, /* FEATURE_Mediabay_power */
- {0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
- {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
- {0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
- {0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
- {0x38,1,0}, /* FEATURE_Modem_power */
- {0x38,0,HRW_SLOW_SCC_PCLK}, /* FEATURE_Slow_SCC_PCLK */
- {0x38,1,0}, /* FEATURE_Sound_Power */
- {0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
- {0x38,0,0}, /* FEATURE_IDE2_enable */
- {0x38,0,0}, /* FEATURE_IDE2_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
- {0x38,0,0}, /* FEATURE_Mediabay_content */
- {0x38,0,0}, /* FEATURE_Airport_reset */
-};
-
-/* Those bits concern heathrow-based PowerBooks (wallstreet/mainstreet).
- * Heathrow-based desktop macs (Beige G3s) are _not_ handled here
- */
-static fbit feature_bits_wallstreet[] __pmacdata = {
- {0x38,0,0}, /* FEATURE_null */
- {0x38,0,HRW_RESET_SCC}, /* FEATURE_Serial_reset */
- {0x38,0,HRW_SCC_ENABLE}, /* FEATURE_Serial_enable */
- {0x38,0,HRW_SCCA_IO}, /* FEATURE_Serial_IO_A */
- {0x38,0,HRW_SCCB_IO}, /* FEATURE_Serial_IO_B */
- {0x38,0,HRW_SWIM_ENABLE}, /* FEATURE_SWIM3_enable */
- {0x38,0,HRW_MESH_ENABLE}, /* FEATURE_MESH_enable */
- {0x38,0,HRW_IDE0_ENABLE}, /* FEATURE_IDE0_enable */
- {0x38,1,HRW_IDE0_RESET_N}, /* FEATURE_IDE0_reset */
- {0x38,0,HRW_IOBUS_ENABLE}, /* FEATURE_IOBUS_enable */
- {0x38,1,HRW_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
- {0x38,1,HRW_BAY_POWER_N}, /* FEATURE_Mediabay_power */
- {0x38,0,HRW_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
- {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
- {0x38,0,HRW_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
- {0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
- {0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
- {0x38,1,HRW_MODEM_POWER_N}, /* FEATURE_Modem_power */
- {0x38,0,HRW_SLOW_SCC_PCLK}, /* FEATURE_Slow_SCC_PCLK */
- {0x38,1,HRW_SOUND_POWER_N}, /* FEATURE_Sound_Power */
- {0x38,0,HRW_SOUND_CLK_ENABLE}, /* FEATURE_Sound_CLK_Enable */
- {0x38,0,0}, /* FEATURE_IDE2_enable */
- {0x38,0,0}, /* FEATURE_IDE2_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
- {0x38,0,0}, /* FEATURE_Mediabay_content */
- {0x38,0,0}, /* FEATURE_Airport_reset */
-};
-
-/*
- * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
- * Mostly the same as the heathrow. They are used on both PowerBooks
- * and desktop machines using the paddington chip
- */
-static fbit feature_bits_paddington[] __pmacdata = {
- {0x38,0,0}, /* FEATURE_null */
- {0x38,0,PADD_RESET_SCC}, /* FEATURE_Serial_reset */
- {0x38,0,HRW_SCC_ENABLE}, /* FEATURE_Serial_enable */
- {0x38,0,HRW_SCCA_IO}, /* FEATURE_Serial_IO_A */
- {0x38,0,HRW_SCCB_IO}, /* FEATURE_Serial_IO_B */
- {0x38,0,HRW_SWIM_ENABLE}, /* FEATURE_SWIM3_enable */
- {0x38,0,HRW_MESH_ENABLE}, /* FEATURE_MESH_enable */
- {0x38,0,HRW_IDE0_ENABLE}, /* FEATURE_IDE0_enable */
- {0x38,1,HRW_IDE0_RESET_N}, /* FEATURE_IDE0_reset */
- {0x38,0,HRW_IOBUS_ENABLE}, /* FEATURE_IOBUS_enable */
- {0x38,1,HRW_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
- {0x38,1,HRW_BAY_POWER_N}, /* FEATURE_Mediabay_power */
- {0x38,0,HRW_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
- {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
- {0x38,0,HRW_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
- {0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
- {0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
- {0x38,1,PADD_MODEM_POWER_N}, /* FEATURE_Modem_power */
- {0x38,0,HRW_SLOW_SCC_PCLK}, /* FEATURE_Slow_SCC_PCLK */
- {0x38,1,HRW_SOUND_POWER_N}, /* FEATURE_Sound_Power */
- {0x38,0,HRW_SOUND_CLK_ENABLE}, /* FEATURE_Sound_CLK_Enable */
- {0x38,0,0}, /* FEATURE_IDE2_enable */
- {0x38,0,0}, /* FEATURE_IDE2_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
- {0x38,0,0}, /* FEATURE_Mediabay_content */
- {0x38,0,0}, /* FEATURE_Airport_reset */
-};
-
-/* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
- * Note: Different sets may be needed for iBook, especially for sound
- */
-static fbit feature_bits_keylargo[] __pmacdata = {
- {0x38,0,0}, /* FEATURE_null */
- {0x38,0,KL0_SCC_RESET}, /* FEATURE_Serial_reset */
- {0x38,0,KL0_SERIAL_ENABLE}, /* FEATURE_Serial_enable */
- {0x38,0,KL0_SCC_A_INTF_ENABLE}, /* FEATURE_Serial_IO_A */
- {0x38,0,KL0_SCC_B_INTF_ENABLE}, /* FEATURE_Serial_IO_B */
- {0x38,0,0}, /* FEATURE_SWIM3_enable */
- {0x38,0,0}, /* FEATURE_MESH_enable */
- {0x3c,0,KL1_EIDE0_ENABLE}, /* FEATURE_IDE0_enable */
- {0x3c,1,KL1_EIDE0_RESET_N}, /* FEATURE_IDE0_reset */
- {0x38,0,0}, /* FEATURE_IOBUS_enable */
- {0x34,1,KL_MBCR_MB0_DEV_RESET}, /* FEATURE_Mediabay_reset */
- {0x34,1,KL_MBCR_MB0_DEV_POWER}, /* FEATURE_Mediabay_power */
- {0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
- {0x3c,0,KL1_EIDE1_ENABLE}, /* FEATURE_IDE1_enable */
- {0x3c,1,KL1_EIDE1_RESET_N}, /* FEATURE_IDE1_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
- {0x38,0,0}, /* FEATURE_BMac_reset */
- {0x38,0,0}, /* FEATURE_BMac_IO_enable */
- {0x40,1,KL2_MODEM_POWER_N}, /* FEATURE_Modem_power */
- {0x38,0,0}, /* FEATURE_Slow_SCC_PCLK */
- {0x38,0,0}, /* FEATURE_Sound_Power */
- {0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
- {0x3c,0,KL1_UIDE_ENABLE}, /* FEATURE_IDE2_enable */
- {0x3c,1,KL1_UIDE_RESET_N}, /* FEATURE_IDE2_reset */
- {0x34,0,KL_MBCR_MB0_DEV_ENABLE},/* FEATURE_Mediabay_IDE_switch */
- {0x34,0,KL_MBCR_MB0_ENABLE}, /* FEATURE_Mediabay_content */
- {0x40,1,KL2_AIRPORT_RESET_N}, /* FEATURE_Airport_reset */
-};
-
-/* definition of a feature controller object */
-struct feature_controller {
- fbit* bits;
- volatile u32* reg;
- struct device_node* device;
- spinlock_t lock;
-};
-
-/* static functions */
-static struct feature_controller*
-feature_add_controller(struct device_node *controller_device, fbit* bits);
-
-static struct feature_controller*
-feature_lookup_controller(struct device_node *device);
-
-static void uninorth_init(void);
-static void keylargo_init(void);
-#ifdef CONFIG_PMAC_PBOOK
-static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
-static void heathrow_wakeup(struct feature_controller* ctrler);
-static void core99_prepare_for_sleep(struct feature_controller* ctrler);
-static void core99_wake_up(struct feature_controller* ctrler);
-#endif /* CONFIG_PMAC_PBOOK */
-
-/* static variables */
-static struct feature_controller controllers[MAX_FEATURE_CONTROLLERS];
-static int controller_count = 0;
-
-/* Core99 stuffs */
-/*static*/ volatile u32* uninorth_base;
-static volatile u32* keylargo_base;
-static struct feature_controller* keylargo;
-static int uninorth_rev;
-static int keylargo_rev;
-static u32 board_features;
-static int airport_pwr_state;
-static struct device_node* airport_dev;
-static struct device_node* uninorth_fw;
-
-/* Feature bits for Apple motherboards */
-#define FTR_NEED_OPENPIC_TWEAK 0x00000001
-#define FTR_CAN_NAP 0x00000002
-#define FTR_HAS_FW_POWER 0x00000004
-#define FTR_CAN_SLEEP 0x00000008
-
-/* This table currently lacks most oldworld machines, but
- * they currently don't need it so...
- *
- * Todo: The whole feature_xxx mecanism need to be redone
- * some way to be able to handle the new kind of features
- * exposed by core99. At this point, the main "tables" will
- * probably be in this table, which will have to be filled with
- * all known machines
- */
-/* Warning: Don't change ordering of entries as some machines
- * adverstise beeing compatible with several models. In those
- * case, the "highest" has to be first
- */
-static struct board_features_t {
- char* compatible;
- u32 features;
-} board_features_datas[] __initdata =
-{
- { "AAPL,PowerMac G3", 0 }, /* Beige G3 */
- { "iMac,1", 0 }, /* First iMac (gossamer) */
- { "PowerMac1,1", 0 }, /* B&W G3 / Yikes */
- { "PowerMac1,2", 0 }, /* B&W G3 / Yikes */
- { "PowerMac2,1", FTR_CAN_SLEEP }, /* r128 based iMac */
- { "PowerMac2,2", FTR_HAS_FW_POWER|FTR_CAN_SLEEP }, /* Summer 2000 iMac */
- { "PowerMac4,1", FTR_CAN_SLEEP }, /* iMac "Flower Power" */
- { "PowerMac3,1", FTR_NEED_OPENPIC_TWEAK }, /* Sawtooth (G4) */
- { "PowerMac3,2", 0 }, /* G4/Dual G4 */
- { "PowerMac3,3", FTR_NEED_OPENPIC_TWEAK }, /* G4/Dual G4 */
- { "PowerMac3,4", 0 }, /* QuickSilver G4 */
- { "PowerMac3,5", 0 }, /* QuickSilver G4 */
- { "PowerMac5,1", FTR_CAN_NAP }, /* Cube */
- { "AAPL,3400/2400", FTR_CAN_SLEEP }, /* 2400/3400 PowerBook */
- { "AAPL,3500", FTR_CAN_SLEEP }, /* 3500 PowerBook (G3) */
- { "AAPL,PowerBook1998", FTR_CAN_SLEEP }, /* Wallstreet PowerBook */
- { "PowerBook1,1", FTR_CAN_SLEEP }, /* 101 (Lombard) PowerBook */
- { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP| /* New polycarbonate iBook */
- 0/*FTR_HAS_FW_POWER*/ },
- { "PowerBook2,1", FTR_CAN_SLEEP }, /* iBook */
- { "PowerBook2,2", FTR_CAN_SLEEP /*| FTR_CAN_NAP*/ }, /* iBook FireWire */
- { "PowerBook3,1", FTR_CAN_SLEEP|FTR_CAN_NAP| /* PowerBook 2000 (Pismo) */
- FTR_HAS_FW_POWER },
- { "PowerBook3,2", FTR_CAN_NAP|FTR_CAN_SLEEP| /* PowerBook Titanium */
- 0/*FTR_HAS_FW_POWER*/ },
- { NULL, 0 }
-};
-
-extern unsigned long powersave_nap;
-
-void __init
-feature_init(void)
-{
- struct device_node *np;
- u32 *rev;
- int i;
- char* model;
-
- if (_machine != _MACH_Pmac)
- return;
-
- np = find_path_device("/");
- if (!np) {
- printk(KERN_ERR "feature.c: Can't find device-tree root !\n");
- return;
- }
- model = (char*)get_property(np, "model", NULL);
- if (model) {
- printk("PowerMac model: %s\n", model);
- /* Figure out motherboard type & options */
- for(i=0;board_features_datas[i].compatible;i++) {
- if (!strcmp(board_features_datas[i].compatible, model)) {
- board_features = board_features_datas[i].features;
- break;
- }
- }
- }
-
- /* Set default value of powersave_nap on machines that support it */
- if (board_features & FTR_CAN_NAP)
- powersave_nap = 1;
-
- /* Track those poor mac-io's */
- np = find_devices("mac-io");
- while (np != NULL) {
- /* KeyLargo contains several (5 ?) FCR registers in mac-io,
- * plus some gpio's which could eventually be handled here.
- */
- if (device_is_compatible(np, "Keylargo")) {
- struct feature_controller* ctrler =
- feature_add_controller(np, feature_bits_keylargo);
- if (ctrler) {
- keylargo = ctrler;
- keylargo_base = ctrler->reg;
- rev = (u32 *)get_property(ctrler->device, "revision-id", NULL);
- if (rev)
- keylargo_rev = *rev;
-
- rev = (u32 *)get_property(ctrler->device, "device-id", NULL);
- if (rev && (*rev) == 0x0025)
- keylargo_rev |= KL_PANGEA_REV;
- }
- } else if (device_is_compatible(np, "paddington")) {
- feature_add_controller(np, feature_bits_paddington);
- /* We disable the modem power bit on Yikes as it can
- * do bad things (it's the nvram power)
- */
- if (machine_is_compatible("PowerMac1,1") ||
- machine_is_compatible("PowerMac1,2")) {
- feature_bits_paddington[FEATURE_Modem_power].mask = 0;
- }
- } else if (machine_is_compatible("AAPL,PowerBook1998")) {
- feature_add_controller(np, feature_bits_wallstreet);
- } else {
- struct feature_controller* ctrler =
- feature_add_controller(np, feature_bits_heathrow);
- if (ctrler)
- out_le32(FREG(ctrler,HEATHROW_FEATURE_REG),
- in_le32(FREG(ctrler,HEATHROW_FEATURE_REG)) | HRW_DEFAULTS);
-
- }
- np = np->next;
- }
- if (controller_count == 0)
- {
- np = find_devices("ohare");
- if (np) {
- if (find_devices("via-pmu") != NULL)
- feature_add_controller(np, feature_bits_ohare_pbook);
- else
- /* else not sure; maybe this is a Starmax? */
- feature_add_controller(np, NULL);
- }
- }
-
- /* Locate core99 Uni-N */
- np = find_devices("uni-n");
- if (np && np->n_addrs > 0) {
- uninorth_base = ioremap(np->addrs[0].address, 0x1000);
- uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
- printk("Uninorth at 0x%08x\n", np->addrs[0].address);
- }
- if (uninorth_base && keylargo_base)
- printk("Uni-N revision: %d, KeyLargo revision: %d %s\n",
- uninorth_rev, keylargo_rev,
- (keylargo_rev & KL_PANGEA_REV) ? "(Pangea chipset)" : "");
-
- if (uninorth_base)
- uninorth_init();
- if (keylargo_base)
- keylargo_init();
-
- if (controller_count)
- printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
-
-#if defined(CONFIG_PMAC_PBOOK) && !defined(CONFIG_DMASOUND_AWACS)
- /* On PowerBooks, we disable the sound chip when dmasound is a module
- * or not used at all
- */
- if (controller_count && find_devices("via-pmu") != NULL) {
- feature_clear(controllers[0].device, FEATURE_Sound_power);
- feature_clear(controllers[0].device, FEATURE_Sound_CLK_enable);
- }
-#endif
-
-#ifdef CONFIG_PMAC_PBOOK
- /* On PowerBooks, we disable the serial ports by default, they
- * will be re-enabled by the driver
- */
-#ifndef CONFIG_XMON
- if (controller_count && find_devices("via-pmu") != NULL) {
- feature_set_modem_power(NULL, 0);
- feature_clear(controllers[0].device, FEATURE_Serial_IO_A);
- feature_clear(controllers[0].device, FEATURE_Serial_IO_B);
- feature_clear(controllers[0].device, FEATURE_Serial_enable);
- if (controller_count > 1) {
- feature_clear(controllers[1].device, FEATURE_Serial_IO_A);
- feature_clear(controllers[1].device, FEATURE_Serial_IO_B);
- feature_clear(controllers[1].device, FEATURE_Serial_enable);
- }
- }
-#endif
-#endif
-}
-
-static struct feature_controller __init *
-feature_add_controller(struct device_node *controller_device, fbit* bits)
-{
- struct feature_controller* controller;
-
- if (controller_count >= MAX_FEATURE_CONTROLLERS) {
- printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n",
- controller_device->full_name, MAX_FEATURE_CONTROLLERS);
- return NULL;
- }
- controller = &controllers[controller_count];
-
- controller->bits = bits;
- controller->device = controller_device;
- if (controller_device->n_addrs == 0) {
- printk(KERN_ERR "No addresses for %s\n",
- controller_device->full_name);
- return NULL;
- }
-
- /* We remap the entire mac-io here. Normally, this will just
- * give us back our already existing BAT mapping
- */
- controller->reg = (volatile u32 *)ioremap(
- controller_device->addrs[0].address,
- controller_device->addrs[0].size);
-
- if (bits == NULL) {
- printk(KERN_INFO "Twiddling the magic ohare bits\n");
- out_le32(FREG(controller,OHARE_FEATURE_REG), STARMAX_FEATURES);
- return NULL;
- }
-
- spin_lock_init(&controller->lock);
-
- controller_count++;
-
- return controller;
-}
-
-static struct feature_controller __pmac *
-feature_lookup_controller(struct device_node *device)
-{
- int i;
-
- if (device == NULL)
- return NULL;
-
- while(device)
- {
- for (i=0; i<controller_count; i++)
- if (device == controllers[i].device)
- return &controllers[i];
- device = device->parent;
- }
-
-#ifdef DEBUG_FEATURE
- printk("feature: <%s> not found on any controller\n",
- device->name);
-#endif
-
- return NULL;
-}
-
-int __pmac
-feature_set(struct device_node* device, enum system_feature f)
-{
- struct feature_controller* controller;
- unsigned long flags;
- unsigned long value;
- fbit* bit;
-
- if (f >= FEATURE_last)
- return -EINVAL;
-
- controller = feature_lookup_controller(device);
- if (!controller)
- return -ENODEV;
- bit = &controller->bits[f];
- if (!bit->mask)
- return -EINVAL;
-
-#ifdef DEBUG_FEATURE
- printk("feature: <%s> setting feature %d in controller @0x%x\n",
- device->name, (int)f, (unsigned int)controller->reg);
-#endif
-
- spin_lock_irqsave(&controller->lock, flags);
- value = in_le32(FREG(controller, bit->reg));
- value = bit->polarity ? (value & ~bit->mask) : (value | bit->mask);
- out_le32(FREG(controller, bit->reg), value);
- (void)in_le32(FREG(controller, bit->reg));
- spin_unlock_irqrestore(&controller->lock, flags);
-
- return 0;
-}
-
-int __pmac
-feature_clear(struct device_node* device, enum system_feature f)
-{
- struct feature_controller* controller;
- unsigned long flags;
- unsigned long value;
- fbit* bit;
-
- if (f >= FEATURE_last)
- return -EINVAL;
-
- controller = feature_lookup_controller(device);
- if (!controller)
- return -ENODEV;
- bit = &controller->bits[f];
- if (!bit->mask)
- return -EINVAL;
-
-#ifdef DEBUG_FEATURE
- printk("feature: <%s> clearing feature %d in controller @0x%x\n",
- device->name, (int)f, (unsigned int)controller->reg);
-#endif
-
- spin_lock_irqsave(&controller->lock, flags);
- value = in_le32(FREG(controller, bit->reg));
- value = bit->polarity ? (value | bit->mask) : (value & ~bit->mask);
- out_le32(FREG(controller, bit->reg), value);
- (void)in_le32(FREG(controller, bit->reg));
- spin_unlock_irqrestore(&controller->lock, flags);
-
- return 0;
-}
-
-int __pmac
-feature_test(struct device_node* device, enum system_feature f)
-{
- struct feature_controller* controller;
- unsigned long value;
- fbit* bit;
-
- if (f >= FEATURE_last)
- return -EINVAL;
-
- controller = feature_lookup_controller(device);
- if (!controller)
- return -ENODEV;
- bit = &controller->bits[f];
- if (!bit->mask)
- return -EINVAL;
-
-#ifdef DEBUG_FEATURE
- printk("feature: <%s> clearing feature %d in controller @0x%x\n",
- device->name, (int)f, (unsigned int)controller->reg);
-#endif
- /* If one feature contains several bits, all of them must be set
- * for value to be true, or all of them must be 0 if polarity is
- * inverse
- */
- value = (in_le32(FREG(controller, bit->reg)) & bit->mask);
- return bit->polarity ? (value == 0) : (value == bit->mask);
-}
-
-int __pmac
-feature_can_sleep(void)
-{
- return ((board_features & FTR_CAN_SLEEP) != 0);
-}
-
-/*
- * Core99 functions
- *
- * Note: We currently assume there is _one_ UniN chip and _one_ KeyLargo
- * chip, which is the case on all Core99 machines so far
- */
-
-/* Only one GMAC is assumed */
-void __pmac
-feature_set_gmac_power(struct device_node* device, int power)
-{
- unsigned long flags;
-
- if (!uninorth_base || !keylargo)
- return;
-
- /* TODO: Handle save/restore of PCI config space here
- */
-
- /* XXX We use the keylargo spinlock, but we never
- * have uninorth without keylargo, so...
- */
- KL_LOCK();
- if (power)
- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
- else
- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
- (void)UN_IN(UNI_N_CLOCK_CNTL);
- KL_UNLOCK();
- udelay(20);
-}
-
-void __pmac
-feature_gmac_phy_reset(struct device_node* device)
-{
- unsigned long flags;
-
- if (!keylargo_base || !keylargo)
- return;
-
- KL_LOCK();
- KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET);
- KL_UNLOCK();
- mdelay(10);
- KL_LOCK();
- KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET,
- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET);
- KL_UNLOCK();
- mdelay(10);
-}
-
-/* Pass the node of the correct controller, please */
-void __pmac
-feature_set_usb_power(struct device_node* device, int power)
-{
- char* prop;
- int number;
- u32 reg;
-
- unsigned long flags;
-
- if (!keylargo_base || !keylargo)
- return;
-
- prop = (char *)get_property(device, "AAPL,clock-id", NULL);
- if (!prop)
- return;
- if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
- number = 0;
- else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
- number = 2;
- else
- return;
-
- KL_LOCK();
- if (power) {
- /* Turn ON */
-
- if (number == 0) {
- KL_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
- (void)KL_IN(KEYLARGO_FCR0);
- KL_UNLOCK();
- mdelay(1);
- KL_LOCK();
- KL_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
- } else {
- KL_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
- KL_UNLOCK();
- (void)KL_IN(KEYLARGO_FCR0);
- mdelay(1);
- KL_LOCK();
- KL_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
- }
- reg = KL_IN(KEYLARGO_FCR4);
- reg &= ~(KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
- KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number));
- reg &= ~(KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
- KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1));
- KL_OUT(KEYLARGO_FCR4, reg);
- (void)KL_IN(KEYLARGO_FCR4);
- udelay(10);
- } else {
- /* Turn OFF */
-
- reg = KL_IN(KEYLARGO_FCR4);
- reg |= KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
- KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number);
- reg |= KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
- KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1);
- KL_OUT(KEYLARGO_FCR4, reg);
- (void)KL_IN(KEYLARGO_FCR4);
- udelay(1);
- if (number == 0) {
- KL_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
- (void)KL_IN(KEYLARGO_FCR0);
- udelay(1);
- KL_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
- (void)KL_IN(KEYLARGO_FCR0);
- } else {
- KL_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
- (void)KL_IN(KEYLARGO_FCR0);
- udelay(1);
- KL_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
- (void)KL_IN(KEYLARGO_FCR0);
- }
- udelay(1);
- }
- KL_UNLOCK();
-}
-
-void __pmac
-feature_set_firewire_power(struct device_node* device, int power)
-{
- unsigned long flags;
-
- /* TODO: should probably handle save/restore of PCI config space here
- */
-
- if (!uninorth_fw || (device && uninorth_fw != device))
- return;
- if (!uninorth_base)
- return;
-
- /* XXX We use the keylargo spinlock, but we never
- * have uninorth without keylargo, so...
- */
- KL_LOCK();
- if (power)
- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
- else
- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
- (void)UN_IN(UNI_N_CLOCK_CNTL);
- KL_UNLOCK();
- udelay(20);
-}
-
-/* Warning: will kill the PHY.. */
-void __pmac
-feature_set_firewire_cable_power(struct device_node* device, int power)
-{
- unsigned long flags;
- u8 gpioValue = power ? 0 : 4;
-
- if (!uninorth_fw || (device && uninorth_fw != device))
- return;
- if (!keylargo_base || !(board_features & FTR_HAS_FW_POWER))
- return;
- KL_LOCK();
- KL_GPIO_OUT(KL_GPIO_FW_CABLE_POWER, gpioValue);
- (void)KL_GPIO_IN(KL_GPIO_FW_CABLE_POWER);
- KL_UNLOCK();
-}
-
-void
-feature_set_modem_power(struct device_node* device, int power)
-{
- unsigned long flags;
-
- if (!device) {
- device = find_devices("ch-a");
- while(device && !device_is_compatible(device, "cobalt"))
- device = device->next;
- if (!device)
- return;
- }
- if (keylargo && (keylargo_rev & KL_PANGEA_REV)) {
- KL_LOCK();
- if (power) {
- /* Assert modem reset */
- KL_GPIO_OUT(KL_GPIO_MODEM_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)KL_GPIO_IN(KL_GPIO_MODEM_RESET);
- udelay(10);
- /* Power up modem */
- KL_GPIO_OUT(KL_GPIO_MODEM_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)KL_GPIO_IN(KL_GPIO_MODEM_POWER);
- udelay(10);
- /* Release modem reset */
- KL_GPIO_OUT(KL_GPIO_MODEM_RESET,
- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)KL_GPIO_IN(KL_GPIO_MODEM_RESET);
- } else {
- /* Power down modem */
- KL_GPIO_OUT(KL_GPIO_MODEM_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)KL_GPIO_IN(KL_GPIO_MODEM_POWER);
- }
- KL_UNLOCK();
- } else {
- if (power) {
- mdelay(300);
- feature_set(device, FEATURE_Modem_power);
- mdelay(5);
- feature_clear(device, FEATURE_Modem_power);
- mdelay(10);
- feature_set(device, FEATURE_Modem_power);
- } else {
- feature_clear(device, FEATURE_Modem_power);
- mdelay(10);
- }
- }
-}
-
-#ifdef CONFIG_SMP
-void __pmac
-feature_core99_kick_cpu(int cpu_nr)
-{
- const int reset_lines[] = { KL_GPIO_RESET_CPU0,
- KL_GPIO_RESET_CPU1,
- KL_GPIO_RESET_CPU2,
- KL_GPIO_RESET_CPU3 };
- int reset_io;
- unsigned long flags;
-
- if (!keylargo_base || cpu_nr > 3)
- return;
- reset_io = reset_lines[cpu_nr];
-
- KL_LOCK();
- KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)KL_GPIO_IN(reset_io);
- udelay(1);
- KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)KL_GPIO_IN(reset_io);
- KL_UNLOCK();
-}
-#endif /* CONFIG_SMP */
-
-void __pmac
-feature_set_airport_power(struct device_node* device, int power)
-{
- unsigned long flags;
-
- if (!keylargo_base || !airport_dev || airport_dev != device)
- return;
- if (airport_pwr_state == power)
- return;
- if (power) {
- /* This code is a reproduction of OF enable-cardslot
- * and init-wireless methods, slightly hacked until
- * I got it working.
- */
- KL_LOCK();
- KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 5);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf);
- KL_UNLOCK();
- mdelay(10);
- KL_LOCK();
- KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 4);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf);
- KL_UNLOCK();
-
- mdelay(10);
-
- KL_LOCK();
- KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
- (void)KL_IN(KEYLARGO_FCR2);
- udelay(10);
- KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xb);
- udelay(10);
- KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xa);
- udelay(10);
- KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xd);
- udelay(10);
- KL_GPIO_OUT(KEYLARGO_GPIO_0+0xd, 0x28);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xd);
- udelay(10);
- KL_GPIO_OUT(KEYLARGO_GPIO_0+0xe, 0x28);
- (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xe);
- KL_UNLOCK();
- udelay(10);
- KL_OUT(0x1c000, 0);
-
- mdelay(1);
- out_8((volatile u8*)KL_FCR(0x1a3e0), 0x41);
- (void)in_8((volatile u8*)KL_FCR(0x1a3e0));
- udelay(10);
- KL_LOCK();
- KL_BIS(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
- (void)KL_IN(KEYLARGO_FCR2);
- KL_UNLOCK();
- mdelay(100);
- } else {
- KL_LOCK();
- KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
- (void)KL_IN(KEYLARGO_FCR2);
- KL_GPIO_OUT(KL_GPIO_AIRPORT_0, 0);
- KL_GPIO_OUT(KL_GPIO_AIRPORT_1, 0);
- KL_GPIO_OUT(KL_GPIO_AIRPORT_2, 0);
- KL_GPIO_OUT(KL_GPIO_AIRPORT_3, 0);
- KL_GPIO_OUT(KL_GPIO_AIRPORT_4, 0);
- (void)KL_GPIO_IN(KL_GPIO_AIRPORT_4);
- KL_UNLOCK();
- }
- airport_pwr_state = power;
-}
-
-/* Initialize the Core99 UniNorth host bridge and memory controller
- */
-static void __init
-uninorth_init(void)
-{
- struct device_node* gmac, *fw;
- unsigned long actrl;
-
- /* Set the arbitrer QAck delay according to what Apple does
- */
- if (uninorth_rev < 0x10) {
- actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
- actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
- UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
- UN_OUT(UNI_N_ARB_CTRL, actrl);
- }
-
- /* Enable GMAC for now for PCI probing. It will be disabled
- * later on after PCI probe
- */
- gmac = find_devices("ethernet");
- while(gmac) {
- if (device_is_compatible(gmac, "gmac"))
- break;
- gmac = gmac->next;
- }
- if (gmac)
- feature_set_gmac_power(gmac, 1);
-
- /* Enable FW before PCI probe. Will be disabled later on
- */
- fw = find_devices("firewire");
- if (fw && (device_is_compatible(fw, "pci106b,18") ||
- device_is_compatible(fw, "pci106b,30"))) {
- uninorth_fw = fw;
- feature_set_firewire_power(fw, 1);
- }
-}
-
-/* Initialize the Core99 KeyLargo ASIC.
- */
-static void __init
-keylargo_init(void)
-{
- struct device_node* np;
-
- KL_BIS(KEYLARGO_FCR2, KL2_MPIC_ENABLE);
-
- /* Lookup for an airport card, and disable it if found
- * to save power (will be re-enabled by driver if used)
- */
- np = find_devices("radio");
- if (np && np->parent == keylargo->device)
- airport_dev = np;
-
- if (airport_dev) {
- airport_pwr_state = 1;
- feature_set_airport_power(airport_dev, 0);
- }
-
-}
-
-#ifdef CONFIG_PMAC_PBOOK
-void __pmac
-feature_prepare_for_sleep(void)
-{
- /* We assume gatwick is second */
- struct feature_controller* ctrler = &controllers[0];
-
- if (controller_count > 1 &&
- device_is_compatible(ctrler->device, "gatwick"))
- ctrler = &controllers[1];
-
- if (ctrler->bits == feature_bits_wallstreet ||
- ctrler->bits == feature_bits_paddington) {
- heathrow_prepare_for_sleep(ctrler);
- return;
- }
- if (ctrler->bits == feature_bits_keylargo) {
- core99_prepare_for_sleep(ctrler);
- return;
- }
-}
-
-void __pmac
-feature_wake_up(void)
-{
- struct feature_controller* ctrler = &controllers[0];
-
- if (controller_count > 1 &&
- device_is_compatible(ctrler->device, "gatwick"))
- ctrler = &controllers[1];
-
- if (ctrler->bits == feature_bits_wallstreet ||
- ctrler->bits == feature_bits_paddington) {
- heathrow_wakeup(ctrler);
- return;
- }
- if (ctrler->bits == feature_bits_keylargo) {
- core99_wake_up(ctrler);
- return;
- }
-}
-
-static u32 save_fcr[5];
-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 void __pmac
-heathrow_prepare_for_sleep(struct feature_controller* ctrler)
-{
- save_mbcr = in_le32(FREG(ctrler, 0x34));
- save_fcr[0] = in_le32(FREG(ctrler, 0x38));
- save_fcr[1] = in_le32(FREG(ctrler, 0x3c));
-
- out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE);
-}
-
-static void __pmac
-heathrow_wakeup(struct feature_controller* ctrler)
-{
- out_le32(FREG(ctrler, 0x38), save_fcr[0]);
- out_le32(FREG(ctrler, 0x3c), save_fcr[1]);
- out_le32(FREG(ctrler, 0x34), save_mbcr);
- mdelay(1);
- out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE);
- mdelay(1);
-}
-
-static void __pmac
-turn_off_keylargo(void)
-{
- u32 temp;
-
- mdelay(1);
- KL_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
- (void)KL_IN(KEYLARGO_FCR0);
- mdelay(100);
-
- KL_BIC(KEYLARGO_FCR0, KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
- KL0_SCC_CELL_ENABLE |
- KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
- KL0_IRDA_CLK19_ENABLE);
-
- (void)KL_IN(KEYLARGO_FCR0); udelay(10);
- KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
- (void)KL_IN(KEYLARGO_MBCR); udelay(10);
-
- KL_BIC(KEYLARGO_FCR1,
- KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
- KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
- KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
- KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
- KL1_UIDE_ENABLE);
- (void)KL_IN(KEYLARGO_FCR1); udelay(10);
-
- KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
- udelay(10);
- KL_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
- udelay(10);
- temp = KL_IN(KEYLARGO_FCR3);
- if (keylargo_rev >= 2)
- temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
-
- temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
- KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
- temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
- | KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
- | KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
- KL_OUT(KEYLARGO_FCR3, temp);
- (void)KL_IN(KEYLARGO_FCR3); udelay(10);
-}
-
-static void __pmac
-turn_off_pangea(void)
-{
- u32 temp;
-
- KL_BIC(KEYLARGO_FCR0, KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
- KL0_SCC_CELL_ENABLE |
- KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
-
- (void)KL_IN(KEYLARGO_FCR0); udelay(10);
- KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
- (void)KL_IN(KEYLARGO_MBCR); udelay(10);
-
- KL_BIC(KEYLARGO_FCR1,
- KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
- KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
- KL1_UIDE_ENABLE);
- (void)KL_IN(KEYLARGO_FCR1); udelay(10);
-
- KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
- udelay(10);
- temp = KL_IN(KEYLARGO_FCR3);
- temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
- KL3_SHUTDOWN_PLLKW35;
- temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
- | KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
- | KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
- KL_OUT(KEYLARGO_FCR3, temp);
- (void)KL_IN(KEYLARGO_FCR3); udelay(10);
-}
-
-static void __pmac
-core99_prepare_for_sleep(struct feature_controller* ctrler)
-{
- int i;
- volatile u8* base8;
-
- /*
- * Save various bits of KeyLargo
- */
-
- /* We power off the wireless slot in case it was not done
- * by the driver. We don't power it on automatically however
- */
- feature_set_airport_power(airport_dev, 0);
-
- /* We power off the FW cable. Should be done by the driver... */
- feature_set_firewire_power(NULL, 0);
- feature_set_firewire_cable_power(NULL, 0);
-
- /* We make sure int. modem is off (in case driver lost it) */
- feature_set_modem_power(NULL, 0);
-
- /* Save the state of the various GPIOs */
- save_gpio_levels[0] = KL_IN(KEYLARGO_GPIO_LEVELS0);
- save_gpio_levels[1] = KL_IN(KEYLARGO_GPIO_LEVELS1);
- base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_EXTINT_0;
- for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
- save_gpio_extint[i] = in_8(base8+i);
- base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_0;
- for (i=0; i<KEYLARGO_GPIO_CNT; i++)
- save_gpio_normal[i] = in_8(base8+i);
-
- /* Save the FCRs */
- save_mbcr = KL_IN(KEYLARGO_MBCR);
- save_fcr[0] = KL_IN(KEYLARGO_FCR0);
- save_fcr[1] = KL_IN(KEYLARGO_FCR1);
- save_fcr[2] = KL_IN(KEYLARGO_FCR2);
- save_fcr[3] = KL_IN(KEYLARGO_FCR3);
- save_fcr[4] = KL_IN(KEYLARGO_FCR4);
-
- /* Save state & config of DBDMA channels */
- for (i=0; i<13; i++) {
- volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
- (keylargo_base + ((0x8000+i*0x100)>>2));
- save_dbdma[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
- save_dbdma[i].cmdptr = in_le32(&chan->cmdptr);
- save_dbdma[i].intr_sel = in_le32(&chan->intr_sel);
- save_dbdma[i].br_sel = in_le32(&chan->br_sel);
- save_dbdma[i].wait_sel = in_le32(&chan->wait_sel);
- }
-
- /*
- * Turn off as much as we can
- */
- if (keylargo_rev & KL_PANGEA_REV)
- turn_off_pangea();
- else
- turn_off_keylargo();
-
- /*
- * Put the host bridge to sleep
- */
-
- save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
- UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
- ~(UNI_N_CLOCK_CNTL_GMAC|UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
- udelay(100);
- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
-
- /*
- * FIXME: A bit of black magic with OpenPIC (don't ask me why)
- */
- if (board_features & FTR_NEED_OPENPIC_TWEAK) {
- KL_BIS(0x506e0, 0x00400000);
- KL_BIS(0x506e0, 0x80000000);
- }
-}
-
-static void __pmac
-core99_wake_up(struct feature_controller* ctrler)
-{
- int i;
- volatile u8* base8;
-
- /*
- * Wakeup the host bridge
- */
- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
- udelay(10);
- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
- udelay(10);
-
- /*
- * Restore KeyLargo
- */
-
- KL_OUT(KEYLARGO_MBCR, save_mbcr);
- (void)KL_IN(KEYLARGO_MBCR); udelay(10);
- KL_OUT(KEYLARGO_FCR0, save_fcr[0]);
- (void)KL_IN(KEYLARGO_FCR0); udelay(10);
- KL_OUT(KEYLARGO_FCR1, save_fcr[1]);
- (void)KL_IN(KEYLARGO_FCR1); udelay(10);
- KL_OUT(KEYLARGO_FCR2, save_fcr[2]);
- (void)KL_IN(KEYLARGO_FCR2); udelay(10);
- KL_OUT(KEYLARGO_FCR3, save_fcr[3]);
- (void)KL_IN(KEYLARGO_FCR3); udelay(10);
- KL_OUT(KEYLARGO_FCR4, save_fcr[4]);
- (void)KL_IN(KEYLARGO_FCR4); udelay(10);
-
- for (i=0; i<13; i++) {
- volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
- (keylargo_base + ((0x8000+i*0x100)>>2));
- out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
- while (in_le32(&chan->status) & ACTIVE)
- mb();
- out_le32(&chan->cmdptr_hi, save_dbdma[i].cmdptr_hi);
- out_le32(&chan->cmdptr, save_dbdma[i].cmdptr);
- out_le32(&chan->intr_sel, save_dbdma[i].intr_sel);
- out_le32(&chan->br_sel, save_dbdma[i].br_sel);
- out_le32(&chan->wait_sel, save_dbdma[i].wait_sel);
- }
-
- KL_OUT(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
- KL_OUT(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
- base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_EXTINT_0;
- for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
- out_8(base8+i, save_gpio_extint[i]);
- base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_0;
- for (i=0; i<KEYLARGO_GPIO_CNT; i++)
- out_8(base8+i, save_gpio_normal[i]);
-
- /* FIXME more black magic with OpenPIC ... */
- if (board_features & FTR_NEED_OPENPIC_TWEAK) {
- KL_BIC(0x506e0, 0x00400000);
- KL_BIC(0x506e0, 0x80000000);
- }
-
- UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
- udelay(100);
-}
-#endif /* CONFIG_PMAC_PBOOK */
diff --git a/arch/ppc/kernel/galaxy_pci.c b/arch/ppc/kernel/galaxy_pci.c
index afe8ffbe1379..4326a2a76b92 100644
--- a/arch/ppc/kernel/galaxy_pci.c
+++ b/arch/ppc/kernel/galaxy_pci.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.galaxy_pci.c 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
*
@@ -27,8 +27,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/machdep.h>
-
-#include "pci.h"
+#include <asm/pci-bridge.h>
/* Preprocessor Defines */
diff --git a/arch/ppc/kernel/gemini_pci.c b/arch/ppc/kernel/gemini_pci.c
deleted file mode 100644
index c3d93c483b4d..000000000000
--- a/arch/ppc/kernel/gemini_pci.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * BK Id: SCCS/s.gemini_pci.c 1.6 10/11/01 08:51:46 trini
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/machdep.h>
-#include <asm/gemini.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pci-bridge.h>
-
-#include "pci.h"
-
-#define pci_config_addr(bus,dev,offset) \
- (0x80000000 | (bus<<16) | (dev<<8) | offset)
-
-
-int
-gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
-{
- unsigned long reg;
- reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
- (offset & ~(0x3))));
- *val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
- return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
-{
- unsigned long reg;
- reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
- (offset & ~(0x3))));
- *val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
- return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
-{
- *val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
- (offset & ~(0x3))));
- return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
-{
- unsigned long reg;
- int shifts = offset & 0x3;
- unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
- (offset & ~(0x3)));
-
- reg = grackle_read(addr);
- reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
- grackle_write(addr, reg );
- return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
-{
- unsigned long reg;
- int shifts = offset & 0x3;
- unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
- (offset & ~(0x3)));
-
- reg = grackle_read(addr);
- reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
- grackle_write(addr, reg );
- return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
-{
- grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
- (offset & ~(0x3))), val);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops gemini_pci_ops =
-{
- gemini_pcibios_read_config_byte,
- gemini_pcibios_read_config_word,
- gemini_pcibios_read_config_dword,
- gemini_pcibios_write_config_byte,
- gemini_pcibios_write_config_word,
- gemini_pcibios_write_config_dword
-};
-
-void __init gemini_pcibios_fixup(void)
-{
- int i;
- struct pci_dev *dev;
-
- pci_for_each_dev(dev) {
- for(i = 0; i < 6; i++) {
- if (dev->resource[i].flags & IORESOURCE_IO) {
- dev->resource[i].start |= (0xfe << 24);
- dev->resource[i].end |= (0xfe << 24);
- }
- }
- }
-}
-
-
-/* The "bootloader" for Synergy boards does none of this for us, so we need to
- lay it all out ourselves... --Dan */
-void __init gemini_find_bridges(void)
-{
- struct pci_controller* hose;
-
- ppc_md.pcibios_fixup = gemini_pcibios_fixup;
-
- hose = pcibios_alloc_controller();
- if (!hose)
- return;
- hose->ops = &gemini_pci_ops;
-}
diff --git a/arch/ppc/kernel/gemini_prom.S b/arch/ppc/kernel/gemini_prom.S
deleted file mode 100644
index e2a09b9d89dc..000000000000
--- a/arch/ppc/kernel/gemini_prom.S
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * BK Id: SCCS/s.gemini_prom.S 1.5 05/17/01 18:14:21 cort
- */
-/*
- * arch/ppc/kernel/gemini_prom.S
- *
- * Not really prom support code (yet), but sort of anti-prom code. The current
- * bootloader does a number of things it shouldn't and doesn't do things that it
- * should. The stuff in here is mainly a hodge-podge collection of setup code
- * to get the board up and running.
- * ---Dan
- */
-
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/gemini.h>
-
-#define HID0_ABE (1<<3)
-
-/*
- * On 750's the MMU is on when Linux is booted, so we need to clear out the
- * bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
- * and turn off the MMU.
- *
- */
-
-_GLOBAL(gemini_prom_init)
-#ifdef CONFIG_SMP
- /* Since the MMU's on, get stuff in rom space that we'll need */
- lis r4,GEMINI_CPUSTAT@h
- ori r4,r4,GEMINI_CPUSTAT@l
- lbz r5,0(r4)
- andi. r5,r5,3
- mr r24,r5 /* cpu # used later on */
-#endif
- mfmsr r4
- li r3,MSR_PR /* ensure supervisor! */
- ori r3,r3,MSR_IR|MSR_DR
- andc r4,r4,r3
- mtmsr r4
- isync
-#if 0
- /* zero out the bats now that the MMU is off */
-prom_no_mmu:
- li r3,0
- mtspr IBAT0U,r3
- mtspr IBAT0L,r3
- mtspr IBAT1U,r3
- mtspr IBAT1L,r3
- mtspr IBAT2U,r3
- mtspr IBAT2L,r3
- mtspr IBAT3U,r3
- mtspr IBAT3L,r3
-
- mtspr DBAT0U,r3
- mtspr DBAT0L,r3
- mtspr DBAT1U,r3
- mtspr DBAT1L,r3
- mtspr DBAT2U,r3
- mtspr DBAT2L,r3
- mtspr DBAT3U,r3
- mtspr DBAT3L,r3
-#endif
-
- /* the bootloader (as far as I'm currently aware) doesn't mess with page
- tables, but since we're already here, might as well zap these, too */
- li r4,0
- mtspr SDR1,r4
-
- li r4,16
- mtctr r4
- li r3,0
- li r4,0
-3: mtsrin r3,r4
- addi r3,r3,1
- bdnz 3b
-
-#ifdef CONFIG_SMP
- /* The 750 book (and Mot/IBM support) says that this will "assist" snooping
- when in SMP. Not sure yet whether this should stay or leave... */
- mfspr r4,HID0
- ori r4,r4,HID0_ABE
- mtspr HID0,r4
- sync
-#endif /* CONFIG_SMP */
- blr
-
-/* apparently, SMon doesn't pay attention to HID0[SRST]. Disable the MMU and
- branch to 0xfff00100 */
-_GLOBAL(_gemini_reboot)
- lis r5,GEMINI_BOOT_INIT@h
- ori r5,r5,GEMINI_BOOT_INIT@l
- li r6,MSR_IP
- mtspr SRR0,r5
- mtspr SRR1,r6
- rfi
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
deleted file mode 100644
index e390a83db0e4..000000000000
--- a/arch/ppc/kernel/gemini_setup.c
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * BK Id: SCCS/s.gemini_setup.c 1.14 10/18/01 11:16:28 trini
- */
-/*
- * linux/arch/ppc/kernel/setup.c
- *
- * Copyright (C) 1995 Linus Torvalds
- * Adapted from 'alpha' version by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- * Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
- *
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/time.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/blk.h>
-#include <linux/console.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/m48t35.h>
-#include <asm/gemini.h>
-#include <asm/time.h>
-
-#include "local_irq.h"
-#include "open_pic.h"
-
-void gemini_find_bridges(void);
-static int gemini_get_clock_speed(void);
-extern void gemini_pcibios_fixup(void);
-
-static char *gemini_board_families[] = {
- "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
-};
-static int gemini_board_count = sizeof(gemini_board_families) /
- sizeof(gemini_board_families[0]);
-
-static unsigned int cpu_7xx[16] = {
- 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
-};
-static unsigned int cpu_6xx[16] = {
- 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
-};
-
-/*
- * prom_init is the Gemini version of prom.c:prom_init. We only need
- * the BSS clearing code, so I copied that out of prom.c. This is a
- * lot simpler than hacking prom.c so it will build with Gemini. -VAL
- */
-
-#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset))
-
-unsigned long
-prom_init(void)
-{
- unsigned long offset = reloc_offset();
- unsigned long phys;
- extern char __bss_start, _end;
-
- /* First zero the BSS -- use memset, some arches don't have
- * caches on yet */
- memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
-
- /* Default */
- phys = offset + KERNELBASE;
-
- gemini_prom_init();
-
- return phys;
-}
-
-int
-gemini_show_cpuinfo(struct seq_file *m)
-{
- unsigned char reg, rev;
- char *family;
- unsigned int type;
-
- reg = readb(GEMINI_FEAT);
- family = gemini_board_families[((reg>>4) & 0xf)];
- if (((reg>>4) & 0xf) > gemini_board_count)
- printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
-
- reg = readb(GEMINI_BREV);
- type = (reg>>4) & 0xf;
- rev = reg & 0xf;
-
- reg = readb(GEMINI_BECO);
-
- seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
- family, type, (rev + 'A'), (reg & 0xf));
-
- seq_printf(m, "board\t\t: Gemini %s", family);
- if (type > 9)
- seq_printf(m, "%c", (type - 10) + 'A');
- else
- seq_printf(m, "%d", type);
-
- seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf));
-
- seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed());
-
- return 0;
-}
-
-static u_char gemini_openpic_initsenses[] = {
- 1,
- 1,
- 1,
- 1,
- 0,
- 0,
- 1, /* remainder are level-triggered */
-};
-
-#define GEMINI_MPIC_ADDR (0xfcfc0000)
-#define GEMINI_MPIC_PCI_CFG (0x80005800)
-
-void __init gemini_openpic_init(void)
-{
-
- OpenPIC_Addr = (volatile struct OpenPIC *)
- grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
- OpenPIC_InitSenses = gemini_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
-
- ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
-}
-
-
-extern unsigned long loops_per_jiffy;
-extern int root_mountflags;
-extern char cmd_line[];
-
-void
-gemini_heartbeat(void)
-{
- static unsigned long led = GEMINI_LEDBASE+(4*8);
- static char direction = 8;
-
- /* We only want to do this on 1 CPU */
- if (smp_processor_id())
- return;
- *(char *)led = 0;
- if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
- (led + direction) < (GEMINI_LEDBASE+(4*8)) )
- direction *= -1;
- led += direction;
- *(char *)led = 0xff;
- ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void __init gemini_setup_arch(void)
-{
- extern char cmd_line[];
-
-
- loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* bootable off CDROM */
- if (initrd_start)
- ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
- else
-#endif
- ROOT_DEV = to_kdev_t(0x0801);
-
- /* nothing but serial consoles... */
- sprintf(cmd_line, "%s console=ttyS0", cmd_line);
-
- printk("Boot arguments: %s\n", cmd_line);
-
- ppc_md.heartbeat = gemini_heartbeat;
- ppc_md.heartbeat_reset = HZ/8;
- ppc_md.heartbeat_count = 1;
-
- /* Lookup PCI hosts */
- gemini_find_bridges();
- /* take special pains to map the MPIC, since it isn't mapped yet */
- gemini_openpic_init();
- /* start the L2 */
- gemini_init_l2();
-}
-
-
-int
-gemini_get_clock_speed(void)
-{
- unsigned long hid1, pvr;
- int clock;
-
- pvr = mfspr(PVR);
- hid1 = (mfspr(HID1) >> 28) & 0xf;
- if (PVR_VER(pvr) == 8 ||
- PVR_VER(pvr) == 12)
- hid1 = cpu_7xx[hid1];
- else
- hid1 = cpu_6xx[hid1];
-
- switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
-
- case 0:
- default:
- clock = (hid1*100)/3;
- break;
-
- case 1:
- clock = (hid1*125)/3;
- break;
-
- case 2:
- clock = (hid1*50);
- break;
- }
-
- return clock;
-}
-
-void __init gemini_init_l2(void)
-{
- unsigned char reg, brev, fam, creg;
- unsigned long cache;
- unsigned long pvr;
-
- reg = readb(GEMINI_L2CFG);
- brev = readb(GEMINI_BREV);
- fam = readb(GEMINI_FEAT);
- pvr = mfspr(PVR);
-
- switch(PVR_VER(pvr)) {
-
- case 8:
- if (reg & 0xc0)
- cache = (((reg >> 6) & 0x3) << 28);
- else
- cache = 0x3 << 28;
-
-#ifdef CONFIG_SMP
- /* Pre-3.0 processor revs had snooping errata. Leave
- their L2's disabled with SMP. -- Dan */
- if (PVR_CFG(pvr) < 3) {
- printk("Pre-3.0 750; L2 left disabled!\n");
- return;
- }
-#endif /* CONFIG_SMP */
-
- /* Special case: VGM5-B's came before L2 ratios were set on
- the board. Processor speed shouldn't be too high, so
- set L2 ratio to 1:1.5. */
- if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
- reg |= 1;
-
- /* determine best cache ratio based upon what the board
- tells us (which sometimes _may_ not be true) and
- the processor speed. */
- else {
- if (gemini_get_clock_speed() > 250)
- reg = 2;
- }
- break;
- case 12:
- {
- static unsigned long l2_size_val = 0;
-
- if (!l2_size_val)
- l2_size_val = _get_L2CR();
- cache = l2_size_val;
- break;
- }
- case 4:
- case 9:
- creg = readb(GEMINI_CPUSTAT);
- if (((creg & 0xc) >> 2) != 1)
- printk("Dual-604 boards don't support the use of L2\n");
- else
- writeb(1, GEMINI_L2CFG);
- return;
- default:
- printk("Unknown processor; L2 left disabled\n");
- return;
- }
-
- cache |= ((1<<reg) << 25);
- cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
- _set_L2CR(0);
- _set_L2CR(cache | L2CR_L2E);
-
-}
-
-void
-gemini_restart(char *cmd)
-{
- __cli();
- /* make a clean restart, not via the MPIC */
- _gemini_reboot();
- for(;;);
-}
-
-void
-gemini_power_off(void)
-{
- for(;;);
-}
-
-void
-gemini_halt(void)
-{
- gemini_restart(NULL);
-}
-
-void __init gemini_init_IRQ(void)
-{
- /* gemini has no 8259 */
- openpic_init(1, 0, 0, -1);
-}
-
-#define gemini_rtc_read(x) (readb(GEMINI_RTC+(x)))
-#define gemini_rtc_write(val,x) (writeb((val),(GEMINI_RTC+(x))))
-
-/* ensure that the RTC is up and running */
-long __init gemini_time_init(void)
-{
- unsigned char reg;
-
- reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-
- if ( reg & M48T35_RTC_STOPPED ) {
- printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
- gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
- gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
- }
- return 0;
-}
-
-#undef DEBUG_RTC
-
-unsigned long
-gemini_get_rtc_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- unsigned char reg;
-
- reg = gemini_rtc_read(M48T35_RTC_CONTROL);
- gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
-#ifdef DEBUG_RTC
- printk("get rtc: reg = %x\n", reg);
-#endif
-
- do {
- sec = gemini_rtc_read(M48T35_RTC_SECONDS);
- min = gemini_rtc_read(M48T35_RTC_MINUTES);
- hour = gemini_rtc_read(M48T35_RTC_HOURS);
- day = gemini_rtc_read(M48T35_RTC_DOM);
- mon = gemini_rtc_read(M48T35_RTC_MONTH);
- year = gemini_rtc_read(M48T35_RTC_YEAR);
- } while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
-#ifdef DEBUG_RTC
- printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n",
- sec, min, hour, day, mon, year);
-#endif
-
- gemini_rtc_write(reg, M48T35_RTC_CONTROL);
-
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
-
- if ((year += 1900) < 1970)
- year += 100;
-#ifdef DEBUG_RTC
- printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n",
- sec, min, hour, day, mon, year);
-#endif
-
- return mktime( year, mon, day, hour, min, sec );
-}
-
-
-int
-gemini_set_rtc_time( unsigned long now )
-{
- unsigned char reg;
- struct rtc_time tm;
-
- to_tm( now, &tm );
-
- reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-#if DEBUG_RTC
- printk("set rtc: reg = %x\n", reg);
-#endif
-
- gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
-#if DEBUG_RTC
- printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
- tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
-#endif
-
- tm.tm_year -= 1900;
- 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);
-#ifdef DEBUG_RTC
- printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
- tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
-#endif
-
- gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
- gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
- gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
- gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
- gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
- gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
-
- /* done writing */
- gemini_rtc_write(reg, M48T35_RTC_CONTROL);
-
- if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
- time_state = TIME_OK;
-
- return 0;
-}
-
-/* use the RTC to determine the decrementer count */
-void __init gemini_calibrate_decr(void)
-{
- int freq, divisor;
- unsigned char reg;
-
- /* determine processor bus speed */
- reg = readb(GEMINI_BSTAT);
-
- switch(((reg & 0x0c)>>2)&0x3) {
- case 0:
- default:
- freq = 66667;
- break;
- case 1:
- freq = 83000;
- break;
- case 2:
- freq = 100000;
- break;
- }
-
- freq *= 1000;
- divisor = 4;
- tb_ticks_per_jiffy = freq / HZ / divisor;
- tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
-}
-
-unsigned long __init gemini_find_end_of_memory(void)
-{
- unsigned long total;
- unsigned char reg;
-
- reg = readb(GEMINI_MEMCFG);
- total = ((1<<((reg & 0x7) - 1)) *
- (8<<((reg >> 3) & 0x7)));
- total *= (1024*1024);
- return total;
-}
-
-static void __init
-gemini_map_io(void)
-{
- io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
- io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
-}
-
-#ifdef CONFIG_SMP
-static int
-smp_gemini_probe(void)
-{
- int i, nr;
-
- nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
- if (nr == 0)
- nr = 4;
-
- if (nr > 1) {
- openpic_request_IPIs();
- for (i = 1; i < nr; ++i)
- smp_hw_index[i] = i;
- }
-
- return nr;
-}
-
-static void
-smp_gemini_kick_cpu(int nr)
-{
- openpic_reset_processor_phys(1 << nr);
- openpic_reset_processor_phys(0);
-}
-
-static void
-smp_gemini_setup_cpu(int cpu_nr)
-{
- if (OpenPIC_Addr)
- do_openpic_setup_cpu();
- if (cpu_nr > 0)
- gemini_init_l2();
-}
-
-static struct smp_ops_t gemini_smp_ops = {
- smp_openpic_message_pass,
- smp_gemini_probe,
- smp_gemini_kick_cpu,
- smp_gemini_setup_cpu,
-};
-#endif /* CONFIG_SMP */
-
-void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- int i;
-
- for(i = 0; i < GEMINI_LEDS; i++)
- gemini_led_off(i);
-
- ISA_DMA_THRESHOLD = 0;
- DMA_MODE_READ = 0;
- DMA_MODE_WRITE = 0;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif
-
- ppc_md.setup_arch = gemini_setup_arch;
- ppc_md.show_cpuinfo = gemini_show_cpuinfo;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = gemini_init_IRQ;
- ppc_md.get_irq = openpic_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = gemini_restart;
- ppc_md.power_off = gemini_power_off;
- ppc_md.halt = gemini_halt;
-
- ppc_md.time_init = gemini_time_init;
- ppc_md.set_rtc_time = gemini_set_rtc_time;
- ppc_md.get_rtc_time = gemini_get_rtc_time;
- ppc_md.calibrate_decr = gemini_calibrate_decr;
-
- ppc_md.find_end_of_memory = gemini_find_end_of_memory;
- ppc_md.setup_io_mappings = gemini_map_io;
-
- /* no keyboard/mouse/video stuff yet.. */
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
- ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
-
-#ifdef CONFIG_SMP
- ppc_md.smp_ops = &gemini_smp_ops;
-#endif /* CONFIG_SMP */
-}
diff --git a/arch/ppc/kernel/gt64260_common.c b/arch/ppc/kernel/gt64260_common.c
new file mode 100644
index 000000000000..4dc0719366cd
--- /dev/null
+++ b/arch/ppc/kernel/gt64260_common.c
@@ -0,0 +1,1666 @@
+/*
+ * arch/ppc/kernel/gt64260_common.c
+ *
+ * Common routines for the Marvell/Galileo GT64260 (Discovery) host bridge,
+ * interrupt controller, memory controller, serial controller, enet controller,
+ * etc.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+/*
+ * The GT64260 port is the result of hard work from many people from
+ * many companies. In particular, employees of Marvell/Galileo, Mission
+ * Critical Linux, Xyterra, and MontaVista Software were heavily involved.
+ */
+
+/*
+ * At last count, the 64260-B-0 has 65 errata and 24 restrictions. The odds of
+ * you getting it to work well, under stress, for a long period of time are
+ * low. If nothing else, you will likely run into an interrupt controller
+ * bug.
+ *
+ * The newer 64260A-B-0 is much improved but has its own problems.
+ * Dave Wilhardt <dwilhardt@zyterra.com> has discovered that you must set
+ * up your PCI snoop regions to be prefetchable with 4-word bursts AND set the
+ * "Memory Write and Invalidate bit" (bit 4) in the cmd reg of each PCI device
+ * before coherency works between PCI and other devices. Many thanks to Dave.
+ *
+ * So far this code has been tested on Marvell/Galileo EV-64260-BP and
+ * an EV-64260A-BP uni-processor boards with 750 and 7400 processors.
+ * It has not yet been tested with a 7410 or 7450, or on an smp system.
+ *
+ * Note: I have not had any luck moving the base register address of the bridge
+ * with the gt64260_set_base() routine. I move it in the bootloader
+ * before starting the kernel. I haven't really looked into it so it
+ * may be an easy fix. -- MAG
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/gt64260.h>
+#include <asm/delay.h>
+
+
+u32 gt64260_base; /* Virtual base address of 64260's regs */
+u32 gt64260_revision; /* Revision of the chip */
+u8 gt64260_pci_exclude_bridge = TRUE;
+
+
+/*
+ *****************************************************************************
+ *
+ * Bridge Initialization Routines
+ *
+ *****************************************************************************
+ */
+static void gt64260_check_errata(struct pci_controller *hose_a,
+ struct pci_controller *hose_b);
+
+/*
+ * Typical '_find_bridges()' routine for boards with a GT64260 bridge.
+ */
+int __init
+gt64260_find_bridges(u32 phys_base_addr, gt64260_bridge_info_t *info,
+ int ((*map_irq)(struct pci_dev *, unsigned char, unsigned char)))
+{
+ struct pci_controller *hose_a, *hose_b;
+ u32 io_base_a, io_base_b;
+ int rc;
+
+
+ gt64260_base = (u32)ioremap(phys_base_addr,GT64260_INTERNAL_SPACE_SIZE);
+
+ hose_a = pcibios_alloc_controller();
+ if (!hose_a)
+ return -1;
+
+ hose_b = pcibios_alloc_controller();
+ if (!hose_b)
+ return -1;
+
+ info->hose_a = hose_a;
+ info->hose_b = hose_b;
+
+ /* Ends up mapping PCI Config addr/data pairs twice */
+ setup_indirect_pci(hose_a,
+ phys_base_addr + GT64260_PCI_0_CONFIG_ADDR,
+ phys_base_addr + GT64260_PCI_0_CONFIG_DATA);
+
+ setup_indirect_pci(hose_b,
+ phys_base_addr + GT64260_PCI_1_CONFIG_ADDR,
+ phys_base_addr + GT64260_PCI_1_CONFIG_DATA);
+
+ if ((rc = gt64260_bridge_init(info)) != 0) {
+ iounmap((void *)hose_a->cfg_addr);
+ iounmap((void *)hose_a->cfg_data);
+ iounmap((void *)hose_b->cfg_addr);
+ iounmap((void *)hose_b->cfg_data);
+ iounmap((void *)gt64260_base);
+ return rc;
+ }
+
+ /* ioremap PCI I/O regions */
+ io_base_b = (u32)ioremap(info->pci_1_io_start_proc,info->pci_1_io_size);
+ io_base_a = (u32)ioremap(info->pci_0_io_start_proc,info->pci_0_io_size);
+ isa_io_base = io_base_a;
+
+ hose_a->first_busno = 0;
+ hose_a->last_busno = 0xff;
+
+ pci_init_resource(&hose_a->io_resource,
+ 0, /* really: io_base_a - isa_io_base */
+ info->pci_0_io_size - 1,
+ IORESOURCE_IO,
+ "host bridge PCI bus 0");
+ hose_a->io_space.start = info->pci_0_io_start_pci;
+ hose_a->io_space.end = info->pci_0_io_start_pci +
+ info->pci_0_io_size - 1;
+ hose_a->io_base_virt = (void *)isa_io_base;
+
+ pci_init_resource(&hose_a->mem_resources[0],
+ info->pci_0_mem_start_proc,
+ info->pci_0_mem_start_proc + info->pci_0_mem_size - 1,
+ IORESOURCE_MEM,
+ "host bridge PCI bus 0");
+ hose_a->mem_space.start = info->pci_0_mem_start_pci_lo;
+ hose_a->mem_space.end = info->pci_0_mem_start_pci_lo +
+ info->pci_0_mem_size - 1;
+ hose_a->pci_mem_offset = (info->pci_0_mem_start_proc -
+ info->pci_0_mem_start_pci_lo);
+
+ hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+
+
+ hose_b->first_busno = hose_a->last_busno + 1;
+ hose_b->bus_offset = hose_b->first_busno;
+ hose_b->last_busno = 0xff;
+
+ pci_init_resource(&hose_b->io_resource,
+ io_base_b - isa_io_base,
+ io_base_b - isa_io_base + info->pci_1_io_size - 1,
+ IORESOURCE_IO,
+ "host bridge PCI bus 1");
+ hose_b->io_space.start = info->pci_1_io_start_pci;
+ hose_b->io_space.end = info->pci_1_io_start_pci +
+ info->pci_1_io_size - 1;
+ hose_b->io_base_virt = (void *)isa_io_base;
+
+ pci_init_resource(&hose_b->mem_resources[0],
+ info->pci_1_mem_start_proc,
+ info->pci_1_mem_start_proc + info->pci_1_mem_size - 1,
+ IORESOURCE_MEM,
+ "host bridge PCI bus 1");
+ hose_b->mem_space.start = info->pci_1_mem_start_pci_lo;
+ hose_b->mem_space.end = info->pci_1_mem_start_pci_lo +
+ info->pci_1_mem_size - 1;
+ hose_b->pci_mem_offset = (info->pci_1_mem_start_proc -
+ info->pci_1_mem_start_pci_lo);
+
+ hose_b->last_busno = pciauto_bus_scan(hose_b, hose_b->first_busno);
+
+
+ ppc_md.pci_exclude_device = gt64260_pci_exclude_device;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = map_irq;
+
+ return 0;
+} /* gt64260_find_bridges() */
+
+/*
+ * gt64260_bridge_init()
+ *
+ * Perform bridge initialization for a "typical" setup for a PPC system.
+ */
+int __init
+gt64260_bridge_init(gt64260_bridge_info_t *info)
+{
+ int window;
+ u16 u16_val;
+ u32 u32_val;
+ int rc = 0;
+ u8 save_exclude;
+
+ /*
+ * Count on firmware to set/clear other bits in this register.
+ *
+ * Set CPU CONFIG Reg bit:
+ * bit 13 - Pipeline
+ * bit 16 - RdOOO
+ *
+ * Clear CPU Config Reg bit:
+ * bit 12 - endianess
+ * bit 27 - RemapWrDis
+ */
+ u32_val = gt_read(GT64260_CPU_CONFIG);
+ u32_val |= ((1<<13) | (1<<16));
+ u32_val &= ~((1<<8) | (1<<12) | (1<<27));
+ gt_write(GT64260_CPU_CONFIG, u32_val);
+
+ /* PCI 0/1 Timeout and Retry limits */
+ u32_val = gt_read(GT64260_PCI_0_TO_RETRY);
+ u32_val |= 0x0000ffff;
+ gt_write(GT64260_PCI_0_TO_RETRY, u32_val);
+
+ u32_val = gt_read(GT64260_PCI_1_TO_RETRY);
+ u32_val |= 0x0000ffff;
+ gt_write(GT64260_PCI_1_TO_RETRY, u32_val);
+
+ save_exclude = gt64260_pci_exclude_bridge;
+ gt64260_pci_exclude_bridge = FALSE;
+
+ /* Set class code to indicate host bridge */
+ early_read_config_dword(info->hose_a,
+ info->hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_CLASS_REVISION,
+ &u32_val);
+ u32_val &= 0x000000ff;
+ gt64260_revision = u32_val; /* a 64260 or 64260A? */
+ u32_val |= (PCI_CLASS_BRIDGE_HOST << 16);
+ early_write_config_dword(info->hose_a,
+ info->hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_CLASS_REVISION,
+ u32_val);
+
+ early_read_config_dword(info->hose_b,
+ info->hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_CLASS_REVISION,
+ &u32_val);
+ u32_val &= 0x000000ff;
+ u32_val |= (PCI_CLASS_BRIDGE_HOST << 16);
+ early_write_config_dword(info->hose_b,
+ info->hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_CLASS_REVISION,
+ u32_val);
+
+ /* Enable 64260 to be PCI master & respond to PCI MEM cycles */
+ early_read_config_word(info->hose_a,
+ info->hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ &u16_val);
+ u16_val |= (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+ early_write_config_word(info->hose_a,
+ info->hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ u16_val);
+
+ early_read_config_word(info->hose_b,
+ info->hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ &u16_val);
+ u16_val |= (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+ early_write_config_word(info->hose_b,
+ info->hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ u16_val);
+
+ gt64260_pci_exclude_bridge = save_exclude;
+
+ /*
+ * Disable all CPU windows on the bridge except for SCS 0 which
+ * is covering all of system memory.:
+ */
+ gt64260_cpu_disable_all_windows();
+
+ /*
+ * Set CPU snoop window to indicate all of system memory
+ * is covered with wirte-back cache.
+ */
+ gt64260_cpu_snoop_set_window(0,
+ 0x00000000,
+ info->mem_size,
+ GT64260_CPU_SNOOP_WB);
+
+ /*
+ * Set up CPU->PCI mappings (so CPU can get at PCI dev regs/mem).
+ * Will only use one of the four CPU->PCI MEM windows on each bus.
+ */
+ gt64260_cpu_set_pci_io_window(0,
+ info->pci_0_io_start_proc,
+ info->pci_0_io_start_pci,
+ info->pci_0_io_size,
+ info->pci_0_io_swap);
+
+ gt64260_cpu_set_pci_mem_window(0,
+ 0,
+ info->pci_0_mem_start_proc,
+ info->pci_0_mem_start_pci_hi,
+ info->pci_0_mem_start_pci_lo,
+ info->pci_0_mem_size,
+ info->pci_0_mem_swap);
+
+ gt64260_cpu_set_pci_io_window(1,
+ info->pci_1_io_start_proc,
+ info->pci_1_io_start_pci,
+ info->pci_1_io_size,
+ info->pci_1_io_swap);
+
+ gt64260_cpu_set_pci_mem_window(1,
+ 0,
+ info->pci_1_mem_start_proc,
+ info->pci_1_mem_start_pci_hi,
+ info->pci_1_mem_start_pci_lo,
+ info->pci_1_mem_size,
+ info->pci_1_mem_swap);
+
+ /*
+ * Set up PCI MEM->system memory mapping (bridge slave PCI window).
+ *
+ * Set BAR enables to allow only the SCS0 slave window to respond
+ * to PCI read/write cycles.
+ */
+ gt64260_pci_bar_enable(0, GT64260_PCI_SLAVE_BAR_REG_ENABLES_SCS_0);
+ gt64260_pci_bar_enable(1, GT64260_PCI_SLAVE_BAR_REG_ENABLES_SCS_0);
+
+ /*
+ * For virt_to_bus & bus_to_virt to work correctly, this mapping
+ * must be the same on both PCI buses.
+ */
+ gt64260_pci_slave_scs_set_window(info->hose_a,
+ 0,
+ 0x00000000,
+ 0x00000000,
+ info->mem_size);
+
+ gt64260_pci_slave_scs_set_window(info->hose_b,
+ 0,
+ 0x00000000,
+ 0x00000000,
+ info->mem_size);
+ pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+
+ /* Disable all the access control windows */
+ for (window=0; window<GT64260_PCI_ACC_CNTL_WINDOWS; window++) {
+ gt64260_pci_acc_cntl_set_window(0, window, 0, 0, 0, 0);
+ gt64260_pci_acc_cntl_set_window(1, window, 0, 0, 0, 0);
+ }
+
+ /* Disable all the PCI snoop regions */
+ for (window=0; window<GT64260_PCI_SNOOP_WINDOWS; window++) {
+ gt64260_pci_snoop_set_window(0, window, 0, 0, 0, 0);
+ gt64260_pci_snoop_set_window(1, window, 0, 0, 0, 0);
+ }
+
+ gt64260_pci_acc_cntl_set_window(0,
+ 0,
+ 0x00000000,
+ 0x00000000,
+ info->mem_size,
+ (GT64260_PCI_ACC_CNTL_PREFETCHEN |
+ GT64260_PCI_ACC_CNTL_MBURST_4_WORDS |
+ GT64260_PCI_ACC_CNTL_SWAP_BYTE));
+
+ gt64260_pci_acc_cntl_set_window(1,
+ 0,
+ 0x00000000,
+ 0x00000000,
+ info->mem_size,
+ (GT64260_PCI_ACC_CNTL_PREFETCHEN |
+ GT64260_PCI_ACC_CNTL_MBURST_4_WORDS |
+ GT64260_PCI_ACC_CNTL_SWAP_BYTE));
+
+ gt64260_pci_snoop_set_window(0,
+ 0,
+ 0x00000000,
+ 0x00000000,
+ info->mem_size,
+ GT64260_PCI_SNOOP_WB);
+
+ gt64260_pci_snoop_set_window(1,
+ 0,
+ 0x00000000,
+ 0x00000000,
+ info->mem_size,
+ GT64260_PCI_SNOOP_WB);
+
+ gt64260_check_errata(info->hose_a, info->hose_b);
+
+
+ /* Set latency timer (to 64) & cacheline size; clear BIST */
+ gt64260_pci_exclude_bridge = FALSE;
+ u32_val = ((0x04 << 8) | (L1_CACHE_LINE_SIZE / 4));
+
+ early_write_config_dword(info->hose_a,
+ info->hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_CACHE_LINE_SIZE,
+ u32_val);
+ early_write_config_dword(info->hose_b,
+ info->hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_CACHE_LINE_SIZE,
+ u32_val);
+ gt64260_pci_exclude_bridge = TRUE;
+
+ return rc;
+} /* gt64260_bridge_init() */
+
+/*
+ * gt64260_check_errata()
+ *
+ * Apply applicable errata and restrictions from 0.5 of the
+ * Errata and Restrictions document from Marvell/Galileo.
+ */
+static void __init
+gt64260_check_errata(struct pci_controller *hose_a,
+ struct pci_controller *hose_b)
+{
+ u32 val;
+ u8 save_exclude;
+
+ /* Currently 2 versions, 64260 and 64260A */
+ if (gt64260_revision == GT64260) {
+ save_exclude = gt64260_pci_exclude_bridge;
+ gt64260_pci_exclude_bridge = FALSE;
+
+ /* FEr#5, FEr#12 */
+ early_read_config_dword(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ &val);
+ val &= ~(PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY);
+ early_write_config_dword(hose_a,
+ hose_a->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ val);
+
+ early_read_config_dword(hose_b,
+ hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ &val);
+ val &= ~(PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY);
+ early_write_config_dword(hose_b,
+ hose_b->first_busno,
+ PCI_DEVFN(0,0),
+ PCI_COMMAND,
+ val);
+ gt64260_pci_exclude_bridge = save_exclude;
+
+ /* FEr#12, FEr#13 */
+ gt_clr_bits(GT64260_PCI_0_CMD, ((1<<4) | (1<<5) | (1<<9)));
+ gt_clr_bits(GT64260_PCI_1_CMD, ((1<<4) | (1<<5) | (1<<9)));
+
+ /* FEr#54 */
+ gt_clr_bits(GT64260_CPU_SNOOP_BASE_0, 0xfffcf000);
+ gt_clr_bits(GT64260_CPU_SNOOP_BASE_1, 0xfffcf000);
+ gt_clr_bits(GT64260_CPU_SNOOP_BASE_2, 0xfffcf000);
+ gt_clr_bits(GT64260_CPU_SNOOP_BASE_3, 0xfffcf000);
+
+ /* R#18 */
+ gt_set_bits(GT64260_SDRAM_CONFIG, (1<<26));
+
+ } else if (gt64260_revision == GT64260A) {
+ /* R#18 */
+ gt_set_bits(GT64260_SDRAM_CONFIG, (1<<26));
+
+ /* No longer errata so turn on */
+ gt_set_bits(GT64260_PCI_0_CMD, ((1<<4) | (1<<5) | (1<<9)));
+ gt_set_bits(GT64260_PCI_1_CMD, ((1<<4) | (1<<5) | (1<<9)));
+ }
+} /* gt64260_check_errata() */
+
+
+/*
+ *****************************************************************************
+ *
+ * General Window Setting Routines
+ *
+ *****************************************************************************
+ */
+
+static int
+gt64260_set_32bit_window(u32 base_addr,
+ u32 size,
+ u32 other_bits,
+ u32 bot_reg,
+ u32 top_reg)
+{
+ u32 val;
+
+ if (size > 0) {
+ /* Set up the window on the CPU side */
+ gt_write(bot_reg, (base_addr >> 20) | other_bits);
+ gt_write(top_reg, (base_addr + size - 1) >> 20);
+ } else { /* Disable window */
+ gt_write(top_reg, 0x00000000);
+ gt_write(bot_reg, 0x00000fff | other_bits);
+ }
+
+ val = gt_read(bot_reg); /* Flush FIFO */
+ return 0;
+} /* gt64260_set_32bit_window() */
+
+static int
+gt64260_set_64bit_window(u32 base_addr_hi,
+ u32 base_addr_lo,
+ u32 size,
+ u32 other_bits,
+ u32 bot_reg_hi,
+ u32 bot_reg_lo,
+ u32 top_reg)
+{
+ int rc;
+
+ if ((rc = gt64260_set_32bit_window(base_addr_lo,
+ size,
+ other_bits,
+ bot_reg_lo,
+ top_reg)) == 0) {
+
+ gt_write(bot_reg_hi, base_addr_hi);
+ base_addr_hi = gt_read(bot_reg_hi); /* Flush FIFO */
+ }
+
+ return rc;
+} /* gt64260_set_64bit_window() */
+
+
+/*
+ *****************************************************************************
+ *
+ * CPU Configuration Routines
+ *
+ *****************************************************************************
+ */
+
+int
+gt64260_cpu_scs_set_window(u32 window,
+ u32 base_addr,
+ u32 size)
+{
+ static u32
+ cpu_scs_windows[GT64260_CPU_SCS_DECODE_WINDOWS][2] = {
+ { GT64260_CPU_SCS_DECODE_0_BOT, GT64260_CPU_SCS_DECODE_0_TOP },
+ { GT64260_CPU_SCS_DECODE_1_BOT, GT64260_CPU_SCS_DECODE_1_TOP },
+ { GT64260_CPU_SCS_DECODE_2_BOT, GT64260_CPU_SCS_DECODE_2_TOP },
+ { GT64260_CPU_SCS_DECODE_3_BOT, GT64260_CPU_SCS_DECODE_3_TOP },
+ }; /* cpu_scs_windows[][] */
+ int rc = -1;
+
+ if (window < GT64260_CPU_SCS_DECODE_WINDOWS) {
+ rc = gt64260_set_32bit_window(base_addr,
+ size,
+ 0,
+ cpu_scs_windows[window][0],
+ cpu_scs_windows[window][1]);
+ }
+
+ return rc;
+} /* gt64260_cpu_scs_set_window() */
+
+int
+gt64260_cpu_cs_set_window(u32 window,
+ u32 base_addr,
+ u32 size)
+{
+ static u32
+ cpu_cs_windows[GT64260_CPU_CS_DECODE_WINDOWS][2] = {
+ { GT64260_CPU_CS_DECODE_0_BOT, GT64260_CPU_CS_DECODE_0_TOP },
+ { GT64260_CPU_CS_DECODE_1_BOT, GT64260_CPU_CS_DECODE_1_TOP },
+ { GT64260_CPU_CS_DECODE_2_BOT, GT64260_CPU_CS_DECODE_2_TOP },
+ { GT64260_CPU_CS_DECODE_3_BOT, GT64260_CPU_CS_DECODE_3_TOP },
+ }; /* cpu_cs_windows[][] */
+ int rc = -1;
+
+ if (window < GT64260_CPU_CS_DECODE_WINDOWS) {
+ rc = gt64260_set_32bit_window(base_addr,
+ size,
+ 0,
+ cpu_cs_windows[window][0],
+ cpu_cs_windows[window][1]);
+ }
+
+ return rc;
+} /* gt64260_cpu_cs_set_window() */
+
+int
+gt64260_cpu_boot_set_window(u32 base_addr,
+ u32 size)
+{
+ int rc;
+
+ rc = gt64260_set_32bit_window(base_addr,
+ size,
+ 0,
+ GT64260_CPU_BOOT_CS_DECODE_0_BOT,
+ GT64260_CPU_BOOT_CS_DECODE_0_TOP);
+
+ return rc;
+} /* gt64260_cpu_boot_set_window() */
+
+/*
+ * gt64260_cpu_set_pci_io_window()
+ *
+ * Set up a CPU window into PCI I/O or MEM space.
+ * Always do Read/Modify/Write to window regs.
+ */
+static int
+gt64260_cpu_pci_set_window(u32 cpu_base_addr,
+ u32 pci_base_addr,
+ u32 size,
+ u32 other_bits,
+ u32 bot_reg,
+ u32 top_reg,
+ u32 remap_reg)
+{
+ u32 val;
+ int rc;
+
+ if ((rc = gt64260_set_32bit_window(cpu_base_addr,
+ size,
+ other_bits,
+ bot_reg,
+ top_reg)) == 0) {
+
+ /* Set up CPU->PCI remapping (on lower 32 bits) */
+ gt_write(remap_reg, pci_base_addr >> 20);
+ val = gt_read(bot_reg); /* Flush FIFO */
+ }
+
+ return rc;
+} /* gt64260_cpu_pci_set_window() */
+
+
+/*
+ * gt64260_cpu_set_pci_io_window()
+ *
+ * Set up a CPU window into PCI I/O space.
+ * Always do Read/Modify/Write to window regs.
+ */
+int
+gt64260_cpu_set_pci_io_window(u32 pci_bus,
+ u32 cpu_base_addr,
+ u32 pci_base_addr,
+ u32 size,
+ u32 swap)
+{
+ /* 2 PCI buses with 1 I/O window each (from CPU point of view) */
+ static u32
+ cpu_pci_io_windows[GT64260_PCI_BUSES][3] = {
+ { GT64260_CPU_PCI_0_IO_DECODE_BOT,
+ GT64260_CPU_PCI_0_IO_DECODE_TOP,
+ GT64260_CPU_PCI_0_IO_REMAP },
+
+ { GT64260_CPU_PCI_1_IO_DECODE_BOT,
+ GT64260_CPU_PCI_1_IO_DECODE_TOP,
+ GT64260_CPU_PCI_1_IO_REMAP },
+ }; /* cpu_pci_io_windows[][] */
+ int rc = -1;
+
+ if (pci_bus < GT64260_PCI_BUSES) {
+ rc = gt64260_cpu_pci_set_window(cpu_base_addr,
+ pci_base_addr,
+ size,
+ swap,
+ cpu_pci_io_windows[pci_bus][0],
+ cpu_pci_io_windows[pci_bus][1],
+ cpu_pci_io_windows[pci_bus][2]);
+ }
+
+ return rc;
+} /* gt64260_cpu_set_pci_io_window() */
+
+/*
+ * gt64260_cpu_set_pci_mem_window()
+ *
+ * Set up a CPU window into PCI MEM space (4 PCI MEM windows per PCI bus).
+ * Always do Read/Modify/Write to window regs.
+ */
+int
+gt64260_cpu_set_pci_mem_window(u32 pci_bus,
+ u32 window,
+ u32 cpu_base_addr,
+ u32 pci_base_addr_hi,
+ u32 pci_base_addr_lo,
+ u32 size,
+ u32 swap_64bit)
+{
+ /* 2 PCI buses with 4 memory windows each (from CPU point of view) */
+ static u32
+ cpu_pci_mem_windows[GT64260_PCI_BUSES][GT64260_PCI_MEM_WINDOWS_PER_BUS][4] = {
+ { /* PCI 0 */
+ { GT64260_CPU_PCI_0_MEM_0_DECODE_BOT,
+ GT64260_CPU_PCI_0_MEM_0_DECODE_TOP,
+ GT64260_CPU_PCI_0_MEM_0_REMAP_HI,
+ GT64260_CPU_PCI_0_MEM_0_REMAP_LO },
+
+ { GT64260_CPU_PCI_0_MEM_1_DECODE_BOT,
+ GT64260_CPU_PCI_0_MEM_1_DECODE_TOP,
+ GT64260_CPU_PCI_0_MEM_1_REMAP_HI,
+ GT64260_CPU_PCI_0_MEM_1_REMAP_LO },
+
+ { GT64260_CPU_PCI_0_MEM_2_DECODE_BOT,
+ GT64260_CPU_PCI_0_MEM_2_DECODE_TOP,
+ GT64260_CPU_PCI_0_MEM_2_REMAP_HI,
+ GT64260_CPU_PCI_0_MEM_2_REMAP_LO },
+
+ { GT64260_CPU_PCI_0_MEM_3_DECODE_BOT,
+ GT64260_CPU_PCI_0_MEM_3_DECODE_TOP,
+ GT64260_CPU_PCI_0_MEM_3_REMAP_HI,
+ GT64260_CPU_PCI_0_MEM_3_REMAP_LO }
+ },
+
+ { /* PCI 1 */
+ { GT64260_CPU_PCI_1_MEM_0_DECODE_BOT,
+ GT64260_CPU_PCI_1_MEM_0_DECODE_TOP,
+ GT64260_CPU_PCI_1_MEM_0_REMAP_HI,
+ GT64260_CPU_PCI_1_MEM_0_REMAP_LO },
+
+ { GT64260_CPU_PCI_1_MEM_1_DECODE_BOT,
+ GT64260_CPU_PCI_1_MEM_1_DECODE_TOP,
+ GT64260_CPU_PCI_1_MEM_1_REMAP_HI,
+ GT64260_CPU_PCI_1_MEM_1_REMAP_LO },
+
+ { GT64260_CPU_PCI_1_MEM_2_DECODE_BOT,
+ GT64260_CPU_PCI_1_MEM_2_DECODE_TOP,
+ GT64260_CPU_PCI_1_MEM_2_REMAP_HI,
+ GT64260_CPU_PCI_1_MEM_2_REMAP_LO },
+
+ { GT64260_CPU_PCI_1_MEM_3_DECODE_BOT,
+ GT64260_CPU_PCI_1_MEM_3_DECODE_TOP,
+ GT64260_CPU_PCI_1_MEM_3_REMAP_HI,
+ GT64260_CPU_PCI_1_MEM_3_REMAP_LO },
+ }
+ }; /* cpu_pci_mem_windows[][][] */
+ u32 remap_reg, remap;
+ int rc = -1;
+
+ if ((pci_bus < GT64260_PCI_BUSES) &&
+ (window < GT64260_PCI_MEM_WINDOWS_PER_BUS)) {
+
+ if (gt64260_cpu_pci_set_window(
+ cpu_base_addr,
+ pci_base_addr_lo,
+ size,
+ swap_64bit,
+ cpu_pci_mem_windows[pci_bus][window][0],
+ cpu_pci_mem_windows[pci_bus][window][1],
+ cpu_pci_mem_windows[pci_bus][window][3]) == 0) {
+
+ remap_reg = cpu_pci_mem_windows[pci_bus][window][2];
+ gt_write(remap_reg, pci_base_addr_hi);
+
+ remap = gt_read(remap_reg); /* Flush FIFO */
+
+ rc = 0;
+ }
+ }
+
+ return rc;
+} /* gt64260_cpu_set_pci_mem_window() */
+
+int
+gt64260_cpu_prot_set_window(u32 window,
+ u32 base_addr,
+ u32 size,
+ u32 access_bits)
+{
+ static u32
+ cpu_prot_windows[GT64260_CPU_PROT_WINDOWS][2] = {
+ { GT64260_CPU_PROT_BASE_0, GT64260_CPU_PROT_TOP_0 },
+ { GT64260_CPU_PROT_BASE_1, GT64260_CPU_PROT_TOP_1 },
+ { GT64260_CPU_PROT_BASE_2, GT64260_CPU_PROT_TOP_2 },
+ { GT64260_CPU_PROT_BASE_3, GT64260_CPU_PROT_TOP_3 },
+ { GT64260_CPU_PROT_BASE_4, GT64260_CPU_PROT_TOP_4 },
+ { GT64260_CPU_PROT_BASE_5, GT64260_CPU_PROT_TOP_5 },
+ { GT64260_CPU_PROT_BASE_6, GT64260_CPU_PROT_TOP_6 },
+ { GT64260_CPU_PROT_BASE_7, GT64260_CPU_PROT_TOP_7 },
+ }; /* cpu_prot_windows[][] */
+ int rc = -1;
+
+ if (window < GT64260_CPU_PROT_WINDOWS) {
+ rc = gt64260_set_32bit_window(base_addr,
+ size,
+ access_bits,
+ cpu_prot_windows[window][0],
+ cpu_prot_windows[window][1]);
+ }
+
+ return rc;
+} /* gt64260_cpu_prot_set_window() */
+
+int
+gt64260_cpu_snoop_set_window(u32 window,
+ u32 base_addr,
+ u32 size,
+ u32 snoop_type)
+{
+ static u32
+ cpu_snoop_windows[GT64260_CPU_SNOOP_WINDOWS][2] = {
+ { GT64260_CPU_SNOOP_BASE_0, GT64260_CPU_SNOOP_TOP_0 },
+ { GT64260_CPU_SNOOP_BASE_1, GT64260_CPU_SNOOP_TOP_1 },
+ { GT64260_CPU_SNOOP_BASE_2, GT64260_CPU_SNOOP_TOP_2 },
+ { GT64260_CPU_SNOOP_BASE_3, GT64260_CPU_SNOOP_TOP_3 },
+ }; /* cpu_snoop_windows[][] */
+ int rc = -1;
+
+ if ((window < GT64260_CPU_SNOOP_WINDOWS) &&
+ (snoop_type <= GT64260_CPU_SNOOP_WB)) {
+
+ rc = gt64260_set_32bit_window(base_addr,
+ size,
+ snoop_type,
+ cpu_snoop_windows[window][0],
+ cpu_snoop_windows[window][1]);
+ }
+
+ return rc;
+} /* gt64260_cpu_snoop_set_window() */
+
+void
+gt64260_cpu_disable_all_windows(void)
+{
+ int pci_bus, window;
+
+ /* Don't disable SCS windows b/c we need to access system memory */
+
+ for (window=0; window<GT64260_CPU_CS_DECODE_WINDOWS; window++) {
+ gt64260_cpu_cs_set_window(window, 0, 0);
+ }
+
+ gt64260_cpu_boot_set_window(0, 0);
+
+ for (pci_bus=0; pci_bus<GT64260_PCI_BUSES; pci_bus++) {
+ gt64260_cpu_set_pci_io_window(pci_bus, 0, 0, 0, 0);
+
+ for (window=0;window<GT64260_PCI_MEM_WINDOWS_PER_BUS;window++) {
+ gt64260_cpu_set_pci_mem_window(pci_bus,
+ window,
+ 0, 0, 0, 0, 0);
+ }
+ }
+
+ for (window=0; window<GT64260_CPU_PROT_WINDOWS; window++) {
+ gt64260_cpu_prot_set_window(window, 0, 0, 0);
+ }
+
+ for (window=0; window<GT64260_CPU_SNOOP_WINDOWS; window++) {
+ gt64260_cpu_snoop_set_window(window, 0, 0, 0);
+ }
+
+ return;
+} /* gt64260_cpu_disable_all_windows() */
+
+
+/*
+ *****************************************************************************
+ *
+ * PCI Slave Window Configuration Routines
+ *
+ *****************************************************************************
+ */
+
+int
+gt64260_pci_bar_enable(u32 pci_bus,
+ u32 enable_bits)
+{
+ u32 reg, val;
+ int rc = -1;
+
+ if (pci_bus < GT64260_PCI_BUSES) {
+ reg = (pci_bus == 0) ? GT64260_PCI_0_SLAVE_BAR_REG_ENABLES :
+ GT64260_PCI_1_SLAVE_BAR_REG_ENABLES;
+
+
+ /* Note: '0' enables, '1' disables */
+ val = gt_read(reg);
+ val |= 0xffffffff; /* Disable everything by default */
+ val &= ~enable_bits;
+ gt_write(reg, val);
+
+ gt_read(reg); /* Flush FIFO */
+
+ rc = 0;
+ }
+
+ return rc;
+} /* gt64260_pci_bar_enable() */
+
+static int
+gt64260_pci_slave_set_window(struct pci_controller *hose,
+ u32 pci_base_addr,
+ u32 cpu_base_addr,
+ u32 bar_size,
+ u32 pci_cfg_fcn,
+ u32 pci_cfg_hdr_offset,
+ u32 bar_size_reg,
+ u32 remap_reg)
+{
+ u32 val;
+ int devfn;
+ u8 save_exclude;
+
+ pci_base_addr &= 0xfffff000;
+ cpu_base_addr &= 0xfffff000;
+ bar_size &= 0xfffff000;
+ devfn = PCI_DEVFN(0, pci_cfg_fcn);
+
+ gt_write(bar_size_reg, (bar_size - 1) & 0xfffff000);
+ gt_write(remap_reg, cpu_base_addr);
+ gt_read(remap_reg); /* Flush FIFO */
+
+ save_exclude = gt64260_pci_exclude_bridge;
+ gt64260_pci_exclude_bridge = FALSE;
+ early_read_config_dword(hose,
+ hose->first_busno,
+ devfn,
+ pci_cfg_hdr_offset,
+ &val);
+ val &= 0x0000000f;
+ early_write_config_dword(hose,
+ hose->first_busno,
+ devfn,
+ pci_cfg_hdr_offset,
+ pci_base_addr | val);
+ gt64260_pci_exclude_bridge = save_exclude;
+
+ return 0;
+} /* gt64260_pci_slave_set_window() */
+
+int
+gt64260_pci_slave_scs_set_window(struct pci_controller *hose,
+ u32 window,
+ u32 pci_base_addr,
+ u32 cpu_base_addr,
+ u32 size)
+{
+ static u32
+ pci_scs_windows[GT64260_PCI_BUSES][GT64260_PCI_SCS_WINDOWS][4] = {
+ { /* PCI 0 */
+ { 0, 0x10,
+ GT64260_PCI_0_SLAVE_SCS_0_SIZE,
+ GT64260_PCI_0_SLAVE_SCS_0_REMAP },
+ { 0, 0x14,
+ GT64260_PCI_0_SLAVE_SCS_1_SIZE,
+ GT64260_PCI_0_SLAVE_SCS_1_REMAP },
+ { 0, 0x18,
+ GT64260_PCI_0_SLAVE_SCS_2_SIZE,
+ GT64260_PCI_0_SLAVE_SCS_2_REMAP },
+ { 0, 0x1c,
+ GT64260_PCI_0_SLAVE_SCS_3_SIZE,
+ GT64260_PCI_0_SLAVE_SCS_3_REMAP },
+ },
+ { /* PCI 1 */
+ { 0, 0x10,
+ GT64260_PCI_1_SLAVE_SCS_0_SIZE,
+ GT64260_PCI_1_SLAVE_SCS_0_REMAP },
+ { 0, 0x14,
+ GT64260_PCI_1_SLAVE_SCS_1_SIZE,
+ GT64260_PCI_1_SLAVE_SCS_1_REMAP },
+ { 0, 0x18,
+ GT64260_PCI_1_SLAVE_SCS_2_SIZE,
+ GT64260_PCI_1_SLAVE_SCS_2_REMAP },
+ { 0, 0x1c,
+ GT64260_PCI_1_SLAVE_SCS_3_SIZE,
+ GT64260_PCI_1_SLAVE_SCS_3_REMAP },
+ }
+ }; /* pci_scs_windows[][][] */
+ int pci_bus;
+ int rc = -1;
+
+ if (window < GT64260_PCI_SCS_WINDOWS) {
+ pci_bus = (hose->first_busno == 0) ? 0 : 1;
+
+ rc = gt64260_pci_slave_set_window(
+ hose,
+ pci_base_addr,
+ cpu_base_addr,
+ size,
+ pci_scs_windows[pci_bus][window][0],
+ pci_scs_windows[pci_bus][window][1],
+ pci_scs_windows[pci_bus][window][2],
+ pci_scs_windows[pci_bus][window][3]);
+ }
+
+ return rc;
+} /* gt64260_pci_slave_scs_set_window() */
+
+int
+gt64260_pci_slave_cs_set_window(struct pci_controller *hose,
+ u32 window,
+ u32 pci_base_addr,
+ u32 cpu_base_addr,
+ u32 size)
+{
+ static u32
+ pci_cs_windows[GT64260_PCI_BUSES][GT64260_PCI_CS_WINDOWS][4] = {
+ { /* PCI 0 */
+ { 1, 0x10,
+ GT64260_PCI_0_SLAVE_CS_0_SIZE,
+ GT64260_PCI_0_SLAVE_CS_0_REMAP },
+ { 1, 0x14,
+ GT64260_PCI_0_SLAVE_CS_1_SIZE,
+ GT64260_PCI_0_SLAVE_CS_1_REMAP },
+ { 1, 0x18,
+ GT64260_PCI_0_SLAVE_CS_2_SIZE,
+ GT64260_PCI_0_SLAVE_CS_2_REMAP },
+ { 1, 0x1c,
+ GT64260_PCI_0_SLAVE_CS_3_SIZE,
+ GT64260_PCI_0_SLAVE_CS_3_REMAP },
+ },
+ { /* PCI 1 */
+ { 1, 0x10,
+ GT64260_PCI_1_SLAVE_CS_0_SIZE,
+ GT64260_PCI_1_SLAVE_CS_0_REMAP },
+ { 1, 0x14,
+ GT64260_PCI_1_SLAVE_CS_1_SIZE,
+ GT64260_PCI_1_SLAVE_CS_1_REMAP },
+ { 1, 0x18,
+ GT64260_PCI_1_SLAVE_CS_2_SIZE,
+ GT64260_PCI_1_SLAVE_CS_2_REMAP },
+ { 1, 0x1c,
+ GT64260_PCI_1_SLAVE_CS_3_SIZE,
+ GT64260_PCI_1_SLAVE_CS_3_REMAP },
+ }
+ }; /* pci_cs_windows[][][] */
+ int pci_bus;
+ int rc = -1;
+
+ if (window < GT64260_PCI_CS_WINDOWS) {
+ pci_bus = (hose->first_busno == 0) ? 0 : 1;
+
+ rc = gt64260_pci_slave_set_window(
+ hose,
+ pci_base_addr,
+ cpu_base_addr,
+ size,
+ pci_cs_windows[pci_bus][window][0],
+ pci_cs_windows[pci_bus][window][1],
+ pci_cs_windows[pci_bus][window][2],
+ pci_cs_windows[pci_bus][window][3]);
+ }
+
+ return rc;
+} /* gt64260_pci_slave_cs_set_window() */
+
+int
+gt64260_pci_slave_boot_set_window(struct pci_controller *hose,
+ u32 pci_base_addr,
+ u32 cpu_base_addr,
+ u32 size)
+{
+ int rc;
+
+ rc = gt64260_pci_slave_set_window(hose,
+ pci_base_addr,
+ cpu_base_addr,
+ size,
+ 1,
+ 0x20,
+ GT64260_PCI_1_SLAVE_BOOT_SIZE,
+ GT64260_PCI_1_SLAVE_BOOT_REMAP);
+
+ return rc;
+} /* gt64260_pci_slave_boot_set_window() */
+
+int
+gt64260_pci_slave_p2p_mem_set_window(struct pci_controller *hose,
+ u32 window,
+ u32 pci_base_addr,
+ u32 other_bus_base_addr,
+ u32 size)
+{
+ static u32
+ pci_p2p_mem_windows[GT64260_PCI_BUSES][GT64260_PCI_P2P_MEM_WINDOWS][4]={
+ { /* PCI 0 */
+ { 2, 0x10,
+ GT64260_PCI_0_SLAVE_P2P_MEM_0_SIZE,
+ GT64260_PCI_0_SLAVE_P2P_MEM_0_REMAP_LO },
+ { 2, 0x14,
+ GT64260_PCI_0_SLAVE_P2P_MEM_1_SIZE,
+ GT64260_PCI_0_SLAVE_P2P_MEM_1_REMAP_LO },
+ },
+ { /* PCI 1 */
+ { 2, 0x10,
+ GT64260_PCI_1_SLAVE_P2P_MEM_0_SIZE,
+ GT64260_PCI_1_SLAVE_P2P_MEM_0_REMAP_LO },
+ { 2, 0x14,
+ GT64260_PCI_1_SLAVE_P2P_MEM_1_SIZE,
+ GT64260_PCI_1_SLAVE_P2P_MEM_1_REMAP_LO },
+ }
+ }; /* pci_p2p_mem_windows[][][] */
+ int pci_bus;
+ int rc = -1;
+
+ if (window < GT64260_PCI_P2P_MEM_WINDOWS) {
+ pci_bus = (hose->first_busno == 0) ? 0 : 1;
+
+ rc = gt64260_pci_slave_set_window(
+ hose,
+ pci_base_addr,
+ other_bus_base_addr,
+ size,
+ pci_p2p_mem_windows[pci_bus][window][0],
+ pci_p2p_mem_windows[pci_bus][window][1],
+ pci_p2p_mem_windows[pci_bus][window][2],
+ pci_p2p_mem_windows[pci_bus][window][3]);
+ }
+
+ return rc;
+} /* gt64260_pci_slave_p2p_mem_set_window() */
+
+int
+gt64260_pci_slave_p2p_io_set_window(struct pci_controller *hose,
+ u32 pci_base_addr,
+ u32 other_bus_base_addr,
+ u32 size)
+{
+ int rc;
+
+ rc = gt64260_pci_slave_set_window(hose,
+ pci_base_addr,
+ other_bus_base_addr,
+ size,
+ 2,
+ 0x18,
+ GT64260_PCI_1_SLAVE_P2P_IO_SIZE,
+ GT64260_PCI_1_SLAVE_P2P_IO_REMAP);
+
+ return rc;
+} /* gt64260_pci_slave_p2p_io_set_window() */
+
+int
+gt64260_pci_slave_dac_scs_set_window(struct pci_controller *hose,
+ u32 window,
+ u32 pci_base_addr_hi,
+ u32 pci_base_addr_lo,
+ u32 cpu_base_addr,
+ u32 size)
+{
+ static u32
+ pci_dac_scs_windows[GT64260_PCI_BUSES][GT64260_PCI_DAC_SCS_WINDOWS][5]={
+ { /* PCI 0 */
+ { 4, 0x10, 0x14,
+ GT64260_PCI_0_SLAVE_DAC_SCS_0_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_SCS_0_REMAP },
+ { 4, 0x18, 0x1c,
+ GT64260_PCI_0_SLAVE_DAC_SCS_1_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_SCS_1_REMAP },
+ { 5, 0x10, 0x14,
+ GT64260_PCI_0_SLAVE_DAC_SCS_2_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_SCS_2_REMAP },
+ { 5, 0x18, 0x1c,
+ GT64260_PCI_0_SLAVE_DAC_SCS_3_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_SCS_3_REMAP },
+ },
+ { /* PCI 1 */
+ { 4, 0x10, 0x14,
+ GT64260_PCI_1_SLAVE_DAC_SCS_0_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_SCS_0_REMAP },
+ { 4, 0x18, 0x1c,
+ GT64260_PCI_1_SLAVE_DAC_SCS_1_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_SCS_1_REMAP },
+ { 5, 0x10, 0x14,
+ GT64260_PCI_1_SLAVE_DAC_SCS_2_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_SCS_2_REMAP },
+ { 5, 0x18, 0x1c,
+ GT64260_PCI_1_SLAVE_DAC_SCS_3_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_SCS_3_REMAP },
+ }
+ }; /* pci_dac_scs_windows[][][] */
+ int pci_bus;
+ int rc = -1;
+
+ if (window < GT64260_PCI_DAC_SCS_WINDOWS) {
+ pci_bus = (hose->first_busno == 0) ? 0 : 1;
+
+ rc = gt64260_pci_slave_set_window(
+ hose,
+ pci_base_addr_lo,
+ cpu_base_addr,
+ size,
+ pci_dac_scs_windows[pci_bus][window][0],
+ pci_dac_scs_windows[pci_bus][window][1],
+ pci_dac_scs_windows[pci_bus][window][3],
+ pci_dac_scs_windows[pci_bus][window][4]);
+
+ early_write_config_dword(
+ hose,
+ hose->first_busno,
+ PCI_DEVFN(0, pci_dac_scs_windows[pci_bus][window][0]),
+ pci_dac_scs_windows[pci_bus][window][2],
+ pci_base_addr_hi);
+ }
+
+ return rc;
+} /* gt64260_pci_slave_dac_scs_set_window() */
+
+int
+gt64260_pci_slave_dac_cs_set_window(struct pci_controller *hose,
+ u32 window,
+ u32 pci_base_addr_hi,
+ u32 pci_base_addr_lo,
+ u32 cpu_base_addr,
+ u32 size)
+{
+ static u32
+ pci_dac_cs_windows[GT64260_PCI_BUSES][GT64260_PCI_DAC_CS_WINDOWS][5] = {
+ { /* PCI 0 */
+ { 6, 0x10, 0x14,
+ GT64260_PCI_0_SLAVE_DAC_CS_0_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_CS_0_REMAP },
+ { 6, 0x18, 0x1c,
+ GT64260_PCI_0_SLAVE_DAC_CS_1_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_CS_1_REMAP },
+ { 6, 0x20, 0x24,
+ GT64260_PCI_0_SLAVE_DAC_CS_2_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_CS_2_REMAP },
+ { 7, 0x10, 0x14,
+ GT64260_PCI_0_SLAVE_DAC_CS_3_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_CS_3_REMAP },
+ },
+ { /* PCI 1 */
+ { 6, 0x10, 0x14,
+ GT64260_PCI_1_SLAVE_DAC_CS_0_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_CS_0_REMAP },
+ { 6, 0x18, 0x1c,
+ GT64260_PCI_1_SLAVE_DAC_CS_1_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_CS_1_REMAP },
+ { 6, 0x20, 0x24,
+ GT64260_PCI_1_SLAVE_DAC_CS_2_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_CS_2_REMAP },
+ { 7, 0x10, 0x14,
+ GT64260_PCI_1_SLAVE_DAC_CS_3_SIZE,
+ GT64260_PCI_1_SLAVE_DAC_CS_3_REMAP },
+ }
+ }; /* pci_dac_cs_windows[][][] */
+ int pci_bus;
+ int rc = -1;
+
+ if (window < GT64260_PCI_CS_WINDOWS) {
+ pci_bus = (hose->first_busno == 0) ? 0 : 1;
+
+ rc = gt64260_pci_slave_set_window(
+ hose,
+ pci_base_addr_lo,
+ cpu_base_addr,
+ size,
+ pci_dac_cs_windows[pci_bus][window][0],
+ pci_dac_cs_windows[pci_bus][window][1],
+ pci_dac_cs_windows[pci_bus][window][3],
+ pci_dac_cs_windows[pci_bus][window][4]);
+
+ early_write_config_dword(
+ hose,
+ hose->first_busno,
+ PCI_DEVFN(0, pci_dac_cs_windows[pci_bus][window][0]),
+ pci_dac_cs_windows[pci_bus][window][2],
+ pci_base_addr_hi);
+ }
+
+ return rc;
+} /* gt64260_pci_slave_dac_cs_set_window() */
+
+int
+gt64260_pci_slave_dac_boot_set_window(struct pci_controller *hose,
+ u32 pci_base_addr_hi,
+ u32 pci_base_addr_lo,
+ u32 cpu_base_addr,
+ u32 size)
+{
+ int rc;
+
+ rc = gt64260_pci_slave_set_window(hose,
+ pci_base_addr_lo,
+ cpu_base_addr,
+ size,
+ 7,
+ 0x18,
+ GT64260_PCI_1_SLAVE_BOOT_SIZE,
+ GT64260_PCI_1_SLAVE_BOOT_REMAP);
+
+ early_write_config_dword(hose,
+ hose->first_busno,
+ PCI_DEVFN(0, 7),
+ 0x1c,
+ pci_base_addr_hi);
+
+ return rc;
+} /* gt64260_pci_slave_dac_boot_set_window() */
+
+int
+gt64260_pci_slave_dac_p2p_mem_set_window(struct pci_controller *hose,
+ u32 window,
+ u32 pci_base_addr_hi,
+ u32 pci_base_addr_lo,
+ u32 other_bus_base_addr,
+ u32 size)
+{
+ static u32
+ pci_dac_p2p_mem_windows[GT64260_PCI_BUSES][GT64260_PCI_DAC_P2P_MEM_WINDOWS][5] = {
+ { /* PCI 0 */
+ { 4, 0x20, 0x24,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_0_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_0_REMAP_LO },
+ { 5, 0x20, 0x24,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_1_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_1_REMAP_LO },
+ },
+ { /* PCI 1 */
+ { 4, 0xa0, 0xa4,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_0_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_0_REMAP_LO },
+ { 5, 0xa0, 0xa4,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_1_SIZE,
+ GT64260_PCI_0_SLAVE_DAC_P2P_MEM_1_REMAP_LO },
+ }
+ }; /* pci_dac_p2p_windows[][][] */
+ int pci_bus;
+ int rc = -1;
+
+ if (window < GT64260_PCI_P2P_MEM_WINDOWS) {
+ pci_bus = (hose->first_busno == 0) ? 0 : 1;
+
+ rc = gt64260_pci_slave_set_window(
+ hose,
+ pci_base_addr_lo,
+ other_bus_base_addr,
+ size,
+ pci_dac_p2p_mem_windows[pci_bus][window][0],
+ pci_dac_p2p_mem_windows[pci_bus][window][1],
+ pci_dac_p2p_mem_windows[pci_bus][window][3],
+ pci_dac_p2p_mem_windows[pci_bus][window][4]);
+
+ early_write_config_dword(
+ hose,
+ hose->first_busno,
+ PCI_DEVFN(0, pci_dac_p2p_mem_windows[pci_bus][window][0]),
+ pci_dac_p2p_mem_windows[pci_bus][window][2],
+ pci_base_addr_hi);
+ }
+
+ return rc;
+} /* gt64260_pci_slave_dac_p2p_mem_set_window() */
+
+
+/*
+ *****************************************************************************
+ *
+ * PCI Control Configuration Routines
+ *
+ *****************************************************************************
+ */
+
+
+int
+gt64260_pci_acc_cntl_set_window(u32 pci_bus,
+ u32 window,
+ u32 base_addr_hi,
+ u32 base_addr_lo,
+ u32 size,
+ u32 features)
+{
+ static u32
+ pci_acc_cntl_windows[GT64260_PCI_BUSES][GT64260_PCI_ACC_CNTL_WINDOWS][3] = {
+ { /* PCI 0 */
+ { GT64260_PCI_0_ACC_CNTL_0_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_0_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_0_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_1_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_1_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_1_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_2_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_2_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_2_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_3_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_3_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_3_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_4_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_4_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_4_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_5_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_5_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_5_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_6_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_6_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_6_TOP },
+
+ { GT64260_PCI_0_ACC_CNTL_7_BASE_HI,
+ GT64260_PCI_0_ACC_CNTL_7_BASE_LO,
+ GT64260_PCI_0_ACC_CNTL_7_TOP },
+ },
+ { /* PCI 1 */
+ { GT64260_PCI_1_ACC_CNTL_0_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_0_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_0_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_1_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_1_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_1_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_2_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_2_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_2_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_3_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_3_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_3_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_4_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_4_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_4_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_5_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_5_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_5_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_6_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_6_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_6_TOP },
+
+ { GT64260_PCI_1_ACC_CNTL_7_BASE_HI,
+ GT64260_PCI_1_ACC_CNTL_7_BASE_LO,
+ GT64260_PCI_1_ACC_CNTL_7_TOP },
+ }
+ }; /* pci_acc_cntl_windows[][][] */
+ int rc = -1;
+
+ if ((pci_bus < GT64260_PCI_BUSES) &&
+ (window < GT64260_PCI_ACC_CNTL_WINDOWS)) {
+
+ rc = gt64260_set_64bit_window(
+ base_addr_hi,
+ base_addr_lo,
+ size,
+ features,
+ pci_acc_cntl_windows[pci_bus][window][0],
+ pci_acc_cntl_windows[pci_bus][window][1],
+ pci_acc_cntl_windows[pci_bus][window][2]);
+ }
+
+ return rc;
+} /* gt64260_pci_acc_cntl_set_window() */
+
+int
+gt64260_pci_snoop_set_window(u32 pci_bus,
+ u32 window,
+ u32 base_addr_hi,
+ u32 base_addr_lo,
+ u32 size,
+ u32 snoop_type)
+{
+ static u32
+ pci_snoop_windows[GT64260_PCI_BUSES][GT64260_PCI_SNOOP_WINDOWS][3] = {
+ { /* PCI 0 */
+ { GT64260_PCI_0_SNOOP_0_BASE_HI,
+ GT64260_PCI_0_SNOOP_0_BASE_LO,
+ GT64260_PCI_0_SNOOP_0_TOP },
+
+ { GT64260_PCI_0_SNOOP_1_BASE_HI,
+ GT64260_PCI_0_SNOOP_1_BASE_LO,
+ GT64260_PCI_0_SNOOP_1_TOP },
+
+ { GT64260_PCI_0_SNOOP_2_BASE_HI,
+ GT64260_PCI_0_SNOOP_2_BASE_LO,
+ GT64260_PCI_0_SNOOP_2_TOP },
+
+ { GT64260_PCI_0_SNOOP_3_BASE_HI,
+ GT64260_PCI_0_SNOOP_3_BASE_LO,
+ GT64260_PCI_0_SNOOP_3_TOP },
+ },
+ { /* PCI 1 */
+ { GT64260_PCI_1_SNOOP_0_BASE_HI,
+ GT64260_PCI_1_SNOOP_0_BASE_LO,
+ GT64260_PCI_1_SNOOP_0_TOP },
+
+ { GT64260_PCI_1_SNOOP_1_BASE_HI,
+ GT64260_PCI_1_SNOOP_1_BASE_LO,
+ GT64260_PCI_1_SNOOP_1_TOP },
+
+ { GT64260_PCI_1_SNOOP_2_BASE_HI,
+ GT64260_PCI_1_SNOOP_2_BASE_LO,
+ GT64260_PCI_1_SNOOP_2_TOP },
+
+ { GT64260_PCI_1_SNOOP_3_BASE_HI,
+ GT64260_PCI_1_SNOOP_3_BASE_LO,
+ GT64260_PCI_1_SNOOP_3_TOP },
+ },
+ }; /* pci_snoop_windows[][][] */
+ int rc = -1;
+
+ if ((pci_bus < GT64260_PCI_BUSES) &&
+ (window < GT64260_PCI_SNOOP_WINDOWS)) {
+
+ rc = gt64260_set_64bit_window(
+ base_addr_hi,
+ base_addr_lo,
+ size,
+ snoop_type,
+ pci_snoop_windows[pci_bus][window][0],
+ pci_snoop_windows[pci_bus][window][1],
+ pci_snoop_windows[pci_bus][window][2]);
+ }
+
+ return rc;
+} /* gt64260_pci_snoop_set_window() */
+
+/*
+ *****************************************************************************
+ *
+ * 64260's Register Base Address Routines
+ *
+ *****************************************************************************
+ */
+
+/*
+ * gt64260_remap_bridge_regs()
+ *
+ * Move the bridge's register to the specified base address.
+ * Assume that there are no other windows overlapping this area and that
+ * all but the highest 3 nibbles are 0.
+ */
+int
+gt64260_set_base(u32 new_base)
+{
+ u32 val;
+ int limit = 100000;
+ int rc = 0;
+
+ val = gt_read(GT64260_INTERNAL_SPACE_DECODE);
+ val = (new_base >> 20) | (val & 0xffff0000);
+ gt_write(GT64260_INTERNAL_SPACE_DECODE, val);
+
+ iounmap((void *)gt64260_base);
+ gt64260_base = (u32)ioremap((new_base & 0xfff00000),
+ GT64260_INTERNAL_SPACE_SIZE);
+
+ do { /* Wait for bridge to move its regs */
+ val = gt_read(GT64260_INTERNAL_SPACE_DECODE);
+ } while ((val != 0xffffffff) && (limit-- > 0));
+
+ if (limit <= 0) {
+ rc = -1;
+ }
+
+ return rc;
+} /* gt64260_remap_bridge_regs() */
+
+/*
+ * gt64260_get_base()
+ *
+ * Return the current virtual base address of the 64260's registers.
+ */
+int
+gt64260_get_base(u32 *base)
+{
+ *base = gt64260_base;
+ return 0;
+} /* gt64260_remap_bridge_regs() */
+
+/*
+ *****************************************************************************
+ *
+ * Exclude PCI config space access to bridge itself
+ *
+ *****************************************************************************
+ */
+
+/*
+ * gt64260_exclude_pci_device()
+ *
+ * This routine causes the PCI subsystem to skip the PCI device in slot 0
+ * (which is the 64260 itself) unless explicitly allowed.
+ */
+int
+gt64260_pci_exclude_device(u8 bus, u8 devfn)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+
+ /* Skip slot 0 and 1 on both hoses */
+ if ((gt64260_pci_exclude_bridge == TRUE) &&
+ (PCI_SLOT(devfn) == 0) &&
+ (hose->first_busno == bus)) {
+
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else {
+ return PCIBIOS_SUCCESSFUL;
+ }
+} /* gt64260_pci_exclude_device() */
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+
+/*
+ * gt64260_putc()
+ *
+ * Dump a character out the MPSC port for gt64260_mpsc_progress
+ * this assumes the baud rate has already been set up and the
+ * MPSC initialized by the bootloader or firmware.
+ */
+
+static inline void
+gt_putc(char c){
+ mb();
+ gt_write(GT64260_MPSC_0_CHR_1, c);
+ mb();
+ gt_write(GT64260_MPSC_0_CHR_2, 0x200);
+ mb();
+
+ udelay(10000);
+}
+
+void
+puthex(unsigned long val){
+
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ gt_putc("0123456789ABCDEF"[(val>>28) & 0x0f]);
+ val <<= 4;
+ }
+ gt_putc('\r');
+ gt_putc('\n');
+
+}
+
+
+void
+gt64260_mpsc_progress(char *s, unsigned short hex){
+ /* spit stuff out the 64260 mpsc */
+
+ volatile char c;
+ while ((c = *s++) != 0){
+ gt_putc(c);
+ if ( c == '\n' ) gt_putc('\r');
+ }
+ gt_putc('\n');
+ gt_putc('\r');
+
+ return;
+}
+
+#endif /* CONFIG_DEBUG_TEXT */
diff --git a/arch/ppc/kernel/gt64260_pic.c b/arch/ppc/kernel/gt64260_pic.c
new file mode 100644
index 000000000000..e0b61032586b
--- /dev/null
+++ b/arch/ppc/kernel/gt64260_pic.c
@@ -0,0 +1,245 @@
+/*
+ * arch/ppc/kernel/gt64260_pic.c
+ *
+ * Interrupt controller support for Galileo's GT64260.
+ *
+ * Author: Chris Zankel <chris@mvista.com>
+ * Modified by: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Based on sources from Rabeeh Khoury / Galileo Technology
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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 file contains the specific functions to support the GT64260
+ * interrupt controller.
+ *
+ * The GT64260 has two main interrupt registers (high and low) that
+ * summarizes the interrupts generated by the units of the GT64260.
+ * Each bit is assigned to an interrupt number, where the low register
+ * are assigned from IRQ0 to IRQ31 and the high cause register
+ * from IRQ32 to IRQ63
+ * The GPP (General Purpose Port) interrupts are assigned from IRQ64 (GPP0)
+ * to IRQ95 (GPP31).
+ * get_irq() returns the lowest interrupt number that is currently asserted.
+ *
+ * Note:
+ * - This driver does not initialize the GPP when used as an interrupt
+ * input.
+ */
+
+#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 <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/gt64260.h>
+
+
+/* ========================== forward declaration ========================== */
+
+static void gt64260_unmask_irq(unsigned int);
+static void gt64260_mask_irq(unsigned int);
+
+/* ========================== local declarations =========================== */
+
+struct hw_interrupt_type gt64260_pic = {
+ " GT64260_PIC ", /* typename */
+ NULL, /* startup */
+ NULL, /* shutdown */
+ gt64260_unmask_irq, /* enable */
+ gt64260_mask_irq, /* disable */
+ gt64260_mask_irq, /* ack */
+ NULL, /* end */
+ NULL /* set_affinity */
+};
+
+u32 gt64260_irq_base = 0; /* GT64260 handles the next 96 IRQs from here */
+
+/* gt64260_init_irq()
+ *
+ * This function initializes the interrupt controller. It assigns
+ * all interrupts from IRQ0 to IRQ95 to the gt64260 interrupt controller.
+ *
+ * Input Variable(s):
+ * None.
+ *
+ * Outpu. Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ *
+ * Note:
+ * We register all GPP inputs as interrupt source, but disable them.
+ */
+
+__init void
+gt64260_init_irq(void)
+{
+ int i;
+
+ if ( ppc_md.progress ) ppc_md.progress("gt64260_init_irq: enter", 0x0);
+
+ ppc_cached_irq_mask[0] = 0;
+ ppc_cached_irq_mask[1] = 0x0f000000; /* Enable GPP intrs */
+ ppc_cached_irq_mask[2] = 0;
+
+ /* disable all interrupts and clear current interrupts */
+ gt_write(GT64260_GPP_INTR_MASK, ppc_cached_irq_mask[2]);
+ gt_write(GT64260_GPP_INTR_CAUSE,0);
+ gt_write(GT64260_IC_CPU_INTR_MASK_LO, ppc_cached_irq_mask[0]);
+ gt_write(GT64260_IC_CPU_INTR_MASK_HI, ppc_cached_irq_mask[1]);
+
+ /* use the gt64260 for all (possible) interrupt sources */
+ for( i = gt64260_irq_base; i < (gt64260_irq_base + 96); i++ ) {
+ irq_desc[i].handler = &gt64260_pic;
+ }
+
+ if ( ppc_md.progress ) ppc_md.progress("gt64260_init_irq: exit", 0x0);
+}
+
+
+/* gt64260_get_irq()
+ *
+ * This function returns the lowest interrupt number of all interrupts that
+ * are currently asserted.
+ *
+ * Input Variable(s):
+ * struct pt_regs* not used
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * int <interrupt number> or -2 (bogus interrupt)
+ *
+ */
+int
+gt64260_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ int irq_gpp;
+
+ irq = gt_read(GT64260_IC_MAIN_CAUSE_LO);
+ irq = __ilog2((irq & 0x3dfffffe) & ppc_cached_irq_mask[0]);
+
+ if (irq == -1) {
+ irq = gt_read(GT64260_IC_MAIN_CAUSE_HI);
+ irq = __ilog2((irq & 0x0f000db7) & ppc_cached_irq_mask[1]);
+
+ if (irq == -1) {
+ irq = -2; /* bogus interrupt, should never happen */
+ } else {
+ if (irq >= 24) {
+ irq_gpp = gt_read(GT64260_GPP_INTR_CAUSE);
+ irq_gpp = __ilog2(irq_gpp &
+ ppc_cached_irq_mask[2]);
+
+ if (irq_gpp == -1) {
+ irq = -2;
+ } else {
+ irq = irq_gpp + 64;
+ gt_write(GT64260_GPP_INTR_CAUSE, ~(1<<(irq-64)));
+ }
+ } else {
+ irq += 32;
+ }
+ }
+ }
+
+ if( irq < 0 ) {
+ return( irq );
+ } else {
+ return( gt64260_irq_base + irq );
+ }
+}
+
+/* gt64260_unmask_irq()
+ *
+ * This function enables an interrupt.
+ *
+ * Input Variable(s):
+ * unsigned int interrupt number (IRQ0...IRQ95).
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ */
+
+static void
+gt64260_unmask_irq(unsigned int irq)
+{
+ irq -= gt64260_irq_base;
+ if (irq > 31) {
+ if (irq > 63) {
+ /* unmask GPP irq */
+ gt_write(GT64260_GPP_INTR_MASK,
+ ppc_cached_irq_mask[2] |= (1<<(irq-64)));
+ } else {
+ /* mask high interrupt register */
+ gt_write(GT64260_IC_CPU_INTR_MASK_HI,
+ ppc_cached_irq_mask[1] |= (1<<(irq-32)));
+ }
+ } else {
+ /* mask low interrupt register */
+ gt_write(GT64260_IC_CPU_INTR_MASK_LO,
+ ppc_cached_irq_mask[0] |= (1<<irq));
+ }
+}
+
+
+/* gt64260_mask_irq()
+ *
+ * This funktion disables the requested interrupt.
+ *
+ * Input Variable(s):
+ * unsigned int interrupt number (IRQ0...IRQ95).
+ *
+ * Output Variable(s):
+ * None.
+ *
+ * Returns:
+ * void
+ */
+
+static void
+gt64260_mask_irq(unsigned int irq)
+{
+ irq -= gt64260_irq_base;
+ if (irq > 31) {
+ if (irq > 63) {
+ /* mask GPP irq */
+ gt_write(GT64260_GPP_INTR_MASK,
+ ppc_cached_irq_mask[2] &= ~(1<<(irq-64)));
+ } else {
+ /* mask high interrupt register */
+ gt_write(GT64260_IC_CPU_INTR_MASK_HI,
+ ppc_cached_irq_mask[1] &= ~(1<<(irq-32)));
+ }
+ } else {
+ /* mask low interrupt register */
+ gt_write(GT64260_IC_CPU_INTR_MASK_LO,
+ ppc_cached_irq_mask[0] &= ~(1<<irq));
+ }
+
+ if (irq == 36) { /* Seems necessary for SDMA interrupts */
+ udelay(1);
+ }
+}
+
diff --git a/arch/ppc/kernel/harrier.c b/arch/ppc/kernel/harrier.c
new file mode 100644
index 000000000000..343ada453eac
--- /dev/null
+++ b/arch/ppc/kernel/harrier.c
@@ -0,0 +1,214 @@
+/*
+ * arch/ppc/kernel/harrier.c
+ *
+ * Motorola MCG Harrier northbridge/memory controller support
+ *
+ * Author: Dale Farnsworth
+ * dale.farnsworth@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/harrier.h>
+
+/*
+ * Initialize the Motorola MCG Harrier host bridge.
+ *
+ * This means setting up the PPC bus to PCI memory and I/O space mappings,
+ * setting the PCI memory space address of the MPIC (mapped straight
+ * through), and ioremap'ing the mpic registers.
+ * 'OpenPIC_Addr' will be set correctly by this routine.
+ * This routine will not change the PCI_CONFIG_ADDR or PCI_CONFIG_DATA
+ * addresses and assumes that the mapping of PCI memory space back to system
+ * memory is set up correctly by PPCBug.
+ */
+int __init
+harrier_init(struct pci_controller *hose,
+ uint ppc_reg_base,
+ ulong processor_pci_mem_start,
+ ulong processor_pci_mem_end,
+ ulong processor_pci_io_start,
+ ulong processor_pci_io_end,
+ ulong processor_mpic_base)
+{
+ uint addr, offset;
+
+ /*
+ * Some sanity checks...
+ */
+ if (((processor_pci_mem_start&0xffff0000) != processor_pci_mem_start) ||
+ ((processor_pci_io_start &0xffff0000) != processor_pci_io_start)) {
+ printk("harrier_init: %s\n",
+ "PPC to PCI mappings must start on 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end &0x0000ffff) != 0x0000ffff) ||
+ ((processor_pci_io_end &0x0000ffff) != 0x0000ffff)) {
+ printk("harrier_init: PPC to PCI mappings %s\n",
+ "must end just before a 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end - processor_pci_mem_start) !=
+ (hose->mem_space.end - hose->mem_space.start)) ||
+ ((processor_pci_io_end - processor_pci_io_start) !=
+ (hose->io_space.end - hose->io_space.start))) {
+ printk("harrier_init: %s\n",
+ "PPC and PCI memory or I/O space sizes don't match");
+ return -1;
+ }
+
+ if ((processor_mpic_base & 0xfffc0000) != processor_mpic_base) {
+ printk("harrier_init: %s\n",
+ "MPIC address must start on 256 KB boundary");
+ return -1;
+ }
+
+ if ((pci_dram_offset & 0xffff0000) != pci_dram_offset) {
+ printk("harrier_init: %s\n",
+ "pci_dram_offset must be multiple of 64 KB");
+ return -1;
+ }
+
+ /*
+ * Program the OTAD/OTOF registers to set up the PCI Mem & I/O
+ * space mappings. These are the mappings going from the processor to
+ * the PCI bus.
+ *
+ * Note: Don't need to 'AND' start/end addresses with 0xffff0000
+ * because sanity check above ensures that they are properly
+ * aligned.
+ */
+
+ /* Set up PPC->PCI Mem mapping */
+ addr = processor_pci_mem_start | (processor_pci_mem_end >> 16);
+ offset = (hose->mem_space.start - processor_pci_mem_start) | 0x92;
+ out_be32((uint *)(ppc_reg_base + HARRIER_OTAD0_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + HARRIER_OTOF0_OFF), offset);
+
+ /* Set up PPC->PCI I/O mapping -- Contiguous I/O space */
+ addr = processor_pci_io_start | (processor_pci_io_end >> 16);
+ offset = (hose->io_space.start - processor_pci_io_start) | 0x80;
+ out_be32((uint *)(ppc_reg_base + HARRIER_OTAD1_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + HARRIER_OTOF1_OFF), offset);
+
+ /* Enable MPIC */
+ OpenPIC_Addr = (void *)processor_mpic_base;
+ addr = (processor_mpic_base >> 16) | 1;
+ out_be16((ushort *)(ppc_reg_base + HARRIER_MBAR_OFF), addr);
+ out_8((u_char *)(ppc_reg_base + HARRIER_MPIC_CSR_OFF),
+ HARRIER_MPIC_OPI_ENABLE);
+
+ return 0;
+}
+
+/*
+ * Find the amount of RAM present.
+ * This assumes that PPCBug has initialized the memory controller (SMC)
+ * on the Harrier correctly (i.e., it does no sanity checking).
+ * It also assumes that the memory base registers are set to configure the
+ * memory as contigous starting with "RAM A BASE", "RAM B BASE", etc.
+ * however, RAM base registers can be skipped (e.g. A, B, C are set,
+ * D is skipped but E is set is okay).
+ */
+#define MB (1024*1024UL)
+
+static uint harrier_size_table[] __initdata = {
+ 0 * MB, /* 0 ==> 0 MB */
+ 32 * MB, /* 1 ==> 32 MB */
+ 64 * MB, /* 2 ==> 64 MB */
+ 64 * MB, /* 3 ==> 64 MB */
+ 128 * MB, /* 4 ==> 128 MB */
+ 128 * MB, /* 5 ==> 128 MB */
+ 128 * MB, /* 6 ==> 128 MB */
+ 256 * MB, /* 7 ==> 256 MB */
+ 256 * MB, /* 8 ==> 256 MB */
+ 256 * MB, /* 9 ==> 256 MB */
+ 512 * MB, /* a ==> 512 MB */
+ 512 * MB, /* b ==> 512 MB */
+ 512 * MB, /* c ==> 512 MB */
+ 1024 * MB, /* d ==> 1024 MB */
+ 1024 * MB, /* e ==> 1024 MB */
+ 2048 * MB, /* f ==> 2048 MB */
+};
+
+/*
+ * *** WARNING: You MUST have a BAT set up to map in the XCSR regs ***
+ *
+ * Read the memory controller's registers to determine the amount of system
+ * memory. Assumes that the memory controller registers are already mapped
+ * into virtual memory--too early to use ioremap().
+ */
+unsigned long __init
+harrier_get_mem_size(uint xcsr_base)
+{
+ ulong last_addr;
+ int i;
+ uint vend_dev_id;
+ uint *size_table;
+ uint val;
+ uint *csrp;
+ uint size;
+ int size_table_entries;
+
+ vend_dev_id = in_be32((uint *)xcsr_base + PCI_VENDOR_ID);
+
+ if (((vend_dev_id & 0xffff0000) >> 16) != PCI_VENDOR_ID_MOTOROLA) {
+ printk("harrier_get_mem_size: %s (0x%x)\n",
+ "Not a Motorola Memory Controller", vend_dev_id);
+ return 0;
+ }
+
+ vend_dev_id &= 0x0000ffff;
+
+ if (vend_dev_id == PCI_DEVICE_ID_MOTOROLA_HARRIER) {
+ size_table = harrier_size_table;
+ size_table_entries = sizeof(harrier_size_table) /
+ sizeof(harrier_size_table[0]);
+ }
+ else {
+ printk("harrier_get_mem_size: %s (0x%x)\n",
+ "Not a Harrier", vend_dev_id);
+ return 0;
+ }
+
+ last_addr = 0;
+
+ csrp = (uint *)(xcsr_base + HARRIER_SDBA_OFF);
+ for (i=0; i<8; i++) {
+ val = in_be32(csrp++);
+
+ if (val & 0x100) { /* If enabled */
+ size = val >> HARRIER_SDB_SIZE_SHIFT;
+ size &= HARRIER_SDB_SIZE_MASK;
+ if (size >= size_table_entries) {
+ break; /* Register not set correctly */
+ }
+ size = size_table[size];
+
+ val &= ~(size-1);
+ val += size;
+
+ if (val > last_addr) {
+ last_addr = val;
+ }
+ }
+ }
+
+ return last_addr;
+}
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 5e13c0a9257d..6a57fa4dad53 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.head.S 1.31 10/18/01 15:02:09 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* PowerPC version
@@ -22,17 +22,18 @@
* 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 <linux/config.h>
-#include "ppc_asm.h"
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/pgtable.h>
#include <asm/cputable.h>
#include <asm/cache.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
#ifdef CONFIG_APUS
#include <asm/amigappc.h>
@@ -48,9 +49,9 @@
ld RB,(n*32)+24(reg); \
mtspr DBAT##n##U,RA; \
mtspr DBAT##n##L,RB; \
-
+
#else /* CONFIG_PPC64BRIDGE */
-
+
/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, reg, RA, RB) \
/* see the comment for clear_bats() -- Cort */ \
@@ -66,10 +67,13 @@
lwz RB,(n*16)+12(reg); \
mtspr DBAT##n##U,RA; \
mtspr DBAT##n##L,RB; \
-1:
+1:
#endif /* CONFIG_PPC64BRIDGE */
.text
+ .stabs "arch/ppc/kernel/",N_SO,0,0,0f
+ .stabs "head.S",N_SO,0,0,0f
+0:
.globl _stext
_stext:
@@ -86,8 +90,8 @@ _start:
* but we're always started by some kind of bootloader now.
* -- Cort
*/
- nop
- nop
+ nop /* used by __secondary_hold on prep (mtx) and chrp smp */
+ nop /* used by __secondary_hold on prep (mtx) and chrp smp */
nop
/* PMAC
@@ -113,7 +117,7 @@ _start:
* PREP
* This is jumped to on prep systems right after the kernel is relocated
* to its proper place in memory by the boot loader. The expected layout
- * of the regs is:
+ * of the regs is:
* r3: ptr to residual data
* r4: initrd_start or if no initrd then 0
* r5: initrd_end - unused if r4 is 0
@@ -124,7 +128,7 @@ _start:
* start_here() to do the real work.
* -- Cort
*/
-
+
.globl __start
__start:
/*
@@ -153,7 +157,6 @@ __start:
bl fix_mem_constants
#endif /* CONFIG_APUS */
-#ifndef CONFIG_GEMINI
/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
* the physical address we are running at, returned by early_init()
*/
@@ -161,28 +164,11 @@ __start:
__after_mmu_off:
bl clear_bats
bl flush_tlbs
-#endif
-#ifndef CONFIG_POWER4
- /* POWER4 doesn't have BATs */
bl initial_bats
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
-#else /* CONFIG_POWER4 */
-/*
- * Load up the SDR1 and segment register values now
- * since we don't have the BATs.
- */
- bl reloc_offset
- addis r4,r3,_SDR1@ha /* get the value from _SDR1 */
- lwz r4,_SDR1@l(r4) /* assume hash table below 4GB */
- mtspr SDR1,r4
- slbia
- lis r5,0x2000 /* set pseudo-segment reg 12 */
- ori r5,r5,0x0ccc
- mtsr 12,r5
-#endif /* CONFIG_POWER4 */
#ifndef CONFIG_APUS
/*
@@ -217,11 +203,17 @@ turn_on_mmu:
SYNC
RFI /* enables MMU */
-#ifdef CONFIG_SMP
+/*
+ * We need __secondary_hold as a place to hold the other cpus on
+ * an SMP machine, even when we are running a UP kernel.
+ */
+ . = 0xc0 /* for prep bootloader */
+ li r3,1 /* MTX only has 1 cpu */
.globl __secondary_hold
__secondary_hold:
/* tell the master we're here */
stw r3,4(0)
+#ifdef CONFIG_SMP
100: lwz r4,0(0)
/* wait until we're told to start */
cmpw 0,r4,r3
@@ -229,7 +221,9 @@ __secondary_hold:
/* our cpu # was at addr 0 - go */
mr r24,r3 /* cpu # */
b __secondary_start
-#endif
+#else
+ b .
+#endif /* CONFIG_SMP */
/*
* Exception entry code. This code runs with address translation
@@ -289,13 +283,11 @@ i##n: \
.long ret_from_except
/* System reset */
-#ifdef CONFIG_SMP /* MVME/MTX and gemini start the secondary here */
-#ifdef CONFIG_GEMINI
+/* core99 pmac starts the seconary here by changing the vector, and
+ putting it back to what it was (UnknownException) when done. */
+#if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)
. = 0x100
b __secondary_start_gemini
-#else /* CONFIG_GEMINI */
- STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
-#endif /* CONFIG_GEMINI */
#else
STD_EXCEPTION(0x100, Reset, UnknownException)
#endif
@@ -388,16 +380,12 @@ HardwareInterrupt:
EXCEPTION_PROLOG;
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
-#ifndef CONFIG_APUS
li r4,0
bl transfer_to_handler
.globl do_IRQ_intercept
do_IRQ_intercept:
.long do_IRQ;
.long ret_from_intercept
-#else
- bl apus_interrupt_entry
-#endif /* CONFIG_APUS */
/* Alignment exception */
. = 0x600
@@ -487,7 +475,7 @@ trap_0f_cont:
Trap_0f:
EXCEPTION_PROLOG
b trap_0f_cont
-
+
/*
* Handle TLB miss for instruction on 603/603e.
* Note: we get an alternate set of r0 - r3 to use automatically.
@@ -636,7 +624,7 @@ DataAddressInvalid:
mtcrf 0x80,r3 /* Restore CR0 */
mtmsr r0
b DataAccess
-
+
/*
* Handle TLB miss for DATA Store on 603/603e
*/
@@ -809,11 +797,11 @@ stack_ovf:
RFI
/*
- * Disable FP for the task which had the FPU previously,
+ * This task wants to use the FPU now.
+ * On UP, disable FP for the task which had the FPU previously,
* and save its floating-point registers in its thread_struct.
- * Enables the FPU for use in the kernel on return.
- * On SMP we know the fpu is free, since we give it up every
- * switch. -- Cort
+ * Load up this task's FP registers from its thread_struct,
+ * enable the FPU for the current task and return to the task.
*/
load_up_fpu:
mfmsr r5
@@ -830,14 +818,13 @@ load_up_fpu:
* to another. Instead we call giveup_fpu in switch_to.
*/
#ifndef CONFIG_SMP
- lis r6,0 /* get __pa constant */
- tophys(r6,r6)
+ tophys(r6,0) /* get __pa constant */
addis r3,r6,last_task_used_math@ha
lwz r4,last_task_used_math@l(r3)
cmpi 0,r4,0
beq 1f
add r4,r4,r6
- addi r4,r4,THREAD /* want THREAD of last_task_used_math */
+ addi r4,r4,THREAD /* want last_task_used_math->thread */
SAVE_32FPRS(0, r4)
mffs fr0
stfd fr0,THREAD_FPSCR-4(r4)
@@ -850,8 +837,10 @@ load_up_fpu:
1:
#endif /* CONFIG_SMP */
/* enable use of FP after return */
- ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1
mfspr r5,SPRG3 /* current task's THREAD (phys) */
+ lwz r4,THREAD_FPEXC_MODE(r5)
+ ori r23,r23,MSR_FP /* enable FP for current */
+ or r23,r23,r4
lfd fr0,THREAD_FPSCR-4(r5)
mtfsf 0xff,fr0
REST_32FPRS(0, r5)
@@ -875,7 +864,7 @@ load_up_fpu:
lwz r21,GPR21(r21)
SYNC
RFI
-
+
/*
* FP unavailable trap from kernel - print a message, but let
* the task use FP in the kernel until it returns to user mode.
@@ -1020,7 +1009,7 @@ giveup_altivec:
#endif /* CONFIG_SMP */
blr
#endif /* CONFIG_ALTIVEC */
-
+
/*
* giveup_fpu(tsk)
* Disable FP for the task given as the argument,
@@ -1031,9 +1020,10 @@ giveup_altivec:
giveup_fpu:
mfmsr r5
ori r5,r5,MSR_FP
- SYNC
+ SYNC_601
+ ISYNC_601
mtmsr r5 /* enable use of fpu now */
- SYNC
+ SYNC_601
isync
cmpi 0,r3,0
beqlr- /* if no previous owner, done */
@@ -1172,62 +1162,6 @@ fix_mem_constants:
sync /* additional sync needed on g4 */
isync /* No speculative loading until now */
blr
-
-apus_interrupt_entry:
- /* This is horrible, but there's no way around it. Enable the
- * data cache so the IRQ hardware register can be accessed
- * without cache intervention. Then disable interrupts and get
- * the current emulated m68k IPL value.
- */
-
- mfmsr 20
- xori r20,r20,MSR_DR
- SYNC
- mtmsr r20
- isync
-
- lis r4,APUS_IPL_EMU@h
-
- li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
- stb r20,APUS_IPL_EMU@l(r4)
- eieio
-
- lbz r3,APUS_IPL_EMU@l(r4)
-
- li r2,IPLEMU_IPLMASK
- rlwinm. r20,r3,32-3,29,31
- bne 2f
- mr r20,r2 /* lvl7! Need to reset state machine. */
- b 3f
-2: cmp 0,r20,r2
- beq 1f
-3: eieio
- stb r2,APUS_IPL_EMU@l(r4)
- ori r20,r20,IPLEMU_SETRESET
- eieio
- stb r20,APUS_IPL_EMU@l(r4)
-1: eieio
- li r20,IPLEMU_DISABLEINT
- stb r20,APUS_IPL_EMU@l(r4)
-
- /* At this point we could do some magic to avoid the overhead
- * of calling the C interrupt handler in case of a spurious
- * interrupt. Could not get a simple hack to work though.
- */
-
- mfmsr r20
- xori r20,r20,MSR_DR
- SYNC
- mtmsr r20
- isync
-
- stw r3,(_CCR+4)(r21);
-
- addi r3,r1,STACK_FRAME_OVERHEAD;
- li r20,MSR_KERNEL;
- bl transfer_to_handler;
- .long do_IRQ;
- .long ret_from_except
/***********************************************************************
* Please note that on APUS the exception handlers are located at the
@@ -1247,10 +1181,9 @@ __secondary_start_gemini:
andc r4,r4,r3
mtspr HID0,r4
sync
- bl prom_init
+ bl gemini_prom_init
b __secondary_start
#endif /* CONFIG_GEMINI */
-
.globl __secondary_start_psurge
__secondary_start_psurge:
li r24,1 /* cpu # */
@@ -1310,7 +1243,6 @@ __secondary_start:
mtspr SPRG3,r4
li r3,0
mtspr SPRG2,r3 /* 0 => r1 has kernel sp */
- stw r3,PT_REGS(r4) /* set thread.regs to 0 for kernel thread */
/* enable MMU and jump to start_secondary */
li r4,MSR_KERNEL
@@ -1347,12 +1279,22 @@ _GLOBAL(__setup_cpu_7400)
bl setup_750_7400_hid0
mtlr r4
blr
+_GLOBAL(__setup_cpu_7410)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ li r3,0
+ mtspr SPRN_L2CR2,r3
+ mtlr r4
+ blr
_GLOBAL(__setup_cpu_7450)
+ mflr r4
+ bl setup_common_caches
+ bl setup_7450_hid0
+ mtlr r4
blr
_GLOBAL(__setup_cpu_power3)
blr
-_GLOBAL(__setup_cpu_power4)
- blr
_GLOBAL(__setup_cpu_generic)
blr
@@ -1407,6 +1349,47 @@ setup_750_7400_hid0:
isync
blr
+/* 7450
+ * Enable Store Gathering (SGE), Branch Folding (FOLD)
+ * Branch History Table (BHTE), Branch Target ICache (BTIC)
+ * Dynamic Power Management (DPM), Speculative (SPD)
+ * Ensure our data cache instructions really operate.
+ * Timebase has to be running or we wouldn't have made it here,
+ * just ensure we don't disable it.
+ * Clear Instruction cache throttling (ICTC)
+ */
+setup_7450_hid0:
+ /* We check for the presence of an L3 cache setup by
+ * the firmware. If any, we disable DOZE capability
+ */
+ mfspr r11,SPRN_L3CR
+ andis. r11,r11,L3CR_L3E@h
+ beq 1f
+ li r7,CPU_FTR_CAN_DOZE
+ lwz r6,CPU_SPEC_FEATURES(r5)
+ andc r6,r6,r7
+ stw r6,CPU_SPEC_FEATURES(r5)
+1:
+ mfspr r11,HID0
+
+ /* All of the bits we have to set.....
+ */
+ ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_BTIC
+ oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
+
+ /* All of the bits we have to clear....
+ */
+ li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI
+ andc r11,r11,r3 /* clear SPD: enable speculative */
+ li r3,0
+
+ mtspr ICTC,r3 /* Instruction Cache Throttling off */
+ isync
+ mtspr HID0,r11
+ sync
+ isync
+ blr
+
/*
* Load stuff into the MMU. Intended to be called with
* IR=0 and DR=0.
@@ -1417,7 +1400,7 @@ load_up_mmu:
tophys(r6,r6)
lwz r6,_SDR1@l(r6)
mtspr SDR1,r6
-#ifdef CONFIG_PPC64BRIDGE
+#ifdef CONFIG_PPC64BRIDGE
/* clear the ASR so we only use the pseudo-segment registers. */
li r6,0
mtasr r6
@@ -1430,7 +1413,6 @@ load_up_mmu:
addi r3,r3,0x111 /* increment VSID */
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
-#ifndef CONFIG_POWER4
/* Load the BAT registers with the values set up by MMU_init.
MMU_init takes care of whether we're on a 601 or not. */
mfpvr r3
@@ -1443,7 +1425,6 @@ load_up_mmu:
LOAD_BAT(1,r3,r4,r5)
LOAD_BAT(2,r3,r4,r5)
LOAD_BAT(3,r3,r4,r5)
-#endif /* CONFIG_POWER4 */
blr
/*
@@ -1519,6 +1500,19 @@ start_here:
TLBSYNC /* ... on all CPUs */
bl load_up_mmu
+
+ /* Add helper information for the Abatron bdiGDB debugger.
+ * We do this here because we know the mmu is disabled, and
+ * will be enabled for real in just a few instructions.
+ */
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r5, 0xf0(r0) /* This much match your Abatron config */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ tophys(r5, r5)
+ stw r6, 0(r5)
+
/* Now turn on the MMU for real! */
li r4,MSR_KERNEL
FIX_SRR1(r4,r5)
@@ -1538,6 +1532,15 @@ _GLOBAL(set_context)
addis r3,r3,0x6000 /* Set Ks, Ku bits */
li r0,NUM_USER_SEGMENTS
mtctr r0
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is passed as second argument.
+ */
+ lis r5, KERNELBASE@h
+ lwz r5, 0xf0(r5)
+ stw r4, 0x4(r5)
+#endif
li r4,0
3:
#ifdef CONFIG_PPC64BRIDGE
@@ -1561,22 +1564,21 @@ _GLOBAL(set_context)
* -- Cort
*/
clear_bats:
-#if !defined(CONFIG_GEMINI)
li r20,0
mfspr r9,PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi r9, 1
beq 1f
-
+
mtspr DBAT0U,r20
- mtspr DBAT0L,r20
+ mtspr DBAT0L,r20
mtspr DBAT1U,r20
mtspr DBAT1L,r20
mtspr DBAT2U,r20
- mtspr DBAT2L,r20
+ mtspr DBAT2L,r20
mtspr DBAT3U,r20
mtspr DBAT3L,r20
-1:
+1:
mtspr IBAT0U,r20
mtspr IBAT0L,r20
mtspr IBAT1U,r20
@@ -1585,10 +1587,8 @@ clear_bats:
mtspr IBAT2L,r20
mtspr IBAT3U,r20
mtspr IBAT3L,r20
-#endif /* !defined(CONFIG_GEMINI) */
blr
-#ifndef CONFIG_GEMINI
flush_tlbs:
lis r20, 0x40
1: addic. r20, r20, -0x1000
@@ -1607,9 +1607,7 @@ mmu_off:
mtspr SRR1,r3
sync
RFI
-#endif
-#ifndef CONFIG_POWER4
/*
* Use the first pair of BAT registers to map the 1st 16MB
* of RAM to KERNELBASE. From this point on we can't safely
@@ -1645,7 +1643,7 @@ initial_bats:
#else
ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
#endif /* CONFIG_APUS */
-
+
#ifdef CONFIG_PPC64BRIDGE
/* clear out the high 32 bits in the BAT */
clrldi r11,r11,32
@@ -1682,7 +1680,6 @@ setup_disp_bat:
blr
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
-#endif /* CONFIG_POWER4 */
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
@@ -1734,12 +1731,12 @@ empty_zero_page:
.globl swapper_pg_dir
swapper_pg_dir:
- .space 4096
+ .space 4096
/*
* This space gets a copy of optional info passed to us by the bootstrap
* Used to pass parameters into the kernel like root=/dev/sda1, etc.
- */
+ */
.globl cmd_line
cmd_line:
.space 512
@@ -1752,3 +1749,9 @@ intercept_table:
.long 0, 0, 0, 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0
+
+/* Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+ .space 8
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index 35e17f1df41c..39553b2363e4 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -1,7 +1,4 @@
/*
- * BK Id: SCCS/s.head_4xx.S 1.6 05/21/01 11:50:00 paulus
- */
-/*
* Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
* Initial PowerPC version.
* Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
@@ -14,6 +11,13 @@
* PowerPC 403GCX modifications.
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
* PowerPC 403GCX/405GP modifications.
+ * Copyright 2000 MontaVista Software Inc.
+ * PPC405 modifications
+ * PowerPC 403GCX/405GP modifications.
+ * Author: MontaVista Software, Inc.
+ * frank_rowand@mvista.com or source@mvista.com
+ * debbie_chu@mvista.com
+ *
*
* Module name: head_4xx.S
*
@@ -28,139 +32,91 @@
*/
#include <linux/config.h>
-
#include <asm/processor.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/mmu.h>
-
-#include "ppc_asm.h"
-
+#include <asm/pgtable.h>
+#include <asm/ibm4xx.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
/* Preprocessor Defines */
#define STND_EXC 0
#define CRIT_EXC 1
-###
-### Check to make sure the right processor has been defined.
-###
-
-#if !defined(CONFIG_4xx)
-#error "This file is only appropriate for kernels supporting the PPC4xx."
-#endif
-
-###
-### Execution entry point.
-###
-
-###
-### As with the other PowerPC ports, it is expected that when code
-### execution begins here, the following registers contain valid, yet
-### optional, information:
-###
-### r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
-### r4 - Starting address of the init RAM disk
-### r5 - Ending address of the init RAM disk
-### r6 - Start of kernel command line string (e.g. "mem=96m")
-### r7 - End of kernel command line string
-###
-
+/* As with the other PowerPC ports, it is expected that when code
+ * execution begins here, the following registers contain valid, yet
+ * optional, information:
+ *
+ * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
+ * r4 - Starting address of the init RAM disk
+ * r5 - Ending address of the init RAM disk
+ * r6 - Start of kernel command line string (e.g. "mem=96m")
+ * r7 - End of kernel command line string
+ *
+ * This is all going to change RSN when we add bi_recs....... -- Dan
+ */
.text
_GLOBAL(_stext)
_GLOBAL(_start)
- ## Save residual data, init RAM disk, and command line parameters
-
+
+ /* Save parameters we are passed.
+ */
mr r31,r3
mr r30,r4
mr r29,r5
mr r28,r6
mr r27,r7
+ li r24,0 /* CPU number */
- ## Set the ID for this CPU
-
- li r24,0
-
- ## Invalidate all TLB entries
+ /* We have to turn on the MMU right away so we get cache modes
+ * set correctly.
+ */
+ bl initial_mmu
- tlbia
-
- ## We should still be executing code at physical address 0x0000xxxx
- ## at this point. However, start_here is at virtual address
- ## 0xC000xxxx. So, set up a TLB mapping to cover this once
- ## translation is enabled.
-
- lis r3,KERNELBASE@h # Load the kernel virtual address
- ori r3,r3,KERNELBASE@l
- tophys(r4,r3) # Load the kernel physical address
-
- ## Save the existing PID and load the kernel PID.
-
- mfspr r7,SPRN_PID # Save the old PID
- li r0,0
- mtspr SPRN_PID,r0 # Load the kernel PID
-
- ## Configure and load entry into TLB slot 0.
-
- clrrwi r4,r4,10 # Mask off the real page number
- ori r4,r4,(TLB_WR | TLB_EX) # Set the write and execute bits
-
- clrrwi r3,r3,10 # Mask off the effective page number
- ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
-
- tlbwe r4,r0,TLB_DATA # Load the data portion of the entry
- tlbwe r3,r0,TLB_TAG # Load the tag portion of the entry
- isync
-
- mtspr SPRN_PID,r7 # Restore the existing PID
-
- ## Establish the exception vector base
-
- lis r4,KERNELBASE@h # EVPR only uses the high 16-bits
- tophys(r0,r4) # Use the physical address
- mtspr SPRN_EVPR,r0
-
- ## Enable the MMU and jump to the main PowerPC kernel start-up code
-
- mfmsr r0 # Get the machine state register
- ori r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation
- mtspr SPRN_SRR1,r0 # Set up the new machine state register
- lis r0,start_here@h
- ori r0,r0,start_here@l
- mtspr SPRN_SRR0,r0 # Set up the new instruction pointer
- rfi # Jump to start_here w/ translation on
-
-
-###
-### Exception vector entry code. This code runs with address translation
-### turned off (i.e. using physical addresses). We assume SPRG3 has the
-### physical address of the current task thread_struct.
-###
-
- ## Common exception code for all exception types.
-
-#define COMMON_PROLOG \
-0: mtspr SPRN_SPRG0,r20; /* We need r20, move it to SPRG0 */\
- mtspr SPRN_SPRG1,r21; /* We need r21, move it to SPRG1 */\
- mfcr r20; /* We need the CR, move it to r20 */\
- mfspr r21,SPRN_SPRG2; /* Exception stack to use */\
- cmpwi cr0,r21,0; /* From user mode or RTAS? */\
- bne 1f; /* Not RTAS, branch */\
- tophys(r21, r1); /* Convert vka in r1 to pka in r21 */\
- subi r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame */\
-1: stw r20,_CCR(r21); /* Save CR on the stack */\
- stw r22,GPR22(r21); /* Save r22 on the stack */\
- stw r23,GPR23(r21); /* r23 Save on the stack */\
- mfspr r20,SPRN_SPRG0; /* Get r20 back out of SPRG0 */\
- stw r20,GPR20(r21); /* Save r20 on the stack */\
- mfspr r22,SPRN_SPRG1; /* Get r21 back out of SPRG0 */\
- stw r22,GPR21(r21); /* Save r21 on the stack */\
- mflr r20; \
- stw r20,_LINK(r21); /* Save LR on the stack */\
- mfctr r22; \
- stw r22,_CTR(r21); /* Save CTR on the stack */\
- mfspr r20,XER; \
- stw r20,_XER(r21); /* Save XER on the stack */
+/* We now have the lower 16 Meg mapped into TLB entries, and the caches
+ * ready to work.
+ */
+turn_on_mmu:
+ li r0,MSR_KERNEL
+ mtspr SRR1,r0
+ lis r0,start_here@h
+ ori r0,r0,start_here@l
+ mtspr SRR0,r0
+ SYNC
+ rfi /* enables MMU */
+
+/* Exception vector entry code. This code runs with address translation
+ * turned off (i.e. using physical addresses). We assume SPRG3 has the
+ * physical address of the current task thread_struct.
+ */
+
+#define COMMON_PROLOG(n) \
+0: mtspr SPRN_SPRG0,r20; /* We need r20, move it to SPRG0 */\
+ mtspr SPRN_SPRG1,r21; /* We need r21, move it to SPRG1 */\
+ mfcr r20; /* We need the CR, move it to r20 */\
+ mfspr r21,SPRN_SPRG2; /* Exception stack to use */\
+ cmpwi cr0,r21,0; /* From user mode or RTAS? */\
+ bne 1f; /* Not RTAS, branch */\
+ tophys(r21, r1); /* Convert vka in r1 to pka in r21 */\
+ subi r21,r21,INT_FRAME_SIZE; /* Allocate an exception frame */\
+1: stw r20,_CCR(r21); /* Save CR on the stack */\
+ stw r22,GPR22(r21); /* Save r22 on the stack */\
+ stw r23,GPR23(r21); /* r23 Save on the stack */\
+ mfspr r20,SPRN_SPRG0; /* Get r20 back out of SPRG0 */\
+ stw r20,GPR20(r21); /* Save r20 on the stack */\
+ mfspr r22,SPRN_SPRG1; /* Get r21 back out of SPRG0 */\
+ stw r22,GPR21(r21); /* Save r21 on the stack */\
+ mflr r20; \
+ stw r20,_LINK(r21); /* Save LR on the stack */\
+ mfctr r22; \
+ stw r22,_CTR(r21); /* Save CTR on the stack */\
+ mfspr r20,XER; \
+ stw r20,_XER(r21); /* Save XER on the stack */\
+ mfspr r20,SPRN_DBCR0; \
+ stw r20,_DBCR0(r21); /* Save Debug Control on the stack */
#define COMMON_EPILOG \
stw r0,GPR0(r21); /* Save r0 on the stack */\
@@ -171,25 +127,22 @@ _GLOBAL(_start)
SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */\
SAVE_GPR(7, r21); /* Save r7 on the stack */
- ## Common exception code for standard (non-critical) exceptions.
-
-#define STND_EXCEPTION_PROLOG \
- COMMON_PROLOG; \
+#define STND_EXCEPTION_PROLOG(n) \
+ COMMON_PROLOG(n); \
mfspr r22,SPRN_SRR0; /* Faulting instruction address */\
+ lis r20,MSR_WE@h; \
mfspr r23,SPRN_SRR1; /* MSR at the time of fault */\
+ andc r23,r23,r20; /* disable processor wait state */\
COMMON_EPILOG;
- ## Common exception code for critical exceptions.
-
-#define CRIT_EXCEPTION_PROLOG \
- COMMON_PROLOG; \
+#define CRIT_EXCEPTION_PROLOG(n) \
+ COMMON_PROLOG(n); \
mfspr r22,SPRN_SRR2; /* Faulting instruction address */\
+ lis r20,MSR_WE@h; \
mfspr r23,SPRN_SRR3; /* MSR at the time of fault */\
+ andc r23,r23,r20; /* disable processor wait state */\
COMMON_EPILOG;
-###
-### Macros for specific exception types
-###
#define START_EXCEPTION(n, label) \
. = n; \
@@ -200,68 +153,213 @@ label:
bl transfer_to_handler; \
.long func; \
.long ret_from_except
-
-
+
+
#define STND_EXCEPTION(n, label, func) \
START_EXCEPTION(n, label); \
- STND_EXCEPTION_PROLOG; \
+ STND_EXCEPTION_PROLOG(n); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
li r7,STND_EXC; \
li r20,MSR_KERNEL; \
FINISH_EXCEPTION(func)
-
+
#define CRIT_EXCEPTION(n, label, func) \
START_EXCEPTION(n, label); \
- CRIT_EXCEPTION_PROLOG; \
+ CRIT_EXCEPTION_PROLOG(n); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
li r7,CRIT_EXC; \
li r20,MSR_KERNEL; \
FINISH_EXCEPTION(func)
-
-###
-### Exception vectors.
-###
-
-### 0x0100 - Critical Interrupt Exception
+/* Exception vectors.
+*/
+
+/* 0x0100 - Critical Interrupt Exception
+*/
CRIT_EXCEPTION(0x0100, CriticalInterrupt, UnknownException)
-### 0x0200 - Machine Check Exception
-
+/* 0x0200 - Machine Check Exception
+*/
+#if 0
CRIT_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#else
+ START_EXCEPTION(0x0200, MachineCheck)
+ CRIT_EXCEPTION_PROLOG(0x0200)
+
+ /*
+ lis r4,0x0400
+ mtdcr DCRN_POB0_BESR0,r4
+ */
+#ifdef DCRN_POB0_BEAR
+ mfdcr r4,DCRN_POB0_BEAR
+ mfdcr r4,DCRN_POB0_BESR0
+ mfdcr r4,DCRN_POB0_BESR1
+#endif
-### 0x0300 - Data Storage Exception
+#ifdef DCRN_PLB0_BEAR
+ mfdcr r4,DCRN_PLB0_ACR
+ mfdcr r4,DCRN_PLB0_BEAR
+ mfdcr r4,DCRN_PLB0_BESR
+#endif
- START_EXCEPTION(0x0300, DataAccess)
- STND_EXCEPTION_PROLOG
- mfspr r5,SPRN_ESR # Grab the ESR, save it, pass as arg3
- stw r5,_ESR(r21)
- mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2
- stw r4,_DEAR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
- li r7,STND_EXC # This is a standard exception
+ li r7,CRIT_EXC
li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
- FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR)
-
-### 0x0400 - Instruction Storage Exception
+ FINISH_EXCEPTION(MachineCheckException)
+#endif
+
+/* 0x0300 - Data Storage Exception
+ * This happens for just a few reasons. U0 set (but we don't do that),
+ * or zone protection fault (user violation, write to protected page).
+ * If this is just an update of modified status, we do that quickly
+ * and exit. Otherwise, we call heavywight functions to do the work.
+ */
+ START_EXCEPTION(0x0300, DataStore)
+ mtspr SPRG0, r20 /* Save some working registers */
+ mtspr SPRG1, r21
+#ifdef CONFIG_403GCX
+ stw r22, 0(r0)
+ stw r23, 4(r0)
+ mfcr r21
+ mfspr r22, SPRN_PID
+ stw r21, 8(r0)
+ stw r22, 12(r0)
+#else
+ mtspr SPRG4, r22
+ mtspr SPRG5, r23
+ mfcr r21
+ mfspr r22, SPRN_PID
+ mtspr SPRG7, r21
+ mtspr SPRG6, r22
+#endif
+
+ /* First, check if it was a zone fault (which means a user
+ * tried to access a kernel or read-protected page - always
+ * a SEGV). All other faults here must be stores, so no
+ * need to check ESR_DST as well. */
+ mfspr r20, SPRN_ESR
+ andis. r20, r20, ESR_DIZ@h
+ bne 2f
+
+ mfspr r20, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r21, r20, 0x8000
+ beq 3f
+ lis r21, swapper_pg_dir@h
+ ori r21, r21, swapper_pg_dir@l
+ li r23, 0
+ mtspr SPRN_PID, r23 /* TLB will have 0 TID */
+ b 4f
+
+ /* Get the PGD for the current thread.
+ */
+3:
+ mfspr r21,SPRG3
+ lwz r21,PGDIR(r21)
+4:
+ tophys(r21, r21)
+ rlwimi r21, r20, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r21, 0(r21) /* Get L1 entry */
+ rlwinm. r22, r21, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ tophys(r22, r22)
+ rlwimi r22, r20, 22, 20, 29 /* Compute PTE address */
+ lwz r21, 0(r22) /* Get Linux PTE */
+
+ andi. r23, r21, _PAGE_RW /* Is it writeable? */
+ beq 2f /* Bail if not */
+
+ /* Update 'changed'.
+ */
+ ori r21, r21, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+ stw r21, 0(r22) /* Update Linux page table */
+
+ /* Most of the Linux PTE is ready to load into the TLB LO.
+ * We set ZSEL, where only the LS-bit determines user access.
+ * We set execute, because we don't have the granularity to
+ * properly set this at the page level (Linux problem).
+ * If shared is set, we cause a zero PID->TID load.
+ * Many of these bits are software only. Bits we don't set
+ * here we (properly should) assume have the appropriate value.
+ */
+ li r22, 0x0ce2
+ andc r21, r21, r22 /* Make sure 20, 21 are zero */
+
+ /* find the TLB index that caused the fault. It has to be here.
+ */
+ tlbsx r23, 0, r20
+
+ tlbwe r21, r23, TLB_DATA /* Load TLB LO */
+
+ /* Done...restore registers and get out of here.
+ */
+#ifdef CONFIG_403GCX
+ lwz r22, 12(r0)
+ lwz r21, 8(r0)
+ mtspr SPRN_PID, r22
+ mtcr r21
+ lwz r23, 4(r0)
+ lwz r22, 0(r0)
+#else
+ mfspr r22, SPRG6
+ mfspr r21, SPRG7
+ mtspr SPRN_PID, r22
+ mtcr r21
+ mfspr r23, SPRG5
+ mfspr r22, SPRG4
+#endif
+ mfspr r21, SPRG1
+ mfspr r20, SPRG0
+ PPC405_ERR77_SYNC
+ rfi /* Should sync shadow TLBs */
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+#ifdef CONFIG_403GCX
+ lwz r22, 12(r0)
+ lwz r21, 8(r0)
+ mtspr SPRN_PID, r22
+ mtcr r21
+ lwz r23, 4(r0)
+ lwz r22, 0(r0)
+#else
+ mfspr r22, SPRG6
+ mfspr r21, SPRG7
+ mtspr SPRN_PID, r22
+ mtcr r21
+ mfspr r23, SPRG5
+ mfspr r22, SPRG4
+#endif
+ mfspr r21, SPRG1
+ mfspr r20, SPRG0
+ b DataAccess
+/* 0x0400 - Instruction Storage Exception
+ * I don't know why it is called "Storage"....This is caused by a fetch
+ * from non-execute or guarded pages.
+ */
START_EXCEPTION(0x0400, InstructionAccess)
- STND_EXCEPTION_PROLOG
- mr r4,r22 # Pass SRR0 as arg2
- mr r5,r23 # Pass SRR1 as arg3
+ STND_EXCEPTION_PROLOG(0x0400)
+ mr r4,r22 /* Pass SRR0 as arg2 */
+ li r5,0 /* Pass zero as arg3 */
addi r3,r1,STACK_FRAME_OVERHEAD
- li r7,STND_EXC # This is a standard exception
+ li r7,STND_EXC
li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
- FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1)
-
-### 0x0500 - External Interrupt Exception
+ rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */
+ FINISH_EXCEPTION(do_page_fault) /* do_page_fault(regs, SRR0, SRR1) */
+/* 0x0500 - External Interrupt Exception
+*/
START_EXCEPTION(0x0500, HardwareInterrupt)
- STND_EXCEPTION_PROLOG
+ STND_EXCEPTION_PROLOG(0x0500)
addi r3,r1,STACK_FRAME_OVERHEAD
li r7,STND_EXC
li r20,MSR_KERNEL
@@ -271,54 +369,70 @@ _GLOBAL(do_IRQ_intercept)
.long do_IRQ
.long ret_from_intercept
-### 0x0600 - Alignment Exception
-
+/* 0x0600 - Alignment Exception
+*/
START_EXCEPTION(0x0600, Alignment)
- STND_EXCEPTION_PROLOG
- mfspr r4,SPRN_DEAR # Grab the DEAR and save it
+ STND_EXCEPTION_PROLOG(0x0600)
+ mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */
stw r4,_DEAR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
- li r7,STND_EXC # This is a standard exception
+ li r7,STND_EXC
li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */
FINISH_EXCEPTION(AlignmentException)
-### 0x0700 - Program Exception
-
+/* 0x0700 - Program Exception
+*/
START_EXCEPTION(0x0700, ProgramCheck)
- STND_EXCEPTION_PROLOG
+ STND_EXCEPTION_PROLOG(0x0700)
addi r3,r1,STACK_FRAME_OVERHEAD
- li r7,STND_EXC # This is a standard exception
+ li r7,STND_EXC
li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */
FINISH_EXCEPTION(ProgramCheckException)
-
- STND_EXCEPTION(0x0800, Trap_08, UnknownException)
+
+
+/* I'm stealing this unused vector location to build a standard exception
+ * frame for Data TLB Access errors. The other Data TLB exceptions will bail
+ * out to this point if they can't resolve the lightweight TLB fault.
+ */
+ START_EXCEPTION(0x0800, DataAccess)
+ STND_EXCEPTION_PROLOG(0x0800)
+ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
+ stw r5,_ESR(r21)
+ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
+ stw r4,_DEAR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r7,STND_EXC
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */
+ FINISH_EXCEPTION(do_page_fault) /* do_page_fault(regs, ESR, DEAR) */
+
STND_EXCEPTION(0x0900, Trap_09, UnknownException)
STND_EXCEPTION(0x0A00, Trap_0A, UnknownException)
- STND_EXCEPTION(0x0B00, Trap_0B, UnknownException)
-### 0x0C00 - System Call Exception
-
+ STND_EXCEPTION(0x0B00, Trap_0B, UnknownException)
+/* 0x0C00 - System Call Exception
+*/
START_EXCEPTION(0x0C00, SystemCall)
- STND_EXCEPTION_PROLOG
+ STND_EXCEPTION_PROLOG(0x0C00)
stw r3,ORIG_GPR3(r21)
- li r7,STND_EXC # This is a standard exception
+ li r7,STND_EXC
li r20,MSR_KERNEL
- rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
+ rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */
FINISH_EXCEPTION(DoSyscall)
STND_EXCEPTION(0x0D00, Trap_0D, UnknownException)
STND_EXCEPTION(0x0E00, Trap_0E, UnknownException)
STND_EXCEPTION(0x0F00, Trap_0F, UnknownException)
-### 0x1000 - Programmable Interval Timer (PIT) Exception
-
+/* 0x1000 - Programmable Interval Timer (PIT) Exception
+*/
START_EXCEPTION(0x1000, Decrementer)
- STND_EXCEPTION_PROLOG
- lis r0,TSR_PIS@h # Set-up the PIT exception mask
- mtspr SPRN_TSR,r0 # Clear the PIT exception
+ STND_EXCEPTION_PROLOG(0x1000)
+ lis r0,TSR_PIS@h /* Set-up the PIT exception mask */
+ mtspr SPRN_TSR,r0 /* Clear the PIT exception */
addi r3,r1,STACK_FRAME_OVERHEAD
- li r7,STND_EXC # This is a standard exception
+ li r7,STND_EXC
li r20,MSR_KERNEL
bl transfer_to_handler
_GLOBAL(timer_interrupt_intercept)
@@ -326,28 +440,239 @@ _GLOBAL(timer_interrupt_intercept)
.long ret_from_intercept
#if 0
-### 0x1010 - Fixed Interval Timer (FIT) Exception
-
+/* NOTE:
+ * FIT and WDT handlers are not implemented yet.
+ */
+
+/* 0x1010 - Fixed Interval Timer (FIT) Exception
+*/
STND_EXCEPTION(0x1010, FITException, UnknownException)
-### 0x1020 - Watchdog Timer (WDT) Exception
+/* 0x1020 - Watchdog Timer (WDT) Exception
+*/
CRIT_EXCEPTION(0x1020, WDTException, UnknownException)
#endif
-### 0x1100 - Data TLB Miss Exception
+/* 0x1100 - Data TLB Miss Exception
+ * As the name implies, translation is not in the MMU, so search the
+ * page tables and fix it. The only purpose of this function is to
+ * load TLB entries from the page table if they exist.
+ */
+ START_EXCEPTION(0x1100, DTLBMiss)
+ mtspr SPRG0, r20 /* Save some working registers */
+ mtspr SPRG1, r21
+#ifdef CONFIG_403GCX
+ stw r22, 0(r0)
+ stw r23, 4(r0)
+ mfcr r21
+ mfspr r22, SPRN_PID
+ stw r21, 8(r0)
+ stw r22, 12(r0)
+#else
+ mtspr SPRG4, r22
+ mtspr SPRG5, r23
+ mfcr r21
+ mfspr r22, SPRN_PID
+ mtspr SPRG7, r21
+ mtspr SPRG6, r22
+#endif
+ mfspr r20, SPRN_DEAR /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r21, r20, 0x8000
+ beq 3f
+ lis r21, swapper_pg_dir@h
+ ori r21, r21, swapper_pg_dir@l
+ li r23, 0
+ mtspr SPRN_PID, r23 /* TLB will have 0 TID */
+ b 4f
+
+ /* Get the PGD for the current thread.
+ */
+3:
+ mfspr r21,SPRG3
+ lwz r21,PGDIR(r21)
+4:
+ tophys(r21, r21)
+ rlwimi r21, r20, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r21, 0(r21) /* Get L1 entry */
+ rlwinm. r22, r21, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ tophys(r22, r22)
+ rlwimi r22, r20, 22, 20, 29 /* Compute PTE address */
+ lwz r21, 0(r22) /* Get Linux PTE */
+ andi. r23, r21, _PAGE_PRESENT
+ beq 2f
- STND_EXCEPTION(0x1100, DTLBMiss, PPC4xx_dtlb_miss)
+ ori r21, r21, _PAGE_ACCESSED
+ stw r21, 0(r22)
+
+ /* Most of the Linux PTE is ready to load into the TLB LO.
+ * We set ZSEL, where only the LS-bit determines user access.
+ * We set execute, because we don't have the granularity to
+ * properly set this at the page level (Linux problem).
+ * If shared is set, we cause a zero PID->TID load.
+ * Many of these bits are software only. Bits we don't set
+ * here we (properly should) assume have the appropriate value.
+ */
+ li r22, 0x0ce2
+ andc r21, r21, r22 /* Make sure 20, 21 are zero */
+
+ b finish_tlb_load
+
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+#ifdef CONFIG_403GCX
+ lwz r22, 12(r0)
+ lwz r21, 8(r0)
+ mtspr SPRN_PID, r22
+ mtcr r21
+ lwz r23, 4(r0)
+ lwz r22, 0(r0)
+#else
+ mfspr r22, SPRG6
+ mfspr r21, SPRG7
+ mtspr SPRN_PID, r22
+ mtcr r21
+ mfspr r23, SPRG5
+ mfspr r22, SPRG4
+#endif
+ mfspr r21, SPRG1
+ mfspr r20, SPRG0
+ b DataAccess
-### 0x1200 - Instruction TLB Miss Exception
+/* 0x1200 - Instruction TLB Miss Exception
+ * Nearly the same as above, except we get our information from different
+ * registers and bailout to a different point.
+ */
+ START_EXCEPTION(0x1200, ITLBMiss)
+ mtspr SPRG0, r20 /* Save some working registers */
+ mtspr SPRG1, r21
+#ifdef CONFIG_403GCX
+ stw r22, 0(r0)
+ stw r23, 4(r0)
+ mfcr r21
+ mfspr r22, SPRN_PID
+ stw r21, 8(r0)
+ stw r22, 12(r0)
+#else
+ mtspr SPRG4, r22
+ mtspr SPRG5, r23
+ mfcr r21
+ mfspr r22, SPRN_PID
+ mtspr SPRG7, r21
+ mtspr SPRG6, r22
+#endif
+ mfspr r20, SRR0 /* Get faulting address */
+
+ /* If we are faulting a kernel address, we have to use the
+ * kernel page tables.
+ */
+ andis. r21, r20, 0x8000
+ beq 3f
+ lis r21, swapper_pg_dir@h
+ ori r21, r21, swapper_pg_dir@l
+ li r23, 0
+ mtspr SPRN_PID, r23 /* TLB will have 0 TID */
+ b 4f
+
+ /* Get the PGD for the current thread.
+ */
+3:
+ mfspr r21,SPRG3
+ lwz r21,PGDIR(r21)
+4:
+ tophys(r21, r21)
+ rlwimi r21, r20, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
+ lwz r21, 0(r21) /* Get L1 entry */
+ rlwinm. r22, r21, 0, 0, 19 /* Extract L2 (pte) base address */
+ beq 2f /* Bail if no table */
+
+ tophys(r22, r22)
+ rlwimi r22, r20, 22, 20, 29 /* Compute PTE address */
+ lwz r21, 0(r22) /* Get Linux PTE */
+ andi. r23, r21, _PAGE_PRESENT
+ beq 2f
- STND_EXCEPTION(0x1200, ITLBMiss, PPC4xx_itlb_miss)
+ ori r21, r21, _PAGE_ACCESSED
+ stw r21, 0(r22)
+
+ /* Most of the Linux PTE is ready to load into the TLB LO.
+ * We set ZSEL, where only the LS-bit determines user access.
+ * We set execute, because we don't have the granularity to
+ * properly set this at the page level (Linux problem).
+ * If shared is set, we cause a zero PID->TID load.
+ * Many of these bits are software only. Bits we don't set
+ * here we (properly should) assume have the appropriate value.
+ */
+ li r22, 0x0ce2
+ andc r21, r21, r22 /* Make sure 20, 21 are zero */
+
+ b finish_tlb_load
+
+ /* Done...restore registers and get out of here.
+ */
+#ifdef CONFIG_403GCX
+ lwz r22, 12(r0)
+ lwz r21, 8(r0)
+ mtspr SPRN_PID, r22
+ mtcr r21
+ lwz r23, 4(r0)
+ lwz r22, 0(r0)
+#else
+ mfspr r22, SPRG6
+ mfspr r21, SPRG7
+ mtspr SPRN_PID, r22
+ mtcr r21
+ mfspr r23, SPRG5
+ mfspr r22, SPRG4
+#endif
+ mfspr r21, SPRG1
+ mfspr r20, SPRG0
+ PPC405_ERR77_SYNC
+ rfi /* Should sync shadow TLBs */
+
+2:
+ /* The bailout. Restore registers to pre-exception conditions
+ * and call the heavyweights to help us out.
+ */
+#ifdef CONFIG_403GCX
+ lwz r22, 12(r0)
+ lwz r21, 8(r0)
+ mtspr SPRN_PID, r22
+ mtcr r21
+ lwz r23, 4(r0)
+ lwz r22, 0(r0)
+#else
+ mfspr r22, SPRG6
+ mfspr r21, SPRG7
+ mtspr SPRN_PID, r22
+ mtcr r21
+ mfspr r23, SPRG5
+ mfspr r22, SPRG4
+#endif
+ mfspr r21, SPRG1
+ mfspr r20, SPRG0
+ b InstructionAccess
STND_EXCEPTION(0x1300, Trap_13, UnknownException)
STND_EXCEPTION(0x1400, Trap_14, UnknownException)
STND_EXCEPTION(0x1500, Trap_15, UnknownException)
STND_EXCEPTION(0x1600, Trap_16, UnknownException)
+#ifdef CONFIG_IBM405_ERR51
+ /* 405GP errata 51 */
+ START_EXCEPTION(0x1700, Trap_17)
+ b DTLBMiss
+#else
STND_EXCEPTION(0x1700, Trap_17, UnknownException)
+#endif
STND_EXCEPTION(0x1800, Trap_18, UnknownException)
STND_EXCEPTION(0x1900, Trap_19, UnknownException)
STND_EXCEPTION(0x1A00, Trap_1A, UnknownException)
@@ -356,73 +681,217 @@ _GLOBAL(timer_interrupt_intercept)
STND_EXCEPTION(0x1D00, Trap_1D, UnknownException)
STND_EXCEPTION(0x1E00, Trap_1E, UnknownException)
STND_EXCEPTION(0x1F00, Trap_1F, UnknownException)
-
-### 0x2000 - Debug Exception
-
- CRIT_EXCEPTION(0x2000, DebugTrap, UnknownException)
-###
-### Other PowerPC processors, namely those derived from the 6xx-series
-### have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
-### However, for the 4xx-series processors these are neither defined nor
-### reserved.
-###
+/* 0x2000 - Debug Exception
+*/
+ START_EXCEPTION(0x2000, DebugTrap)
+ b check_single_step_in_exception
+ret_to_debug_exception:
+ CRIT_EXCEPTION_PROLOG(0x2000)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r7,CRIT_EXC;
+ li r20,MSR_KERNEL
+ FINISH_EXCEPTION(DebugException)
-###
-### This code finishes saving the registers to the exception frame
-### and jumps to the appropriate handler for the exception, turning
-### on address translation.
-###
+/* Make sure the final interrupt handler has not spilled past the
+ * end of its allotted space.
+ */
+ .=0x2100
+/* Check for a single step debug exception while in an exception
+ * handler before state has been saved. This is to catch the case
+ * where an instruction that we are trying to single step causes
+ * an exception (eg ITLB miss) and thus the first instruction of
+ * the exception handler generates a single step debug exception.
+ *
+ * If we get a debug trap on the first instruction of an exception handler,
+ * we reset the MSR_DE in the _exception handlers_ MSR (the debug trap is
+ * a critical exception, so we are using SPRN_SRR3 to manipulate the MSR).
+ * The exception handler was handling a non-critical interrupt, so it will
+ * save (and later restore) the MSR via SPRN_SRR1, which will still have
+ * the MSR_DE bit set.
+ */
+check_single_step_in_exception:
+
+ /* This first instruction was already executed by the exception
+ * handler and must be the first instruction of every exception
+ * handler.
+ */
+ mtspr SPRN_SPRG0,r20 /* Save some working registers... */
+ mtspr SPRN_SPRG1,r21
+ mfcr r20 /* ..and the cr because we change it */
+
+ mfspr r21,SPRN_SRR3 /* MSR at the time of fault */
+ andi. r21,r21,MSR_PR
+ bne+ 2f /* trapped from problem state */
+
+ mfspr r21,SPRN_SRR2 /* Faulting instruction address */
+ cmplwi r21,0x2100
+ bgt+ 2f /* address above exception vectors */
+
+ lis r21,DBSR_IC@h /* Remove the trap status */
+ mtspr SPRN_DBSR,r21
+
+ mfspr r21,SPRN_SRR3
+ rlwinm r21,r21,0,23,21 /* clear MSR_DE */
+ mtspr SPRN_SRR3, r21 /* restore MSR at rcfi without DE */
+
+ mtcrf 0xff,r20 /* restore registers */
+ mfspr r21,SPRN_SPRG1
+ mfspr r20,SPRN_SPRG0
+
+ sync
+ rfci /* return to the exception handler */
+
+2:
+ mtcrf 0xff,r20 /* restore registers */
+ mfspr r21,SPRN_SPRG1
+ mfspr r20,SPRN_SPRG0
+ b ret_to_debug_exception
+
+/* Other PowerPC processors, namely those derived from the 6xx-series
+ * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
+ * However, for the 4xx-series processors these are neither defined nor
+ * reserved.
+ */
+
+ /* Damn, I came up one instruction too many to fit into the
+ * exception space :-). Both the instruction and data TLB
+ * miss get to this point to load the TLB.
+ * r20 - EA of fault
+ * r21 - TLB LO (info from Linux PTE)
+ * r22, r23 - avilable to use
+ * PID - loaded with proper value when we get here
+ * Upon exit, we reload everything and RFI.
+ * Actually, it will fit now, but oh well.....a common place
+ * to load the TLB.
+ */
+finish_tlb_load:
+
+ /* Since it has a unified TLB, and we can take data faults on
+ * instruction pages by copying data, we have to check if the
+ * EPN is already in the TLB.
+ */
+ tlbsx. r23, 0, r20
+ beq 6f
+
+ /* load the next available TLB index.
+ */
+ lis r22, tlb_4xx_index@h
+ ori r22, r22, tlb_4xx_index@l
+ tophys(r22, r22)
+ lwz r23, 0(r22)
+ addi r23, r23, 1
+#ifdef CONFIG_PIN_TLB
+ cmpwi 0, r23, 61 /* reserve entries 62, 63 for kernel */
+ ble 7f
+ li r23, 0
+7:
+#else
+ andi. r23, r23, (PPC4XX_TLB_SIZE-1)
+#endif
+ stw r23, 0(r22)
+
+6:
+ tlbwe r21, r23, TLB_DATA /* Load TLB LO */
+
+ /* Create EPN. This is the faulting address plus a static
+ * set of bits. These are size, valid, E, U0, and ensure
+ * bits 20 and 21 are zero.
+ */
+ li r22, 0x00c0
+ rlwimi r20, r22, 0, 20, 31
+ tlbwe r20, r23, TLB_TAG /* Load TLB HI */
+
+ /* Done...restore registers and get out of here.
+ */
+#ifdef CONFIG_403GCX
+ lwz r22, 12(r0)
+ lwz r21, 8(r0)
+ mtspr SPRN_PID, r22
+ mtcr r21
+ lwz r23, 4(r0)
+ lwz r22, 0(r0)
+#else
+ mfspr r22, SPRG6
+ mfspr r21, SPRG7
+ mtspr SPRN_PID, r22
+ mtcr r21
+ mfspr r23, SPRG5
+ mfspr r22, SPRG4
+#endif
+ mfspr r21, SPRG1
+ mfspr r20, SPRG0
+ PPC405_ERR77_SYNC
+ rfi /* Should sync shadow TLBs */
+
+/* This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
+ */
_GLOBAL(transfer_to_handler)
- stw r22,_NIP(r21) # Save the faulting IP on the stack
- stw r23,_MSR(r21) # Save the exception MSR on the stack
- SAVE_4GPRS(8, r21) # Save r8 through r11 on the stack
- SAVE_8GPRS(12, r21) # Save r12 through r19 on the stack
- SAVE_8GPRS(24, r21) # Save r24 through r31 on the stack
- andi. r23,r23,MSR_PR # Is this from user space?
- mfspr r23,SPRN_SPRG3 # If from user, fix up THREAD.regs
- beq 2f # No, it is from the kernel; branch.
+ stw r22,_NIP(r21) /* Save the faulting IP on the stack */
+ stw r23,_MSR(r21) /* Save the exception MSR on stack */
+ SAVE_4GPRS(8, r21) /* Save r8 through r11 on the stack */
+ SAVE_8GPRS(12, r21) /* Save r12 through r19 on the stack */
+ SAVE_8GPRS(24, r21) /* Save r24 through r31 on the stack */
+ andi. r23,r23,MSR_PR /* Is this from user space? */
+ mfspr r23,SPRN_SPRG3 /* If from user, fix up THREAD.regs */
+ beq 2f /* No, it is from the kernel; branch. */
addi r24,r1,STACK_FRAME_OVERHEAD
- stw r24,PT_REGS(r23) #
-2: addi r2,r23,-THREAD # Set r2 to current thread
+ stw r24,PT_REGS(r23)
+2: addi r2,r23,-THREAD /* Set r2 to current thread */
tovirt(r2,r2)
mflr r23
- andi. r24,r23,0x3f00 # Get vector offset
+ andi. r24,r23,0x3f00 /* Get vector offset */
stw r24,TRAP(r21)
+ li r22,RESULT
+ /* No need to put an erratum #77 workaround here
+ because interrupts are currently disabled */
+ stwcx. r22,r22,r21 /* Clear the reservation */
li r22,0
stw r22,RESULT(r21)
- mtspr SPRN_SPRG2,r22 # r1 is now the kernel stack pointer
- addi r24,r2,TASK_STRUCT_SIZE # Check for kernel stack overflow
+ mtspr SPRN_SPRG2,r22 /* r1 is now the kernel stack pointer */
+ addi r24,r2,TASK_STRUCT_SIZE /* Check for kernel stack overflow */
cmplw cr0,r1,r2
cmplw cr1,r1,r24
crand cr1,cr1,cr4
- bgt- stack_ovf # If r2 < r1 < r2 + TASK_STRUCT_SIZE
- lwz r24,0(r23) # Virtual address of the handler
- lwz r23,4(r23) # Handler return pointer
- cmpwi cr0,r7,STND_EXC # What type of exception is this?
- bne 3f # It is a critical exception...
-
- ## Standard exception jump path
-
- mtspr SPRN_SRR0,r24 # Set up the instruction pointer
- mtspr SPRN_SRR1,r20 # Set up the machine state register
- mtlr r23 # Set up the return pointer
+ bgt- stack_ovf /* If r2 < r1 < r2 + TASK_STRUCT_SIZE */
+ lwz r24,0(r23) /* Virtual address of the handler */
+ lwz r23,4(r23) /* Handler return pointer */
+ cmpwi cr0,r7,STND_EXC /* What type of exception is this? */
+ bne 3f /* It is a critical exception... */
+
+ /* Standard exception jump path
+ */
+
+ /* We have to recover r7 from the register save stack.
+ * It was used to indicate standard/critical exception. In
+ * the case of a standard exception that is the system call
+ * trap, it may have originally contained one of the syscall
+ * parameters and we have to get it back now.
+ */
+ lwz r7,GPR7(r21)
+ mtspr SPRN_SRR0,r24 /* Set up the instruction pointer */
+ mtspr SPRN_SRR1,r20 /* Set up the machine state register */
+ mtlr r23 /* Set up the return pointer */
SYNC
- rfi # Enable the MMU, jump to the handler
+ /* We shouldn't need a 405 erratum #77 workaround here, because we're not
+ * actually returning to the interrupted instruction yet. */
+ rfi
- ## Critical exception jump path
+ /* Critical exception jump path
+ */
-3: mtspr SPRN_SRR2,r24 # Set up the instruction pointer
- mtspr SPRN_SRR3,r20 # Set up the machine state register
- mtlr r23 # Set up the return pointer
+3: mtspr SPRN_SRR2,r24 /* Set up the instruction pointer */
+ mtspr SPRN_SRR3,r20 /* Set up the machine state register */
+ mtlr r23 /* Set up the return pointer */
SYNC
- rfci # Enable the MMU, jump to the handler
+ rfci
-###
-### On kernel stack overlow, load up an initial stack pointer and call
-### StackOverflow(regs), which should NOT return.
-###
+/* On kernel stack overlow, load up an initial stack pointer and call
+ * StackOverflow(regs), which should NOT return.
+ */
stack_ovf:
addi r3,r1,STACK_FRAME_OVERHEAD
@@ -432,143 +901,198 @@ stack_ovf:
lis r24,StackOverflow@ha
addi r24,r24,StackOverflow@l
li r20,MSR_KERNEL
- mtspr SPRN_SRR0,r24 # Set up the instruction pointer
- mtspr SPRN_SRR1,r20 # Set up the machine state register
+ mtspr SPRN_SRR0,r24
+ mtspr SPRN_SRR1,r20
SYNC
- rfi # Enable the MMU, jump to StackOverflow
-
-###
-### extern void giveup_altivec(struct task_struct *prev)
-###
-### The PowerPC 4xx family of processors do not have AltiVec capabilities, so
-### this just returns.
-###
+ rfi
+/* extern void giveup_altivec(struct task_struct *prev)
+ *
+ * The PowerPC 4xx family of processors do not have AltiVec capabilities, so
+ * this just returns.
+ */
_GLOBAL(giveup_altivec)
blr
-
-###
-### extern void giveup_fpu(struct task_struct *prev)
-###
-### The PowerPC 4xx family of processors do not have an FPU, so this just
-### returns.
-###
+/* extern void giveup_fpu(struct task_struct *prev)
+ *
+ * The PowerPC 4xx family of processors do not have an FPU, so this just
+ * returns.
+ */
_GLOBAL(giveup_fpu)
blr
-###
-### extern void abort(void)
-###
-### At present, this routine just applies a system reset.
-###
-
+/* extern void abort(void)
+ *
+ * At present, this routine just applies a system reset.
+ */
_GLOBAL(abort)
- mfspr r13,SPRN_DBCR
- oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
- mtspr SPRN_DBCR,r13
-
+ mfspr r13,SPRN_DBCR0
+ oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
+ mtspr SPRN_DBCR0,r13
-###
-### This is where the main kernel code starts.
-###
+/* This is where the main kernel code starts.
+ */
start_here:
- ## Establish a pointer to the current task
-
+
+ /* ptr to current */
lis r2,init_task_union@h
ori r2,r2,init_task_union@l
-
- ## Clear out the BSS as per ANSI C requirements
-
- lis r7,_end@ha
- addi r7,r7,_end@l
- lis r8,__bss_start@ha
- addi r8,r8,__bss_start@l
- subf r7,r8,r7
- addi r7,r7,3
- srwi. r7,r7,2
- beq 2f
- addi r8,r8,-4
- mtctr r7
- li r0,0
-3: stwu r0,4(r8)
- bdnz 3b
- ## Stack
-
-2: addi r1,r2,TASK_UNION_SIZE
+ /* ptr to phys current thread */
+ tophys(r4,r2)
+ addi r4,r4,THREAD /* init task's THREAD */
+ mtspr SPRG3,r4
+ li r3,0
+ mtspr SPRG2,r3 /* 0 => r1 has kernel sp */
+
+ /* stack */
+ addi r1,r2,TASK_UNION_SIZE
li r0,0
stwu r0,-STACK_FRAME_OVERHEAD(r1)
- ## Determine what type of platform this is.
+ bl early_init /* We have to do this with MMU on */
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
mr r3,r31
mr r4,r30
mr r5,r29
mr r6,r28
mr r7,r27
- bl identify_machine
-
- ## Initialize the memory management unit.
-
+ bl machine_init
bl MMU_init
- ## Go back to running unmapped so that we can change to our
- ## exception vectors.
-
+/* Go back to running unmapped so we can load up new values
+ * and change to using our exception vectors.
+ * On the 4xx, all we have to do is invalidate the TLB to clear
+ * the old 16M byte TLB mappings.
+ */
lis r4,2f@h
ori r4,r4,2f@l
tophys(r4,r4)
li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtspr SPRN_SRR0,r4 # Set up the instruction pointer
- mtspr SPRN_SRR1,r3 # Set up the machine state register
+ mtspr SRR0,r4
+ mtspr SRR1,r3
rfi
- ## Load up the kernel context
-
-2: SYNC # Force all PTE updates to finish
-# tlbia # Clear all TLB entries
-# sync # Wait for tlbia to finish...
-
- ## Set up for using our exception vectors
-
- tophys(r4,r2) # Pointer to physical current thread
- addi r4,r4,THREAD # The init task thread
- mtspr SPRN_SPRG3,r4 # Save it for exceptions later
- li r3,0 #
- mtspr SPRN_SPRG2,r3 # 0 implies r1 has kernel stack pointer
-
- ## Really turn on the MMU and jump into the kernel
-
- lis r4,MSR_KERNEL@h
- ori r4,r4,MSR_KERNEL@l
- lis r3,start_kernel@h
- ori r3,r3,start_kernel@l
- mtspr SPRN_SRR0,r3 # Set up the instruction pointer
- mtspr SPRN_SRR1,r4 # Set up the machine state register
- rfi # Enable the MMU, jump to the kernel
+/* Load up the kernel context */
+2:
+ SYNC /* Force all PTE updates to finish */
+#ifndef CONFIG_PIN_TLB
+ tlbia /* Clear all TLB entries */
+ sync /* wait for tlbia/tlbie to finish */
+#endif
+
+ /* set up the PTE pointers for the Abatron bdiGDB.
+ */
+ lis r6, swapper_pg_dir@h
+ ori r6, r6, swapper_pg_dir@l
+ lis r5, abatron_pteptrs@h
+ ori r5, r5, abatron_pteptrs@l
+ stw r5, 0xf0(r0) /* Must match your Abatron config file */
+ tophys(r5,r5)
+ stw r6, 0(r5)
+
+/* Now turn on the MMU for real! */
+ li r4,MSR_KERNEL
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SRR0,r3
+ mtspr SRR1,r4
+ rfi /* enable MMU and jump to start_kernel */
+
+/* Set up the initial MMU state so we can do the first level of
+ * kernel initialization. This maps the first 16 MBytes of memory 1:1
+ * virtual to physical and more importantly sets the cache mode.
+ */
+initial_mmu:
+ tlbia /* Invalidate all TLB entries */
+ sync
+
+ /* We should still be executing code at physical address 0x0000xxxx
+ * at this point. However, start_here is at virtual address
+ * 0xC000xxxx. So, set up a TLB mapping to cover this once
+ * translation is enabled.
+ */
+
+ lis r3,KERNELBASE@h /* Load the kernel virtual address */
+ ori r3,r3,KERNELBASE@l
+ tophys(r4,r3) /* Load the kernel physical address */
+
+ /* Load the kernel PID.
+ */
+ li r0,0
+ mtspr SPRN_PID,r0
+ sync
+
+ /* Configure and load two entries into TLB slots 62 and 63.
+ * In case we are pinning TLBs, these are reserved in by the
+ * other TLB functions. If not reserving, then it doesn't
+ * matter where they are loaded.
+ */
+ clrrwi r4,r4,10 /* Mask off the real page number */
+ ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
+
+ clrrwi r3,r3,10 /* Mask off the effective page number */
+ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
+
+ li r0,62 /* TLB slot 62 */
+
+ tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */
+ tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */
+
+ addis r4, r4, 0x0100 /* Map next 16 M entries */
+ addis r3, r3, 0x0100
+
+ li r0,63 /* TLB slot 63 */
+
+ tlbwe r4,r0,TLB_DATA
+ tlbwe r3,r0,TLB_TAG
+ isync
+
+ /* Establish the exception vector base
+ */
+ lis r4,KERNELBASE@h /* EVPR only uses the high 16-bits */
+ tophys(r0,r4) /* Use the physical address */
+ mtspr SPRN_EVPR,r0
+
+ blr
+
_GLOBAL(set_context)
+
+#ifdef CONFIG_BDI_SWITCH
+ /* Context switch the PTE pointer for the Abatron BDI2000.
+ * The PGDIR is the second parameter.
+ */
+ lis r5, KERNELBASE@h
+ lwz r5, 0xf0(r5)
+ stw r4, 0x4(r5)
+#endif
mtspr SPRN_PID,r3
blr
-###
-### We put a few things here that have to be page-aligned. This stuff
-### goes at the beginning of the data segment, which is page-aligned.
-###
-
+/* We put a few things here that have to be page-aligned. This stuff
+ * goes at the beginning of the data segment, which is page-aligned.
+ */
.data
_GLOBAL(sdata)
_GLOBAL(empty_zero_page)
.space 4096
_GLOBAL(swapper_pg_dir)
- .space 4096
-
-###
-### This space gets a copy of optional info passed to us by the bootstrap
-### which is used to pass parameters into the kernel like root=/dev/sda1, etc.
-###
+ .space 4096
+/* This space gets a copy of optional info passed to us by the bootstrap
+ * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
_GLOBAL(cmd_line)
.space 512
+
+/* Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+abatron_pteptrs:
+ .space 8
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 542a2bc32dc4..766a59507e29 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.head_8xx.S 1.23 09/16/01 19:32:54 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* arch/ppc/kernel/except_8xx.S
@@ -24,14 +24,15 @@
*
*/
-#include "ppc_asm.h"
+#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
-#include <linux/config.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/pgtable.h>
#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
.text
.globl _stext
@@ -334,7 +335,7 @@ InstructionTLBMiss:
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load the MI_TWC with the attributes
- * for this page, which has only bit 31 set.
+ * for this "segment."
*/
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
@@ -343,7 +344,7 @@ InstructionTLBMiss:
stw r3, 12(r0)
lwz r3, 12(r0)
#endif
- mtspr MI_TWC, r21 /* Set page attributes */
+ mtspr MI_TWC, r21 /* Set segment attributes */
#ifdef CONFIG_8xx_CPU6
li r3, 0x3b80
stw r3, 12(r0)
@@ -362,8 +363,6 @@ InstructionTLBMiss:
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
- li r21, 0x0600
- andc r20, r20, r21 /* Clear 21, 22 */
li r21, 0x00f0
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
@@ -456,8 +455,6 @@ DataStoreTLBMiss:
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
- li r21, 0x0600
- andc r20, r20, r21 /* Clear 21, 22 */
li r21, 0x00f0
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
@@ -521,6 +518,34 @@ DataTLBError:
andis. r21, r20, 0x0200 /* If set, indicates store op */
beq 2f
+ /* The EA of a data TLB miss is automatically stored in the MD_EPN
+ * register. The EA of a data TLB error is automatically stored in
+ * the DAR, but not the MD_EPN register. We must copy the 20 most
+ * significant bits of the EA from the DAR to MD_EPN before we
+ * start walking the page tables. We also need to copy the CASID
+ * value from the M_CASID register.
+ * Addendum: The EA of a data TLB error is _supposed_ to be stored
+ * in DAR, but it seems that this doesn't happen in some cases, such
+ * as when the error is due to a dcbi instruction to a page with a
+ * TLB that doesn't have the changed bit set. In such cases, there
+ * does not appear to be any way to recover the EA of the error
+ * since it is neither in DAR nor MD_EPN. As a workaround, the
+ * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs
+ * are initialized in mapin_ram(). This will avoid the problem,
+ * assuming we only use the dcbi instruction on kernel addresses.
+ */
+ mfspr r20, DAR
+ rlwinm r21, r20, 0, 0, 19
+ ori r21, r21, MD_EVALID
+ mfspr r20, M_CASID
+ rlwimi r21, r20, 0, 28, 31
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3780
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
+ mtspr MD_EPN, r21
+
mfspr r20, M_TWB /* Get level 1 table entry address */
/* If we are faulting a kernel address, we have to use the
@@ -564,8 +589,6 @@ DataTLBError:
* set. All other Linux PTE bits control the behavior
* of the MMU.
*/
- li r21, 0x0600
- andc r20, r20, r21 /* Clear 21, 22 */
li r21, 0x00f0
rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */
@@ -769,16 +792,31 @@ start_here:
* kernel initialization. This maps the first 8 MBytes of memory 1:1
* virtual to physical. Also, set the cache mode since that is defined
* by TLB entries and perform any additional mapping (like of the IMMR).
+ * If configured to pin some TLBs, we pin the first 8 Mbytes of kernel,
+ * 24 Mbytes of data, and the 8M IMMR space. Anything not covered by
+ * these mappings is mapped by page tables.
*/
initial_mmu:
tlbia /* Invalidate all TLB entries */
+#ifdef CONFIG_PIN_TLB
+ lis r8, MI_RSV4I@h
+ ori r8, r8, 0x1c00
+#else
li r8, 0
- mtspr MI_CTR, r8 /* Set instruction control to zero */
- lis r8, MD_RESETVAL@h
+#endif
+ mtspr MI_CTR, r8 /* Set instruction MMU control */
+
+#ifdef CONFIG_PIN_TLB
+ lis r10, (MD_RSV4I | MD_RESETVAL)@h
+ ori r10, r10, 0x1c00
+ mr r8, r10
+#else
+ lis r10, MD_RESETVAL@h
+#endif
#ifndef CONFIG_8xx_COPYBACK
- oris r8, r8, MD_WTDEF@h
+ oris r10, r10, MD_WTDEF@h
#endif
- mtspr MD_CTR, r8 /* Set data TLB control */
+ mtspr MD_CTR, r10 /* Set data TLB control */
/* Now map the lower 8 Meg into the TLBs. For this quick hack,
* we can load the instruction and data TLB registers with the
@@ -802,6 +840,10 @@ initial_mmu:
/* Map another 8 MByte at the IMMR to get the processor
* internal registers (among other things).
*/
+#ifdef CONFIG_PIN_TLB
+ addi r10, r10, 0x0100
+ mtspr MD_CTR, r10
+#endif
mfspr r9, 638 /* Get current IMMR */
andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */
@@ -815,6 +857,30 @@ initial_mmu:
ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
mtspr MD_RPN, r8
+#ifdef CONFIG_PIN_TLB
+ /* Map two more 8M kernel data pages.
+ */
+ addi r10, r10, 0x0100
+ mtspr MD_CTR, r10
+
+ lis r8, KERNELBASE@h /* Create vaddr for TLB */
+ addis r8, r8, 0x0080 /* Add 8M */
+ ori r8, r8, MI_EVALID /* Mark it valid */
+ mtspr MD_EPN, r8
+ li r9, MI_PS8MEG /* Set 8M byte page */
+ ori r9, r9, MI_SVALID /* Make it valid */
+ mtspr MD_TWC, r9
+ li r11, MI_BOOTINIT /* Create RPN for address 0 */
+ addis r11, r11, 0x0080 /* Add 8M */
+ mtspr MD_RPN, r8
+
+ addis r8, r8, 0x0080 /* Add 8M */
+ mtspr MD_EPN, r8
+ mtspr MD_TWC, r9
+ addis r11, r11, 0x0080 /* Add 8M */
+ mtspr MD_RPN, r8
+#endif
+
/* Since the cache is enabled according to the information we
* just loaded into the TLB, invalidate and enable the caches here.
* We should probably check/set other modes....later.
diff --git a/arch/ppc/kernel/i8259.c b/arch/ppc/kernel/i8259.c
index 3f5bed25ea58..bc9d5d069523 100644
--- a/arch/ppc/kernel/i8259.c
+++ b/arch/ppc/kernel/i8259.c
@@ -1,13 +1,17 @@
/*
- * BK Id: SCCS/s.i8259.c 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
#include <linux/stddef.h>
#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/io.h>
-#include "i8259.h"
+#include <asm/i8259.h>
+
+static volatile char *pci_intack; /* RO, gives us the irq vector */
unsigned char cached_8259[2] = { 0xff, 0xff };
#define cached_A1 (cached_8259[0])
@@ -17,32 +21,56 @@ static spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED;
int i8259_pic_irq_offset;
-int i8259_irq(int cpu)
+/* Acknowledge the irq using the PCI host bridge's interrupt acknowledge
+ * feature. (Polling is somehow broken on some IBM and Motorola PReP boxes.)
+ */
+int i8259_irq(void)
{
int irq;
-
+
spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
- /*
- * Perform an interrupt acknowledge cycle on controller 1
- */
- outb(0x0C, 0x20);
- irq = inb(0x20) & 7;
- if (irq == 2)
- {
- /*
- * Interrupt is cascaded so perform interrupt
- * acknowledge on controller 2
- */
- outb(0x0C, 0xA0);
- irq = (inb(0xA0) & 7) + 8;
- }
- else if (irq==7)
- {
- /*
- * This may be a spurious interrupt
- *
- * Read the interrupt status register. If the most
- * significant bit is not set then there is no valid
+
+ irq = *pci_intack & 0xff;
+ if (irq==7) {
+ /*
+ * This may be a spurious interrupt.
+ *
+ * Read the interrupt status register (ISR). If the most
+ * significant bit is not set then there is no valid
+ * interrupt.
+ */
+ if(~inb(0x20)&0x80) {
+ irq = -1;
+ }
+ }
+ spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
+ return irq;
+}
+
+/* Poke the 8259's directly using poll commands. */
+int i8259_poll(void)
+{
+ int irq;
+
+ spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
+ /*
+ * Perform an interrupt acknowledge cycle on controller 1
+ */
+ outb(0x0C, 0x20); /* prepare for poll */
+ irq = inb(0x20) & 7;
+ if (irq == 2) {
+ /*
+ * Interrupt is cascaded so perform interrupt
+ * acknowledge on controller 2
+ */
+ outb(0x0C, 0xA0); /* prepare for poll */
+ irq = (inb(0xA0) & 7) + 8;
+ } else if (irq==7) {
+ /*
+ * This may be a spurious interrupt
+ *
+ * Read the interrupt status register. If the most
+ * significant bit is not set then there is no valid
* interrupt
*/
outb(0x0b, 0x20);
@@ -58,44 +86,44 @@ int i8259_irq(int cpu)
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
{
unsigned long flags;
-
+
spin_lock_irqsave(&i8259_lock, flags);
- if ( irq_nr >= i8259_pic_irq_offset )
- irq_nr -= i8259_pic_irq_offset;
-
- if (irq_nr > 7) {
- cached_A1 |= 1 << (irq_nr-8);
- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x20,0xA0); /* Non-specific EOI */
- outb(0x20,0x20); /* Non-specific EOI to cascade */
- } else {
- cached_21 |= 1 << irq_nr;
- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);
- outb(0x20,0x20); /* Non-specific EOI */
- }
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+
+ if (irq_nr > 7) {
+ cached_A1 |= 1 << (irq_nr-8);
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x20,0xA0); /* Non-specific EOI */
+ outb(0x20,0x20); /* Non-specific EOI to cascade */
+ } else {
+ cached_21 |= 1 << irq_nr;
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20); /* Non-specific EOI */
+ }
spin_unlock_irqrestore(&i8259_lock, flags);
}
static void i8259_set_irq_mask(int irq_nr)
{
- outb(cached_A1,0xA1);
- outb(cached_21,0x21);
+ outb(cached_A1,0xA1);
+ outb(cached_21,0x21);
}
-
+
static void i8259_mask_irq(unsigned int irq_nr)
{
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
- if ( irq_nr >= i8259_pic_irq_offset )
- irq_nr -= i8259_pic_irq_offset;
- if ( irq_nr < 8 )
- cached_21 |= 1 << irq_nr;
- else
- cached_A1 |= 1 << (irq_nr-8);
- i8259_set_irq_mask(irq_nr);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 |= 1 << irq_nr;
+ else
+ cached_A1 |= 1 << (irq_nr-8);
+ i8259_set_irq_mask(irq_nr);
spin_unlock_irqrestore(&i8259_lock, flags);
}
@@ -104,13 +132,13 @@ static void i8259_unmask_irq(unsigned int irq_nr)
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
- if ( irq_nr >= i8259_pic_irq_offset )
- irq_nr -= i8259_pic_irq_offset;
- if ( irq_nr < 8 )
- cached_21 &= ~(1 << irq_nr);
- else
- cached_A1 &= ~(1 << (irq_nr-8));
- i8259_set_irq_mask(irq_nr);
+ if ( irq_nr >= i8259_pic_irq_offset )
+ irq_nr -= i8259_pic_irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 &= ~(1 << irq_nr);
+ else
+ cached_A1 &= ~(1 << (irq_nr-8));
+ i8259_set_irq_mask(irq_nr);
spin_unlock_irqrestore(&i8259_lock, flags);
}
@@ -121,36 +149,62 @@ static void i8259_end_irq(unsigned int irq)
}
struct hw_interrupt_type i8259_pic = {
- " i8259 ",
- NULL,
- NULL,
- i8259_unmask_irq,
- i8259_mask_irq,
- i8259_mask_and_ack_irq,
- i8259_end_irq,
- NULL
+ " i8259 ",
+ NULL,
+ NULL,
+ i8259_unmask_irq,
+ i8259_mask_irq,
+ i8259_mask_and_ack_irq,
+ i8259_end_irq,
+ NULL
};
-void __init i8259_init(void)
+static struct resource pic1_iores = {
+ "8259 (master)", 0x20, 0x21, IORESOURCE_BUSY
+};
+
+static struct resource pic2_iores = {
+ "8259 (slave)", 0xa0, 0xa1, IORESOURCE_BUSY
+};
+
+static struct resource pic_edgectrl_iores = {
+ "8259 edge control", 0x4d0, 0x4d1, IORESOURCE_BUSY
+};
+
+void __init i8259_init(long intack_addr)
{
unsigned long flags;
-
+
spin_lock_irqsave(&i8259_lock, flags);
- /* init master interrupt controller */
- outb(0x11, 0x20); /* Start init sequence */
- outb(0x00, 0x21); /* Vector base */
- outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0x21); /* Select 8086 mode */
- outb(0xFF, 0x21); /* Mask all */
- /* init slave interrupt controller */
- outb(0x11, 0xA0); /* Start init sequence */
- outb(0x08, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0xA1); /* Select 8086 mode */
- outb(0xFF, 0xA1); /* Mask all */
- outb(cached_A1, 0xA1);
- outb(cached_21, 0x21);
+ /* init master interrupt controller */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x00, 0x21); /* Vector base */
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0x21); /* Select 8086 mode */
+
+ /* init slave interrupt controller */
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x08, 0xA1); /* Vector base */
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0xA1); /* Select 8086 mode */
+
+ /* always read ISR */
+ outb(0x0B, 0x20);
+ outb(0x0B, 0xA0);
+
+ /* Mask all interrupts */
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+
spin_unlock_irqrestore(&i8259_lock, flags);
- request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
- "82c59 secondary cascade", NULL );
+
+ /* reserve our resources */
+ request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
+ "82c59 secondary cascade", NULL );
+ request_resource(&ioport_resource, &pic1_iores);
+ request_resource(&ioport_resource, &pic2_iores);
+ request_resource(&ioport_resource, &pic_edgectrl_iores);
+
+ if (intack_addr)
+ pci_intack = ioremap(intack_addr, 1);
}
diff --git a/arch/ppc/kernel/i8259.h b/arch/ppc/kernel/i8259.h
deleted file mode 100644
index c23eadfe3c95..000000000000
--- a/arch/ppc/kernel/i8259.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * BK Id: SCCS/s.i8259.h 1.5 05/17/01 18:14:21 cort
- */
-
-#ifndef _PPC_KERNEL_i8259_H
-#define _PPC_KERNEL_i8259_H
-
-#include "local_irq.h"
-
-extern struct hw_interrupt_type i8259_pic;
-
-void i8259_init(void);
-int i8259_irq(int);
-
-#endif /* _PPC_KERNEL_i8259_H */
diff --git a/arch/ppc/kernel/iSeries_asm.h b/arch/ppc/kernel/iSeries_asm.h
new file mode 100644
index 000000000000..098a5980fa5a
--- /dev/null
+++ b/arch/ppc/kernel/iSeries_asm.h
@@ -0,0 +1,62 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * arch/ppc/kernel/iSeries_asm.h
+ *
+ * Definitions used by various bits of low-level assembly code on iSeries.
+ *
+ * Copyright (C) 2001 IBM Corp.
+ *
+ * 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.
+ */
+
+#define CHECKLPQUEUE(ra,rb,rc) \
+ mfspr rb,SPRG1; /* Get Paca address */\
+ lbz ra,PACALPPACA+LPPACAIPIINT(rb); /* Get IPI int flag */\
+ cmpi 0,ra,0; /* IPI occurred in hypervisor ? */\
+ bne 99f; /* If so, skip rest */\
+ lwz ra,PACALPQUEUE(rb); /* Get LpQueue address */\
+ cmpi 0,ra,0; /* Does LpQueue exist? */\
+ beq 99f; /* If not skip rest */\
+ lbz rb,LPQINUSEWORD(ra); /* Test for LpQueue recursion */\
+ cmpi 0,rb,1; /* If we are about to recurse */\
+ beq 99f; /* If so, skip rest */\
+ lwz rb,LPQCUREVENTPTR(ra); /* Get current LpEvent */\
+ lbz rb,LPEVENTFLAGS(rb); /* Get Valid bit */\
+ lbz rc,LPQOVERFLOW(ra); /* Get LpQueue overflow */\
+ andi. ra,rb,0x0080; /* Isolate Valid bit */\
+ or. ra,ra,rc; /* 0 == no pending events */\
+99:
+
+#define CHECKDECR(ra,rb) \
+ mfspr rb,SPRG1; /* Get Paca address */\
+ lbz ra,PACALPPACA+LPPACADECRINT(rb); /* Get DECR int flag */\
+ cmpi 0,ra,0; /* DECR occurred in hypervisor ? */\
+ beq 99f; /* If not, skip rest */\
+ xor ra,ra,ra; \
+ stb ra,PACALPPACA+LPPACADECRINT(rb); /* Clear DECR int flag */\
+99:
+
+#define CHECKANYINT(ra,rb,rc) \
+ mfspr rb,SPRG1; /* Get Paca address */\
+ ld ra,PACALPPACA+LPPACAANYINT(rb); /* Get all interrupt flags */\
+ /* Note use of ld, protected by soft/hard disabled */\
+ cmpldi 0,ra,0; /* Any interrupt occurred while soft disabled? */\
+ bne 99f; /* If so, skip rest */\
+ lwz ra,PACALPQUEUE(rb); /* Get LpQueue address */\
+ cmpi 0,ra,0; /* Does LpQueue exist? */\
+ beq 99f; /* If not skip rest */\
+ lwz rb,LPQINUSEWORD(ra); /* Test for LpQueue recursion */\
+ cmpi 0,rb,1; /* If we are about to recurse */\
+ beq 99f; /* If so, skip rest */\
+ lwz rb,LPQCUREVENTPTR(ra); /* Get current LpEvent */\
+ lbz rb,LPEVENTFLAGS(rb); /* Get Valid bit */\
+ lbz rc,LPQOVERFLOW(ra); /* Get LpQueue overflow */\
+ andi. ra,rb,0x0080; /* Isolate Valid bit */\
+ or. ra,ra,rc; /* 0 == no pending events */\
+99:
+
diff --git a/arch/ppc/kernel/iSeries_head.S b/arch/ppc/kernel/iSeries_head.S
new file mode 100644
index 000000000000..46765589e983
--- /dev/null
+++ b/arch/ppc/kernel/iSeries_head.S
@@ -0,0 +1,1512 @@
+/*
+ * arch/ppc/kernel/iSeries_head.S
+ *
+ * Adapted from arch/ppc/kernel/head.S
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ * Adapted for iSeries by Mike Corrigan
+ * Updated by Dave Boutcher
+ *
+ * This file contains the low-level support and setup for the
+ * iSeries LPAR platform.
+ *
+ * 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 <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
+#include "iSeries_asm.h"
+
+
+ .text
+ .globl _stext
+_stext:
+
+/* iSeries LPAR
+ *
+ * In an iSeries partition, the operating system has no direct access
+ * to the hashed page table. The iSeries hypervisor manages the
+ * hashed page table, and is directed by the operating system in the
+ * partition. The partition, Linux in this case, always runs with
+ * MSR.IR and MSR.DR equal to 1. The hypervisor establishes
+ * addressibility for the first 64 MB of memory at 0xC0000000 by
+ * building a hashed page table and setting segment register 12.
+ *
+ * The partition memory is not physically contiguous, nor necessarily
+ * addressable with a 32-bit address. The hypervisor provides functions
+ * which the kernel can use to discover the layout of memory. The
+ * iSeries LPAR specific code in the kernel will build a table that maps
+ * contiguous pseudo-real addresses starting at zero to the actual
+ * physical addresses owned by this partition. In 32-bit mode we will
+ * restrict ourselves to no more than 768 MB (or maybe 1 GB)
+ *
+ * When Linux interrupt handlers get control, the hypervisor has
+ * already saved SRR0 and SRR1 into a control block shared between
+ * the hypervisor and Linux. This is know as the ItLpPaca. The values
+ * in the actual SRR0 and SRR1 are not valid. This requires a change in
+ * the way the SPRG registers are used. The definitions are:
+ *
+ * Register old definition new definition
+ *
+ * SPRG0 temp - used to save gpr reserved for hypervisor
+ * SPRG1 temp - used to save gpr addr of Paca
+ * SPRG2 0 or kernel stack frame temp - used to save gpr
+ * SPRG3 Linux thread Linux thread
+ *
+ * The Paca contains the address of the ItLpPaca. The Paca is known only
+ * to Linux, while the ItLpPaca is shared between Linux and the
+ * hypervisor.
+ *
+ * The value that used to be in SPRG2 will now be saved in the Paca,
+ * as will at least one GPR.
+ */
+
+ .globl __start
+__start:
+ b start_here
+
+
+ . = 0x020
+
+ /* iSeries LPAR hypervisor expects a 64-bit offset of
+ the hvReleaseData structure (see HvReleaseData.h)
+ at offset 0x20. This is the base for all common
+ control blocks between the hypervisor and the kernel
+ */
+
+ .long 0
+ .long hvReleaseData-KERNELBASE
+ .long 0
+ .long msChunks-KERNELBASE
+ .long 0
+ .long pidhash-KERNELBASE
+ /* Pointer to start of embedded System.map */
+ .long 0
+ .globl embedded_sysmap_start
+embedded_sysmap_start:
+ .long 0
+ /* Pointer to end of embedded System.map */
+ .long 0
+ .globl embedded_sysmap_end
+embedded_sysmap_end:
+ .long 0
+
+
+ . = 0x060
+
+ .globl ste_fault_count
+ste_fault_count:
+ .long 0
+ .globl set_context_count
+set_context_count:
+ .long 0
+ .globl yield_count
+yield_count:
+ .long 0
+ .globl update_times_count
+update_times_count:
+ .long 0
+ .globl update_wall_jiffies_count
+update_wall_jiffies_count:
+ .long 0
+ .globl update_wall_jiffies_ticks
+update_wall_jiffies_ticks:
+ .long 0
+
+
+/*
+ * We assume SPRG1 has the address of the Paca and SPRG3
+ * has the address of the task's thread_struct.
+ * SPRG2 is used as a scratch register (as required by the
+ * hypervisor). SPRG0 is reserved for the hypervisor.
+ *
+ * The ItLpPaca has the values of SRR0 and SRR1 that the
+ * hypervisor saved at the point of the actual interrupt.
+ *
+ * The Paca contains the value that the non-LPAR PPC Linux Kernel
+ * keeps in SPRG2, which is either zero (if the interrupt
+ * occurred in the kernel) or the address of the available
+ * space on the kernel stack (if the interrupt occurred
+ * in user code).
+*/
+#define EXCEPTION_PROLOG_1 \
+ mtspr SPRG2,r20; /* use SPRG2 as scratch reg */\
+ mfspr r20,SPRG1; /* get Paca */\
+ /* must do std not stw because soft disable protects \
+ * 64-bit register use (in HvCall, maybe others) \
+ */\
+ std r21,PACAR21(r20); /* Save GPR21 in Paca */\
+ std r22,PACAR22(r20); /* Save GPR22 in Paca */\
+ mfcr r22 /* Get CR */
+
+#define EXCEPTION_PROLOG_2 \
+ lwz r21,PACAKSAVE(r20); /* exception stack to use */\
+ cmpwi 0,r21,0; /* user mode or kernel */\
+ bne 1f; /* 0 -> r1, else use PACAKSAVE */\
+ subi r21,r1,INT_FRAME_SIZE; /* alloc exc. frame */\
+1: stw r1,GPR1(r21); \
+ mr r1,r21; \
+ stw r22,_CCR(r1); /* save CR in stackframe */ \
+ mflr r22; \
+ stw r22,_LINK(r1); /* Save LR in stackframe */ \
+ bl save_regs; /* now save everything else */ \
+ ld r22,PACALPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */\
+ ld r23,PACALPPACA+LPPACASRR1(r20) /* Get SRR1 from ItLpPaca */
+
+#define EXCEPTION_PROLOG_EXIT \
+ mtcrf 0xff,r22; \
+ ld r22,PACALPPACA+LPPACASRR0(r20); \
+ ld r21,PACALPPACA+LPPACASRR1(r20); \
+ mtspr SRR0,r22; \
+ mtspr SRR1,r21; \
+ ld r22,PACAR22(r20); \
+ ld r21,PACAR21(r20); \
+ mfspr r20,SPRG2; \
+ RFI
+
+#define EXCEPTION_PROLOG \
+ EXCEPTION_PROLOG_1; \
+ EXCEPTION_PROLOG_2
+
+
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR0), and r23 (SRR1).
+ */
+
+/*
+ * Exception vectors.
+ */
+#define STD_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r20,0; /* soft disabled */\
+ bl transfer_to_handler; \
+ .long hdlr; \
+ .long ret_from_except
+
+/* System reset */
+ . = 0x100
+SystemReset:
+ mfspr r3,SPRG3 /* Get Paca address */
+ mtspr SPRG1,r3 /* Set Linux SPRG1 -> Paca */
+ lhz r24,PACAPACAINDEX(r3) /* Get processor # */
+ cmpi 0,r24,0 /* Are we processor 0? */
+ beq start_here /* Start up the first processor */
+ mfspr r4,CTRLF
+ li r5,RUNLATCH
+ andc r4,r4,r5 /* Turn off the run light */
+ mtspr CTRLT,r4
+1:
+ HMT_LOW
+#ifdef CONFIG_SMP
+ lbz r23,PACAPROCSTART(r3) /* Test if this processor
+ * should start */
+ cmpi 0,r23,0
+ bne secondary_start
+secondary_smp_loop:
+ /* Let the Hypervisor know we are alive */
+ /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
+ lis r3,0x8002
+ rldicr r0,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
+ rldicl r3,r3,0,48 /* r3 = r3 & 0x000000000000ffff */
+ or r3,r3,r0 /* r3 = r3 | r0 */
+#else /* CONFIG_SMP */
+ /* Yield the processor. This is required for non-SMP kernels
+ which are running on multi-threaded machines. */
+ lis r3,0x8000
+ rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
+ addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */
+ li r4,0 /* "yield timed" */
+ li r5,-1 /* "yield forever" */
+#endif /* CONFIG_SMP */
+ li r0,-1 /* r0=-1 indicates a Hypervisor call */
+ sc /* Invoke the hypervisor via a system call */
+ mfspr r3,SPRG1 /* Put r3 back */
+ b 1b /* If SMP not configured, secondaries
+ * loop forever */
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data access exception. */
+ . = 0x300
+DataAccess:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r1)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r1)
+
+ andis. r0,r5,0x0020 /* Is this a segment fault? */
+ bne ste_fault /* Yes - go reload segment regs */
+
+ /* This should and with 0xd7ff */
+ andis. r0,r5,0xa470 /* Can we handle as little fault? */
+ bne 1f /* */
+
+ rlwinm r3,r5,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */
+
+ /*
+ * r3 contains the required access permissions
+ * r4 contains the faulting address
+ */
+
+ stw r22,_NIP(r1) /* Help with debug if dsi loop */
+ bl hash_page /* Try to handle as hpte fault */
+ lwz r4,_DAR(r1) /* Get original DAR */
+ lwz r5,_DSISR(r1) /* and original DSISR */
+
+1: addi r3,r1,STACK_FRAME_OVERHEAD
+ lwz r20,_SOFTE(r1)
+ bl transfer_to_handler
+ .long do_page_fault
+ .long ret_from_except
+
+
+/* Instruction access exception. */
+ . = 0x400
+InstructionAccess:
+ EXCEPTION_PROLOG
+ mr r4,r22
+ mr r5,r23
+
+ andis. r0,r23,0x0020 /* Is this a segment fault? */
+ bne ste_fault /* Yes - go reload segment regs */
+
+ andis. r0,r23,0x4000 /* no pte found? */
+ beq 1f /* if so, try to put a PTE */
+
+ li r3,0
+ bl hash_page /* Try to handle as hpte fault */
+ mr r4,r22
+ mr r5,r23
+
+1: addi r3,r1,STACK_FRAME_OVERHEAD
+ lwz r20,_SOFTE(r1)
+ bl transfer_to_handler
+ .long do_page_fault
+ .long ret_from_except
+
+/* External interrupt */
+ . = 0x500;
+HardwareInterrupt:
+ EXCEPTION_PROLOG_1
+ lbz r21,PACAPROCENABLED(r20)
+ cmpi 0,r21,0
+ bne 1f
+ EXCEPTION_PROLOG_EXIT
+1: EXCEPTION_PROLOG_2
+do_pending_int:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r4,0
+ li r20,0 /* Soft disabled */
+ bl transfer_to_handler
+ .globl do_IRQ_intercept
+do_IRQ_intercept:
+ .long do_IRQ;
+ .long ret_from_intercept
+
+/* Alignment exception */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r1)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lbz r20,PACAPROCENABLED(r20) /* preserve soft en/disabled */
+ bl transfer_to_handler
+ .long AlignmentException
+ .long ret_from_except
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lbz r20,PACAPROCENABLED(r20) /* preserve soft en/disabled */
+ bl transfer_to_handler
+ .long ProgramCheckException
+ .long ret_from_except
+
+/* Floating-point unavailable */
+ . = 0x800
+FPUnavailable:
+ EXCEPTION_PROLOG
+ lwz r3,PACAKSAVE(r20)
+ cmpwi 0,r3,0
+ beq 1f
+ b load_up_fpu
+1:
+ li r20,0 /* soft disabled */
+ bl transfer_to_handler /* if from kernel, take a trap */
+ .long KernelFP
+ .long ret_from_except
+
+ . = 0x900
+Decrementer:
+ EXCEPTION_PROLOG_1
+ lbz r21,PACAPROCENABLED(r20)
+ cmpi 0,r21,0
+ bne 1f
+
+ li r21,1
+ stb r21,PACALPPACA+LPPACADECRINT(r20)
+ lwz r21,PACADEFAULTDECR(r20)
+ mtspr DEC,r21
+ EXCEPTION_PROLOG_EXIT
+1: EXCEPTION_PROLOG_2
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,0 /* Soft disabled */
+ bl transfer_to_handler
+ .globl timer_interrupt_intercept
+timer_interrupt_intercept:
+ .long timer_interrupt
+ .long ret_from_intercept
+
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+/* System call */
+ . = 0xc00
+SystemCall:
+ EXCEPTION_PROLOG
+ /* Store r3 to the kernel stack */
+ stw r3,ORIG_GPR3(r1)
+ lbz r20,PACAPROCENABLED(r20) /* preserve soft en/disabled */
+ bl transfer_to_handler
+ .long DoSyscall
+ .long ret_from_except
+
+/* Single step - not used on 601 */
+ STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
+/*
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+*/
+ STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
+/*
+ STD_EXCEPTION(0x1400, SMI, SMIException)
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, TAUException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, RunMode, RunModeException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+*/
+ . = 0x3000
+
+ /* This code saves: CTR, XER, DAR, DSISR, SRR0, SRR1, */
+ /* r0, r2-r13, r20-r24 */
+ /* It uses R22 as a scratch register */
+save_regs:
+ ld r22,PACAR21(r20) /* Get GPR21 from Paca */
+ stw r22,GPR21(r1) /* Save GPR21 in stackframe */
+ ld r22,PACAR22(r20) /* Get GPR22 from Paca */
+ stw r22,GPR22(r1) /* Save GPR22 in stackframe */
+ stw r23,GPR23(r1) /* Save GPR23 in stackframe */
+ stw r24,GPR24(r1) /* Save GPR24 in stackframe */
+ mfspr r22,SPRG2 /* Get GPR20 from SPRG2 */
+ stw r22,GPR20(r1) /* Save GPR20 in stackframe */
+ mfctr r22
+ stw r22,_CTR(r1)
+ mfspr r22,XER
+ stw r22,_XER(r1)
+ lbz r22,PACAPROCENABLED(r20)/* Get soft enabled/disabled */
+ stw r22,_SOFTE(r1)
+ stw r0,GPR0(r1)
+ SAVE_8GPRS(2, r1)
+ SAVE_4GPRS(10, r1)
+ blr
+
+ste_fault:
+ bl set_kernel_segregs
+
+ mfspr r3,SPRG1
+ li r4,0
+ stb r4,PACAPROCENABLED(r3) /* Soft disable prevents going to */
+ /* do_pending_int on recursive fault */
+
+ lis r3,ste_fault_count@ha
+ lwz r4,ste_fault_count@l(r3)
+ addi r4,r4,1
+ stw r4,ste_fault_count@l(r3)
+
+ mfspr r3,SPRG3 /* get thread */
+ addi r3,r3,-THREAD /* get 'current' */
+ lwz r3,MM(r3) /* get mm */
+ cmpi 0,r3,0 /* if no mm */
+ beq 1f /* then use context 0 (kernel) */
+ lwz r3,CONTEXT(r3) /* get context */
+1:
+ /* set_context kills r0, r3, r4 and CTR */
+ bl set_context
+
+ lwz r3,_SOFTE(r1)
+ cmpi 0,r3,0
+ beq 5f /* skip checks if restoring disabled */
+
+ CHECKANYINT(r4,r5,r6) /* if pending interrupts, process them */
+ bne- do_pending_int
+5:
+ mfspr r4,SPRG1
+ stb r3,PACAPROCENABLED(r4) /* Restore enabled/disabled */
+
+ b fault_exit
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
+ *
+ * At this point r0-r13, r20-r24, CCR, CTR, LINK, XER, DAR and DSISR
+ * are saved on a stack. SRR0 is in r22, SRR1 is in r23
+ * r1 points to the stackframe, r1 points to the kernel stackframe
+ * We no longer have any dependency on data saved in the PACA, SRR0, SRR1
+ * DAR or DSISR. We now copy the registers to the kernel stack (which
+ * might cause little faults). Any little fault will be handled without
+ * saving state. Thus when the little fault is completed, it will rfi
+ * back to the original faulting instruction.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+
+ mfspr r6,SPRG1
+ li r7,0
+ stw r7,PACAKSAVE(r6) /* Force new frame for recursive fault */
+
+ /* Restore the regs used above -- parameters to syscall */
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+
+ stw r22,_NIP(r1)
+ stw r23,_MSR(r1)
+ SAVE_4GPRS(14, r1)
+ SAVE_2GPRS(18, r1)
+ SAVE_4GPRS(25, r1)
+ SAVE_2GPRS(29, r1)
+ SAVE_GPR(31, r1)
+
+ andi. r23,r23,MSR_PR
+ mfspr r23,SPRG3 /* if from user, fix up THREAD.regs */
+ beq 2f
+ addi r24,r1,STACK_FRAME_OVERHEAD
+ stw r24,PT_REGS(r23)
+2: addi r2,r23,-THREAD /* set r2 to current */
+ li r22,RESULT
+ stwcx. r22,r22,r1 /* to clear the reservation */
+ li r22,0
+ stw r22,RESULT(r1)
+ mfspr r23,SPRG1 /* Get Paca address */
+ stb r20,PACAPROCENABLED(r23) /* soft enable or disabled */
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r1)
+ addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
+ cmplw 0,r1,r2
+ cmplw 1,r1,r24
+ crand 1,1,4
+ bgt- stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ li r20,MSR_KERNEL
+ ori r20,r20,MSR_EE /* Always hard enabled */
+ FIX_SRR1(r20,r22)
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ RFI /* jump to handler, enable MMU */
+
+/*
+ * On kernel stack overflow, load up an initial stack pointer
+ * and call StackOverflow(regs), which should not return.
+ */
+stack_ovf:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ lis r1,init_task_union@ha
+ addi r1,r1,init_task_union@l
+ addi r1,r1,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
+ mfspr r24,SPRG1
+ li r20,0
+ stb r20,PACAPROCENABLED(r24) /* soft disable */
+ lis r24,StackOverflow@ha
+ addi r24,r24,StackOverflow@l
+ li r20,MSR_KERNEL
+ ori r20,r20,MSR_EE /* Always hard enabled */
+ FIX_SRR1(r20,r22)
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ RFI
+
+/*
+ * Disable FP for the task which had the FPU previously,
+ * and save its floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ * On SMP we know the fpu is free, since we give it up every
+ * switch. -- Cort
+ * Assume r20 points to PACA on entry
+ */
+load_up_fpu:
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ SYNC
+ MTMSRD(r5) /* enable use of fpu now */
+ isync
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_fpu in switch_to.
+ */
+#ifndef CONFIG_SMP
+ lis r3,last_task_used_math@ha
+ lwz r4,last_task_used_math@l(r3)
+ cmpi 0,r4,0
+ beq 1f
+ addi r4,r4,THREAD /* want last_task_used_math->thread */
+ SAVE_32FPRS(0, r4)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR-4(r4)
+ lwz r5,PT_REGS(r4)
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r20,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r20 /* disable FP for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+ /* enable use of FP after return */
+ ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1
+ mfspr r5,SPRG3 /* current task's THREAD (phys) */
+ lfd fr0,THREAD_FPSCR-4(r5)
+ mtfsf 0xff,fr0
+ REST_32FPRS(0, r5)
+#ifndef CONFIG_SMP
+ subi r4,r5,THREAD
+ stw r4,last_task_used_math@l(r3)
+#endif /* CONFIG_SMP */
+ /* restore registers and return */
+ lwz r3,_CCR(r21)
+ lwz r4,_LINK(r21)
+ mtcrf 0xff,r3
+ mtlr r4
+ REST_GPR(1, r21)
+ REST_4GPRS(3, r21)
+ /* we haven't used ctr or xer */
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+
+ REST_GPR(20, r21)
+ REST_2GPRS(22, r21)
+ lwz r21,GPR21(r21)
+ SYNC
+ RFI
+
+/*
+ * FP unavailable trap from kernel - print a message, but let
+ * the task use FP in the kernel until it returns to user mode.
+ */
+KernelFP:
+ lwz r3,_MSR(r1)
+ ori r3,r3,MSR_FP
+ stw r3,_MSR(r1) /* enable use of FP after return */
+ lis r3,86f@h
+ ori r3,r3,86f@l
+ mr r4,r2 /* current */
+ lwz r5,_NIP(r1)
+ bl printk
+ b ret_from_except
+86: .string "floating point used in kernel (task=%p, pc=%x)\n"
+ .align 4
+
+/*
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ */
+ .globl giveup_fpu
+giveup_fpu:
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ mtmsr r5 /* enable use of fpu now */
+ cmpi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpi 0,r5,0
+ SAVE_32FPRS(0, r3)
+ mffs fr0
+ stfd fr0,THREAD_FPSCR-4(r3)
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r3,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r3 /* disable FP for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+ li r5,0
+ lis r4,last_task_used_math@ha
+ stw r5,last_task_used_math@l(r4)
+#endif /* CONFIG_SMP */
+ blr
+
+#ifdef CONFIG_SMP
+secondary_start:
+ lis r3,0,
+ mr r4,r24
+ bl identify_cpu
+ bl call_setup_cpu /* Call setup_cpu for this CPU */
+
+ /* get current */
+ HMT_MEDIUM /* Set thread priority to MEDIUM */
+ lis r2,current_set@h
+ ori r2,r2,current_set@l
+ slwi r24,r24,2 /* get current_set[cpu#] */
+ lwzx r2,r2,r24
+
+ /* stack */
+ addi r1,r2,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
+ li r0,0
+ stw r0,0(r1)
+
+ /* load up the MMU */
+ bl load_up_mmu
+
+ /* ptr to phys current thread */
+ addi r4,r2,THREAD /* phys address of our thread_struct */
+ rlwinm r4,r4,0,0,31
+ mtspr SPRG3,r4
+
+ /* Set up address of Paca in current thread */
+ lis r23,xPaca@ha
+ addi r23,r23,xPaca@l
+ /* r24 has CPU # * 4 at this point. The Paca is 2048 bytes
+ long so multiply r24 by 512 to index into the array of Pacas */
+ slwi r24,r24,9
+ add r23,r23,r24
+ rlwinm r23,r23,0,0,31
+ mtspr SPRG1,r23
+
+ li r3,0
+ stw r3,PACAKSAVE(r23) /* 0 => r1 has kernel sp */
+
+ stb r3,PACAPROCENABLED(r23) /* Soft disabled */
+
+ /* enable MMU and jump to start_secondary */
+
+ li r4,MSR_KERNEL
+ ori r4,r4,MSR_EE /* Hard enabled */
+ lis r3,start_secondary@h
+ ori r3,r3,start_secondary@l
+ mtspr SRR0,r3
+ FIX_SRR1(r4,r3)
+ mtspr SRR1,r4
+ RFI
+#endif /* CONFIG_SMP */
+
+/*
+ * Load stuff into the MMU. Intended to be called with
+ * IR=0 and DR=0.
+ */
+load_up_mmu:
+ li r0,16 /* load up segment register values */
+ mtctr r0 /* for context 0 */
+ lis r3,0x2000 /* Ku = 1, VSID = 0 */
+ li r4,0
+3: mtsrin r3,r4
+ addi r3,r3,0x111 /* increment VSID */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+ blr
+
+/*
+ * This is where the main kernel code starts.
+ */
+start_here:
+
+ /* ptr to current */
+
+ lis r2,init_task_union@h
+ ori r2,r2,init_task_union@l
+
+ /* Set up for using our exception vectors */
+
+ addi r4,r2,THREAD /* init task's THREAD */
+ rlwinm r4,r4,0,0,31
+ mtspr SPRG3,r4
+
+ /* Get address of Paca for processor 0 */
+ lis r11,xPaca@ha
+ addi r11,r11,xPaca@l
+ rlwinm r11,r11,0,0,31
+ mtspr SPRG1,r11
+
+ li r3,0
+ stw r3,PACAKSAVE(r11) /* 0 => r1 has kernel sp */
+
+ stb r3,PACAPROCENABLED(r11) /* Soft disabled */
+
+ addi r1,r2,TASK_UNION_SIZE
+ li r0,0
+ stwu r0,-STACK_FRAME_OVERHEAD(r1)
+
+ /* fix klimit for system map */
+ lis r6,embedded_sysmap_end@ha
+ lwz r7,embedded_sysmap_end@l(r6)
+
+ cmpi 0,r7,0
+ beq 5f
+
+ lis r6, KERNELBASE@h
+ add r7,r7,r6
+ addi r7,r7,4095
+ li r6,0x0FFF
+ andc r7,r7,r6
+
+ lis r6,klimit@ha
+ stw r7,klimit@l(r6)
+5:
+
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+ bl early_init /* We have to do this with MMU on */
+
+ mr r3,r31
+ mr r4,r30
+ mr r5,r29
+ mr r6,r28
+ mr r7,r27
+ li r6,0 /* No cmdline parameters */
+ bl platform_init
+ bl MMU_init
+
+ bl load_up_mmu
+
+ li r4,MSR_KERNEL
+ ori r4,r4,MSR_EE /* Hard enabled */
+ FIX_SRR1(r4,r5)
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SRR0,r3
+ mtspr SRR1,r4
+ RFI /* ensure correct MSR and jump to
+ start_kernel */
+hash_page:
+ mflr r21 /* Save LR in r21 */
+
+ /*
+ * We hard enable here (but first soft disable) so that the hash_page
+ * code can spin on the hash_table_lock without problem on a shared
+ * processor
+ */
+ li r0,0
+ stb r0,PACAPROCENABLED(r20) /* Soft disable */
+
+ mfmsr r0
+ ori r0,r0,MSR_EE
+ mtmsr r0 /* Hard enable */
+
+ bl create_hpte /* add the hash table entry */
+ /*
+ * Now go back to hard disabled
+ */
+ mfmsr r0
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r0,r0,r4
+ mtmsr r0 /* Hard disable */
+
+ lwz r0,_SOFTE(r1)
+ mtlr r21 /* restore LR */
+ mr r21,r1 /* restore r21 */
+
+ cmpi 0,r0,0 /* See if we will soft enable in */
+ /* fault_exit */
+ beq 5f /* if not, skip checks */
+
+ CHECKANYINT(r4,r5,r6) /* if pending interrupts, process them */
+ bne- do_pending_int
+
+5: stb r0,PACAPROCENABLED(r20) /* Restore soft enable/disable */
+
+ cmpi 0,r3,0 /* check return code form create_hpte */
+ bnelr
+
+/*
+ * htab_reloads counts the number of times we have to fault an
+ * HPTE into the hash table. This should only happen after a
+ * fork (because fork does a flush_tlb_mm) or a vmalloc or ioremap.
+ * Where a page is faulted into a process's address space,
+ * update_mmu_cache gets called to put the HPTE into the hash table
+ * and those are counted as preloads rather than reloads.
+ */
+ lis r2,htab_reloads@ha
+ lwz r3,htab_reloads@l(r2)
+ addi r3,r3,1
+ stw r3,htab_reloads@l(r2)
+
+fault_exit:
+
+ lwz r3,_CCR(r1)
+ lwz r4,_LINK(r1)
+ lwz r5,_CTR(r1)
+ lwz r6,_XER(r1)
+
+ mtcrf 0xff,r3
+ mtlr r4
+ mtctr r5
+ mtspr XER,r6
+
+ lwz r0,GPR0(r1)
+ REST_8GPRS(2, r1)
+ REST_4GPRS(10, r1)
+ FIX_SRR1(r23,r20)
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+ REST_4GPRS(20, r1)
+
+ lwz r1,GPR1(r1)
+ RFI
+
+/*
+ * Set up the segment registers for a new context.
+ * context in r3
+ */
+_GLOBAL(set_context)
+ mulli r3,r3,897 /* multiply context by skew factor */
+ rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */
+ addis r3,r3,0x6000 /* Set Ks, Ku bits */
+ li r0,NUM_USER_SEGMENTS
+ mtctr r0
+
+ li r4,0
+3:
+ mtsrin r3,r4
+ addi r3,r3,0x111 /* next VSID */
+ rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+ isync
+
+set_kernel_segregs:
+
+/*
+ * Reload the last four segment registers because they
+ * might have been clobbered by the hypervisor if we
+ * are running on a shared processor
+ */
+ lis r3,0x2000 /* Set Ku = 1 */
+ addi r3,r3,0xCCC /* Set VSID = CCC */
+ lis r4,0xC000 /* Set SR = C */
+ li r0,4 /* Load regs C, D, E and F */
+ mtctr r0
+4: mtsrin r3,r4
+ addi r3,r3,0x111 /* increment VSID */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 4b
+ isync
+
+ blr
+
+
+/* Hypervisor call
+ *
+ * Invoke the iSeries hypervisor (PLIC) via the System Call instruction.
+ * Parameters are passed to this routine in registers r3 - r10 and are
+ * converted to 64-bit by combining registers. eg. r3 <- r3
+ * r4 <- r5,r6, r5 <- r7,r8, r6 <- r9,r10
+ *
+ * r3 contains the HV function to be called
+ * r5,r6 contain the first 64-bit operand
+ * r7,r8 contain the second 64-bit operand
+ * r9,r10 contain the third 64-bit operand
+ * caller's stack frame +8 contains the fourth 64-bit operand
+ * caller's stack frame +16 contains the fifth 64-bit operand
+ * caller's stack frame +24 contains the sixth 64-bit operand
+ * caller's stack frame +32 contains the seventh 64-bit operand
+ *
+ */
+
+_GLOBAL(HvCall)
+_GLOBAL(HvCall0)
+_GLOBAL(HvCall1)
+_GLOBAL(HvCall2)
+_GLOBAL(HvCall3)
+_GLOBAL(HvCall4)
+_GLOBAL(HvCall5)
+_GLOBAL(HvCall6)
+_GLOBAL(HvCall7)
+ /*
+ * Stack a frame and save one reg so we can hang on to
+ * the old MSR
+ */
+ stwu r1,-64(r1)
+ stw r31,60(r1)
+
+ stw r22,24(r1)
+ stw r23,28(r1)
+ stw r24,32(r1)
+ stw r25,36(r1)
+ stw r26,40(r1)
+ stw r27,44(r1)
+ stw r28,48(r1)
+ stw r29,52(r1)
+
+ /*
+ * The hypervisor assumes CR fields 0-4 are volatile, but
+ * gcc assumes CR fields 2-7 are non-volatile.
+ * We must save and restore the CR here
+ */
+ mfcr r31
+ stw r31,20(r1)
+
+ /* Before we can convert to using 64-bit registers we must
+ * soft disable external interrupts as the interrupt handlers
+ * don't preserve the high half of the registers
+ */
+
+ mfspr r11,SPRG1 /* Get the Paca pointer */
+ lbz r31,PACAPROCENABLED(r11) /* Get soft enable/disable flag */
+ li r0,0
+ stb r0,PACAPROCENABLED(r11) /* Soft disable */
+
+ /* Get parameters four through seven */
+
+ lwz r22,72(r1)
+ lwz r23,76(r1)
+ lwz r24,80(r1)
+ lwz r25,84(r1)
+ lwz r26,88(r1)
+ lwz r27,92(r1)
+ lwz r28,96(r1)
+ lwz r29,100(r1)
+ /* Now it is safe to operate on 64-bit registers
+ *
+ * Format the operands into the 64-bit registers
+ *
+ */
+ rldicr r5,r5,32,31 /* r5 = r5 << 32 */
+ rldicl r6,r6,0,32 /* r6 = r6 & 0x00000000ffffffff */
+ or r4,r5,r6 /* r4 = r5 | r6 */
+ rldicr r7,r7,32,31 /* r7 = r7 << 32 */
+ rldicl r8,r8,0,32 /* r8 = r8 & 0x00000000ffffffff */
+ or r5,r7,r8 /* r5 = r7 | r8 */
+ rldicr r9,r9,32,31 /* r9 = r9 << 32 */
+ rldicl r10,r10,0,32 /* r10 = r10 & 0x00000000ffffffff */
+ or r6,r9,r10 /* r6 = r9 | r10 */
+ rldicr r22,r22,32,31 /* r22 = r22 << 32 */
+ rldicl r23,r23,0,32 /* r23 = r23 & 0x00000000ffffffff */
+ or r7,r22,r23 /* r7 = r22 | r23 */
+ rldicr r24,r24,32,31 /* r24 = r24 << 32 */
+ rldicl r25,r25,0,32 /* r25 = r25 & 0x00000000ffffffff */
+ or r8,r24,r25 /* r8 = r24 | r25 */
+ rldicr r26,r26,32,31 /* r26 = r26 << 32 */
+ rldicl r27,r27,0,32 /* r27 = r27 & 0x00000000ffffffff */
+ or r9,r26,r27 /* r9 = r26 | r27 */
+ rldicr r28,r28,32,31 /* r28 = r28 << 32 */
+ rldicl r29,r29,0,32 /* r29 = r29 & 0x00000000ffffffff */
+ or r10,r28,r29 /* r10 = r28 | r29 */
+
+ /*
+ * Extract the hypervisor function call number from R3
+ * and format it into the 64-bit R3.
+ */
+ rldicr r0,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
+ rldicl r3,r3,0,48 /* r3 = r3 & 0x000000000000ffff */
+ or r3,r3,r0 /* r3 = r3 | r0 */
+
+ /*
+ * r0 = 0xffffffffffffffff indicates a hypervisor call
+ */
+ li r0,-1 /* r1 = 0xffffffffffffffff */
+
+ /* Invoke the hypervisor via the System Call instruction */
+
+ sc
+
+ HMT_MEDIUM
+
+ /* Return value in 64-bit R3
+ * format it into R3 and R4
+ */
+ rldicl r4,r3,0,32 /* r4 = r3 & 0x00000000ffffffff */
+ rldicl r3,r3,32,32 /* r3 = (r3 >> 32) & 0x00000000ffffffff */
+
+ /* We are now done with 64-bit registers it is safe to touch
+ * the stack again.
+ */
+ lwz r22,24(r1)
+ lwz r23,28(r1)
+ lwz r24,32(r1)
+ lwz r25,36(r1)
+ lwz r26,40(r1)
+ lwz r27,44(r1)
+ lwz r28,48(r1)
+ lwz r29,52(r1)
+
+ /* While we were running in the hypervisor, a decrementer or
+ * external interrupt may have occured. If we are about to
+ * enable here, we must check for these and process them
+ */
+
+ cmpi 0,r31,0 /* check if going to enable */
+ beq 1f /* skip checks if staying disabled */
+
+ /* Save r3, r4 and LR */
+ stw r3,52(r1)
+ stw r4,48(r1)
+ mflr r3
+ stw r3,44(r1)
+
+ /* enable and check for decrementers/lpEvents */
+ mr r3,r31
+ bl __restore_flags
+
+ /* Restore r3, r4 and LR */
+ lwz r3,44(r1)
+ mtlr r3
+ lwz r3,52(r1)
+ lwz r4,48(r1)
+
+1:
+ /*
+ * Unstack the frame and restore r31 and the CR
+ */
+ lwz r31,20(r1)
+ mtcrf 0xff,r31
+ lwz r31,60(r1)
+ lwz r1,0(r1)
+
+ blr
+
+/* Hypervisor call with return data
+ *
+ * Invoke the iSeries hypervisor (PLIC) via the System Call instruction.
+ * The Hv function ID is passed in r3
+ * The address of the return data structure is passed in r4
+ * Parameters are passed to this routine in registers r5 - r10 and are
+ * converted to 64-bit by combining registers. eg. r3 <- r3
+ * r4 <- r5,r6, r5 <- r7,r8, r6 <- r9,r10
+ *
+ * r3 contains the HV function to be called
+ * r4 contains the address of the return data structure
+ * r5,r6 contain the first 64-bit operand
+ * r7,r8 contain the second 64-bit operand
+ * r9,r10 contain the third 64-bit operand
+ * caller's stack frame +8 contains the fourth 64-bit operand
+ * caller's stack frame +16 contains the fifth 64-bit operand
+ * caller's stack frame +24 contains the sixth 64-bit operand
+ * caller's stack frame +32 contains the seventh 64-bit operand
+ *
+ */
+
+_GLOBAL(HvCallRet16)
+_GLOBAL(HvCall0Ret16)
+_GLOBAL(HvCall1Ret16)
+_GLOBAL(HvCall2Ret16)
+_GLOBAL(HvCall3Ret16)
+_GLOBAL(HvCall4Ret16)
+_GLOBAL(HvCall5Ret16)
+_GLOBAL(HvCall6Ret16)
+_GLOBAL(HvCall7Ret16)
+
+ /*
+ * Stack a frame and save some regs
+ */
+ stwu r1,-64(r1)
+ stw r31,60(r1)
+ stw r30,56(r1)
+
+ stw r22,24(r1)
+ stw r23,28(r1)
+ stw r24,32(r1)
+ stw r25,36(r1)
+ stw r26,40(r1)
+ stw r27,44(r1)
+ stw r28,48(r1)
+ stw r29,52(r1)
+
+ mr r30,r4 /* Save return data address */
+
+ /*
+ * The hypervisor assumes CR fields 0-4 are volatile, but
+ * gcc assumes CR fields 2-7 are non-volatile.
+ * We must save and restore the CR here
+ */
+ mfcr r31
+ stw r31,20(r1)
+
+ /* Before we can convert to using 64-bit registers we must
+ * soft disable external interrupts as the interrupt handlers
+ * don't preserve the high half of the registers
+ */
+
+ mfspr r11,SPRG1 /* Get the Paca pointer */
+ lbz r31,PACAPROCENABLED(r11) /* Get soft enable/disable flag */
+ li r0,0
+ stb r0,PACAPROCENABLED(r11) /* Soft disable */
+
+ /* Get parameters four through seven */
+
+ lwz r22,76(r1)
+ lwz r23,80(r1)
+ lwz r24,84(r1)
+ lwz r25,88(r1)
+ lwz r26,92(r1)
+ lwz r27,96(r1)
+ lwz r28,100(r1)
+ lwz r29,104(r1)
+
+ /* Now it is safe to operate on 64-bit registers
+ *
+ */
+
+ /*
+ * Format the operands into the 64-bit registers
+ */
+
+ rldicr r5,r5,32,31 /* r5 = r5 << 32 */
+ rldicl r6,r6,0,32 /* r6 = r6 & 0x00000000ffffffff */
+ or r4,r5,r6 /* r4 = r5 | r6 */
+ rldicr r7,r7,32,31 /* r7 = r7 << 32 */
+ rldicl r8,r8,0,32 /* r8 = r8 & 0x00000000ffffffff */
+ or r5,r7,r8 /* r5 = r7 | r8 */
+ rldicr r9,r9,32,31 /* r9 = r9 << 32 */
+ rldicl r10,r10,0,32 /* r10 = r10 & 0x00000000ffffffff */
+ or r6,r9,r10 /* r6 = r9 | r10 */
+ rldicr r22,r22,32,31 /* r22 = r22 << 32 */
+ rldicl r23,r23,0,32 /* r23 = r23 & 0x00000000ffffffff */
+ or r7,r22,r23 /* r7 = r22 | r23 */
+ rldicr r24,r24,32,31 /* r24 = r24 << 32 */
+ rldicl r25,r25,0,32 /* r25 = r25 & 0x00000000ffffffff */
+ or r8,r24,r25 /* r8 = r24 | r25 */
+ rldicr r26,r26,32,31 /* r26 = r26 << 32 */
+ rldicl r27,r27,0,32 /* r27 = r27 & 0x00000000ffffffff */
+ or r9,r26,r27 /* r9 = r26 | r27 */
+ rldicr r28,r28,32,31 /* r28 = r28 << 32 */
+ rldicl r29,r29,0,32 /* r29 = r29 & 0x00000000ffffffff */
+ or r10,r28,r29 /* r10 = r28 | r29 */
+ /*
+ * Extract the hypervisor function call number from R3
+ * and format it into the 64-bit R3.
+ */
+ rldicr r0,r3,32,15 /* r4 = (r3 << 32) & 0xffff000000000000 */
+ rldicl r3,r3,0,48 /* r3 = r3 & 0x000000000000ffff */
+ or r3,r3,r0 /* r3 = r3 | r4 */
+
+ /*
+ * r0 = 0xffffffffffffffff indicates a hypervisor call
+ */
+ li r0,-1 /* r1 = 0xffffffffffffffff */
+
+ /* Invoke the hypervisor via the System Call instruction */
+
+ sc
+
+ HMT_MEDIUM
+
+ /* Return values in 64-bit R3, R4, R5 and R6
+ * place R3 and R4 into data structure, R5 into R3,R4
+ */
+ rldicl r6,r3,32,32 /* r6 = (r3 >> 32) & 0x00000000ffffffff */
+ rldicl r7,r3,0,32 /* r7 = r3 & 0x00000000ffffffff */
+ rldicl r8,r4,32,32 /* r8 = (r4 >> 32) & 0x00000000ffffffff */
+ rldicl r9,r4,0,32 /* r9 = r4 & 0x00000000ffffffff */
+
+ rldicl r4,r5,0,32 /* r4 = r5 & 0x00000000ffffffff */
+ rldicl r3,r5,32,32 /* r3 = (r5 >> 32) & 0x00000000ffffffff */
+
+ /* We are now done with 64-bit registers it is safe to touch
+ * the stack again.
+ */
+ stw r6,0(r30) /* Save returned data */
+ stw r7,4(r30)
+ stw r8,8(r30)
+ stw r9,12(r30)
+
+ lwz r22,24(r1)
+ lwz r23,28(r1)
+ lwz r24,32(r1)
+ lwz r25,36(r1)
+ lwz r26,40(r1)
+ lwz r27,44(r1)
+ lwz r28,48(r1)
+ lwz r29,52(r1)
+
+ /* While we were running in the hypervisor, a decrementer or
+ * external interrupt may have occured. If we are about to
+ * enable here, we must check for these and process them
+ */
+
+ cmpi 0,r31,0 /* check if going to enable */
+ beq 1f /* skip checks if staying disabled */
+
+ /* Save r3, r4 and LR */
+ stw r3,48(r1)
+ stw r4,44(r1)
+ mflr r3
+ stw r3,40(r1)
+
+ /* enable and check for decrementers/lpEvents */
+ mr r3,r31
+ bl __restore_flags
+
+ lwz r3,40(r1)
+ mtlr r3
+ lwz r3,48(r1)
+ lwz r4,44(r1)
+
+1:
+ /*
+ * Unstack the frame and restore r30, r31 and CR
+ */
+ lwz r31,20(r1)
+ mtcrf 0xff,r31
+ lwz r30,56(r1)
+ lwz r31,60(r1)
+ lwz r1,0(r1)
+
+ blr
+
+
+/* Hypervisor call (use no stack)
+ *
+ * These functions must be called with interrupts soft disabled.
+ * The caller is responsible for saving the non-volatile CR
+ * The operands should already be formatted into the 64-bit registers
+ *
+ * Invoke the iSeries hypervisor (PLIC) via the System Call instruction.
+ *
+ * r3 contains the HV function to be called
+ * r4 contains the first 64-bit operand
+ * r5 contains the second 64-bit operand
+ * r6 contains the third 64-bit operand
+ * r7 contains the fourth 64-bit operand
+ * r8 contains the fifth 64-bit operand
+ * r9 contains the sixth 64-bit operand
+ * r10 contains the seventh 64-bit operand
+ *
+ * data is returned in 64-bit registers r3-r6
+ *
+ */
+
+_GLOBAL(HvXCall)
+_GLOBAL(HvXCall0)
+_GLOBAL(HvXCall1)
+_GLOBAL(HvXCall2)
+_GLOBAL(HvXCall3)
+ /*
+ * Extract the hypervisor function call number from R3
+ * and format it into the 64-bit R3.
+ */
+ rldicr r0,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
+ rldicl r3,r3,0,48 /* r3 = r3 & 0x000000000000ffff */
+ or r3,r3,r0 /* r3 = r3 | r0 */
+
+ /*
+ * r0 = 0xffffffffffffffff indicates a hypervisor call
+ */
+ li r0,-1 /* r1 = 0xffffffffffffffff */
+
+ /* Invoke the hypervisor via the System Call instruction */
+
+ sc
+
+ blr
+
+_GLOBAL(__setup_cpu_power3)
+ blr
+_GLOBAL(__setup_cpu_power4)
+ blr
+_GLOBAL(__setup_cpu_generic)
+ blr
+
+_GLOBAL(iSeries_check_intr)
+ mflr r31
+ lwz r5,_SOFTE(r1)
+ cmpi 0,r5,0
+ beqlr
+ mfspr r5,SPRG1
+ lbz r5,PACAPROCENABLED(r5)
+ cmpi 0,r5,0
+ bnelr
+ /* Check for lost decrementer interrupts.
+ * (If decrementer popped while we were in the hypervisor)
+ * (calls timer_interrupt if so)
+ */
+3: CHECKDECR(r4,r5)
+ /* Check for pending interrupts. If no interrupts pending,
+ * then CR0 = "eq" and r4 == 0
+ * (kills registers r5 and r6)
+ */
+ beq+ 1f
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl timer_interrupt
+1:
+ CHECKLPQUEUE(r4,r5,r6)
+ beq+ 2f
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl do_IRQ
+ b 3b
+
+2: mtlr r31
+ blr
+
+/*
+ * Fake an interrupt from kernel mode.
+ * This is used when enable_irq loses an interrupt.
+ * We only fill in the stack frame minimally.
+ */
+_GLOBAL(fake_interrupt)
+ mflr r0
+ stw r0,4(r1)
+ stwu r1,-INT_FRAME_SIZE(r1)
+ stw r0,_NIP(r1)
+ stw r0,_LINK(r1)
+ mfmsr r3
+ stw r3,_MSR(r1)
+ li r0,0x0fac
+ stw r0,TRAP(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r4,1
+ bl do_IRQ
+ addi r1,r1,INT_FRAME_SIZE
+ lwz r0,4(r1)
+
+ mtlr r0
+ blr
+
+/*
+ * Fake a decrementer from kernel mode.
+ * This is used when the decrementer pops in
+ * the hypervisor. We only fill in the stack
+ * frame minimally
+ */
+_GLOBAL(fake_decrementer)
+ mflr r0
+ stw r0,4(r1)
+ stwu r1,-INT_FRAME_SIZE(r1)
+ stw r0,_NIP(r1)
+ stw r0,_LINK(r1)
+ mfmsr r3
+ stw r3,_MSR(r1)
+ li r0,0x0fac
+ stw r0,TRAP(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl timer_interrupt
+ addi r1,r1,INT_FRAME_SIZE
+ lwz r0,4(r1)
+
+ mtlr r0
+ blr
+
+_GLOBAL(create_hpte)
+ stwu r1,-INT_FRAME_SIZE(r1)
+ stw r0,GPR0(r1)
+ lwz r0,0(r1)
+ stw r0,GPR1(r1)
+ /* r3-r13 are caller saved */
+ stw r2,GPR2(r1)
+ SAVE_8GPRS(4, r1)
+ SAVE_2GPRS(12, r1)
+ SAVE_4GPRS(20,r1)
+ mfspr r20,XER
+ mfctr r22
+ stw r20,_XER(r1)
+ stw r22,_CTR(r1)
+ mflr r20
+ mfmsr r22
+ stw r20,_NIP(r1)
+ stw r22,_MSR(r1)
+ stw r20,_LINK(r1)
+ bl iSeries_create_hpte
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ REST_8GPRS(4, r1)
+ REST_2GPRS(12, r1)
+ lwz r20,_NIP(r1)
+ lwz r22,_XER(r1)
+ mtlr r20
+ mtspr XER,r22
+ lwz r20,_CTR(r1)
+ mtctr r20
+
+ REST_4GPRS(20,r1)
+ addi r1,r1,INT_FRAME_SIZE
+ blr
+
+###
+### extern void abort(void)
+###
+### Invoke the hypervisor to kill the partition.
+###
+
+_GLOBAL(abort)
+
+
+/*
+ * We put a few things here that have to be page-aligned.
+ * This stuff goes at the beginning of the data segment,
+ * which is page-aligned.
+ */
+ .data
+ .globl sdata
+sdata:
+
+ .globl empty_zero_page
+empty_zero_page:
+ .space 4096
+
+ .globl swapper_pg_dir
+swapper_pg_dir:
+ .space 4096
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */
+ .globl cmd_line
+cmd_line:
+ .space 512
diff --git a/arch/ppc/kernel/iSeries_misc.S b/arch/ppc/kernel/iSeries_misc.S
new file mode 100644
index 000000000000..983611b80276
--- /dev/null
+++ b/arch/ppc/kernel/iSeries_misc.S
@@ -0,0 +1,469 @@
+ /*
+ * 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.
+ * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
+ * updated by Dave Boutcher (boutcher@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 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sys.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
+#include "iSeries_asm.h"
+
+ .text
+ .align 5
+
+#ifdef CONFIG_SMP
+ .comm hash_table_lock,4
+#endif /* CONFIG_SMP */
+
+_GLOBAL(is_msr_enabled)
+ mfmsr r3
+ andi. r3,r3,MSR_EE
+ beqlr /* Return r3=0 indicating disabled */
+ li r3,1
+ blr /* Return r3=1 indicating enabled */
+
+_GLOBAL(is_soft_enabled)
+ mfspr r3,SPRG1
+ lbz r3,PACAPROCENABLED(r3)
+ blr
+
+_GLOBAL(get_tb64)
+ /* hard disable because we are using a 64-bit register
+ * and we don't want it to get trashed in an interrupt
+ * handler
+ */
+
+ mfmsr r5
+ rlwinm r0,r5,0,17,15 /* clear MSR_EE in r0 */
+ mtmsr r0 /* hard disable */
+
+ mftb r3
+ rldicl r4,r3,0,32
+ rldicl r3,r3,32,32
+
+ mtmsr r5 /* restore MSR_EE */
+ blr
+
+/* void __save_flags(unsigned long *flags) */
+_GLOBAL(__save_flags_ptr)
+ mfspr r4,SPRG1 /* Get Paca pointer */
+ lbz r4,PACAPROCENABLED(r4)
+ stw r4,0(r3)
+ blr
+_GLOBAL(__save_flags_ptr_end)
+
+/* void __restore_flags(unsigned long flags) */
+_GLOBAL(__restore_flags)
+ cmpi 0,r3,0 /* Are we enabling? */
+ beq 0f /* No - then skip interrupt checks */
+
+3:
+ mfspr r4,SPRG1
+ lbz r4,PACAPROCENABLED(r4)
+ cmpi 0,r4,0 /* Are we already enabled? */
+ bne 0f /* Yes - then skip interrupt checks */
+
+ CHECKDECR(r4,r5)
+ bne- do_fake_decrementer
+
+ CHECKLPQUEUE(r4,r5,r6)
+ bne- do_lost_interrupts
+2:
+ mfmsr r0
+ rlwinm r0,r0,0,17,15 /* hard disable */
+ mtmsr r0
+
+ CHECKANYINT(r4,r5,r6)
+ ori r0,r0,MSR_EE
+ beq 1f
+ mtmsr r0 /* hard enable */
+ b 3b /* process more interrupts */
+1:
+ mfspr r4,SPRG1
+ stb r3,PACAPROCENABLED(r4)
+ mtmsr r0 /* hard enable */
+ blr
+0:
+ mfspr r4,SPRG1
+ stb r3,PACAPROCENABLED(r4)
+ blr
+_GLOBAL(__restore_flags_end)
+
+_GLOBAL(__cli)
+ mfspr r4,SPRG1
+ li r3,0
+ stb r3,PACAPROCENABLED(r4)
+ blr /* Done */
+_GLOBAL(__cli_end)
+
+_GLOBAL(__sti)
+ li r3,1
+ b __restore_flags
+_GLOBAL(__sti_end)
+
+/*
+ * We were about to enable interrupts but we have to simulate
+ * some interrupts that were lost by enable_irq first.
+ */
+_GLOBAL(do_lost_interrupts)
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+ stw r3,28(r1)
+1: bl fake_interrupt
+ bl check_softirqs
+ mfmsr r0
+ rlwinm r0,r0,0,17,15 /* hard disable */
+ mtmsr r0
+
+ CHECKANYINT(r4,r5,r6)
+ ori r0,r0,MSR_EE
+ beq 2f
+ mtmsr r0 /* hard enable */
+ b 1b /* process more interrupts */
+
+2: lwz r3,28(r1)
+ mfspr r4,SPRG1
+ stb r3,PACAPROCENABLED(r4) /* restore soft interrupt state */
+ mtmsr r0 /* hard enable */
+ lwz r0,36(r1)
+ mtlr r0
+
+ addi r1,r1,32
+ blr
+
+/*
+ * Simulate a decrementer interrupt
+ */
+do_fake_decrementer:
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+ stw r3,28(r1)
+ bl fake_decrementer
+ bl check_softirqs
+ lwz r0,36(r1)
+ mtlr r0
+
+ lwz r3,28(r1)
+ addi r1,r1,32
+
+ mfmsr r0 /* hard disable */
+ rlwinm r0,r0,0,17,15
+ mtmsr r0
+
+ CHECKANYINT(r4,r5,r6) /* Check for any interrupts pending */
+ ori r0,r0,MSR_EE
+ beq 1f
+ mtmsr r0 /* hard enable */
+ b do_lost_interrupts /* Handle more interrupts */
+
+1: mfspr r4,SPRG1
+ stb r3,PACAPROCENABLED(r4) /* soft enable */
+ mtmsr r0 /* hard enable */
+ blr
+
+/*
+ * do softirqs if necessary
+ */
+check_softirqs:
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+
+ lis r4,irq_stat@ha
+ addi r4,r4,irq_stat@l
+#ifdef CONFIG_SMP
+ lwz r3,CPU(r2)
+ slwi r3,r3,7
+ add r4,r4,r3
+#endif
+ lwz r5,0(r4)
+ lwz r4,4(r4)
+ and. r5,r5,r4
+ beq+ 2f
+ bl do_softirq
+2:
+ lwz r0,36(r1)
+ mtlr r0
+
+ addi r1,r1,32
+ blr
+
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+
+_GLOBAL(flush_icache_range)
+
+
+/*
+ * Flush the data cache to memory
+ *
+ * Different models of iSeries's have different cache line sizes
+ * and in some cases i-cache and d-cache line sizes differ from
+ * each other.
+ */
+
+ lis r7,iSeries_dcache_line_size@ha
+ lhz r7,iSeries_dcache_line_size@l(r7)
+ addi r5,r7,-1
+ andc r6,r3,r5 /* round low to line bdy */
+ subf r8,r6,r4 /* compute length */
+ add r8,r8,r5 /* ensure we get enough */
+ lis r9,iSeries_log_dcache_line_size@ha
+ lhz r9,iSeries_log_dcache_line_size@l(r9)
+ srw. r8,r8,r9 /* compute line count */
+ beqlr /* nothing to do? */
+ mtctr r8
+1: dcbst 0,r6
+ add r6,r6,r7
+ bdnz 1b
+ sync
+
+/* Now invalidate the instruction cache */
+
+ lis r7,iSeries_icache_line_size@ha
+ lhz r7,iSeries_icache_line_size@l(r7)
+ addi r5,r7,-1
+ andc r6,r3,r5 /* round low to line bdy */
+ subf r8,r6,r4 /* compute length */
+ add r8,r8,r5
+ lis r9,iSeries_log_icache_line_size@ha
+ lhz r9,iSeries_log_icache_line_size@l(r9)
+ srw. r8,r8,r9 /* compute line count */
+ beqlr /* nothing to do? */
+ mtctr r8
+2: icbi 0,r6
+ add r6,r6,r7
+ bdnz 2b
+ sync
+ isync
+ blr
+
+
+/*
+ * Like above, but only do the D-cache.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+
+/*
+ * Flush the data cache to memory
+ *
+ * Different models of iSeries's have different cache line sizes
+ */
+
+ lis r7,iSeries_dcache_line_size@ha
+ lhz r7,iSeries_dcache_line_size@l(r7)
+ addi r5,r7,-1
+ andc r6,r3,r5 /* round low to line bdy */
+ subf r8,r6,r4 /* compute length */
+ add r8,r8,r5 /* ensure we get enough */
+ lis r9,iSeries_log_dcache_line_size@ha
+ lhz r9,iSeries_log_dcache_line_size@l(r9)
+ srw. r8,r8,r9 /* compute line count */
+ beqlr /* nothing to do? */
+ mtctr r8
+0: dcbst 0,r6
+ add r6,r6,r7
+ bdnz 0b
+ sync
+ blr
+
+
+/*
+ * Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ * void __flush_page_to_ram(void *page)
+ * void __flush_dcache_icache(void *page)
+ */
+_GLOBAL(__flush_page_to_ram)
+_GLOBAL(__flush_dcache_icache)
+
+/*
+ * Flush the data cache to memory
+ *
+ * Different models of iSeries's have different cache line sizes
+ */
+
+/* Flush the dcache */
+
+ rlwinm r3,r3,0,0,19 /* Page align */
+ lis r4,iSeries_dcache_lines_per_page@ha
+ lhz r4,iSeries_dcache_lines_per_page@l(r4)
+ lis r5,iSeries_dcache_line_size@ha
+ lhz r5,iSeries_dcache_line_size@l(r5)
+ mr r6,r3
+ mtctr r4
+0: dcbst 0,r6
+ add r6,r6,r5
+ bdnz 0b
+ sync
+
+/* Now invalidate the icache */
+
+ lis r4,iSeries_icache_lines_per_page@ha
+ lhz r4,iSeries_icache_lines_per_page@l(r4)
+ lis r5,iSeries_icache_line_size@ha
+ lhz r5,iSeries_icache_line_size@l(r5)
+ mtctr r4
+1: icbi 0,r3
+ add r3,r3,r5
+ bdnz 1b
+ sync
+ isync
+ blr
+
+
+/*
+ * Flush a particular page from the instruction cache.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ * void __flush_icache_page(void *page)
+ */
+_GLOBAL(__flush_icache_page)
+
+
+/*
+ * Different models of iSeries's have different cache line sizes
+ */
+
+/* Invalidate the icache */
+
+ rlwinm r3,r3,0,0,19 /* Page align */
+ lis r4,iSeries_icache_lines_per_page@ha
+ lhz r4,iSeries_icache_lines_per_page@l(r4)
+ lis r5,iSeries_icache_line_size@ha
+ lhz r5,iSeries_icache_line_size@l(r5)
+ mtctr r4
+1: icbi 0,r3
+ add r3,r3,r5
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced). This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+
+ rlwinm r3,r3,0,0,19 /* Page align */
+ lis r4,iSeries_dcache_lines_per_page@ha
+ lhz r4,iSeries_dcache_lines_per_page@l(r4)
+ lis r5,iSeries_dcache_line_size@ha
+ lhz r5,iSeries_dcache_line_size@l(r5)
+ mtctr r4
+0: dcbz 0,r3
+ add r3,r3,r5
+ bdnz 0b
+ blr
+
+
+/*
+ * Copy a whole page. We use the dcbz instruction on the destination
+ * to reduce memory traffic (it eliminates the unnecessary reads of
+ * the destination into cache). This requires that the destination
+ * is cacheable.
+ */
+#define COPY_16_BYTES \
+ lwz r6,4(r4); \
+ lwz r7,8(r4); \
+ lwz r8,12(r4); \
+ lwzu r9,16(r4); \
+ stw r6,4(r3); \
+ stw r7,8(r3); \
+ stw r8,12(r3); \
+ stwu r9,16(r3)
+
+_GLOBAL(copy_page)
+
+ rlwinm r3,r3,0,0,19 /* Page align */
+ rlwinm r4,r4,0,0,19
+ lis r5,iSeries_dcache_lines_per_page@ha
+ lhz r5,iSeries_dcache_lines_per_page@l(r5)
+ lis r6,iSeries_dcache_line_size@ha
+ lhz r0,iSeries_dcache_line_size@l(r6)
+ mtctr r5
+ addi r3,r3,-4
+ addi r4,r4,-4
+ li r10,4
+
+ cmpi 0,r0,32
+ beq do_32_byte_line
+ cmpi 0,r0,64
+ beq do_64_byte_line
+ cmpi 0,r0,128
+ beq do_128_byte_line
+
+ /* We don't have code specifically for this cache line size */
+ /* Assume that the cache line size is at least 16 (and of */
+ /* course a multiple of 16) */
+ /* This code will work for all power-of-2 cache line sizes */
+ /* from 16 to 4096 */
+
+1: mr r5,r0
+ dcbz r10,r3
+0: COPY_16_BYTES
+ addi r5,r5,-16
+ or. r5,r5,r5
+ bne 0b
+ bdnz 1b
+ blr
+
+do_32_byte_line:
+ dcbz r10,r3
+ COPY_16_BYTES
+ COPY_16_BYTES
+ bdnz do_32_byte_line
+ blr
+
+do_64_byte_line:
+ dcbz r10,r3
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ bdnz do_64_byte_line
+ blr
+
+do_128_byte_line:
+ dcbz r10,r3
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ COPY_16_BYTES
+ bdnz do_128_byte_line
+ blr
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 2d93e549ccea..e6f2230d835f 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.idle.c 1.16 10/16/01 15:58:42 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Idle daemon for PowerPC. Idle daemon will handle any action
@@ -32,6 +32,20 @@
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/cputable.h>
+#ifdef CONFIG_PPC_ISERIES
+#include <asm/time.h>
+#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/HvCall.h>
+#include <asm/hardirq.h>
+
+static void yield_shared_processor(void);
+static void run_light_on(int on);
+
+extern unsigned long yield_count;
+
+#else /* CONFIG_PPC_ISERIES */
+#define run_light_on(x) do { } while (0)
+#endif /* CONFIG_PPC_ISERIES */
void zero_paged(void);
void power_save(void);
@@ -53,21 +67,27 @@ int idled(void)
do_power_save = 1;
/* endless loop with no priority at all */
- current->nice = 20;
- init_idle();
for (;;) {
+#ifdef CONFIG_PPC_ISERIES
+ if (!current->need_resched) {
+ /* Turn off the run light */
+ run_light_on(0);
+ yield_shared_processor();
+ }
+ HMT_low();
+#endif
#ifdef CONFIG_SMP
-
if (!do_power_save) {
/*
* Deal with another CPU just having chosen a thread to
* run here:
*/
- int oldval = xchg(&current->need_resched, -1);
+ unsigned long oldval;
- if (!oldval) {
- while (need_resched())
- barrier(); /* Do Nothing */
+ oldval = xchg(&current->work, 0xff000000);
+ if (!(oldval & 0xff000000)) {
+ while (current->work.need_resched == -1)
+ barrier(); /* Do Nothing */
}
}
#endif
@@ -75,9 +95,17 @@ int idled(void)
power_save();
if (need_resched()) {
+ run_light_on(1);
schedule();
check_pgt_cache();
}
+#ifdef CONFIG_PPC_ISERIES
+ else {
+ run_light_on(0);
+ yield_shared_processor();
+ HMT_low();
+ }
+#endif /* CONFIG_PPC_ISERIES */
}
return 0;
}
@@ -108,6 +136,7 @@ unsigned long get_zero_page_fast(void)
register unsigned long tmp;
asm ( "101:lwarx %1,0,%3\n" /* reserve zero_cache */
" lwz %0,0(%1)\n" /* get next -- new zero_cache */
+ PPC405_ERR77(0,%3)
" stwcx. %0,0,%3\n" /* update zero_cache */
" bne- 101b\n" /* if lost reservation try again */
: "=&r" (tmp), "=&r" (page), "+m" (zero_cache)
@@ -205,6 +234,7 @@ void zero_paged(void)
#ifdef CONFIG_SMP
" sync\n" /* let store settle */
#endif
+ PPC405_ERR77(0,%2)
" stwcx. %3,0,%2\n" /* update zero_cache in mem */
" bne- 101b\n" /* if lost reservation try again */
: "=&r" (tmp), "+m" (zero_quicklist)
@@ -228,6 +258,13 @@ void zero_paged(void)
void power_save(void)
{
unsigned long hid0;
+ int nap = powersave_nap;
+
+ /* 7450 has no DOZE mode mode, we return if powersave_nap
+ * isn't enabled
+ */
+ if (!nap && cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_SPEC7450)
+ return;
/*
* Disable interrupts to prevent a lost wakeup
* when going to sleep. This is necessary even with
@@ -255,3 +292,64 @@ void power_save(void)
_nmask_and_or_msr(0, MSR_EE);
}
+#ifdef CONFIG_PPC_ISERIES
+
+extern void fake_interrupt(void);
+extern u64 get_tb64(void);
+
+void run_light_on(int on)
+{
+ unsigned long CTRL;
+
+ CTRL = mfspr(CTRLF);
+ CTRL = on? (CTRL | RUNLATCH): (CTRL & ~RUNLATCH);
+ mtspr(CTRLT, CTRL);
+}
+
+void yield_shared_processor(void)
+{
+ struct Paca *paca;
+ u64 tb;
+
+ /* Poll for I/O events */
+ __cli();
+ __sti();
+
+ paca = (struct Paca *)mfspr(SPRG1);
+ if ( paca->xLpPaca.xSharedProc ) {
+ HvCall_setEnabledInterrupts( HvCall_MaskIPI |
+ HvCall_MaskLpEvent |
+ HvCall_MaskLpProd |
+ HvCall_MaskTimeout );
+
+ /*
+ * Check here for any of the above pending...
+ * IPI and Decrementers are indicated in ItLpPaca
+ * LpEvents are indicated on the LpQueue
+ *
+ * Disabling/enabling will check for LpEvents, IPIs
+ * and decrementers
+ */
+ __cli();
+ __sti();
+
+ ++yield_count;
+
+ /* Get current tb value */
+ tb = get_tb64();
+ /* Compute future tb value when yield will expire */
+ tb += tb_ticks_per_jiffy;
+ HvCall_yieldProcessor( HvCall_YieldTimed, tb );
+
+ /* Check here for any of the above pending or timeout expired*/
+ __cli();
+ /*
+ * The decrementer stops during the yield. Just force
+ * a fake decrementer now and the timer_interrupt
+ * code will straighten it all out
+ */
+ paca->xLpPaca.xDecrInt = 1;
+ __sti();
+ }
+}
+#endif /* CONFIG_PPC_ISERIES */
diff --git a/arch/ppc/kernel/indirect_pci.c b/arch/ppc/kernel/indirect_pci.c
index b79ceee3c5db..0addbd871bef 100644
--- a/arch/ppc/kernel/indirect_pci.c
+++ b/arch/ppc/kernel/indirect_pci.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.indirect_pci.c 1.10 09/08/01 15:47:42 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Support for indirect PCI bridges.
@@ -24,8 +24,6 @@
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
-#include "pci.h"
-
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
@@ -35,9 +33,13 @@ indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
\
+ if (ppc_md.pci_exclude_device) \
+ if (ppc_md.pci_exclude_device(dev->bus->number, dev->devfn)) \
+ return PCIBIOS_DEVICE_NOT_FOUND; \
+ \
out_be32(hose->cfg_addr, \
((offset & 0xfc) << 24) | (dev->devfn << 16) \
- | (dev->bus->number << 8) | 0x80); \
+ | ((dev->bus->number - hose->bus_offset) << 8) | 0x80); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return PCIBIOS_SUCCESSFUL; \
}
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index c5f422016adf..5c5e37aabb0e 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.irq.c 1.32 08/24/01 20:07:37 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* arch/ppc/kernel/irq.c
@@ -51,20 +51,15 @@
#include <asm/uaccess.h>
#include <asm/bitops.h>
-#include <asm/hydra.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
-#include <asm/gg2.h>
#include <asm/cache.h>
#include <asm/prom.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigappc.h>
#include <asm/ptrace.h>
-#include "local_irq.h"
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
extern atomic_t ipi_recv;
extern atomic_t ipi_sent;
@@ -190,9 +185,6 @@ setup_irq(unsigned int irq, struct irqaction * new)
* now, this is what I need. -- Dan
*/
#define request_irq request_8xxirq
-#elif defined(CONFIG_APUS)
-#define request_irq request_sysirq
-#define free_irq sys_free_irq
#endif
void free_irq(unsigned int irq, void* dev_id)
@@ -374,15 +366,12 @@ void enable_irq(unsigned int irq)
int show_interrupts(struct seq_file *p, void *v)
{
-#ifdef CONFIG_APUS
- return show_apus_interrupts(p, v);
-#else
int i, j;
struct irqaction * action;
seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- seq_printf(p, "CPU%d ",j);
+ seq_printf(p, "CPU%d ", j);
seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
@@ -393,38 +382,35 @@ int show_interrupts(struct seq_file *p, void *v)
#ifdef CONFIG_SMP
for (j = 0; j < smp_num_cpus; j++)
seq_printf(p, "%10u ",
- kstat.irqs[cpu_logical_map(j)][i]);
+ kstat.irqs[cpu_logical_map(j)][i]);
#else
seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */
- if ( irq_desc[i].handler )
- seq_printf(p, " %s ", irq_desc[i].handler->typename );
+ if (irq_desc[i].handler)
+ seq_printf(p, " %s ", irq_desc[i].handler->typename);
else
seq_puts(p, " None ");
seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge ");
- seq_printf(p, " %s",action->name);
- for (action=action->next; action; action = action->next) {
+ seq_printf(p, " %s", action->name);
+ for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
- }
seq_putc(p, '\n');
}
#ifdef CONFIG_TAU_INT
if (tau_initialized){
seq_puts(p, "TAU: ");
for (j = 0; j < smp_num_cpus; j++)
- seq_printf(p, "%10u ",
- tau_interrupts(j));
+ seq_printf(p, "%10u ", tau_interrupts(j));
seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
}
#endif
#ifdef CONFIG_SMP
/* should this be per processor send/receive? */
seq_printf(p, "IPI (recv/sent): %10u/%u\n",
- atomic_read(&ipi_recv), atomic_read(&ipi_sent));
+ atomic_read(&ipi_recv), atomic_read(&ipi_sent));
#endif
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
return 0;
-#endif /* CONFIG_APUS */
}
static inline void
@@ -535,31 +521,35 @@ out:
spin_unlock(&desc->lock);
}
+#ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_pic.c */
int do_IRQ(struct pt_regs *regs)
{
int cpu = smp_processor_id();
- int irq;
- hardirq_enter(cpu);
-
- /* every arch is required to have a get_irq -- Cort */
- irq = ppc_md.get_irq(regs);
-
- if (irq >= 0) {
- ppc_irq_dispatch_handler( regs, irq );
- } else if (irq != -2) {
- /* -2 means ignore, already handled */
- if (ppc_spurious_interrupts < 10)
- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
- irq, regs->nip);
+ int irq, first = 1;
+ hardirq_enter( cpu );
+
+ /*
+ * Every platform is required to implement ppc_md.get_irq.
+ * This function will either return an irq number or -1 to
+ * indicate there are no more pending. But the first time
+ * through the loop this means there wasn't and IRQ pending.
+ * The value -2 is for buggy hardware and means that this IRQ
+ * has already been handled. -- Tom
+ */
+ while ((irq = ppc_md.get_irq(regs)) >= 0) {
+ ppc_irq_dispatch_handler(regs, irq);
+ first = 0;
+ }
+ if (irq != -2 && first)
/* That's not SMP safe ... but who cares ? */
ppc_spurious_interrupts++;
- }
hardirq_exit( cpu );
if (softirq_pending(cpu))
do_softirq();
return 1; /* lets ret_from_int know we can do checks */
}
+#endif /* CONFIG_PPC_ISERIES */
unsigned long probe_irq_on (void)
{
@@ -591,7 +581,6 @@ void __init init_IRQ(void)
#ifdef CONFIG_SMP
unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile long global_irq_lock; /* pendantic :long for set_bit--RR*/
-atomic_t global_irq_count;
atomic_t global_bh_count;
@@ -602,8 +591,7 @@ static void show(char * str)
int cpu = smp_processor_id();
printk("\n%s, CPU %d:\n", str, cpu);
- printk("irq: %d [%d %d]\n",
- atomic_read(&global_irq_count),
+ printk("irq: [%d %d]\n",
local_irq_count(0),
local_irq_count(1));
printk("bh: %d [%d %d]\n",
@@ -643,11 +631,9 @@ static inline void wait_on_irq(int cpu)
* for bottom half handlers unless we're
* already executing in one..
*/
- if (!atomic_read(&global_irq_count)) {
- if (local_bh_count(cpu)
- || !atomic_read(&global_bh_count))
- break;
- }
+ if (!irqs_running())
+ if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
+ break;
/* Duh, we have to loop. Release the lock to avoid deadlocks */
clear_bit(0,&global_irq_lock);
@@ -658,16 +644,19 @@ static inline void wait_on_irq(int cpu)
count = ~0;
}
__sti();
- /* don't worry about the lock race Linus found
- * on intel here. -- Cort
+ /*
+ * We have to allow irqs to arrive between __sti and __cli
+ * Some cpus apparently won't cause the interrupt
+ * for several instructions. We hope that isync will
+ * catch this --Troy
*/
+ __asm__ __volatile__ ("isync");
__cli();
- if (atomic_read(&global_irq_count))
+ if (irqs_running())
continue;
if (global_irq_lock)
continue;
- if (!local_bh_count(cpu)
- && atomic_read(&global_bh_count))
+ if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
continue;
if (!test_and_set_bit(0,&global_irq_lock))
break;
@@ -698,7 +687,7 @@ void synchronize_bh(void)
*/
void synchronize_irq(void)
{
- if (atomic_read(&global_irq_count)) {
+ if (irqs_running()) {
/* Stupid approach */
cli();
sti();
diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S
index d208577bca00..b3ec25cca703 100644
--- a/arch/ppc/kernel/l2cr.S
+++ b/arch/ppc/kernel/l2cr.S
@@ -30,13 +30,19 @@
***********
Thu, July 13, 2000.
- Terry: Added isync to correct for an errata.
+
+ 22 August 2001.
+ - DanM: Finally added the 7450 patch I've had for the past
+ several months. The L2CR is similar, but I'm going
+ to assume the user of this functions knows what they
+ are doing.
Author: Terry Greeniaus (tgree@phys.ualberta.ca)
Please e-mail updates to this file to me, thanks!
*/
#include <asm/processor.h>
#include <asm/cputable.h>
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
/* Usage:
@@ -71,6 +77,15 @@
features, such as L2DO which caches only data, or L2TS which
causes cache pushes from the L1 cache to go to the L2 cache
instead of to main memory.
+
+IMPORTANT:
+ Starting with the 7450, the bits in this register have moved
+ or behave differently. The Enable, Parity Enable, Size,
+ and L2 Invalidate are the only bits that have not moved.
+ The size is read-only for these processors with internal L2
+ cache, and the invalidate is a control as well as status.
+ -- Dan
+
*/
/*
* Summary: this procedure ignores the L2I bit in the value passed in,
@@ -115,6 +130,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
/**** Might be a good idea to set L2DO here - to prevent instructions
from getting into the cache. But since we invalidate
the next time we enable the cache it doesn't really matter.
+ Don't do this unless you accomodate all processor variations.
+ The bit moved on the 7450.....
****/
lis r4,0x0002
@@ -159,12 +176,21 @@ END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
sync
isync /* For errata */
+BEGIN_FTR_SECTION
+ /* On the 7450, we wait for the L2I bit to clear......
+ */
+10: mfspr r3,L2CR
+ andis. r4,r3,0x0020
+ bne 10b
+ b 11f
+END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
+
/* Wait for the invalidation to complete */
3: mfspr r3,L2CR
rlwinm. r4,r3,0,31,31
bne 3b
- rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */
+11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */
sync
mtspr L2CR,r3
sync
diff --git a/arch/ppc/kernel/local_irq.h b/arch/ppc/kernel/local_irq.h
deleted file mode 100644
index 045e864a476d..000000000000
--- a/arch/ppc/kernel/local_irq.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * BK Id: SCCS/s.local_irq.h 1.7 05/17/01 18:14:21 cort
- */
-
-#ifndef _PPC_KERNEL_LOCAL_IRQ_H
-#define _PPC_KERNEL_LOCAL_IRQ_H
-
-#include <linux/kernel_stat.h>
-#include <linux/interrupt.h>
-#include <linux/cache.h>
-#include <linux/spinlock.h>
-#include <linux/irq.h>
-
-void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
-
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-
-extern int ppc_spurious_interrupts;
-extern int ppc_second_irq;
-extern struct irqaction *ppc_irq_action[NR_IRQS];
-
-#endif /* _PPC_KERNEL_LOCAL_IRQ_H */
diff --git a/arch/ppc/kernel/m8260_setup.c b/arch/ppc/kernel/m8260_setup.c
index dfdfb004dadd..a05530474cfd 100644
--- a/arch/ppc/kernel/m8260_setup.c
+++ b/arch/ppc/kernel/m8260_setup.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.m8260_setup.c 1.30 11/13/01 21:26:07 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/arch/ppc/kernel/setup.c
@@ -45,8 +45,9 @@
#include <asm/mpc8260.h>
#include <asm/immap_8260.h>
#include <asm/machdep.h>
-
+#include <asm/bootinfo.h>
#include <asm/time.h>
+
#include "ppc8260_pic.h"
static int m8260_set_rtc_time(unsigned long time);
@@ -98,17 +99,25 @@ static uint rtc_time;
static static int
m8260_set_rtc_time(unsigned long time)
{
+#ifdef CONFIG_TQM8260
+ ((immap_t *)IMAP_ADDR)->im_sit.sit_tmcnt = time;
+ ((immap_t *)IMAP_ADDR)->im_sit.sit_tmcntsc = 0x3;
+#else
rtc_time = time;
+#endif
return(0);
}
static unsigned long
m8260_get_rtc_time(void)
{
-
+#ifdef CONFIG_TQM8260
+ return ((immap_t *)IMAP_ADDR)->im_sit.sit_tmcnt;
+#else
/* Get time from the RTC.
*/
return((unsigned long)rtc_time);
+#endif
}
static void
@@ -121,8 +130,11 @@ m8260_restart(char *cmd)
* of the reset vector. If that doesn't work for you, change this
* or the reboot program to send a proper address.
*/
+#ifdef CONFIG_TQM8260
+ startaddr = 0x40000104;
+#else
startaddr = 0xff000104;
-
+#endif
if (cmd != NULL) {
if (!strncmp(cmd, "startaddr=", 10))
startaddr = simple_strtoul(&cmd[10], NULL, 0);
@@ -150,14 +162,13 @@ m8260_show_percpuinfo(struct seq_file *m, int i)
bd_t *bp;
bp = (bd_t *)__res;
-
+
seq_printf(m, "core clock\t: %d MHz\n"
"CPM clock\t: %d MHz\n"
"bus clock\t: %d MHz\n",
bp->bi_intfreq / 1000000,
bp->bi_cpmfreq / 1000000,
bp->bi_busfreq / 1000000);
-
return 0;
}
@@ -178,7 +189,7 @@ m8260_init_IRQ(void)
#endif
for ( i = 0 ; i < NR_SIU_INTS ; i++ )
irq_desc[i].handler = &ppc8260_pic;
-
+
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
*/
@@ -197,7 +208,7 @@ m8260_find_end_of_memory(void)
{
bd_t *binfo;
extern unsigned char __res[];
-
+
binfo = (bd_t *)__res;
return binfo->bi_memsize;
@@ -219,22 +230,20 @@ void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+ parse_bootinfo(find_bootinfo());
if ( r3 )
memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
-
+
#ifdef CONFIG_BLK_DEV_INITRD
/* take care of initrd if we have one */
- if ( r4 )
- {
+ if ( r4 ) {
initrd_start = r4 + KERNELBASE;
initrd_end = r5 + KERNELBASE;
}
#endif /* CONFIG_BLK_DEV_INITRD */
/* take care of cmd line */
- if ( r6 )
- {
-
+ if ( r6 ) {
*(char *)(r7+KERNELBASE) = 0;
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c
index ace85d3dcf69..dade12003a8a 100644
--- a/arch/ppc/kernel/m8xx_setup.c
+++ b/arch/ppc/kernel/m8xx_setup.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.m8xx_setup.c 1.40 11/13/01 21:26:07 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*
* linux/arch/ppc/kernel/setup.c
*
@@ -43,8 +43,9 @@
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/machdep.h>
-
+#include <asm/bootinfo.h>
#include <asm/time.h>
+
#include "ppc8xx_pic.h"
static int m8xx_set_rtc_time(unsigned long time);
@@ -57,25 +58,30 @@ extern void m8xx_ide_init(void);
extern unsigned long find_available_memory(void);
extern void m8xx_cpm_reset(uint);
+extern void rpxfb_alloc_pages(void);
void __init
m8xx_setup_arch(void)
{
int cpm_page;
-
+
cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
-
+
/* Reset the Communication Processor Module.
*/
m8xx_cpm_reset(cpm_page);
+#ifdef CONFIG_FB_RPX
+ rpxfb_alloc_pages();
+#endif
+
#ifdef notdef
ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
#endif
-
+
#ifdef CONFIG_BLK_DEV_INITRD
#if 0
- ROOT_DEV = to_kdev_t(0x0200); /* floppy */
+ ROOT_DEV = to_kdev_t(0x0200); /* floppy */
rd_prompt = 1;
rd_doload = 1;
rd_image_start = 0;
@@ -105,6 +111,9 @@ abort(void)
xmon(0);
#endif
machine_restart(NULL);
+
+ /* not reached */
+ for (;;);
}
/* A place holder for time base interrupts, if they are ever enabled. */
@@ -217,7 +226,7 @@ m8xx_restart(char *cmd)
__asm__("mtmsr %0" : : "r" (msr) );
dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
- printk("Restart failed\n");
+ printk("Restart failed\n");
while(1);
}
@@ -240,9 +249,9 @@ m8xx_show_percpuinfo(struct seq_file *m, int i)
bd_t *bp;
bp = (bd_t *)__res;
-
- seq_printf(m, "clock\t\t: %ldMHz\n"
- "bus clock\t: %ldMHz\n",
+
+ seq_printf(m, "clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
bp->bi_intfreq / 1000000,
bp->bi_busfreq / 1000000);
@@ -263,7 +272,7 @@ m8xx_init_IRQ(void)
for ( i = 0 ; i < NR_SIU_INTS ; i++ )
irq_desc[i].handler = &ppc8xx_pic;
-
+
/* We could probably incorporate the CPM into the multilevel
* interrupt structure.
*/
@@ -296,7 +305,7 @@ m8xx_find_end_of_memory(void)
{
bd_t *binfo;
extern unsigned char __res[];
-
+
binfo = (bd_t *)__res;
return binfo->bi_memsize;
@@ -343,9 +352,11 @@ void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+ parse_bootinfo(find_bootinfo());
+
if ( r3 )
memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
-
+
#ifdef CONFIG_PCI
m8xx_setup_pci_ptrs();
#endif
@@ -360,7 +371,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif /* CONFIG_BLK_DEV_INITRD */
/* take care of cmd line */
if ( r6 )
- {
+ {
*(char *)(r7+KERNELBASE) = 0;
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
@@ -394,5 +405,5 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
m8xx_ide_init();
-#endif
+#endif
}
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 376fa23dc4b2..6e01a5c36d52 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.misc.S 1.32 10/18/01 17:29:53 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* This file contains miscellaneous low-level functions.
@@ -23,7 +23,9 @@
#include <asm/page.h>
#include <asm/cache.h>
#include <asm/cputable.h>
-#include "ppc_asm.h"
+#include <asm/mmu.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
.text
@@ -39,7 +41,6 @@ _GLOBAL(__delay)
* Returns (address we're running at) - (address we were linked at)
* for use before the text and data are mapped to KERNELBASE.
*/
-
_GLOBAL(reloc_offset)
mflr r0
bl 1f
@@ -51,6 +52,62 @@ _GLOBAL(reloc_offset)
blr
/*
+ * add_reloc_offset(x) returns x + reloc_offset().
+ */
+_GLOBAL(add_reloc_offset)
+ mflr r0
+ bl 1f
+1: mflr r5
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r5,r4,r5
+ add r3,r3,r5
+ mtlr r0
+ blr
+
+/*
+ * sub_reloc_offset(x) returns x - reloc_offset().
+ */
+_GLOBAL(sub_reloc_offset)
+ mflr r0
+ bl 1f
+1: mflr r5
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r5,r4,r5
+ subf r3,r5,r3
+ mtlr r0
+ blr
+
+/*
+ * reloc_got2 runs through the .got2 section adding an offset
+ * to each entry.
+ */
+_GLOBAL(reloc_got2)
+ mflr r11
+ lis r7,__got2_start@ha
+ addi r7,r7,__got2_start@l
+ lis r8,__got2_end@ha
+ addi r8,r8,__got2_end@l
+ subf r8,r7,r8
+ srwi. r8,r8,2
+ beqlr
+ mtctr r8
+ bl 1f
+1: mflr r0
+ lis r4,1b@ha
+ addi r4,r4,1b@l
+ subf r0,r4,r0
+ add r7,r0,r7
+2: lwz r0,0(r7)
+ add r0,r0,r3
+ stw r0,0(r7)
+ addi r7,r7,4
+ bdnz 2b
+ mtlr r11
+ blr
+
+/*
* identify_cpu,
* called with r3 = data offset and r4 = CPU number
* doesn't change r3
@@ -81,6 +138,7 @@ _GLOBAL(identify_cpu)
* r3 = data offset (not changed)
*/
_GLOBAL(do_cpu_ftr_fixups)
+#ifndef CONFIG_PPC_ISERIES
/* Get CPU 0 features */
addis r6,r3,cur_cpu_spec@ha
addi r6,r6,cur_cpu_spec@l
@@ -124,10 +182,16 @@ _GLOBAL(do_cpu_ftr_fixups)
sync /* additional sync needed on g4 */
isync
b 1b
+#else /* CONFIG_PPC_ISERIES */
+ blr
+#endif /* CONFIG_PPC_ISERIES */
/*
* call_setup_cpu - call the setup_cpu function for this cpu
* r3 = data offset, r24 = cpu number
+ *
+ * Don't change register layout, the setup function may rely
+ * on r5 containing a relocated pointer to the current cpu spec.
*/
_GLOBAL(call_setup_cpu)
addis r5,r3,cur_cpu_spec@ha
@@ -141,6 +205,7 @@ _GLOBAL(call_setup_cpu)
mr r3,r24
bctr
+#ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_misc.S */
/* void __save_flags_ptr(unsigned long *flags) */
_GLOBAL(__save_flags_ptr)
mfmsr r4
@@ -268,7 +333,7 @@ _GLOBAL(__sti)
nop
nop
_GLOBAL(__sti_end)
-
+#endif /* CONFIG_PPC_ISERIES */
/*
* complement mask on the msr then "or" some values on.
@@ -288,6 +353,20 @@ _GLOBAL(_nmask_and_or_msr)
* Flush MMU TLB
*/
_GLOBAL(_tlbia)
+#if defined(CONFIG_4xx) && defined(CONFIG_PIN_TLB)
+ /* This needs to be coordinated with other pinning functions since
+ * we don't keep a memory location of number of entries to reduce
+ * cache pollution during these operations.
+ */
+ lis r3, 0
+ sync
+1:
+ tlbwe r3, r3, TLB_TAG /* just ensure V is clear */
+ addi r3, r3, 1 /* so r3 works fine for that */
+ cmpwi 0, r3, 61 /* reserve last two entries */
+ ble 1b
+ isync
+#else
#if defined(CONFIG_SMP)
mfmsr r10
SYNC
@@ -296,11 +375,12 @@ _GLOBAL(_tlbia)
SYNC
lis r9,hash_table_lock@h
ori r9,r9,hash_table_lock@l
- lwz r8,PROCESSOR(r2)
+ lwz r8,CPU(r2)
oris r8,r8,10
10: lwarx r7,0,r9
cmpi 0,r7,0
bne- 10b
+ /* No 405 Erratum 77 fix needed here, because 4xx can't do SMP */
stwcx. r8,0,r9
bne- 10b
#endif /* CONFIG_SMP */
@@ -314,12 +394,24 @@ _GLOBAL(_tlbia)
mtmsr r10
SYNC
#endif
+#endif
blr
/*
* Flush MMU TLB for a particular address
*/
_GLOBAL(_tlbie)
+#ifdef CONFIG_4xx
+ tlbsx. r3, 0, r3
+ bne 10f
+ sync
+ /* There are only 64 TLB entries, so r3 < 64, which means bit 25, is clear.
+ * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate
+ * the TLB entry. */
+ tlbwe r3, r3, TLB_TAG
+ isync
+10:
+#else
#if defined(CONFIG_SMP)
mfmsr r10
SYNC
@@ -328,11 +420,12 @@ _GLOBAL(_tlbie)
SYNC
lis r9,hash_table_lock@h
ori r9,r9,hash_table_lock@l
- lwz r8,PROCESSOR(r2)
+ lwz r8,CPU(r2)
oris r8,r8,11
10: lwarx r7,0,r9
cmpi 0,r7,0
bne- 10b
+ PPC405_ERR77(0,r9)
stwcx. r8,0,r9
bne- 10b
eieio
@@ -346,6 +439,7 @@ _GLOBAL(_tlbie)
mtmsr r10
SYNC
#endif
+#endif /* CONFIG_4xx */
blr
/*
@@ -358,8 +452,17 @@ _GLOBAL(flush_instruction_cache)
lis r5, IDC_INVALL@h
mtspr IC_CST, r5
#elif defined(CONFIG_4xx)
+#ifdef CONFIG_403GCX
+ li r3, 512
+ mtctr r3
+ lis r4, KERNELBASE@h
+1: iccci 0, r4
+ addi r4, r4, 16
+ bdnz 1b
+#else
lis r3, KERNELBASE@h
iccci 0,r3
+#endif
#else
mfspr r3,PVR
rlwinm r3,r3,16,16,31
@@ -369,10 +472,11 @@ _GLOBAL(flush_instruction_cache)
mfspr r3,HID0
ori r3,r3,HID0_ICFI
mtspr HID0,r3
-#endif /* CONFIG_8xx */
+#endif /* CONFIG_8xx/4xx */
isync
blr
+#ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_misc.S */
/*
* Write any modified data cache blocks out to memory
* and invalidate the corresponding instruction cache blocks.
@@ -469,15 +573,40 @@ _GLOBAL(invalidate_dcache_range)
sync /* wait for dcbi's to get to ram */
blr
+#ifdef CONFIG_NOT_COHERENT_CACHE
+/* This is a bad one....It is used by 'consistent_sync' functions when
+ * there isn't any handle on the virtual address needed by the usual
+ * cache flush instructions. On the MPC8xx, we can use the cache line
+ * flush command, on others all we can do is read enough data to completely
+ * reload the cache, flushing old data out.
+ */
+
+/* Cache organization. The 4xx has a 8K (128 line) cache, and the 8xx
+ * has 1, 2, 4, 8K variants. For now, cover worst case. When we can
+ * deteremine actual size, we will use that later.
+ */
+#define CACHE_NWAYS 2
+#define CACHE_NLINES 128
+
+_GLOBAL(flush_dcache_all)
+ li r4, (CACHE_NWAYS * CACHE_NLINES)
+ mtctr r4
+ lis r5, KERNELBASE@h
+1: lwz r3, 0(r5) /* Load one word from every line */
+ addi r5, r5, L1_CACHE_LINE_SIZE
+ bdnz 1b
+ blr
+#endif /* CONFIG_NOT_COHERENT_CACHE */
+
/*
* Flush a particular page from the data cache to RAM.
* Note: this is necessary because the instruction cache does *not*
* snoop from the data cache.
* This is a no-op on the 601 which has a unified cache.
*
- * void __flush_page_to_ram(void *page)
+ * void __flush_dcache_icache(void *page)
*/
-_GLOBAL(__flush_page_to_ram)
+_GLOBAL(__flush_dcache_icache)
mfspr r5,PVR
rlwinm r5,r5,16,16,31
cmpi 0,r5,1
@@ -497,28 +626,6 @@ _GLOBAL(__flush_page_to_ram)
sync
isync
blr
-
-/*
- * Flush a particular page from the instruction cache.
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- * This is a no-op on the 601 which has a unified cache.
- *
- * void __flush_icache_page(void *page)
- */
-_GLOBAL(__flush_icache_page)
- mfspr r5,PVR
- rlwinm r5,r5,16,16,31
- cmpi 0,r5,1
- beqlr /* for 601, do nothing */
- li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
- mtctr r4
-1: icbi 0,r3
- addi r3,r3,L1_CACHE_LINE_SIZE
- bdnz 1b
- sync
- isync
- blr
/*
* Clear a page using the dcbz instruction, which doesn't cause any
@@ -563,8 +670,8 @@ _GLOBAL(copy_page)
li r5,4
#ifndef CONFIG_8xx
-#if MAX_L1_COPY_PREFETCH > 1
- li r0,MAX_L1_COPY_PREFETCH
+#if MAX_COPY_PREFETCH > 1
+ li r0,MAX_COPY_PREFETCH
li r11,4
mtctr r0
11: dcbt r11,r4
@@ -599,6 +706,7 @@ _GLOBAL(copy_page)
#endif
bdnz 1b
blr
+#endif /* CONFIG_PPC_ISERIES */
/*
* Atomic [test&set] exchange
@@ -610,6 +718,7 @@ _GLOBAL(copy_page)
_GLOBAL(xchg_u32)
mr r5,r3 /* Save pointer */
10: lwarx r3,0,r5 /* Fetch old value & reserve */
+ PPC405_ERR77(0,r5)
stwcx. r4,0,r5 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
blr
@@ -621,12 +730,14 @@ _GLOBAL(xchg_u32)
_GLOBAL(atomic_clear_mask)
10: lwarx r5,0,r4
andc r5,r5,r3
+ PPC405_ERR77(0,r4)
stwcx. r5,0,r4
bne- 10b
blr
_GLOBAL(atomic_set_mask)
10: lwarx r5,0,r4
or r5,r5,r3
+ PPC405_ERR77(0,r4)
stwcx. r5,0,r4
bne- 10b
blr
@@ -866,10 +977,8 @@ _GLOBAL(kernel_thread)
sc
cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */
- li r0,0 /* clear out p->thread.regs */
- stw r0,THREAD+PT_REGS(r2) /* since we don't have user ctx */
- addi r1,r2,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
- stw r0,0(r1)
+ li r0,0 /* make top-level stack frame */
+ stwu r0,-16(r1)
mtlr r6 /* fn addr in lr */
mr r3,r4 /* load arg and call fn */
blrl
diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c
index 2ff838e89c04..cdc35c4d363e 100644
--- a/arch/ppc/kernel/mk_defs.c
+++ b/arch/ppc/kernel/mk_defs.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.mk_defs.c 1.11 08/19/01 22:43:23 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* This program is used to generate definitions needed by
@@ -28,6 +28,13 @@
#include <asm/processor.h>
#include <asm/cputable.h>
+#ifdef CONFIG_PPC_ISERIES
+#include <asm/iSeries/Paca.h>
+#include <asm/iSeries/ItLpPaca.h>
+#include <asm/iSeries/ItLpQueue.h>
+#include <asm/iSeries/HvLpEvent.h>
+#endif /* CONFIG_PPC_ISERIES */
+
#define DEFINE(sym, val) \
asm volatile("\n#define\t" #sym "\t%0" : : "i" (val))
@@ -37,10 +44,8 @@ main(void)
/*DEFINE(KERNELBASE, KERNELBASE);*/
DEFINE(STATE, offsetof(struct task_struct, state));
DEFINE(NEXT_TASK, offsetof(struct task_struct, next_task));
- DEFINE(COUNTER, offsetof(struct task_struct, counter));
- DEFINE(PROCESSOR, offsetof(struct task_struct, processor));
-#error DEFINE(SIGPENDING, offsetof(struct task_struct, sigpending));
DEFINE(THREAD, offsetof(struct task_struct, thread));
+ DEFINE(CPU, offsetof(struct task_struct, cpu));
DEFINE(MM, offsetof(struct task_struct, mm));
DEFINE(ACTIVE_MM, offsetof(struct task_struct, active_mm));
DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
@@ -48,10 +53,13 @@ main(void)
DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
- DEFINE(PT_TRACESYS, PT_TRACESYS);
DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-#error DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
-#error DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
+ DEFINE(TASK_WORK, offsetof(struct task_struct, work));
+ DEFINE(NEED_RESCHED, offsetof(struct task_struct, work.need_resched));
+ DEFINE(SYSCALL_TRACE, offsetof(struct task_struct, work.syscall_trace));
+ DEFINE(SIGPENDING, offsetof(struct task_struct, work.sigpending));
+ DEFINE(NOTIFY_RESUME, offsetof(struct task_struct, work.notify_resume));
+ DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
#ifdef CONFIG_ALTIVEC
@@ -127,6 +135,35 @@ main(void)
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
+#ifdef CONFIG_PPC_ISERIES
+ DEFINE(PACAPROCENABLED, offsetof(struct Paca, xProcEnabled));
+ DEFINE(PACAPACAINDEX, offsetof(struct Paca, xPacaIndex));
+ DEFINE(PACAPROCSTART, offsetof(struct Paca, xProcStart));
+ DEFINE(PACAKSAVE, offsetof(struct Paca, xKsave));
+ DEFINE(PACASAVEDMSR, offsetof(struct Paca, xSavedMsr));
+ DEFINE(PACASAVEDLR, offsetof(struct Paca, xSavedLr));
+ DEFINE(PACACONTEXTOVERFLOW, offsetof(struct Paca, xContextOverflow));
+ DEFINE(PACAR21, offsetof(struct Paca, xR21));
+ DEFINE(PACAR22, offsetof(struct Paca, xR22));
+ DEFINE(PACALPQUEUE, offsetof(struct Paca, lpQueuePtr));
+ DEFINE(PACALPPACA, offsetof(struct Paca, xLpPaca));
+ DEFINE(PACA_STRUCT_SIZE, sizeof(struct Paca));
+ DEFINE(LPREGSAV, offsetof(struct Paca, xRegSav));
+ DEFINE(PACADEFAULTDECR, offsetof(struct Paca, default_decr));
+ DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xRsvd));
+ DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0));
+ DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
+ DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xDecrInt));
+ DEFINE(LPPACAIPIINT, offsetof(struct ItLpPaca, xIpiCnt));
+ DEFINE(LPQCUREVENTPTR, offsetof(struct ItLpQueue, xSlicCurEventPtr));
+ DEFINE(LPQOVERFLOW, offsetof(struct ItLpQueue, xPlicOverflowIntPending));
+ DEFINE(LPQINUSEWORD, offsetof(struct ItLpQueue, xInUseWord));
+ DEFINE(LPEVENTFLAGS, offsetof(struct HvLpEvent, xFlags));
+ DEFINE(CONTEXT, offsetof(struct mm_struct, context));
+ DEFINE(_SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, mq));
+ DEFINE(PACA_EXT_INTS, offsetof(struct Paca, ext_ints));
+#endif /* CONFIG_PPC_ISERIES */
+
DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
return 0;
}
diff --git a/arch/ppc/kernel/mpc10x_common.c b/arch/ppc/kernel/mpc10x_common.c
new file mode 100644
index 000000000000..facbf56019d7
--- /dev/null
+++ b/arch/ppc/kernel/mpc10x_common.c
@@ -0,0 +1,378 @@
+
+/*
+ * arch/ppc/kernel/mpc10x_common.c
+ *
+ * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
+ * Mem ctlr, EPIC, etc.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+/*
+ * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/mpc10x.h>
+
+
+/* Set resources to match bridge memory map */
+void __init
+mpc10x_bridge_set_resources(int map, struct pci_controller *hose)
+{
+
+ switch (map) {
+ case MPC10X_MEM_MAP_A:
+ pci_init_resource(&hose->io_resource,
+ 0x00000000,
+ 0x3f7fffff,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource (&hose->mem_resources[0],
+ 0xc0000000,
+ 0xfeffffff,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+ break;
+ case MPC10X_MEM_MAP_B:
+ pci_init_resource(&hose->io_resource,
+ 0x00000000,
+ 0x00bfffff,
+ IORESOURCE_IO,
+ "PCI host bridge");
+
+ pci_init_resource (&hose->mem_resources[0],
+ 0x80000000,
+ 0xfcffffff,
+ IORESOURCE_MEM,
+ "PCI host bridge");
+ break;
+ default:
+ printk("mpc10x_bridge_set_resources: "
+ "Invalid map specified\n");
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit1", 0x100);
+ }
+}
+/*
+ * Do some initialization and put the EUMB registers at the specified address
+ * (also map the EPIC registers into virtual space--OpenPIC_Addr will be set).
+ *
+ * The EPIC is not on the 106, only the 8240 and 107.
+ */
+int __init
+mpc10x_bridge_init(struct pci_controller *hose,
+ uint current_map,
+ uint new_map,
+ uint phys_eumb_base)
+{
+ int host_bridge, picr1, picr1_bit;
+ ulong pci_config_addr, pci_config_data;
+ u_char pir, byte;
+
+ if (ppc_md.progress) ppc_md.progress("mpc10x:enter", 0x100);
+
+ /* Set up for current map so we can get at config regs */
+ switch (current_map) {
+ case MPC10X_MEM_MAP_A:
+ setup_indirect_pci(hose,
+ MPC10X_MAPA_CNFG_ADDR,
+ MPC10X_MAPA_CNFG_DATA);
+ break;
+ case MPC10X_MEM_MAP_B:
+ setup_indirect_pci(hose,
+ MPC10X_MAPB_CNFG_ADDR,
+ MPC10X_MAPB_CNFG_DATA);
+ break;
+ default:
+ printk("mpc10x_bridge_init: %s\n",
+ "Invalid current map specified");
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit1", 0x100);
+ return -1;
+ }
+
+ /* Make sure its a supported bridge */
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_VENDOR_ID,
+ &host_bridge);
+
+ switch (host_bridge) {
+ case MPC10X_BRIDGE_106:
+ case MPC10X_BRIDGE_8240:
+ case MPC10X_BRIDGE_107:
+ case MPC10X_BRIDGE_8245:
+ break;
+ default:
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit2", 0x100);
+ return -1;
+ }
+
+ switch (new_map) {
+ case MPC10X_MEM_MAP_A:
+ MPC10X_SETUP_HOSE(hose, A);
+ pci_config_addr = MPC10X_MAPA_CNFG_ADDR;
+ pci_config_data = MPC10X_MAPA_CNFG_DATA;
+ picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_A;
+ break;
+ case MPC10X_MEM_MAP_B:
+ MPC10X_SETUP_HOSE(hose, B);
+ pci_config_addr = MPC10X_MAPB_CNFG_ADDR;
+ pci_config_data = MPC10X_MAPB_CNFG_DATA;
+ picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_B;
+ break;
+ default:
+ printk("mpc10x_bridge_init: %s\n",
+ "Invalid new map specified");
+ if (ppc_md.progress)
+ ppc_md.progress("mpc10x:exit3", 0x100);
+ return -1;
+ }
+
+ /* Make bridge use the 'new_map', if not already usng it */
+ if (current_map != new_map) {
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ &picr1);
+
+ picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
+ picr1_bit;
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ picr1);
+
+ asm volatile("sync");
+
+ /* Undo old mappings & map in new cfg data/addr regs */
+ iounmap((void *)hose->cfg_addr);
+ iounmap((void *)hose->cfg_data);
+
+ setup_indirect_pci(hose,
+ pci_config_addr,
+ pci_config_data);
+ }
+
+ /* Setup resources to match map */
+ mpc10x_bridge_set_resources(new_map, hose);
+
+ /*
+ * Want processor accesses of 0xFDxxxxxx to be mapped
+ * to PCI memory space at 0x00000000. Do not want
+ * host bridge to respond to PCI memory accesses of
+ * 0xFDxxxxxx. Do not want host bridge to respond
+ * to PCI memory addresses 0xFD000000-0xFDFFFFFF;
+ * want processor accesses from 0x000A0000-0x000BFFFF
+ * to be forwarded to system memory.
+ *
+ * Only valid if not in agent mode and using MAP B.
+ */
+ if (new_map == MPC10X_MEM_MAP_B) {
+ early_read_config_byte(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_MAPB_OPTIONS_REG,
+ &byte);
+
+ byte &= ~(MPC10X_CFG_MAPB_OPTIONS_PFAE |
+ MPC10X_CFG_MAPB_OPTIONS_PCICH |
+ MPC10X_CFG_MAPB_OPTIONS_PROCCH);
+
+ if (host_bridge != MPC10X_BRIDGE_106) {
+ byte |= MPC10X_CFG_MAPB_OPTIONS_CFAE;
+ }
+
+ early_write_config_byte(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_MAPB_OPTIONS_REG,
+ byte);
+ }
+
+ if (host_bridge != MPC10X_BRIDGE_106) {
+ early_read_config_byte(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PIR_REG,
+ &pir);
+
+ if (pir != MPC10X_CFG_PIR_HOST_BRIDGE) {
+ printk("Host bridge in Agent mode\n");
+ /* Read or Set LMBAR & PCSRBAR? */
+ }
+
+ /* Set base addr of the 8240/107 EUMB. */
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_EUMBBAR,
+ phys_eumb_base);
+
+ /* Map EPIC register part of EUMB into vitual memory */
+ OpenPIC_Addr =
+ ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
+ MPC10X_EUMB_EPIC_SIZE);
+ }
+
+#ifdef CONFIG_MPC10X_STORE_GATHERING
+ mpc10x_enable_store_gathering(hose);
+#endif
+
+ if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100);
+ return 0;
+}
+
+/*
+ * Need to make our own PCI config space access macros because
+ * mpc10x_get_mem_size() is called before the data structures are set up for
+ * the 'early_xxx' and 'indirect_xxx' routines to work.
+ * Assumes bus 0.
+ */
+#define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr))
+#define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val))
+
+#define MPC10X_PCI_OP(rw, size, type, op, mask) \
+static void \
+mpc10x_##rw##_config_##size(uint *cfg_addr, uint *cfg_data, int devfn, int offset, type val) \
+{ \
+ out_be32(cfg_addr, \
+ ((offset & 0xfc) << 24) | (devfn << 16) \
+ | (0 << 8) | 0x80); \
+ MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \
+ return; \
+}
+
+MPC10X_PCI_OP(read, byte, u8 *, in_8, 3)
+MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
+#if 0 /* Not used */
+MPC10X_PCI_OP(write, byte, u8, out_8, 3)
+MPC10X_PCI_OP(read, word, u16 *, in_le16, 2)
+MPC10X_PCI_OP(write, word, u16, out_le16, 2)
+MPC10X_PCI_OP(write, dword, u32, out_le32, 0)
+#endif
+
+/*
+ * Read the memory controller registers to determine the amount of memory in
+ * the system. This assumes that the firmware has correctly set up the memory
+ * controller registers.
+ */
+unsigned long __init
+mpc10x_get_mem_size(uint mem_map)
+{
+ uint *config_addr, *config_data, val;
+ ulong start, end, total, offset;
+ int i;
+ u_char bank_enables;
+
+ switch (mem_map) {
+ case MPC10X_MEM_MAP_A:
+ config_addr = (uint *)MPC10X_MAPA_CNFG_ADDR;
+ config_data = (uint *)MPC10X_MAPA_CNFG_DATA;
+ break;
+ case MPC10X_MEM_MAP_B:
+ config_addr = (uint *)MPC10X_MAPB_CNFG_ADDR;
+ config_data = (uint *)MPC10X_MAPB_CNFG_DATA;
+ break;
+ default:
+ return 0;
+ }
+
+ mpc10x_read_config_byte(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ MPC10X_MCTLR_MEM_BANK_ENABLES,
+ &bank_enables);
+
+ total = 0;
+
+ for (i=0; i<8; i++) {
+ if (bank_enables & (1 << i)) {
+ offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ start = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ start = (val << 28) | (start << 20);
+
+ offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ end = (val >> ((i & 3) << 3)) & 0xff;
+
+ offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
+ mpc10x_read_config_dword(config_addr,
+ config_data,
+ PCI_DEVFN(0,0),
+ offset,
+ &val);
+ val = (val >> ((i & 3) << 3)) & 0x03;
+ end = (val << 28) | (end << 20) | 0xfffff;
+
+ total += (end - start + 1);
+ }
+ }
+
+ return total;
+}
+
+int __init
+mpc10x_enable_store_gathering(struct pci_controller *hose)
+{
+ uint picr1;
+
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ &picr1);
+
+ picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN;
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ MPC10X_CFG_PICR1_REG,
+ picr1);
+
+ return 0;
+}
diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c
deleted file mode 100644
index 8d49dbbefff5..000000000000
--- a/arch/ppc/kernel/oak_setup.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * BK Id: SCCS/s.oak_setup.c 1.12 11/13/01 21:26:07 paulus
- */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: oak_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-#include <linux/seq_file.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include <asm/time.h>
-#include "oak_setup.h"
-
-
-
-
-
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init oak_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = oak_setup_arch;
- ppc_md.show_percpuinfo = oak_show_percpuinfo;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = oak_init_IRQ;
- ppc_md.get_irq = oak_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = oak_restart;
- ppc_md.power_off = oak_power_off;
- ppc_md.halt = oak_halt;
-
- ppc_md.time_init = oak_time_init;
- ppc_md.set_rtc_time = oak_set_rtc_time;
- ppc_md.get_rtc_time = oak_get_rtc_time;
- ppc_md.calibrate_decr = oak_calibrate_decr;
-
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
-}
-
-/*
- * Document me.
- */
-void __init
-oak_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int oak_show_percpuinfo()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-oak_show_percpuinfo(struct seq_file *m, int i)
-{
- bd_t *bp = (bd_t *)__res;
-
- seq_printf(m, "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return 0;
-}
-
-/*
- * Document me.
- */
-void __init
-oak_init_IRQ(void)
-{
- int i;
-
- ppc4xx_pic_init();
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].handler = ppc4xx_pic;
- }
-
- return;
-}
-
-/*
- * Document me.
- */
-int
-oak_get_irq(struct pt_regs *regs)
-{
- return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-oak_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-oak_power_off(void)
-{
- oak_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-oak_halt(void)
-{
- oak_restart(NULL);
-}
-
-/*
- * Document me.
- */
-long __init
-oak_time_init(void)
-{
- /* XXX - Implement me */
- return 0;
-}
-
-/*
- * Document me.
- */
-int __init
-oak_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-oak_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init oak_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-oak_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
diff --git a/arch/ppc/kernel/oak_setup.h b/arch/ppc/kernel/oak_setup.h
deleted file mode 100644
index c51e15ec6b0c..000000000000
--- a/arch/ppc/kernel/oak_setup.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * BK Id: SCCS/s.oak_setup.h 1.5 05/17/01 18:14:21 cort
- */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: oak_setup.h
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __OAK_SETUP_H__
-#define __OAK_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void oak_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void oak_setup_arch(void);
-extern int oak_setup_residual(char *buffer);
-extern void oak_init_IRQ(void);
-extern int oak_get_irq(struct pt_regs *regs);
-extern void oak_restart(char *cmd);
-extern void oak_power_off(void);
-extern void oak_halt(void);
-extern void oak_time_init(void);
-extern int oak_set_rtc_time(unsigned long now);
-extern unsigned long oak_get_rtc_time(void);
-extern void oak_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __OAK_SETUP_H__ */
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
index c5c8a7e155f0..676d97101e9b 100644
--- a/arch/ppc/kernel/open_pic.c
+++ b/arch/ppc/kernel/open_pic.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.open_pic.c 1.31 10/11/01 12:09:11 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
@@ -17,40 +17,40 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/init.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/sections.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
-#include "local_irq.h"
-#include "open_pic.h"
#include "open_pic_defs.h"
+#ifdef CONFIG_PRPMC800
+#define OPENPIC_BIG_ENDIAN
+#endif
+
void* OpenPIC_Addr;
static volatile struct OpenPIC *OpenPIC = NULL;
u_int OpenPIC_NumInitSenses __initdata = 0;
u_char *OpenPIC_InitSenses __initdata = NULL;
extern int use_of_interrupt_tree;
-void find_ISUs(void);
-
static u_int NumProcessors;
static u_int NumSources;
-#ifdef CONFIG_POWER3
-static int NumISUs;
-#endif
static int open_pic_irq_offset;
static volatile unsigned char* chrp_int_ack_special;
-
-OpenPIC_SourcePtr ISU[OPENPIC_MAX_ISU];
+static volatile OpenPIC_Source *ISR[NR_IRQS];
/* Global Operations */
static void openpic_disable_8259_pass_through(void);
static void openpic_set_priority(u_int pri);
static void openpic_set_spurious(u_int vector);
+static void openpic_enable_sie(void);
+static void openpic_eicr_set_clk(u_int clkval);
+static void openpic_eicr_set_clk(u_int clkval);
#ifdef CONFIG_SMP
/* Interprocessor Interrupts */
@@ -67,7 +67,7 @@ static void openpic_enable_irq(u_int irq);
static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level);
-static void openpic_mapirq(u_int irq, u_int cpumask);
+static void openpic_mapirq(u_int irq, u_int cpumask, u_int keepmask);
/*
* These functions are not used but the code is kept here
@@ -150,7 +150,8 @@ struct hw_interrupt_type open_pic_ipi = {
*/
extern unsigned long* _get_SP(void);
#define check_arg_irq(irq) \
- if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \
+ if (irq < open_pic_irq_offset || irq >= NumSources+open_pic_irq_offset \
+ || ISR[irq - open_pic_irq_offset] == 0) { \
printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \
print_backtrace(_get_SP()); }
#define check_arg_cpu(cpu) \
@@ -166,23 +167,25 @@ extern unsigned long* _get_SP(void);
#define check_arg_cpu(cpu) do {} while (0)
#endif
-#ifdef CONFIG_POWER3
- #define GET_ISU(source) ISU[(source) >> 4][(source) & 0xf]
-#else
- #define GET_ISU(source) ISU[0][(source)]
-#endif
-
u_int openpic_read(volatile u_int *addr)
{
u_int val;
+#ifdef OPENPIC_BIG_ENDIAN
+ val = in_be32(addr);
+#else
val = in_le32(addr);
+#endif
return val;
}
static inline void openpic_write(volatile u_int *addr, u_int val)
{
+#ifdef OPENPIC_BIG_ENDIAN
+ out_be32(addr, val);
+#else
out_le32(addr, val);
+#endif
}
static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
@@ -221,7 +224,7 @@ static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
u_int openpic_read_IPI(volatile u_int* addr)
{
u_int val = 0;
-#ifdef CONFIG_POWER3
+#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
val = in_be32(addr);
#else
val = in_le32(addr);
@@ -260,6 +263,20 @@ static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int
}
#endif /* CONFIG_SMP */
+void openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
+{
+ volatile OpenPIC_Source *src = first_ISR;
+ int i, last_irq;
+
+ last_irq = first_irq + num_irqs;
+ if (last_irq > NumSources)
+ NumSources = last_irq;
+ if (src == 0)
+ src = &((struct OpenPIC *)OpenPIC_Addr)->Source[first_irq];
+ for (i = first_irq; i < last_irq; ++i, ++src)
+ ISR[i] = src;
+}
+
void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
int programmer_switch_irq)
{
@@ -273,7 +290,13 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
}
OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr;
- if ( ppc_md.progress ) ppc_md.progress("openpic enter",0x122);
+#ifdef CONFIG_EPIC_SERIAL_MODE
+ /* Have to start from ground zero.
+ */
+ openpic_reset();
+#endif
+
+ if (ppc_md.progress) ppc_md.progress("openpic enter", 0x122);
t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
switch (t & OPENPIC_FEATURE_VERSION_MASK) {
@@ -292,8 +315,11 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
}
NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
- NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
- OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
+ if (NumSources == 0)
+ openpic_set_sources(0,
+ ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
+ OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1,
+ NULL);
printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n",
version, NumProcessors, NumSources, OpenPIC);
timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
@@ -328,8 +354,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
}
#endif
- find_ISUs();
-
/* Initialize external interrupts */
if (ppc_md.progress) ppc_md.progress("openpic ext",0x3bc);
@@ -338,13 +362,16 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
/* SIOint (8259 cascade) is special */
if (offset) {
openpic_initirq(0, 8, offset, 1, 1);
- openpic_mapirq(0, 1<<0);
+ openpic_mapirq(0, 1<<0, 0);
}
/* Init all external sources */
for (i = 1; i < NumSources; i++) {
int pri, sense;
+ if (ISR[i] == 0)
+ continue;
+
/* the bootloader may have left it enabled (bad !) */
openpic_disable_irq(i+offset);
@@ -356,7 +383,7 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
/* Enabled, Priority 8 or 9 */
openpic_initirq(i, pri, i+offset, !sense, sense);
/* Processor 0 */
- openpic_mapirq(i, 1<<0);
+ openpic_mapirq(i, 1<<0, 0);
}
/* Init descriptors */
@@ -373,43 +400,17 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
"82c59 cascade", NULL))
printk("Unable to get OpenPIC IRQ 0 for cascade\n");
}
+#ifdef CONFIG_EPIC_SERIAL_MODE
+ openpic_disable_8259_pass_through();
+ openpic_eicr_set_clk(7); /* Slowest value until we know better */
+ openpic_enable_sie();
openpic_set_priority(0);
- openpic_disable_8259_pass_through();
-
- if (ppc_md.progress) ppc_md.progress("openpic exit",0x222);
-}
-
-#ifdef CONFIG_POWER3
-void openpic_setup_ISU(int isu_num, unsigned long addr)
-{
- if (isu_num >= OPENPIC_MAX_ISU)
- return;
- ISU[isu_num] = (OpenPIC_SourcePtr) ioremap(addr, 0x400);
- if (isu_num >= NumISUs)
- NumISUs = isu_num + 1;
-}
-#endif
-
-void find_ISUs(void)
-{
-#ifdef CONFIG_POWER3
- /* Use /interrupt-controller/reg and
- * /interrupt-controller/interrupt-ranges from OF device tree
- * the ISU array is setup in chrp_pci.c in ibm_add_bridges
- * as a result
- * -- tgall
- */
-
- /* basically each ISU is a bus, and this assumes that
- * open_pic_isu_count interrupts per bus are possible
- * ISU == Interrupt Source
- */
- NumSources = NumISUs * 0x10;
-
#else
- /* for non-distributed OpenPIC implementations it's in the IDU -- Cort */
- ISU[0] = (OpenPIC_Source *)OpenPIC->Source;
+ openpic_disable_8259_pass_through();
+ openpic_set_priority(0);
#endif
+
+ if (ppc_md.progress) ppc_md.progress("openpic exit",0x222);
}
static void openpic_reset(void)
@@ -421,6 +422,18 @@ static void openpic_reset(void)
mb();
}
+static void openpic_enable_sie(void)
+{
+ openpic_setfield(&OpenPIC->Global.Global_Configuration1,
+ OPENPIC_EICR_SIE);
+}
+
+static void openpic_eicr_set_clk(u_int clkval)
+{
+ openpic_writefield(&OpenPIC->Global.Global_Configuration1,
+ OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
+}
+
#ifdef notused
static void openpic_enable_8259_pass_through(void)
{
@@ -602,8 +615,8 @@ void __init do_openpic_setup_cpu(void)
* we should make sure we also change the default values of irq_affinity
* in irq.c.
*/
- for (i = 0; i < NumSources ; i++)
- openpic_mapirq(i, openpic_read(&GET_ISU(i).Destination) | msk);
+ for (i = 0; i < NumSources; i++)
+ openpic_mapirq(i, msk, ~0U);
#endif /* CONFIG_IRQ_ALL_CPUS */
openpic_set_priority(0);
@@ -653,26 +666,29 @@ static void __init openpic_maptimer(u_int timer, u_int cpumask)
*/
static void openpic_enable_irq(u_int irq)
{
+ volatile u_int *vpp;
+
check_arg_irq(irq);
- openpic_clearfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
+ vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
+ openpic_clearfield(vpp, OPENPIC_MASK);
/* make sure mask gets to controller before we return to user */
do {
mb(); /* sync is probably useless here */
- } while(openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
- OPENPIC_MASK));
+ } while (openpic_readfield(vpp, OPENPIC_MASK));
}
static void openpic_disable_irq(u_int irq)
{
+ volatile u_int *vpp;
u32 vp;
check_arg_irq(irq);
- openpic_setfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
+ vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
+ openpic_setfield(vpp, OPENPIC_MASK);
/* make sure mask gets to controller before we return to user */
do {
mb(); /* sync is probably useless here */
- vp = openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
- OPENPIC_MASK | OPENPIC_ACTIVITY);
+ vp = openpic_readfield(vpp, OPENPIC_MASK | OPENPIC_ACTIVITY);
} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
}
@@ -709,7 +725,7 @@ void openpic_disable_ipi(u_int irq)
*/
static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
{
- openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
+ openpic_safe_writefield(&ISR[irq]->Vector_Priority,
OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
(pri << OPENPIC_PRIORITY_SHIFT) | vec |
@@ -721,9 +737,13 @@ static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
/*
* Map an interrupt source to one or more CPUs
*/
-static void openpic_mapirq(u_int irq, u_int physmask)
+static void openpic_mapirq(u_int irq, u_int physmask, u_int keepmask)
{
- openpic_write(&GET_ISU(irq).Destination, physmask);
+ if (ISR[irq] == 0)
+ return;
+ if (keepmask != 0)
+ physmask |= openpic_read(&ISR[irq]->Destination) & keepmask;
+ openpic_write(&ISR[irq]->Destination, physmask);
}
#ifdef notused
@@ -734,9 +754,10 @@ static void openpic_mapirq(u_int irq, u_int physmask)
*/
static void openpic_set_sense(u_int irq, int sense)
{
- openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
- OPENPIC_SENSE_LEVEL,
- (sense ? OPENPIC_SENSE_LEVEL : 0));
+ if (ISR[irq] != 0)
+ openpic_safe_writefield(&ISR[irq]->Vector_Priority,
+ OPENPIC_SENSE_LEVEL,
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
}
#endif /* notused */
@@ -757,7 +778,7 @@ static void openpic_end_irq(unsigned int irq_nr)
static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask)
{
- openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask));
+ openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask), 0);
}
#ifdef CONFIG_SMP
@@ -784,9 +805,6 @@ openpic_get_irq(struct pt_regs *regs)
/*
* Clean up needed. -VAL
*/
-#ifndef CONFIG_GEMINI
- extern int i8259_irq(int cpu);
-#endif
int irq = openpic_irq();
/* Management of the cascade should be moved out of here */
@@ -801,7 +819,7 @@ openpic_get_irq(struct pt_regs *regs)
irq = *chrp_int_ack_special;
#ifndef CONFIG_GEMINI
else
- irq = i8259_irq( smp_processor_id() );
+ irq = i8259_poll();
#endif
openpic_eoi();
}
@@ -858,9 +876,11 @@ openpic_sleep_save_intrs(void)
for (i=0; i<OPENPIC_NUM_IPI; i++)
save_ipi_vp[i] = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(i));
for (i=0; i<NumSources; i++) {
- save_irq_src_vp[i] = openpic_read(&OpenPIC->Source[i].Vector_Priority)
+ if (ISR[i] == 0)
+ continue;
+ save_irq_src_vp[i] = openpic_read(&ISR[i]->Vector_Priority)
& ~OPENPIC_ACTIVITY;
- save_irq_src_dest[i] = openpic_read(&OpenPIC->Source[i].Destination);
+ save_irq_src_dest[i] = openpic_read(&ISR[i]->Destination);
}
spin_unlock_irqrestore(&openpic_setup_lock, flags);
}
@@ -876,15 +896,19 @@ openpic_sleep_restore_intrs(void)
openpic_reset();
for (i=0; i<OPENPIC_NUM_IPI; i++)
- openpic_write(&OpenPIC->Global.IPI_Vector_Priority(i), save_ipi_vp[i]);
+ openpic_write(&OpenPIC->Global.IPI_Vector_Priority(i),
+ save_ipi_vp[i]);
for (i=0; i<NumSources; i++) {
- openpic_write(&OpenPIC->Source[i].Vector_Priority, save_irq_src_vp[i]);
- openpic_write(&OpenPIC->Source[i].Destination, save_irq_src_dest[i]);
+ if (ISR[i] == 0)
+ continue;
+ openpic_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
+ openpic_write(&ISR[i]->Destination, save_irq_src_dest[i]);
}
openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset);
openpic_disable_8259_pass_through();
for (i=0; i<NumProcessors; i++)
- openpic_write(&OpenPIC->Processor[i].Current_Task_Priority, save_cpu_task_pri[i]);
+ openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
+ save_cpu_task_pri[i]);
spin_unlock_irqrestore(&openpic_setup_lock, flags);
}
diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h
deleted file mode 100644
index 0e236c0b3848..000000000000
--- a/arch/ppc/kernel/open_pic.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * BK Id: SCCS/s.open_pic.h 1.14 10/11/01 12:09:12 trini
- */
-/*
- * arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
- *
- * Copyright (C) 1997 Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-#ifndef _PPC_KERNEL_OPEN_PIC_H
-#define _PPC_KERNEL_OPEN_PIC_H
-
-#include <linux/config.h>
-
-#define OPENPIC_SIZE 0x40000
-
-/*
- * Non-offset'ed vector numbers
- */
-
-#define OPENPIC_VEC_TIMER 64 /* and up */
-#define OPENPIC_VEC_IPI 72 /* and up */
-#define OPENPIC_VEC_SPURIOUS 127
-
-/* OpenPIC IRQ controller structure */
-extern struct hw_interrupt_type open_pic;
-
-/* OpenPIC IPI controller structure */
-#ifdef CONFIG_SMP
-extern struct hw_interrupt_type open_pic_ipi;
-#endif /* CONFIG_SMP */
-
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-extern void* OpenPIC_Addr;
-
-/* Exported functions */
-extern void openpic_init(int, int, unsigned char *, int);
-extern u_int openpic_irq(void);
-extern void openpic_eoi(void);
-extern void openpic_request_IPIs(void);
-extern void do_openpic_setup_cpu(void);
-extern int openpic_get_irq(struct pt_regs *regs);
-extern void openpic_reset_processor_phys(u_int cpumask);
-extern void openpic_setup_ISU(int isu_num, unsigned long addr);
-extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
-extern void smp_openpic_message_pass(int target, int msg, unsigned long data,
- int wait);
-
-extern inline int openpic_to_irq(int irq)
-{
- /* IRQ 0 usually means 'disabled'.. don't mess with it
- * exceptions to this (sandpoint maybe?)
- * shouldn't use openpic_to_irq
- */
- if (irq != 0){
- return irq += NUM_8259_INTERRUPTS;
- } else {
- return 0;
- }
-}
-/*extern int open_pic_irq_offset;*/
-#endif /* _PPC_KERNEL_OPEN_PIC_H */
diff --git a/arch/ppc/kernel/open_pic_defs.h b/arch/ppc/kernel/open_pic_defs.h
index 56497f9579ac..753461a5e8e7 100644
--- a/arch/ppc/kernel/open_pic_defs.h
+++ b/arch/ppc/kernel/open_pic_defs.h
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.open_pic_defs.h 1.8 08/20/01 22:33:28 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/openpic.h -- OpenPIC definitions
@@ -209,6 +209,14 @@ extern volatile struct OpenPIC *OpenPIC;
#define OPENPIC_CONFIG_BASE_MASK 0x000fffff
/*
+ * Global Configuration Register 1
+ * This is the EICR on EPICs.
+ */
+
+#define OPENPIC_EICR_S_CLK_MASK 0x70000000
+#define OPENPIC_EICR_SIE 0x08000000
+
+ /*
* Vendor Identification Register
*/
diff --git a/arch/ppc/kernel/pci-dma.c b/arch/ppc/kernel/pci-dma.c
index 1a7b56b89e82..2e37b3117585 100644
--- a/arch/ppc/kernel/pci-dma.c
+++ b/arch/ppc/kernel/pci-dma.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.pci-dma.c 1.5 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
@@ -25,7 +25,11 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ ret = consistent_alloc(gfp, size, dma_handle);
+#else
ret = (void *)__get_free_pages(gfp, get_order(size));
+#endif
if (ret != NULL) {
memset(ret, 0, size);
@@ -37,5 +41,9 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
void pci_free_consistent(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ consistent_free(vaddr);
+#else
free_pages((unsigned long)vaddr, get_order(size));
+#endif
}
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 57c4223a482f..77e1de956a6b 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.pci.c 1.35 11/13/01 08:19:57 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Common pmac/prep/chrp pci routines. -- Cort
@@ -19,16 +19,13 @@
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm/sections.h>
#include <asm/pci-bridge.h>
-#include <asm/residual.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
-#include <asm/gg2.h>
#include <asm/uaccess.h>
-#include "pci.h"
-
-#define DEBUG
+#undef DEBUG
#ifdef DEBUG
#define DBG(x...) printk(x)
@@ -42,8 +39,13 @@ unsigned long pci_dram_offset = 0;
void pcibios_make_OF_bus_map(void);
+static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
+static int probe_resource(struct pci_bus *parent, struct resource *pr,
+ struct resource *res, struct resource **conflict);
+static void update_bridge_base(struct pci_bus *bus, int i);
static void pcibios_fixup_resources(struct pci_dev* dev);
static void fixup_broken_pcnet32(struct pci_dev* dev);
+static int reparent_resources(struct resource *parent, struct resource *res);
static void fixup_rev1_53c810(struct pci_dev* dev);
#ifdef CONFIG_ALL_PPC
static void pcibios_fixup_cardbus(struct pci_dev* dev);
@@ -66,7 +68,7 @@ struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
#ifdef CONFIG_ALL_PPC
/* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
- { PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, pcibios_fixup_cardbus },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_ANY_ID, pcibios_fixup_cardbus },
#endif /* CONFIG_ALL_PPC */
{ 0 }
};
@@ -96,7 +98,7 @@ fixup_broken_pcnet32(struct pci_dev* dev)
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
+ struct resource *res, int resource)
{
u32 new, check;
int reg;
@@ -104,6 +106,7 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
unsigned long io_offset;
new = res->start;
+ res->flags &= ~IORESOURCE_UNSET;
if (hose && res->flags & IORESOURCE_IO) {
io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
new -= io_offset;
@@ -128,6 +131,9 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
"%s/%d (%08x != %08x)\n", dev->slot_name, resource,
new, check);
}
+ printk(KERN_INFO "PCI: moved device %s resource %d (%lx) to %x\n",
+ dev->slot_name, resource, res->flags,
+ new & ~PCI_REGION_FLAG_MASK);
}
static void
@@ -143,13 +149,14 @@ pcibios_fixup_resources(struct pci_dev *dev)
}
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
struct resource *res = dev->resource + i;
- if (!res->start || !res->flags)
+ if (!res->flags)
continue;
- if (res->end == 0xffffffff) {
+ if (!res->start || res->end == 0xffffffff) {
DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
dev->slot_name, i, res->start, res->end);
res->end -= res->start;
res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
continue;
}
offset = 0;
@@ -169,24 +176,35 @@ pcibios_fixup_resources(struct pci_dev *dev)
#endif
}
}
+
+ /* Call machine specific resource fixup */
+ if (ppc_md.pcibios_fixup_resources)
+ ppc_md.pcibios_fixup_resources(dev);
}
#ifdef CONFIG_ALL_PPC
static void
pcibios_fixup_cardbus(struct pci_dev* dev)
{
+ if (_machine != _MACH_Pmac)
+ return;
/*
* Fix the interrupt routing on the TI1211 chip on the 1999
* G3 powerbook, which doesn't get initialized properly by OF.
+ * Same problem with the 1410 of the new titanium pbook which
+ * has the same register.
*/
if (dev->vendor == PCI_VENDOR_ID_TI
- && dev->device == PCI_DEVICE_ID_TI_1211) {
- u32 val;
+ && (dev->device == PCI_DEVICE_ID_TI_1211 ||
+ dev->device == PCI_DEVICE_ID_TI_1410)) {
+ u8 val;
/* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
signal out the MFUNC0 pin */
- if (pci_read_config_dword(dev, 0x8c, &val) == 0
- && val == 0)
- pci_write_config_dword(dev, 0x8c, 2);
+ if (pci_read_config_byte(dev, 0x8c, &val) == 0)
+ pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2);
+ /* Disable ISA interrupt mode */
+ if (pci_read_config_byte(dev, 0x92, &val) == 0)
+ pci_write_config_byte(dev, 0x92, val & ~0x06);
}
}
#endif /* CONFIG_ALL_PPC */
@@ -271,25 +289,245 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
for (ln = bus_list->next; ln != bus_list; ln=ln->next) {
bus = pci_bus_b(ln);
for (i = 0; i < 4; ++i) {
- if ((res = bus->resource[i]) == NULL || !res->flags)
+ if ((res = bus->resource[i]) == NULL || !res->flags
+ || res->start > res->end)
continue;
if (bus->parent == NULL)
pr = (res->flags & IORESOURCE_IO)?
&ioport_resource: &iomem_resource;
- else
+ else {
pr = pci_find_parent_resource(bus->self, res);
+ if (pr == res) {
+ /* this happens when the generic PCI
+ * code (wrongly) decides that this
+ * bridge is transparent -- paulus
+ */
+ continue;
+ }
+ }
- if (pr && request_resource(pr, res) == 0)
- continue;
+ DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n",
+ res->start, res->end, res->flags, pr);
+ if (pr) {
+ if (request_resource(pr, res) == 0)
+ continue;
+ /*
+ * Must be a conflict with an existing entry.
+ * Move that entry (or entries) under the
+ * bridge resource and try again.
+ */
+ if (reparent_resources(pr, res) == 0)
+ continue;
+ }
printk(KERN_ERR "PCI: Cannot allocate resource region "
"%d of PCI bridge %d\n", i, bus->number);
- DBG("PCI: resource is %lx..%lx (%lx), parent %p\n",
- res->start, res->end, res->flags, pr);
+ if (pci_relocate_bridge_resource(bus, i))
+ bus->resource[i] = NULL;
}
pcibios_allocate_bus_resources(&bus->children);
}
}
+/*
+ * Reparent resource children of pr that conflict with res
+ * under res, and make res replace those children.
+ */
+static int __init
+reparent_resources(struct resource *parent, struct resource *res)
+{
+ struct resource *p, **pp;
+ struct resource **firstpp = NULL;
+
+ for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+ if (p->end < res->start)
+ continue;
+ if (res->end < p->start)
+ break;
+ if (p->start < res->start || p->end > res->end)
+ return -1; /* not completely contained */
+ if (firstpp == NULL)
+ firstpp = pp;
+ }
+ if (firstpp == NULL)
+ return -1; /* didn't find any conflicting entries? */
+ res->parent = parent;
+ res->child = *firstpp;
+ res->sibling = *pp;
+ *firstpp = res;
+ *pp = NULL;
+ for (p = res->child; p != NULL; p = p->sibling) {
+ p->parent = res;
+ DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n",
+ p->name, p->start, p->end, res->name);
+ }
+ return 0;
+}
+
+/*
+ * A bridge has been allocated a range which is outside the range
+ * of its parent bridge, so it needs to be moved.
+ */
+static int __init
+pci_relocate_bridge_resource(struct pci_bus *bus, int i)
+{
+ struct resource *res, *pr, *conflict;
+ unsigned long try, size;
+ int j;
+ struct pci_bus *parent = bus->parent;
+
+ if (parent == NULL) {
+ /* shouldn't ever happen */
+ printk(KERN_ERR "PCI: can't move host bridge resource\n");
+ return -1;
+ }
+ res = bus->resource[i];
+ pr = NULL;
+ for (j = 0; j < 4; j++) {
+ struct resource *r = parent->resource[j];
+ if (!r)
+ continue;
+ if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
+ continue;
+ if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
+ pr = r;
+ break;
+ }
+ if (res->flags & IORESOURCE_PREFETCH)
+ pr = r;
+ }
+ if (pr == NULL)
+ return -1;
+ size = res->end - res->start;
+ if (pr->start > pr->end || size > pr->end - pr->start)
+ return -1;
+ try = pr->end;
+ for (;;) {
+ res->start = try - size;
+ res->end = try;
+ if (probe_resource(bus->parent, pr, res, &conflict) == 0)
+ break;
+ if (conflict->start <= pr->start + size)
+ return -1;
+ try = conflict->start - 1;
+ }
+ if (request_resource(pr, res)) {
+ DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n",
+ res->start, res->end);
+ return -1; /* "can't happen" */
+ }
+ update_bridge_base(bus, i);
+ printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n",
+ bus->number, i, res->start, res->end);
+ return 0;
+}
+
+static int __init
+probe_resource(struct pci_bus *parent, struct resource *pr,
+ struct resource *res, struct resource **conflict)
+{
+ struct pci_bus *bus;
+ struct pci_dev *dev;
+ struct resource *r;
+ struct list_head *ln;
+ int i;
+
+ for (r = pr->child; r != NULL; r = r->sibling) {
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ for (ln = parent->children.next; ln != &parent->children;
+ ln = ln->next) {
+ bus = pci_bus_b(ln);
+ for (i = 0; i < 4; ++i) {
+ if ((r = bus->resource[i]) == NULL)
+ continue;
+ if (!r->flags || r->start > r->end || r == res)
+ continue;
+ if (pci_find_parent_resource(bus->self, r) != pr)
+ continue;
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ }
+ for (ln = parent->devices.next; ln != &parent->devices; ln=ln->next) {
+ dev = pci_dev_b(ln);
+ for (i = 0; i < 6; ++i) {
+ r = &dev->resource[i];
+ if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ continue;
+ if (pci_find_parent_resource(bus->self, r) != pr)
+ continue;
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void __init
+update_bridge_base(struct pci_bus *bus, int i)
+{
+ struct resource *res = bus->resource[i];
+ u8 io_base_lo, io_limit_lo;
+ u16 mem_base, mem_limit;
+ u16 cmd;
+ unsigned long start, end, off;
+ struct pci_dev *dev = bus->self;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (!hose) {
+ printk("update_bridge_base: no hose?\n");
+ return;
+ }
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(dev, PCI_COMMAND,
+ cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
+ if (res->flags & IORESOURCE_IO) {
+ off = (unsigned long) hose->io_base_virt - isa_io_base;
+ start = res->start - off;
+ end = res->end - off;
+ io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;
+ io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;
+ if (end > 0xffff) {
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+ start >> 16);
+ pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+ end >> 16);
+ io_base_lo |= PCI_IO_RANGE_TYPE_32;
+ } else
+ io_base_lo |= PCI_IO_RANGE_TYPE_16;
+ pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);
+ pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);
+
+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == IORESOURCE_MEM) {
+ off = hose->pci_mem_offset;
+ mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK;
+ mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK;
+ pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base);
+ pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit);
+
+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {
+ off = hose->pci_mem_offset;
+ mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK;
+ mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK;
+ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base);
+ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit);
+
+ } else {
+ DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n",
+ dev->slot_name, i, res->flags);
+ }
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+}
+
static inline void alloc_resource(struct pci_dev *dev, int idx)
{
struct resource *pr, *r = &dev->resource[idx];
@@ -304,6 +542,7 @@ static inline void alloc_resource(struct pci_dev *dev, int idx)
DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n",
pr, pr->start, pr->end, pr->flags);
/* We'll assign a new address later */
+ r->flags |= IORESOURCE_UNSET;
r->end -= r->start;
r->start = 0;
}
@@ -323,8 +562,8 @@ pcibios_allocate_resources(int pass)
r = &dev->resource[idx];
if (r->parent) /* Already allocated */
continue;
- if (!r->start) /* Not assigned at all */
- continue;
+ if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ continue; /* Not assigned at all */
if (r->flags & IORESOURCE_IO)
disabled = !(command & PCI_COMMAND_IO);
else
@@ -370,7 +609,7 @@ pcibios_assign_resources(void)
* or because we have decided the old address was
* unusable for some reason.
*/
- if (!r->start && r->end &&
+ if ((r->flags & IORESOURCE_UNSET) && r->end &&
(!ppc_md.pcibios_enable_device_hook ||
!ppc_md.pcibios_enable_device_hook(dev, 1)))
pci_assign_resource(dev, idx);
@@ -396,9 +635,9 @@ pcibios_enable_resources(struct pci_dev *dev)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
- for(idx=0; idx<6; idx++) {
+ for (idx=0; idx<6; idx++) {
r = &dev->resource[idx];
- if (!r->start && r->end) {
+ if (r->flags & IORESOURCE_UNSET) {
printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
return -EINVAL;
}
@@ -438,7 +677,7 @@ pcibios_alloc_controller(void)
/*
* Functions below are used on OpenFirmware machines.
*/
-static void
+static void __openfirmware
make_one_node_map(struct device_node* node, u8 pci_bus)
{
int *bus_range;
@@ -449,7 +688,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
bus_range = (int *) get_property(node, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s\n",
- node->full_name);
+ node->full_name);
return;
}
pci_to_OF_bus_map[pci_bus] = bus_range[0];
@@ -472,7 +711,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
}
}
-void
+void __openfirmware
pcibios_make_OF_bus_map(void)
{
int i;
@@ -512,17 +751,17 @@ pcibios_make_OF_bus_map(void)
#endif
}
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
+
+static struct device_node* __openfirmware
+scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
{
struct device_node* sub_node;
for (; node != 0;node = node->sibling) {
- unsigned int *class_code, *reg;
+ unsigned int *class_code;
- reg = (unsigned int *) get_property(node, "reg", 0);
- if (reg && ((reg[0] >> 8) & 0xff) == dev_fn
- && ((reg[0] >> 16) & 0xff) == bus)
+ if (filter(node, data))
return node;
/* For PCI<->PCI bridges or CardBus bridges, we go down
@@ -535,13 +774,34 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
strcmp(node->name, "multifunc-device"))
continue;
- sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn);
+ sub_node = scan_OF_pci_childs(node->child, filter, data);
if (sub_node)
return sub_node;
}
return NULL;
}
+static int
+scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+{
+ unsigned int *reg;
+ u8* fdata = (u8*)data;
+
+ reg = (unsigned int *) get_property(node, "reg", 0);
+ if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
+ && ((reg[0] >> 16) & 0xff) == fdata[0])
+ return 1;
+ return 0;
+}
+
+static struct device_node* __openfirmware
+scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+{
+ u8 filter_data[2] = {bus, dev_fn};
+
+ return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+}
+
/*
* Scans the OF tree for a device node matching a PCI device
*/
@@ -598,6 +858,12 @@ pci_find_hose_for_OF_device(struct device_node* node)
return NULL;
}
+static int __openfirmware
+find_OF_pci_device_filter(struct device_node* node, void* data)
+{
+ return ((void *)node == data);
+}
+
/*
* Returns the PCI device matching a given OF node
*/
@@ -605,21 +871,40 @@ int
pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
{
unsigned int *reg;
- int i;
+ struct pci_controller* hose;
+ struct pci_dev* dev;
if (!have_of)
return -ENODEV;
+ /* Make sure it's really a PCI device */
+ hose = pci_find_hose_for_OF_device(node);
+ if (!hose || !hose->arch_data)
+ return -ENODEV;
+ if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
+ find_OF_pci_device_filter, (void *)node))
+ return -ENODEV;
reg = (unsigned int *) get_property(node, "reg", 0);
if (!reg)
return -ENODEV;
*bus = (reg[0] >> 16) & 0xff;
- for (i=0; pci_to_OF_bus_map && i<pci_bus_count; i++)
- if (pci_to_OF_bus_map[i] == *bus) {
- *bus = i;
- break;
- }
*devfn = ((reg[0] >> 8) & 0xff);
- return 0;
+
+ /* Ok, here we need some tweak. If we have already renumbered
+ * all busses, we can't rely on the OF bus number any more.
+ * the pci_to_OF_bus_map is not enough as several PCI busses
+ * may match the same OF bus number.
+ */
+ if (!pci_to_OF_bus_map)
+ return 0;
+ pci_for_each_dev(dev) {
+ if (pci_to_OF_bus_map[dev->bus->number] != *bus)
+ continue;
+ if (dev->devfn != *devfn)
+ continue;
+ *bus = dev->bus->number;
+ return 0;
+ }
+ return -ENODEV;
}
void __init
@@ -709,6 +994,24 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
ranges += np;
}
}
+
+/* We create the "pci-OF-bus-map" property now so it appears in the
+ * /proc device tree
+ */
+void __init
+pci_create_OF_bus_map(void)
+{
+ struct property* of_prop;
+
+ of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
+ if (of_prop && find_path_device("/")) {
+ memset(of_prop, -1, sizeof(struct property) + 256);
+ of_prop->name = "pci-OF-bus-map";
+ of_prop->length = 256;
+ of_prop->value = (unsigned char *)&of_prop[1];
+ prom_add_property(find_path_device("/"), of_prop);
+ }
+}
#endif /* CONFIG_ALL_PPC */
void __init
@@ -739,6 +1042,10 @@ pcibios_init(void)
if (pci_assign_all_busses && have_of)
pcibios_make_OF_bus_map();
+ /* Do machine dependent PCI interrupt routing */
+ if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)
+ pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);
+
/* Call machine dependant fixup */
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
@@ -754,10 +1061,23 @@ pcibios_init(void)
ppc_md.pcibios_after_init();
}
-int __init
-pcibios_assign_all_busses(void)
+unsigned char __init
+common_swizzle(struct pci_dev *dev, unsigned char *pinp)
{
- return pci_assign_all_busses;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (dev->bus->number != hose->first_busno) {
+ u8 pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
+
+ /* The slot is the idsel of the last bridge. */
+ }
+ return PCI_SLOT(dev->devfn);
}
void __init
@@ -863,7 +1183,7 @@ int pcibios_enable_device(struct pci_dev *dev)
old_cmd = cmd;
for (idx=0; idx<6; idx++) {
r = &dev->resource[idx];
- if (!r->start && r->end) {
+ if (r->flags & IORESOURCE_UNSET) {
printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
return -EINVAL;
}
@@ -1152,6 +1472,19 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
return result;
}
+void __init
+pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
+ int flags, char *name)
+{
+ res->start = start;
+ res->end = end;
+ res->flags = flags;
+ res->name = name;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+}
+
/*
* Null PCI config access functions, for the case when we can't
* find a hose.
diff --git a/arch/ppc/kernel/pci.h b/arch/ppc/kernel/pci.h
deleted file mode 100644
index 61b2e187c331..000000000000
--- a/arch/ppc/kernel/pci.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * BK Id: SCCS/s.pci.h 1.10 08/08/01 16:35:43 paulus
- */
-
-#ifndef __PPC_KERNEL_PCI_H__
-#define __PPC_KERNEL_PCI_H__
-
-/* Configure those in your xxx_init() or xxx_setup_arch() function */
-extern unsigned long isa_io_base;
-extern unsigned long isa_mem_base;
-extern unsigned long pci_dram_offset;
-
-/* Set this to 1 if you want the kernel to re-assign all PCI
- * bus numbers
- */
-extern int pci_assign_all_busses;
-
-
-extern struct pci_controller* pcibios_alloc_controller(void);
-extern struct pci_controller* pci_find_hose_for_OF_device(
- struct device_node* node);
-
-extern void setup_indirect_pci(struct pci_controller* hose,
- u32 cfg_addr, u32 cfg_data);
-extern void setup_grackle(struct pci_controller *hose);
-
-#endif /* __PPC_KERNEL_PCI_H__ */
diff --git a/arch/ppc/kernel/pci_auto.c b/arch/ppc/kernel/pci_auto.c
new file mode 100644
index 000000000000..1f716f296802
--- /dev/null
+++ b/arch/ppc/kernel/pci_auto.c
@@ -0,0 +1,519 @@
+/*
+ * arch/ppc/kernel/pci_auto.c
+ *
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+/*
+ * The CardBus support is very preliminary. Preallocating space is
+ * the way to go but will require some change in card services to
+ * make it useful. Eventually this will ensure that we can put
+ * multiple CB bridges behind multiple P2P bridges. For now, at
+ * least it ensures that we place the CB bridge BAR and assigned
+ * initial bus numbers. I definitely need to do something about
+ * the lack of 16-bit I/O support. -MDP
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/pci-bridge.h>
+
+#define PCIAUTO_IDE_MODE_MASK 0x05
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+static int pciauto_upper_iospc;
+static int pciauto_upper_memspc;
+
+void __init pciauto_setup_bars(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int bar_limit)
+{
+ int bar_response, bar_size, bar_value;
+ int bar, addr_mask;
+ int * upper_limit;
+ int found_mem64 = 0;
+
+ DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
+ current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
+
+ for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
+ /* Tickle the BAR and get the response */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ 0xffffffff);
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ &bar_response);
+
+ /* If BAR is not implemented go to the next BAR */
+ if (!bar_response)
+ continue;
+
+ /* Check the BAR type and set our address mask */
+ if (bar_response & PCI_BASE_ADDRESS_SPACE) {
+ addr_mask = PCI_BASE_ADDRESS_IO_MASK;
+ upper_limit = &pciauto_upper_iospc;
+ DBG("PCI Autoconfig: BAR 0x%x, I/O, ", bar);
+ } else {
+ if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ found_mem64 = 1;
+
+ addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
+ upper_limit = &pciauto_upper_memspc;
+ DBG("PCI Autoconfig: BAR 0x%x, Mem ", bar);
+ }
+
+ /* Calculate requested size */
+ bar_size = ~(bar_response & addr_mask) + 1;
+
+ /* Allocate a base address */
+ bar_value = (*upper_limit - bar_size) & ~(bar_size - 1);
+
+ /* Write it out and update our limit */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ bar_value);
+
+ *upper_limit = bar_value;
+
+ /*
+ * If we are a 64-bit decoder then increment to the
+ * upper 32 bits of the bar and force it to locate
+ * in the lower 4GB of memory.
+ */
+ if (found_mem64) {
+ bar += 4;
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ bar,
+ 0x00000000);
+ found_mem64 = 0;
+ }
+
+ DBG("size=0x%x, address=0x%x\n",
+ bar_size, bar_value);
+ }
+
+}
+
+void __init pciauto_prescan_setup_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ /* Configure bus number registers */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PRIMARY_BUS,
+ current_bus);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SECONDARY_BUS,
+ sub_bus + 1);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ 0xff);
+
+ /* Round memory allocator to 1MB boundary */
+ pciauto_upper_memspc &= ~(0x100000 - 1);
+ *memsave = pciauto_upper_memspc;
+
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_upper_iospc &= ~(0x1000 - 1);
+ *iosave = pciauto_upper_iospc;
+
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_MEMORY_LIMIT,
+ ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_LIMIT,
+ ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_LIMIT_UPPER16,
+ ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
+
+ /* Zero upper 32 bits of prefetchable base/limit */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_BASE_UPPER32,
+ 0);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_LIMIT_UPPER32,
+ 0);
+}
+
+void __init pciauto_postscan_setup_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ int cmdstat;
+
+ /* Configure bus number registers */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ sub_bus);
+
+ /*
+ * Round memory allocator to 1MB boundary.
+ * If no space used, allocate minimum.
+ */
+ pciauto_upper_memspc &= ~(0x100000 - 1);
+ if (*memsave == pciauto_upper_memspc)
+ pciauto_upper_memspc -= 0x00100000;
+
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_MEMORY_BASE,
+ pciauto_upper_memspc >> 16);
+
+ /* Allocate 1MB for pre-fretch */
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_MEMORY_LIMIT,
+ ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+
+ pciauto_upper_memspc -= 0x100000;
+
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PREF_MEMORY_BASE,
+ pciauto_upper_memspc >> 16);
+
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_upper_iospc &= ~(0x1000 - 1);
+ if (*iosave == pciauto_upper_iospc)
+ pciauto_upper_iospc -= 0x1000;
+
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_BASE,
+ (pciauto_upper_iospc & 0x0000f000) >> 8);
+ early_write_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_IO_BASE_UPPER16,
+ pciauto_upper_iospc >> 16);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ &cmdstat);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+}
+
+void __init pciauto_prescan_setup_cardbus_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ /* Configure bus number registers */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_PRIMARY_BUS,
+ current_bus);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SECONDARY_BUS,
+ sub_bus + 1);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ 0xff);
+
+ /* Round memory allocator to 4KB boundary */
+ pciauto_upper_memspc &= ~(0x1000 - 1);
+ *memsave = pciauto_upper_memspc;
+
+ /* Round I/O allocator to 4 byte boundary */
+ pciauto_upper_iospc &= ~(0x4 - 1);
+ *iosave = pciauto_upper_iospc;
+
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x20,
+ pciauto_upper_memspc - 1);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x30,
+ pciauto_upper_iospc - 1);
+}
+
+void __init pciauto_postscan_setup_cardbus_bridge(struct pci_controller *hose,
+ int current_bus,
+ int pci_devfn,
+ int sub_bus,
+ int *iosave,
+ int *memsave)
+{
+ int cmdstat;
+
+ /*
+ * Configure subordinate bus number. The PCI subsystem
+ * bus scan will renumber buses (reserving three additional
+ * for this PCI<->CardBus bridge for the case where a CardBus
+ * adapter contains a P2P or CB2CB bridge.
+ */
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_SUBORDINATE_BUS,
+ sub_bus);
+
+ /*
+ * Reserve an additional 4MB for mem space and 16KB for
+ * I/O space. This should cover any additional space
+ * requirement of unusual CardBus devices with
+ * additional bridges that can consume more address space.
+ *
+ * Although pcmcia-cs currently will reprogram bridge
+ * windows, the goal is to add an option to leave them
+ * alone and use the bridge window ranges as the regions
+ * that are searched for free resources upon hot-insertion
+ * of a device. This will allow a PCI<->CardBus bridge
+ * configured by this routine to happily live behind a
+ * P2P bridge in a system.
+ */
+ pciauto_upper_memspc -= 0x00400000;
+ pciauto_upper_iospc -= 0x00004000;
+
+ /* Round memory allocator to 4KB boundary */
+ pciauto_upper_memspc &= ~(0x1000 - 1);
+
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x1c,
+ pciauto_upper_memspc);
+
+ /* Round I/O allocator to 4 byte boundary */
+ pciauto_upper_iospc &= ~(0x4 - 1);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ 0x2c,
+ pciauto_upper_iospc);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ &cmdstat);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+}
+
+int __init pciauto_bus_scan(struct pci_controller *hose, int current_bus)
+{
+ int sub_bus, pci_devfn, pci_class, cmdstat, found_multi = 0;
+ unsigned short vid;
+ unsigned char header_type;
+
+ /*
+ * Fetch our I/O and memory space upper boundaries used
+ * to allocated base addresses on this hose.
+ */
+ if (current_bus == hose->first_busno) {
+ pciauto_upper_iospc = hose->io_space.end + 1;
+ pciauto_upper_memspc = hose->mem_space.end + 1;
+ }
+
+ sub_bus = current_bus;
+
+ for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+ /* Skip our host bridge */
+ if ( (current_bus == hose->first_busno) && (pci_devfn == 0) )
+ continue;
+
+ if (PCI_FUNC(pci_devfn) && !found_multi)
+ continue;
+
+ /* If config space read fails from this device, move on */
+ if (early_read_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_HEADER_TYPE,
+ &header_type))
+ continue;
+
+ if (!PCI_FUNC(pci_devfn))
+ found_multi = header_type & 0x80;
+
+ early_read_config_word(hose,
+ current_bus,
+ pci_devfn,
+ PCI_VENDOR_ID,
+ &vid);
+
+ if (vid != 0xffff) {
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_CLASS_REVISION, &pci_class);
+ if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI ) {
+ int iosave, memsave;
+
+ DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn));
+ /* Allocate PCI I/O and/or memory space */
+ pciauto_setup_bars(hose,
+ current_bus,
+ pci_devfn,
+ PCI_BASE_ADDRESS_1);
+
+ pciauto_prescan_setup_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ sub_bus = pciauto_bus_scan(hose, sub_bus+1);
+ pciauto_postscan_setup_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
+ int iosave, memsave;
+
+ DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
+ /* Place CardBus Socket/ExCA registers */
+ pciauto_setup_bars(hose,
+ current_bus,
+ pci_devfn,
+ PCI_BASE_ADDRESS_0);
+
+ pciauto_prescan_setup_cardbus_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ sub_bus = pciauto_bus_scan(hose, sub_bus+1);
+ pciauto_postscan_setup_cardbus_bridge(hose,
+ current_bus,
+ pci_devfn,
+ sub_bus,
+ &iosave,
+ &memsave);
+ } else {
+ if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
+ unsigned char prg_iface;
+
+ early_read_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_CLASS_PROG,
+ &prg_iface);
+ if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
+ DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n");
+ continue;
+ }
+ }
+ /* Allocate PCI I/O and/or memory space */
+ pciauto_setup_bars(hose,
+ current_bus,
+ pci_devfn,
+ PCI_BASE_ADDRESS_5);
+
+ /*
+ * Enable some standard settings
+ */
+ early_read_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ &cmdstat);
+ early_write_config_dword(hose,
+ current_bus,
+ pci_devfn,
+ PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ early_write_config_byte(hose,
+ current_bus,
+ pci_devfn,
+ PCI_LATENCY_TIMER,
+ 0x80);
+ }
+ }
+ }
+ return sub_bus;
+}
diff --git a/arch/ppc/kernel/pmac_backlight.c b/arch/ppc/kernel/pmac_backlight.c
deleted file mode 100644
index 63c8a8646e58..000000000000
--- a/arch/ppc/kernel/pmac_backlight.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_backlight.c 1.8 09/08/01 15:47:42 paulus
- */
-/*
- * Miscellaneous procedures for dealing with the PowerMac hardware.
- * Contains support for the backlight.
- *
- * Copyright (C) 2000 Benjamin Herrenschmidt
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/reboot.h>
-#include <linux/nvram.h>
-#include <asm/sections.h>
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-#include <asm/backlight.h>
-
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-static struct backlight_controller *backlighter = NULL;
-static void* backlighter_data = NULL;
-static int backlight_autosave = 0;
-static int backlight_level = BACKLIGHT_MAX;
-static int backlight_enabled = 1;
-
-void __pmac
-register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
-{
- struct device_node* bk_node;
- char *prop;
- int valid = 0;
-
- bk_node = find_devices("backlight");
-
-#ifdef CONFIG_ADB_PMU
- /* Special case for the old PowerBook since I can't test on it */
- backlight_autosave = machine_is_compatible("AAPL,3400/2400")
- || machine_is_compatible("AAPL,3500");
- if ((backlight_autosave
- || machine_is_compatible("AAPL,PowerBook1998")
- || machine_is_compatible("PowerBook1,1"))
- && !strcmp(type, "pmu"))
- valid = 1;
-#endif
- if (bk_node) {
- prop = get_property(bk_node, "backlight-control", NULL);
- if (prop && !strncmp(prop, type, strlen(type)))
- valid = 1;
- }
- if (!valid)
- return;
- backlighter = ctrler;
- backlighter_data = data;
-
- if (bk_node && !backlight_autosave)
- prop = get_property(bk_node, "bklt", NULL);
- else
- prop = NULL;
- if (prop) {
- backlight_level = ((*prop)+1) >> 1;
- if (backlight_level > BACKLIGHT_MAX)
- backlight_level = BACKLIGHT_MAX;
- }
-
-#ifdef CONFIG_ADB_PMU
- if (backlight_autosave) {
- struct adb_request req;
- pmu_request(&req, NULL, 2, 0xd9, 0);
- while (!req.complete)
- pmu_poll();
- backlight_level = req.reply[1] >> 4;
- }
-#endif
- if (!backlighter->set_enable(1, backlight_level, data))
- backlight_enabled = 1;
-
- printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n",
- type, backlight_level);
-}
-
-void __pmac
-unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
-{
- /* We keep the current backlight level (for now) */
- if (ctrler == backlighter && data == backlighter_data)
- backlighter = NULL;
-}
-
-int __pmac
-set_backlight_enable(int enable)
-{
- int rc;
-
- if (!backlighter)
- return -ENODEV;
- rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
- if (!rc)
- backlight_enabled = enable;
- return rc;
-}
-
-int __pmac
-get_backlight_enable(void)
-{
- if (!backlighter)
- return -ENODEV;
- return backlight_enabled;
-}
-
-int __pmac
-set_backlight_level(int level)
-{
- int rc = 0;
-
- if (!backlighter)
- return -ENODEV;
- if (level < BACKLIGHT_MIN)
- level = BACKLIGHT_OFF;
- if (level > BACKLIGHT_MAX)
- level = BACKLIGHT_MAX;
- if (backlight_enabled)
- rc = backlighter->set_level(level, backlighter_data);
- if (!rc)
- backlight_level = level;
- if (!rc && !backlight_autosave) {
- level <<=1;
- if (level & 0x10)
- level |= 0x01;
- // -- todo: save to property "bklt"
- }
- return rc;
-}
-
-int __pmac
-get_backlight_level(void)
-{
- if (!backlighter)
- return -ENODEV;
- return backlight_level;
-}
diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c
deleted file mode 100644
index 54c83ef97450..000000000000
--- a/arch/ppc/kernel/pmac_nvram.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_nvram.c 1.15 09/08/01 15:47:42 paulus
- */
-/*
- * Miscellaneous procedures for dealing with the PowerMac hardware.
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/nvram.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-#undef DEBUG
-
-#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
-
-#define CORE99_SIGNATURE 0x5a
-#define CORE99_ADLER_START 0x14
-
-/* Core99 nvram is a flash */
-#define CORE99_FLASH_STATUS_DONE 0x80
-#define CORE99_FLASH_STATUS_ERR 0x38
-#define CORE99_FLASH_CMD_ERASE_CONFIRM 0xd0
-#define CORE99_FLASH_CMD_ERASE_SETUP 0x20
-#define CORE99_FLASH_CMD_RESET 0xff
-#define CORE99_FLASH_CMD_WRITE_SETUP 0x40
-
-/* CHRP NVRAM header */
-struct chrp_header {
- u8 signature;
- u8 cksum;
- u16 len;
- char name[12];
- u8 data[0];
-};
-
-struct core99_header {
- struct chrp_header hdr;
- u32 adler;
- u32 generation;
- u32 reserved[2];
-};
-
-/*
- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
- */
-static int nvram_naddrs;
-static volatile unsigned char *nvram_addr;
-static volatile unsigned char *nvram_data;
-static int nvram_mult, is_core_99;
-static int core99_bank = 0;
-static int nvram_partitions[3];
-
-/* FIXME: kmalloc fails to allocate the image now that I had to move it
- * before time_init(). For now, I allocate a static buffer here
- * but it's a waste of space on all but core99 machines
- */
-#if 0
-static char* nvram_image;
-#else
-static char nvram_image[NVRAM_SIZE] __pmacdata;
-#endif
-
-extern int pmac_newworld;
-
-static u8 __openfirmware
-chrp_checksum(struct chrp_header* hdr)
-{
- u8 *ptr;
- u16 sum = hdr->signature;
- for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
- sum += *ptr;
- while (sum > 0xFF)
- sum = (sum & 0xFF) + (sum>>8);
- return sum;
-}
-
-static u32 __pmac
-core99_calc_adler(u8 *buffer)
-{
- int cnt;
- u32 low, high;
-
- buffer += CORE99_ADLER_START;
- low = 1;
- high = 0;
- for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
- if ((cnt % 5000) == 0) {
- high %= 65521UL;
- high %= 65521UL;
- }
- low += buffer[cnt];
- high += low;
- }
- low %= 65521UL;
- high %= 65521UL;
-
- return (high << 16) | low;
-}
-
-static u32 __pmac
-core99_check(u8* datas)
-{
- struct core99_header* hdr99 = (struct core99_header*)datas;
-
- if (hdr99->hdr.signature != CORE99_SIGNATURE) {
-#ifdef DEBUG
- printk("Invalid signature\n");
-#endif
- return 0;
- }
- if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
-#ifdef DEBUG
- printk("Invalid checksum\n");
-#endif
- return 0;
- }
- if (hdr99->adler != core99_calc_adler(datas)) {
-#ifdef DEBUG
- printk("Invalid adler\n");
-#endif
- return 0;
- }
- return hdr99->generation;
-}
-
-static int __pmac
-core99_erase_bank(int bank)
-{
- int stat, i;
-
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-
- out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
- out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
- do { stat = in_8(base); }
- while(!(stat & CORE99_FLASH_STATUS_DONE));
- out_8(base, CORE99_FLASH_CMD_RESET);
- if (stat & CORE99_FLASH_STATUS_ERR) {
- printk("nvram: flash error 0x%02x on erase !\n", stat);
- return -ENXIO;
- }
- for (i=0; i<NVRAM_SIZE; i++)
- if (base[i] != 0xff) {
- printk("nvram: flash erase failed !\n");
- return -ENXIO;
- }
- return 0;
-}
-
-static int __pmac
-core99_write_bank(int bank, u8* datas)
-{
- int i, stat = 0;
-
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-
- for (i=0; i<NVRAM_SIZE; i++) {
- out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
- out_8(base+i, datas[i]);
- do { stat = in_8(base); }
- while(!(stat & CORE99_FLASH_STATUS_DONE));
- if (stat & CORE99_FLASH_STATUS_ERR)
- break;
- }
- out_8(base, CORE99_FLASH_CMD_RESET);
- if (stat & CORE99_FLASH_STATUS_ERR) {
- printk("nvram: flash error 0x%02x on write !\n", stat);
- return -ENXIO;
- }
- for (i=0; i<NVRAM_SIZE; i++)
- if (base[i] != datas[i]) {
- printk("nvram: flash write failed !\n");
- return -ENXIO;
- }
- return 0;
-}
-
-static void __init
-lookup_partitions(void)
-{
- u8 buffer[17];
- int i, offset;
- struct chrp_header* hdr;
-
- if (pmac_newworld) {
- nvram_partitions[pmac_nvram_OF] = -1;
- nvram_partitions[pmac_nvram_XPRAM] = -1;
- nvram_partitions[pmac_nvram_NR] = -1;
- hdr = (struct chrp_header *)buffer;
-
- offset = 0;
- buffer[16] = 0;
- do {
- for (i=0;i<16;i++)
- buffer[i] = nvram_read_byte(offset+i);
- if (!strcmp(hdr->name, "common"))
- nvram_partitions[pmac_nvram_OF] = offset + 0x10;
- if (!strcmp(hdr->name, "APL,MacOS75")) {
- nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
- nvram_partitions[pmac_nvram_NR] = offset + 0x110;
- }
- offset += (hdr->len * 0x10);
- } while(offset < NVRAM_SIZE);
- } else {
- nvram_partitions[pmac_nvram_OF] = 0x1800;
- nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
- nvram_partitions[pmac_nvram_NR] = 0x1400;
- }
-#ifdef DEBUG
- printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
- printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
- printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
-#endif
-}
-
-void __init
-pmac_nvram_init(void)
-{
- struct device_node *dp;
-
- nvram_naddrs = 0;
-
- dp = find_devices("nvram");
- if (dp == NULL) {
- printk(KERN_ERR "Can't find NVRAM device\n");
- return;
- }
- nvram_naddrs = dp->n_addrs;
- is_core_99 = device_is_compatible(dp, "nvram,flash");
- if (is_core_99) {
- int i;
- u32 gen_bank0, gen_bank1;
-
- if (nvram_naddrs < 1) {
- printk(KERN_ERR "nvram: no address\n");
- return;
- }
-#if 0
- nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
- if (!nvram_image) {
- printk(KERN_ERR "nvram: can't allocate image\n");
- return;
- }
-#endif
- nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
-#ifdef DEBUG
- printk("nvram: Checking bank 0...\n");
-#endif
- gen_bank0 = core99_check((u8 *)nvram_data);
- gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
- core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
-#ifdef DEBUG
- printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
- printk("nvram: Active bank is: %d\n", core99_bank);
-#endif
- for (i=0; i<NVRAM_SIZE; i++)
- nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
- } else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
- nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
- dp->addrs[0].size);
- nvram_mult = 1;
- } else if (nvram_naddrs == 1) {
- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
- } else if (nvram_naddrs == 2) {
- nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
- } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
- nvram_naddrs = -1;
- } else {
- printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
- nvram_naddrs);
- }
- lookup_partitions();
-}
-
-void __pmac
-pmac_nvram_update(void)
-{
- struct core99_header* hdr99;
-
- if (!is_core_99 || !nvram_data || !nvram_image)
- return;
- if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
- NVRAM_SIZE))
- return;
-#ifdef DEBUG
- printk("Updating nvram...\n");
-#endif
- hdr99 = (struct core99_header*)nvram_image;
- hdr99->generation++;
- hdr99->hdr.signature = CORE99_SIGNATURE;
- hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
- hdr99->adler = core99_calc_adler(nvram_image);
- core99_bank = core99_bank ? 0 : 1;
- if (core99_erase_bank(core99_bank)) {
- printk("nvram: Error erasing bank %d\n", core99_bank);
- return;
- }
- if (core99_write_bank(core99_bank, nvram_image))
- printk("nvram: Error writing bank %d\n", core99_bank);
-}
-
-unsigned char __openfirmware
-nvram_read_byte(int addr)
-{
- switch (nvram_naddrs) {
-#ifdef CONFIG_ADB_PMU
- case -1: {
- struct adb_request req;
-
- if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
- (addr >> 8) & 0xff, addr & 0xff))
- break;
- while (!req.complete)
- pmu_poll();
- return req.reply[1];
- }
-#endif
- case 1:
- if (is_core_99)
- return nvram_image[addr];
- return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
- case 2:
- *nvram_addr = addr >> 5;
- eieio();
- return nvram_data[(addr & 0x1f) << 4];
- }
- return 0;
-}
-
-void __openfirmware
-nvram_write_byte(unsigned char val, int addr)
-{
- switch (nvram_naddrs) {
-#ifdef CONFIG_ADB_PMU
- case -1: {
- struct adb_request req;
-
- if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
- (addr >> 8) & 0xff, addr & 0xff, val))
- break;
- while (!req.complete)
- pmu_poll();
- break;
- }
-#endif
- case 1:
- if (is_core_99) {
- nvram_image[addr] = val;
- break;
- }
- nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
- break;
- case 2:
- *nvram_addr = addr >> 5;
- eieio();
- nvram_data[(addr & 0x1f) << 4] = val;
- break;
- }
- eieio();
-}
-
-int __pmac
-pmac_get_partition(int partition)
-{
- return nvram_partitions[partition];
-}
-
-u8 __pmac
-pmac_xpram_read(int xpaddr)
-{
- int offset = nvram_partitions[pmac_nvram_XPRAM];
-
- if (offset < 0)
- return 0;
-
- return nvram_read_byte(xpaddr + offset);
-}
-
-void __pmac
-pmac_xpram_write(int xpaddr, u8 data)
-{
- int offset = nvram_partitions[pmac_nvram_XPRAM];
-
- if (offset < 0)
- return;
-
- nvram_write_byte(xpaddr + offset, data);
-}
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
deleted file mode 100644
index 4693731798fe..000000000000
--- a/arch/ppc/kernel/pmac_pci.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_pci.c 1.27 09/08/01 15:47:42 paulus
- */
-/*
- * Support for PCI bridges found on Power Macintoshes.
- * At present the "bandit" and "chaos" bridges are supported.
- * Fortunately you access configuration space in the same
- * way with either bridge.
- *
- * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * 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 <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/feature.h>
-
-#include "pci.h"
-
-#undef DEBUG
-
-static void add_bridges(struct device_node *dev);
-
-/* XXX Could be per-controller, but I don't think we risk anything by
- * assuming we won't have both UniNorth and Bandit */
-static int has_uninorth;
-
-/*
- * Magic constants for enabling cache coherency in the bandit/PSX bridge.
- */
-#define BANDIT_DEVID_2 8
-#define BANDIT_REVID 3
-
-#define BANDIT_DEVNUM 11
-#define BANDIT_MAGIC 0x50
-#define BANDIT_COHERENT 0x40
-
-static int __init
-fixup_one_level_bus_range(struct device_node *node, int higher)
-{
- for (; node != 0;node = node->sibling) {
- int * bus_range;
- unsigned int *class_code;
- int len;
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down */
- class_code = (unsigned int *) get_property(node, "class-code", 0);
- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
- continue;
- bus_range = (int *) get_property(node, "bus-range", &len);
- if (bus_range != NULL && len > 2 * sizeof(int)) {
- if (bus_range[1] > higher)
- higher = bus_range[1];
- }
- higher = fixup_one_level_bus_range(node->child, higher);
- }
- return higher;
-}
-
-/* This routine fixes the "bus-range" property of all bridges in the
- * system since they tend to have their "last" member wrong on macs
- *
- * Note that the bus numbers manipulated here are OF bus numbers, they
- * are not Linux bus numbers.
- */
-static void __init
-fixup_bus_range(struct device_node *bridge)
-{
- int * bus_range;
- int len;
-
- /* Lookup the "bus-range" property for the hose */
- bus_range = (int *) get_property(bridge, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s\n",
- bridge->full_name);
- return;
- }
- bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
-}
-
-/*
- * Apple MacRISC (UniNorth, Bandit, Chaos) PCI controllers.
- *
- * The "Bandit" version is present in all early PCI PowerMacs,
- * and up to the first ones using Grackle. Some machines may
- * have 2 bandit controllers (2 PCI busses).
- *
- * "Chaos" is used in some "Bandit"-type machines as a bridge
- * for the separate display bus. It is accessed the same
- * way as bandit, but cannot be probed for devices. It therefore
- * has its own config access functions.
- *
- * The "UniNorth" version is present in all Core99 machines
- * (iBook, G4, new IMacs, and all the recent Apple machines).
- * It contains 3 controllers in one ASIC.
- */
-
-#define MACRISC_CFA0(devfn, off) \
- ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
- | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
- | (((unsigned long)(off)) & 0xFCUL))
-
-#define MACRISC_CFA1(bus, devfn, off) \
- ((((unsigned long)(bus)) << 16) \
- |(((unsigned long)(devfn)) << 8) \
- |(((unsigned long)(off)) & 0xFCUL) \
- |1UL)
-
-static unsigned int __pmac
-macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
-{
- unsigned int caddr;
-
- if (bus == hose->first_busno) {
- if (dev_fn < (11 << 3))
- return 0;
- caddr = MACRISC_CFA0(dev_fn, offset);
- } else
- caddr = MACRISC_CFA1(bus, dev_fn, offset);
-
- /* Uninorth will return garbage if we don't read back the value ! */
- do {
- out_le32(hose->cfg_addr, caddr);
- } while(in_le32(hose->cfg_addr) != caddr);
-
- offset &= has_uninorth ? 0x07 : 0x03;
- return (unsigned int)(hose->cfg_data) + (unsigned int)offset;
-}
-
-#define cfg_read(val, addr, type, op, op2) \
- *val = op((type)(addr))
-#define cfg_write(val, addr, type, op, op2) \
- op((type *)(addr), (val)); (void) op2((type *)(addr))
-
-#define cfg_read_bad(val, size) *val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte 0xff
-#define bad_word 0xffff
-#define bad_dword 0xffffffffU
-
-#define MACRISC_PCI_OP(rw, size, type, op, op2) \
-static int __pmac \
-macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
-{ \
- struct pci_controller *hose = dev->sysdata; \
- unsigned int addr; \
- \
- addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
- if (!addr) { \
- cfg_##rw##_bad(val, size) \
- return PCIBIOS_DEVICE_NOT_FOUND; \
- } \
- cfg_##rw(val, addr, type, op, op2); \
- return PCIBIOS_SUCCESSFUL; \
-}
-
-MACRISC_PCI_OP(read, byte, u8 *, in_8, x)
-MACRISC_PCI_OP(read, word, u16 *, in_le16, x)
-MACRISC_PCI_OP(read, dword, u32 *, in_le32, x)
-MACRISC_PCI_OP(write, byte, u8, out_8, in_8)
-MACRISC_PCI_OP(write, word, u16, out_le16, in_le16)
-MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32)
-
-static struct pci_ops macrisc_pci_ops =
-{
- macrisc_read_config_byte,
- macrisc_read_config_word,
- macrisc_read_config_dword,
- macrisc_write_config_byte,
- macrisc_write_config_word,
- macrisc_write_config_dword
-};
-
-/*
- * Verifiy that a specific (bus, dev_fn) exists on chaos
- */
-static int __pmac
-chaos_validate_dev(struct pci_dev *dev, int offset)
-{
- if(pci_device_to_OF_node(dev) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) &&
- (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-#define CHAOS_PCI_OP(rw, size, type) \
-static int __pmac \
-chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
-{ \
- int result = chaos_validate_dev(dev, off); \
- if(result == PCIBIOS_BAD_REGISTER_NUMBER) { \
- cfg_##rw##_bad(val, size) \
- return PCIBIOS_BAD_REGISTER_NUMBER; \
- } \
- if(result == PCIBIOS_SUCCESSFUL) \
- return macrisc_##rw##_config_##size(dev, off, val); \
- return result; \
-}
-
-CHAOS_PCI_OP(read, byte, u8 *)
-CHAOS_PCI_OP(read, word, u16 *)
-CHAOS_PCI_OP(read, dword, u32 *)
-CHAOS_PCI_OP(write, byte, u8)
-CHAOS_PCI_OP(write, word, u16)
-CHAOS_PCI_OP(write, dword, u32)
-
-static struct pci_ops chaos_pci_ops =
-{
- chaos_read_config_byte,
- chaos_read_config_word,
- chaos_read_config_dword,
- chaos_write_config_byte,
- chaos_write_config_word,
- chaos_write_config_dword
-};
-
-
-/*
- * For a bandit bridge, turn on cache coherency if necessary.
- * N.B. we could clean this up using the hose ops directly.
- */
-static void __init
-init_bandit(struct pci_controller *bp)
-{
- unsigned int vendev, magic;
- int rev;
-
- /* read the word at offset 0 in config space for device 11 */
- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
- udelay(2);
- vendev = in_le32((volatile unsigned int *)bp->cfg_data);
- if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +
- PCI_VENDOR_ID_APPLE) {
- /* read the revision id */
- out_le32(bp->cfg_addr,
- (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
- udelay(2);
- rev = in_8(bp->cfg_data);
- if (rev != BANDIT_REVID)
- printk(KERN_WARNING
- "Unknown revision %d for bandit at %08lx\n",
- rev, bp->io_base_phys);
- } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
- printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
- return;
- }
-
- /* read the revision id */
- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
- udelay(2);
- rev = in_8(bp->cfg_data);
- if (rev != BANDIT_REVID)
- printk(KERN_WARNING "Unknown revision %d for bandit at %08lx\n",
- rev, bp->io_base_phys);
-
- /* read the word at offset 0x50 */
- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
- udelay(2);
- magic = in_le32((volatile unsigned int *)bp->cfg_data);
- if ((magic & BANDIT_COHERENT) != 0)
- return;
- magic |= BANDIT_COHERENT;
- udelay(2);
- out_le32((volatile unsigned int *)bp->cfg_data, magic);
- printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %08lx\n",
- bp->io_base_phys);
-}
-
-
-/*
- * Tweak the PCI-PCI bridge chip on the blue & white G3s.
- */
-static void __init
-init_p2pbridge(void)
-{
- struct device_node *p2pbridge;
- struct pci_controller* hose;
- u8 bus, devfn;
- u16 val;
-
- /* XXX it would be better here to identify the specific
- PCI-PCI bridge chip we have. */
- if ((p2pbridge = find_devices("pci-bridge")) == 0
- || p2pbridge->parent == NULL
- || strcmp(p2pbridge->parent->name, "pci") != 0)
- return;
- if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
-#ifdef DEBUG
- printk("Can't find PCI infos for PCI<->PCI bridge\n");
-#endif
- return;
- }
- /* Warning: At this point, we have not yet renumbered all busses.
- * So we must use OF walking to find out hose
- */
- hose = pci_find_hose_for_OF_device(p2pbridge);
- if (!hose) {
-#ifdef DEBUG
- printk("Can't find hose for PCI<->PCI bridge\n");
-#endif
- return;
- }
- if (early_read_config_word(hose, bus, devfn,
- PCI_BRIDGE_CONTROL, &val) < 0) {
- printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
- return;
- }
- val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
- early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
-}
-
-void __init
-pmac_find_bridges(void)
-{
- add_bridges(find_devices("bandit"));
- add_bridges(find_devices("chaos"));
- add_bridges(find_devices("pci"));
- init_p2pbridge();
-}
-
-#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
- | (((o) & ~3) << 24))
-
-#define GRACKLE_PICR1_STG 0x00000040
-#define GRACKLE_PICR1_LOOPSNOOP 0x00000010
-
-/* N.B. this is called before bridges is initialized, so we can't
- use grackle_pcibios_{read,write}_config_dword. */
-static inline void grackle_set_stg(struct pci_controller* bp, int enable)
-{
- unsigned int val;
-
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- val = in_le32((volatile unsigned int *)bp->cfg_data);
- val = enable? (val | GRACKLE_PICR1_STG) :
- (val & ~GRACKLE_PICR1_STG);
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- out_le32((volatile unsigned int *)bp->cfg_data, val);
- (void)in_le32((volatile unsigned int *)bp->cfg_data);
-}
-
-static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
-{
- unsigned int val;
-
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- val = in_le32((volatile unsigned int *)bp->cfg_data);
- val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
- (val & ~GRACKLE_PICR1_LOOPSNOOP);
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- out_le32((volatile unsigned int *)bp->cfg_data, val);
- (void)in_le32((volatile unsigned int *)bp->cfg_data);
-}
-
-static int __init
-setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
-{
- pci_assign_all_busses = 1;
- has_uninorth = 1;
- hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
- /* We "know" that the bridge at f2000000 has the PCI slots. */
- return addr->address == 0xf2000000;
-}
-
-static void __init
-setup_bandit(struct pci_controller* hose, struct reg_property* addr)
-{
- hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = (volatile unsigned int *)
- ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = (volatile unsigned char *)
- ioremap(addr->address + 0xc00000, 0x1000);
- init_bandit(hose);
-}
-
-static void __init
-setup_chaos(struct pci_controller* hose, struct reg_property* addr)
-{
- /* assume a `chaos' bridge */
- hose->ops = &chaos_pci_ops;
- hose->cfg_addr = (volatile unsigned int *)
- ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = (volatile unsigned char *)
- ioremap(addr->address + 0xc00000, 0x1000);
-}
-
-void __init
-setup_grackle(struct pci_controller *hose)
-{
- setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
- if (machine_is_compatible("AAPL,PowerBook1998"))
- grackle_set_loop_snoop(hose, 1);
-#if 0 /* Disabled for now, HW problems ??? */
- grackle_set_stg(hose, 1);
-#endif
-}
-
-/*
- * We assume that if we have a G3 powermac, we have one bridge called
- * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
- * if we have one or more bandit or chaos bridges, we don't have a MPC106.
- */
-static void __init
-add_bridges(struct device_node *dev)
-{
- int len;
- struct pci_controller *hose;
- struct reg_property *addr;
- char* disp_name;
- int *bus_range;
- int first = 1, primary;
-
- for (; dev != NULL; dev = dev->next) {
- addr = (struct reg_property *) get_property(dev, "reg", &len);
- if (addr == NULL || len < sizeof(*addr)) {
- printk(KERN_WARNING "Can't use %s: no address\n",
- dev->full_name);
- continue;
- }
- bus_range = (int *) get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
- dev->full_name);
- }
-
- hose = pcibios_alloc_controller();
- if (!hose)
- continue;
- hose->arch_data = dev;
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- disp_name = NULL;
- primary = first;
- if (device_is_compatible(dev, "uni-north")) {
- primary = setup_uninorth(hose, addr);
- disp_name = "UniNorth";
- } else if (strcmp(dev->name, "pci") == 0) {
- /* XXX assume this is a mpc106 (grackle) */
- setup_grackle(hose);
- disp_name = "Grackle (MPC106)";
- } else if (strcmp(dev->name, "bandit") == 0) {
- setup_bandit(hose, addr);
- disp_name = "Bandit";
- } else if (strcmp(dev->name, "chaos") == 0) {
- setup_chaos(hose, addr);
- disp_name = "Chaos";
- primary = 0;
- }
- printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
- disp_name, addr->address, hose->first_busno, hose->last_busno);
-#ifdef DEBUG
- printk(" ->Hose at 0x%08lx, cfg_addr=0x%08lx,cfg_data=0x%08lx\n",
- hose, hose->cfg_addr, hose->cfg_data);
-#endif
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, primary);
-
- /* Fixup "bus-range" OF property */
- fixup_bus_range(dev);
-
- first &= !primary;
- }
-}
-
-static void __init
-pcibios_fixup_OF_interrupts(void)
-{
- struct pci_dev* dev;
-
- pci_for_each_dev(dev)
- {
- /*
- * Open Firmware often doesn't initialize the,
- * PCI_INTERRUPT_LINE config register properly, so we
- * should find the device node and se if it has an
- * AAPL,interrupts property.
- */
- unsigned char pin;
- struct device_node* node;
-
- if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) || !pin)
- continue; /* No interrupt generated -> no fixup */
- node = pci_device_to_OF_node(dev);
- if (!node) {
- printk("No OF node for device %x:%x\n", dev->bus->number, dev->devfn >> 3);
- continue;
- }
- /* this is the node, see if it has interrupts */
- if (node->n_intrs > 0)
- dev->irq = node->intrs[0].line;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
-void __init
-pmac_pcibios_fixup(void)
-{
- /* Fixup interrupts according to OF tree */
- pcibios_fixup_OF_interrupts();
-}
-
-int __pmac
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
-{
- struct device_node* node;
- int updatecfg = 0;
-
- node = pci_device_to_OF_node(dev);
-
- /* We don't want to enable USB controllers absent from the OF tree
- * (iBook second controller)
- */
- if (dev->vendor == PCI_VENDOR_ID_APPLE
- && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node)
- return -EINVAL;
-
- /* Firewire & GMAC were disabled after PCI probe, the driver is
- * claiming them, we must re-enable them now.
- */
- if (node && !strcmp(node->name, "firewire") &&
- (device_is_compatible(node, "pci106b,18") ||
- device_is_compatible(node, "pci106b,30"))) {
- feature_set_firewire_cable_power(node, 1);
- feature_set_firewire_power(node, 1);
- updatecfg = 1;
- }
- if (node && !strcmp(node->name, "ethernet") &&
- device_is_compatible(node, "gmac")) {
- feature_set_gmac_power(node, 1);
- updatecfg = 1;
- }
-
- if (updatecfg) {
- u16 cmd;
-
- /*
- * Make sure PCI is correctly configured
- *
- * We use old pci_bios versions of the function since, by
- * default, gmac is not powered up, and so will be absent
- * from the kernel initial PCI lookup.
- *
- * Should be replaced by 2.4 new PCI mecanisms and really
- * regiser the device.
- */
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
- }
-
- return 0;
-}
-
-/* We power down some devices after they have been probed. They'll
- * be powered back on later on
- */
-void __init
-pmac_pcibios_after_init(void)
-{
- struct device_node* nd;
-
-#ifdef CONFIG_BLK_DEV_IDE
- struct pci_dev *dev;
-
- /* OF fails to initialize IDE controllers on macs
- * (and maybe other machines)
- *
- * Ideally, this should be moved to the IDE layer, but we need
- * to check specifically with Andre Hedrick how to do it cleanly
- * since the common IDE code seem to care about the fact that the
- * BIOS may have disabled a controller.
- *
- * -- BenH
- */
- pci_for_each_dev(dev) {
- if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
- pci_enable_device(dev);
- }
-#endif /* CONFIG_BLK_DEV_IDE */
-
- nd = find_devices("firewire");
- while (nd) {
- if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
- device_is_compatible(nd, "pci106b,30"))
- && device_is_compatible(nd->parent, "uni-north")) {
- feature_set_firewire_power(nd, 0);
- feature_set_firewire_cable_power(nd, 0);
- }
- nd = nd->next;
- }
- nd = find_devices("ethernet");
- while (nd) {
- if (nd->parent && device_is_compatible(nd, "gmac")
- && device_is_compatible(nd->parent, "uni-north"))
- feature_set_gmac_power(nd, 0);
- nd = nd->next;
- }
-}
-
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
deleted file mode 100644
index 295e4a44b870..000000000000
--- a/arch/ppc/kernel/pmac_pic.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_pic.c 1.20 09/08/01 15:47:42 paulus
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/pci.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/time.h>
-
-#include "pmac_pic.h"
-#include "open_pic.h"
-
-/* pmac */struct pmac_irq_hw {
- unsigned int flag;
- unsigned int enable;
- unsigned int ack;
- unsigned int level;
-};
-
-/* XXX these addresses should be obtained from the device tree */
-static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
- (struct pmac_irq_hw *) 0xf3000020,
- (struct pmac_irq_hw *) 0xf3000010,
- (struct pmac_irq_hw *) 0xf4000020,
- (struct pmac_irq_hw *) 0xf4000010,
-};
-
-static int max_irqs;
-static int max_real_irqs;
-
-static spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED;
-
-
-#define GATWICK_IRQ_POOL_SIZE 10
-static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
-
-/*
- * Mark an irq as "lost". This is only used on the pmac
- * since it can lose interrupts (see pmac_set_irq_mask).
- * -- Cort
- */
-void __pmac __set_lost(unsigned long irq_nr)
-{
- if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
- atomic_inc(&ppc_n_lost_interrupts);
- set_dec(1);
- }
-}
-
-static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
- unsigned long flags;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- clear_bit(irq_nr, ppc_cached_irq_mask);
- if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
- atomic_dec(&ppc_n_lost_interrupts);
- spin_lock_irqsave(&pmac_pic_lock, flags);
- out_le32(&pmac_irq_hw[i]->ack, bit);
- out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
- out_le32(&pmac_irq_hw[i]->ack, bit);
- do {
- /* make sure ack gets to controller before we enable
- interrupts */
- mb();
- } while(in_le32(&pmac_irq_hw[i]->flag) & bit);
- spin_unlock_irqrestore(&pmac_pic_lock, flags);
-}
-
-static void __pmac pmac_set_irq_mask(unsigned int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
- unsigned long flags;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- spin_lock_irqsave(&pmac_pic_lock, flags);
- /* enable unmasked interrupts */
- out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
-
- do {
- /* make sure mask gets to controller before we
- return to user */
- mb();
- } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
- != (ppc_cached_irq_mask[i] & bit));
-
- /*
- * Unfortunately, setting the bit in the enable register
- * when the device interrupt is already on *doesn't* set
- * the bit in the flag register or request another interrupt.
- */
- if ((bit & ppc_cached_irq_mask[i])
- && (ld_le32(&pmac_irq_hw[i]->level) & bit)
- && !(ld_le32(&pmac_irq_hw[i]->flag) & bit))
- __set_lost((ulong)irq_nr);
- spin_unlock_irqrestore(&pmac_pic_lock, flags);
-}
-
-static void __pmac pmac_mask_irq(unsigned int irq_nr)
-{
- clear_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr);
- mb();
-}
-
-static void __pmac pmac_unmask_irq(unsigned int irq_nr)
-{
- set_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr);
-}
-
-static void __pmac pmac_end_irq(unsigned int irq_nr)
-{
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
- set_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr);
- }
-}
-
-
-struct hw_interrupt_type pmac_pic = {
- " PMAC-PIC ",
- NULL,
- NULL,
- pmac_unmask_irq,
- pmac_mask_irq,
- pmac_mask_and_ack_irq,
- pmac_end_irq,
- NULL
-};
-
-struct hw_interrupt_type gatwick_pic = {
- " GATWICK ",
- NULL,
- NULL,
- pmac_unmask_irq,
- pmac_mask_irq,
- pmac_mask_and_ack_irq,
- pmac_end_irq,
- NULL
-};
-
-static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- int irq, bits;
-
- for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
- int i = irq >> 5;
- bits = ld_le32(&pmac_irq_hw[i]->flag)
- | ppc_lost_interrupts[i];
- if (bits == 0)
- continue;
- irq += __ilog2(bits);
- break;
- }
- /* The previous version of this code allowed for this case, we
- * don't. Put this here to check for it.
- * -- Cort
- */
- if ( irq_desc[irq].handler != &gatwick_pic )
- printk("gatwick irq not from gatwick pic\n");
- else
- ppc_irq_dispatch_handler( regs, irq );
-}
-
-int
-pmac_get_irq(struct pt_regs *regs)
-{
- int irq;
- unsigned long bits = 0;
-
-#ifdef CONFIG_SMP
- void psurge_smp_message_recv(struct pt_regs *);
-
- /* IPI's are a hack on the powersurge -- Cort */
- if ( smp_processor_id() != 0 ) {
- psurge_smp_message_recv(regs);
- return -2; /* ignore, already handled */
- }
-#endif /* CONFIG_SMP */
- for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
- int i = irq >> 5;
- bits = ld_le32(&pmac_irq_hw[i]->flag)
- | ppc_lost_interrupts[i];
- if (bits == 0)
- continue;
- irq += __ilog2(bits);
- break;
- }
-
- return irq;
-}
-
-/* This routine will fix some missing interrupt values in the device tree
- * on the gatwick mac-io controller used by some PowerBooks
- */
-static void __init
-pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
-{
- struct device_node *node;
- int count;
-
- memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
- node = gw->child;
- count = 0;
- while(node)
- {
- /* Fix SCC */
- if (strcasecmp(node->name, "escc") == 0)
- if (node->child) {
- if (node->child->n_intrs < 3) {
- node->child->intrs = &gatwick_int_pool[count];
- count += 3;
- }
- node->child->n_intrs = 3;
- node->child->intrs[0].line = 15+irq_base;
- node->child->intrs[1].line = 4+irq_base;
- node->child->intrs[2].line = 5+irq_base;
- printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
- node->child->intrs[0].line,
- node->child->intrs[1].line,
- node->child->intrs[2].line);
- }
- /* Fix media-bay & left SWIM */
- if (strcasecmp(node->name, "media-bay") == 0) {
- struct device_node* ya_node;
-
- if (node->n_intrs == 0)
- node->intrs = &gatwick_int_pool[count++];
- node->n_intrs = 1;
- node->intrs[0].line = 29+irq_base;
- printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
- node->intrs[0].line);
-
- ya_node = node->child;
- while(ya_node)
- {
- if (strcasecmp(ya_node->name, "floppy") == 0) {
- if (ya_node->n_intrs < 2) {
- ya_node->intrs = &gatwick_int_pool[count];
- count += 2;
- }
- ya_node->n_intrs = 2;
- ya_node->intrs[0].line = 19+irq_base;
- ya_node->intrs[1].line = 1+irq_base;
- printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
- ya_node->intrs[0].line, ya_node->intrs[1].line);
- }
- if (strcasecmp(ya_node->name, "ata4") == 0) {
- if (ya_node->n_intrs < 2) {
- ya_node->intrs = &gatwick_int_pool[count];
- count += 2;
- }
- ya_node->n_intrs = 2;
- ya_node->intrs[0].line = 14+irq_base;
- ya_node->intrs[1].line = 3+irq_base;
- printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
- ya_node->intrs[0].line, ya_node->intrs[1].line);
- }
- ya_node = ya_node->sibling;
- }
- }
- node = node->sibling;
- }
- if (count > 10) {
- printk("WARNING !! Gatwick interrupt pool overflow\n");
- printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
- printk(" requested = %d\n", count);
- }
-}
-
-/*
- * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
- * card which includes an ohare chip that acts as a second interrupt
- * controller. If we find this second ohare, set it up and fix the
- * interrupt value in the device tree for the ethernet chip.
- */
-static int __init enable_second_ohare(void)
-{
- unsigned char bus, devfn;
- unsigned short cmd;
- unsigned long addr;
- struct device_node *irqctrler = find_devices("pci106b,7");
- struct device_node *ether;
-
- if (irqctrler == NULL || irqctrler->n_addrs <= 0)
- return -1;
- addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
- pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
- max_irqs = 64;
- if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
- struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
- if (!hose)
- printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
- else {
- early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
- cmd &= ~PCI_COMMAND_IO;
- early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
- }
- }
-
- /* Fix interrupt for the modem/ethernet combo controller. The number
- in the device tree (27) is bogus (correct for the ethernet-only
- board but not the combo ethernet/modem board).
- The real interrupt is 28 on the second controller -> 28+32 = 60.
- */
- ether = find_devices("pci1011,14");
- if (ether && ether->n_intrs > 0) {
- ether->intrs[0].line = 60;
- printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
- ether->intrs[0].line);
- }
-
- /* Return the interrupt number of the cascade */
- return irqctrler->intrs[0].line;
-}
-
-void __init
-pmac_pic_init(void)
-{
- int i;
- struct device_node *irqctrler;
- unsigned long addr;
- int irq_cascade = -1;
-
- /* We first try to detect Apple's new Core99 chipset, since mac-io
- * is quite different on those machines and contains an IBM MPIC2.
- */
- irqctrler = find_type_devices("open-pic");
- if (irqctrler != NULL)
- {
- printk("PowerMac using OpenPIC irq controller\n");
- if (irqctrler->n_addrs > 0)
- {
- int nmi_irq = -1;
- unsigned char senses[NR_IRQS];
-#ifdef CONFIG_XMON
- struct device_node* pswitch;
-
- pswitch = find_devices("programmer-switch");
- if (pswitch && pswitch->n_intrs)
- nmi_irq = pswitch->intrs[0].line;
-#endif /* CONFIG_XMON */
- prom_get_irq_senses(senses, 0, NR_IRQS);
- OpenPIC_InitSenses = senses;
- OpenPIC_NumInitSenses = NR_IRQS;
- ppc_md.get_irq = openpic_get_irq;
- OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
- irqctrler->addrs[0].size);
- openpic_init(1, 0, 0, nmi_irq);
-#ifdef CONFIG_XMON
- if (nmi_irq >= 0)
- request_irq(nmi_irq, xmon_irq, 0,
- "NMI - XMON", 0);
-#endif /* CONFIG_XMON */
- return;
- }
- irqctrler = NULL;
- }
-
- /*
- * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
- * 1998 G3 Series PowerBooks have 128,
- * other powermacs have 32.
- * The combo ethernet/modem card for the Powerstar powerbooks
- * (2400/3400/3500, ohare based) has a second ohare chip
- * effectively making a total of 64.
- */
- max_irqs = max_real_irqs = 32;
- irqctrler = find_devices("mac-io");
- if (irqctrler)
- {
- max_real_irqs = 64;
- if (irqctrler->next)
- max_irqs = 128;
- else
- max_irqs = 64;
- }
- for ( i = 0; i < max_real_irqs ; i++ )
- irq_desc[i].handler = &pmac_pic;
-
- /* get addresses of first controller */
- if (irqctrler) {
- if (irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 0; i < 2; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (2 - i) * 0x10);
- }
-
- /* get addresses of second controller */
- irqctrler = irqctrler->next;
- if (irqctrler && irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 2; i < 4; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (4 - i) * 0x10);
- irq_cascade = irqctrler->intrs[0].line;
- if (device_is_compatible(irqctrler, "gatwick"))
- pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
- }
- } else {
- /* older powermacs have a GC (grand central) or ohare at
- f3000000, with interrupt control registers at f3000020. */
- addr = (unsigned long) ioremap(0xf3000000, 0x40);
- pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
- }
-
- /* PowerBooks 3400 and 3500 can have a second controller in a second
- ohare chip, on the combo ethernet/modem card */
- if (machine_is_compatible("AAPL,3400/2400")
- || machine_is_compatible("AAPL,3500"))
- irq_cascade = enable_second_ohare();
-
- /* disable all interrupts in all controllers */
- for (i = 0; i * 32 < max_irqs; ++i)
- out_le32(&pmac_irq_hw[i]->enable, 0);
-
- /* get interrupt line of secondary interrupt controller */
- if (irq_cascade >= 0) {
- printk(KERN_INFO "irq: secondary controller on irq %d\n",
- (int)irq_cascade);
- for ( i = max_real_irqs ; i < max_irqs ; i++ )
- irq_desc[i].handler = &gatwick_pic;
- request_irq( irq_cascade, gatwick_action, SA_INTERRUPT,
- "cascade", 0 );
- }
- printk("System has %d possible interrupts\n", max_irqs);
- if (max_irqs != max_real_irqs)
- printk(KERN_DEBUG "%d interrupts on main controller\n",
- max_real_irqs);
-
-#ifdef CONFIG_XMON
- request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
-#endif /* CONFIG_XMON */
-}
-
-#ifdef CONFIG_PMAC_PBOOK
-/*
- * These procedures are used in implementing sleep on the powerbooks.
- * sleep_save_intrs() saves the states of all interrupt enables
- * and disables all interrupts except for the nominated one.
- * sleep_restore_intrs() restores the states of all interrupt enables.
- */
-unsigned int sleep_save_mask[2];
-
-void __pmac
-pmac_sleep_save_intrs(int viaint)
-{
- sleep_save_mask[0] = ppc_cached_irq_mask[0];
- sleep_save_mask[1] = ppc_cached_irq_mask[1];
- ppc_cached_irq_mask[0] = 0;
- ppc_cached_irq_mask[1] = 0;
- if (viaint > 0)
- set_bit(viaint, ppc_cached_irq_mask);
- out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
- if (max_real_irqs > 32)
- out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
- (void)in_le32(&pmac_irq_hw[0]->flag);
- /* make sure mask gets to controller before we return to caller */
- mb();
- (void)in_le32(&pmac_irq_hw[0]->enable);
-}
-
-void __pmac
-pmac_sleep_restore_intrs(void)
-{
- int i;
-
- out_le32(&pmac_irq_hw[0]->enable, 0);
- if (max_real_irqs > 32)
- out_le32(&pmac_irq_hw[1]->enable, 0);
- mb();
- for (i = 0; i < max_real_irqs; ++i)
- if (test_bit(i, sleep_save_mask))
- pmac_unmask_irq(i);
-}
-#endif /* CONFIG_PMAC_PBOOK */
diff --git a/arch/ppc/kernel/pmac_pic.h b/arch/ppc/kernel/pmac_pic.h
deleted file mode 100644
index 2e27ea202b2b..000000000000
--- a/arch/ppc/kernel/pmac_pic.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_pic.h 1.9 08/19/01 22:23:04 paulus
- */
-#ifndef _PPC_KERNEL_PMAC_PIC_H
-#define _PPC_KERNEL_PMAC_PIC_H
-
-#include "local_irq.h"
-
-extern struct hw_interrupt_type pmac_pic;
-
-void pmac_pic_init(void);
-int pmac_get_irq(struct pt_regs *regs);
-
-#endif /* _PPC_KERNEL_PMAC_PIC_H */
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
deleted file mode 100644
index ad11963bda86..000000000000
--- a/arch/ppc/kernel/pmac_setup.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_setup.c 1.43 11/13/01 21:26:07 paulus
- */
-/*
- * linux/arch/ppc/kernel/setup.c
- *
- * PowerPC version
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- * Adapted for Power Macintosh by Paul Mackerras
- * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * Derived from "arch/alpha/kernel/setup.c"
- * Copyright (C) 1995 Linus Torvalds
- *
- * 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.
- *
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/blk.h>
-#include <linux/vt_kern.h>
-#include <linux/console.h>
-#include <linux/ide.h>
-#include <linux/pci.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-#include <linux/seq_file.h>
-
-#include <asm/processor.h>
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/ohare.h>
-#include <asm/mediabay.h>
-#include <asm/feature.h>
-#include <asm/machdep.h>
-#include <asm/keyboard.h>
-#include <asm/dma.h>
-#include <asm/bootx.h>
-#include <asm/cputable.h>
-#include <asm/btext.h>
-
-#include <asm/time.h>
-#include "local_irq.h"
-#include "pmac_pic.h"
-#include "../mm/mem_pieces.h"
-
-#undef SHOW_GATWICK_IRQS
-
-extern long pmac_time_init(void);
-extern unsigned long pmac_get_rtc_time(void);
-extern int pmac_set_rtc_time(unsigned long nowtime);
-extern void pmac_read_rtc_time(void);
-extern void pmac_calibrate_decr(void);
-extern void pmac_pcibios_fixup(void);
-extern void pmac_find_bridges(void);
-
-extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep,
- char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
-extern void mackbd_leds(unsigned char leds);
-extern void __init mackbd_init_hw(void);
-extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char mac_hid_kbd_unexpected_up(unsigned char keycode);
-extern void mac_hid_init_hw(void);
-extern unsigned char mac_hid_kbd_sysrq_xlate[];
-extern unsigned char pckbd_sysrq_xlate[];
-extern unsigned char mackbd_sysrq_xlate[];
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern int keyboard_sends_linux_keycodes;
-extern void pmac_nvram_update(void);
-
-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
-extern void pmac_pcibios_after_init(void);
-
-struct device_node *memory_node;
-
-unsigned char drive_info;
-
-int ppc_override_l2cr = 0;
-int ppc_override_l2cr_value;
-int has_l2cache = 0;
-
-static int current_root_goodness = -1;
-
-extern char saved_command_line[];
-
-extern int pmac_newworld;
-
-#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */
-
-extern void zs_kgdb_hook(int tty_num);
-static void ohare_init(void);
-#ifdef CONFIG_BOOTX_TEXT
-void pmac_progress(char *s, unsigned short hex);
-#endif
-
-sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t psurge_smp_ops;
-extern struct smp_ops_t core99_smp_ops;
-
-volatile static long int core99_l2_cache;
-void __init
-core99_init_l2(void)
-{
- int cpu = smp_processor_id();
-
- if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
- return;
-
- if (cpu == 0){
- core99_l2_cache = _get_L2CR();
- printk("CPU0: L2CR is %lx\n", core99_l2_cache);
- } else {
- printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
- _set_L2CR(0);
- _set_L2CR(core99_l2_cache);
- printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
- }
-}
-#endif /* CONFIG_SMP */
-
-/*
- * Assume here that all clock rates are the same in a
- * smp system. -- Cort
- */
-int __openfirmware
-of_show_percpuinfo(struct seq_file *m, int i)
-{
- struct device_node *cpu_node;
- int *fp, s;
-
- cpu_node = find_type_devices("cpu");
- if (!cpu_node)
- return 0;
- for (s = 0; s < i && cpu_node->next; s++)
- cpu_node = cpu_node->next;
- fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
- if (fp)
- seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
- return 0;
-}
-
-int __pmac
-pmac_show_cpuinfo(struct seq_file *m)
-{
- struct device_node *np;
- char *pp;
- int plen;
-
- /* find motherboard type */
- seq_printf(m, "machine\t\t: ");
- np = find_devices("device-tree");
- if (np != NULL) {
- pp = (char *) get_property(np, "model", NULL);
- if (pp != NULL)
- seq_printf(m, "%s\n", pp);
- else
- seq_printf(m, "PowerMac\n");
- pp = (char *) get_property(np, "compatible", &plen);
- if (pp != NULL) {
- seq_printf(m, "motherboard\t:");
- while (plen > 0) {
- int l = strlen(pp) + 1;
- seq_printf(m, " %s", pp);
- plen -= l;
- pp += l;
- }
- seq_printf(m, "\n");
- }
- } else
- seq_printf(m, "PowerMac\n");
-
- /* find l2 cache info */
- np = find_devices("l2-cache");
- if (np == 0)
- np = find_type_devices("cache");
- if (np != 0) {
- unsigned int *ic = (unsigned int *)
- get_property(np, "i-cache-size", NULL);
- unsigned int *dc = (unsigned int *)
- get_property(np, "d-cache-size", NULL);
- seq_printf(m, "L2 cache\t:");
- has_l2cache = 1;
- if (get_property(np, "cache-unified", NULL) != 0 && dc) {
- seq_printf(m, " %dK unified", *dc / 1024);
- } else {
- if (ic)
- seq_printf(m, " %dK instruction", *ic / 1024);
- if (dc)
- seq_printf(m, "%s %dK data",
- (ic? " +": ""), *dc / 1024);
- }
- pp = get_property(np, "ram-type", NULL);
- if (pp)
- seq_printf(m, " %s", pp);
- seq_printf(m, "\n");
- }
-
- /* find ram info */
- np = find_devices("memory");
- if (np != 0) {
- int n;
- struct reg_property *reg = (struct reg_property *)
- get_property(np, "reg", &n);
-
- if (reg != 0) {
- unsigned long total = 0;
-
- for (n /= sizeof(struct reg_property); n > 0; --n)
- total += (reg++)->size;
- seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
- }
- }
-
- /* Checks "l2cr-value" property in the registry */
- np = find_devices("cpus");
- if (np == 0)
- np = find_type_devices("cpu");
- if (np != 0) {
- unsigned int *l2cr = (unsigned int *)
- get_property(np, "l2cr-value", NULL);
- if (l2cr != 0) {
- seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
- }
- }
-
- /* Indicate newworld/oldworld */
- seq_printf(m, "pmac-generation\t: %s\n",
- pmac_newworld ? "NewWorld" : "OldWorld");
-
-
- return 0;
-}
-
-#ifdef CONFIG_SCSI
-/* Find the device number for the disk (if any) at target tgt
- on host adaptor host. We just need to get the prototype from
- sd.h */
-#include <linux/blkdev.h>
-#include "../../../drivers/scsi/scsi.h"
-#include "../../../drivers/scsi/sd.h"
-
-#endif
-
-#ifdef CONFIG_VT
-/*
- * Dummy mksound function that does nothing.
- * The real one is in the dmasound driver.
- */
-static void __pmac
-pmac_mksound(unsigned int hz, unsigned int ticks)
-{
-}
-#endif /* CONFIG_VT */
-
-static volatile u32 *sysctrl_regs;
-
-void __init
-pmac_setup_arch(void)
-{
- struct device_node *cpu;
- int *fp;
- unsigned long pvr;
-
- pvr = PVR_VER(mfspr(PVR));
-
- /* Set loops_per_jiffy to a half-way reasonable value,
- for use until calibrate_delay gets called. */
- cpu = find_type_devices("cpu");
- if (cpu != 0) {
- fp = (int *) get_property(cpu, "clock-frequency", NULL);
- if (fp != 0) {
- if (pvr == 4 || pvr >= 8)
- /* 604, G3, G4 etc. */
- loops_per_jiffy = *fp / HZ;
- else
- /* 601, 603, etc. */
- loops_per_jiffy = *fp / (2*HZ);
- } else
- loops_per_jiffy = 50000000 / HZ;
- }
-
- /* this area has the CPU identification register
- and some registers used by smp boards */
- sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
- ohare_init();
-
- /* Lookup PCI hosts */
- pmac_find_bridges();
-
- /* Checks "l2cr-value" property in the registry */
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
- struct device_node *np = find_devices("cpus");
- if (np == 0)
- np = find_type_devices("cpu");
- if (np != 0) {
- unsigned int *l2cr = (unsigned int *)
- get_property(np, "l2cr-value", NULL);
- if (l2cr != 0) {
- ppc_override_l2cr = 1;
- ppc_override_l2cr_value = *l2cr;
- _set_L2CR(0);
- _set_L2CR(ppc_override_l2cr_value);
- }
- }
- }
-
- if (ppc_override_l2cr)
- printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
- ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
- ? "enabled" : "disabled");
-
-#ifdef CONFIG_SMP
- /* somewhat of a hack */
- core99_init_l2();
-#endif
-
-#ifdef CONFIG_KGDB
- zs_kgdb_hook(0);
-#endif
-
-#ifdef CONFIG_ADB_CUDA
- find_via_cuda();
-#else
- if (find_devices("via-cuda")) {
- printk("WARNING ! Your machine is Cuda based but your kernel\n");
- printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n");
- }
-#endif
-#ifdef CONFIG_ADB_PMU
- find_via_pmu();
-#else
- if (find_devices("via-pmu")) {
- printk("WARNING ! Your machine is PMU based but your kernel\n");
- printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
- }
-#endif
-#ifdef CONFIG_NVRAM
- pmac_nvram_init();
-#endif
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-#ifdef CONFIG_VT
- kd_mksound = pmac_mksound;
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- else
-#endif
- ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
-
-#ifdef CONFIG_SMP
- /* Check for Core99 */
- if (find_devices("uni-n"))
- ppc_md.smp_ops = &core99_smp_ops;
- else
- ppc_md.smp_ops = &psurge_smp_ops;
-#endif /* CONFIG_SMP */
-}
-
-static void __init ohare_init(void)
-{
- /*
- * Turn on the L2 cache.
- * We assume that we have a PSX memory controller iff
- * we have an ohare I/O controller.
- */
- if (find_devices("ohare") != NULL) {
- if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
- if (sysctrl_regs[4] & 0x10)
- sysctrl_regs[4] |= 0x04000020;
- else
- sysctrl_regs[4] |= 0x04000000;
- if(has_l2cache)
- printk(KERN_INFO "Level 2 cache enabled\n");
- }
- }
-}
-
-extern char *bootpath;
-extern char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-extern kdev_t boot_dev;
-
-void __init
-pmac_init2(void)
-{
-#ifdef CONFIG_ADB_PMU
- via_pmu_start();
-#endif
-#ifdef CONFIG_ADB_CUDA
- via_cuda_start();
-#endif
-#ifdef CONFIG_PMAC_PBOOK
- media_bay_init();
-#endif
-}
-
-#ifdef CONFIG_SCSI
-void __init
-note_scsi_host(struct device_node *node, void *host)
-{
- int l;
- char *p;
-
- l = strlen(node->full_name);
- if (bootpath != NULL && bootdevice != NULL
- && strncmp(node->full_name, bootdevice, l) == 0
- && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
- boot_host = host;
- /*
- * There's a bug in OF 1.0.5. (Why am I not surprised.)
- * If you pass a path like scsi/sd@1:0 to canon, it returns
- * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
- * That is, the scsi target number doesn't get preserved.
- * So we pick the target number out of bootpath and use that.
- */
- p = strstr(bootpath, "/sd@");
- if (p != NULL) {
- p += 4;
- boot_target = simple_strtoul(p, NULL, 10);
- p = strchr(p, ':');
- if (p != NULL)
- boot_part = simple_strtoul(p + 1, NULL, 10);
- }
- }
-}
-#endif
-
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-kdev_t __init
-find_ide_boot(void)
-{
- char *p;
- int n;
- kdev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
- if (bootdevice == NULL)
- return 0;
- p = strrchr(bootdevice, '/');
- if (p == NULL)
- return 0;
- n = p - bootdevice;
-
- return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-void __init
-find_boot_device(void)
-{
-#if defined(CONFIG_SCSI) && defined(CONFIG_BLK_DEV_SD)
- if (boot_host != NULL) {
- boot_dev = sd_find_target(boot_host, boot_target);
- if (boot_dev != 0)
- return;
- }
-#endif
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
- boot_dev = find_ide_boot();
-#endif
-}
-
-/* can't be __init - can be called whenever a disk is first accessed */
-void __pmac
-note_bootable_part(kdev_t dev, int part, int goodness)
-{
- static int found_boot = 0;
- char *p;
-
- /* Do nothing if the root has been mounted already. */
- if (init_task.fs->rootmnt != NULL)
- return;
- if ((goodness <= current_root_goodness) &&
- (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE)))
- return;
- p = strstr(saved_command_line, "root=");
- if (p != NULL && (p == saved_command_line || p[-1] == ' '))
- return;
-
- if (!found_boot) {
- find_boot_device();
- found_boot = 1;
- }
- if (boot_dev == 0 || dev == boot_dev) {
- ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part);
- boot_dev = NODEV;
- current_root_goodness = goodness;
- }
-}
-
-void __pmac
-pmac_restart(char *cmd)
-{
-#ifdef CONFIG_ADB_CUDA
- struct adb_request req;
-#endif /* CONFIG_ADB_CUDA */
-
-#ifdef CONFIG_NVRAM
- pmac_nvram_update();
-#endif
-
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_RESET_SYSTEM);
- for (;;)
- cuda_poll();
- break;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- pmu_restart();
- break;
-#endif /* CONFIG_ADB_PMU */
- default: ;
- }
-}
-
-void __pmac
-pmac_power_off(void)
-{
-#ifdef CONFIG_ADB_CUDA
- struct adb_request req;
-#endif /* CONFIG_ADB_CUDA */
-
-#ifdef CONFIG_NVRAM
- pmac_nvram_update();
-#endif
-
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_POWERDOWN);
- for (;;)
- cuda_poll();
- break;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- pmu_shutdown();
- break;
-#endif /* CONFIG_ADB_PMU */
- default: ;
- }
-}
-
-void __pmac
-pmac_halt(void)
-{
- pmac_power_off();
-}
-
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-static int __pmac
-pmac_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
- /*
- * We only do the check_region if `from' looks like a genuine
- * I/O port number. If it actually refers to a memory-mapped
- * register, it should be OK.
- */
- if (from < ~_IO_BASE)
- return check_region(from, extent);
- return 0;
-}
-
-static void __pmac
-pmac_ide_request_region(ide_ioreg_t from,
- unsigned int extent,
- const char *name)
-{
- if (from < ~_IO_BASE)
- request_region(from, extent, name);
-}
-
-static void __pmac
-pmac_ide_release_region(ide_ioreg_t from,
- unsigned int extent)
-{
- if (from < ~_IO_BASE)
- release_region(from, extent);
-}
-
-/*
- * This is only used if we have a PCI IDE controller, not
- * for the IDE controller in the ohare/paddington/heathrow/keylargo.
- */
-static void __pmac
-pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
- ide_ioreg_t ctrl_port, int *irq)
-{
- ide_ioreg_t reg = data_port;
- int i;
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
- }
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-}
-#endif
-
-/*
- * Read in a property describing some pieces of memory.
- */
-
-static void __init
-get_mem_prop(char *name, struct mem_pieces *mp)
-{
- struct reg_property *rp;
- int i, s;
- unsigned int *ip;
- int nac = prom_n_addr_cells(memory_node);
- int nsc = prom_n_size_cells(memory_node);
-
- ip = (unsigned int *) get_property(memory_node, name, &s);
- if (ip == NULL) {
- printk(KERN_ERR "error: couldn't get %s property on /memory\n",
- name);
- abort();
- }
- s /= (nsc + nac) * 4;
- rp = mp->regions;
- for (i = 0; i < s; ++i, ip += nac+nsc) {
- if (nac >= 2 && ip[nac-2] != 0)
- continue;
- rp->address = ip[nac-1];
- if (nsc >= 2 && ip[nac+nsc-2] != 0)
- rp->size = ~0U;
- else
- rp->size = ip[nac+nsc-1];
- ++rp;
- }
- mp->n_regions = rp - mp->regions;
-
- /* Make sure the pieces are sorted. */
- mem_pieces_sort(mp);
- mem_pieces_coalesce(mp);
-}
-
-/*
- * On systems with Open Firmware, collect information about
- * physical RAM and which pieces are already in use.
- * At this point, we have (at least) the first 8MB mapped with a BAT.
- * Our text, data, bss use something over 1MB, starting at 0.
- * Open Firmware may be using 1MB at the 4MB point.
- */
-unsigned long __init
-pmac_find_end_of_memory(void)
-{
- unsigned long a, total;
- struct mem_pieces phys_mem;
-
- memory_node = find_devices("memory");
- if (memory_node == NULL) {
- printk(KERN_ERR "can't find memory node\n");
- abort();
- }
-
- /*
- * Find out where physical memory is, and check that it
- * starts at 0 and is contiguous. It seems that RAM is
- * always physically contiguous on Power Macintoshes.
- *
- * Supporting discontiguous physical memory isn't hard,
- * it just makes the virtual <-> physical mapping functions
- * more complicated (or else you end up wasting space
- * in mem_map).
- */
- get_mem_prop("reg", &phys_mem);
- if (phys_mem.n_regions == 0)
- panic("No RAM??");
- a = phys_mem.regions[0].address;
- if (a != 0)
- panic("RAM doesn't start at physical address 0");
- total = phys_mem.regions[0].size;
-
- if (phys_mem.n_regions > 1) {
- printk("RAM starting at 0x%x is not contiguous\n",
- phys_mem.regions[1].address);
- printk("Using RAM from 0 to 0x%lx\n", total-1);
- }
-
- return total;
-}
-
-void __init
-select_adb_keyboard(void)
-{
-#ifdef CONFIG_VT
-#ifdef CONFIG_INPUT
- ppc_md.kbd_init_hw = mac_hid_init_hw;
- ppc_md.kbd_translate = mac_hid_kbd_translate;
- ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up;
- ppc_md.kbd_setkeycode = 0;
- ppc_md.kbd_getkeycode = 0;
- ppc_md.kbd_leds = 0;
-#ifdef CONFIG_MAGIC_SYSRQ
-#ifdef CONFIG_MAC_ADBKEYCODES
- if (!keyboard_sends_linux_keycodes) {
- ppc_md.ppc_kbd_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
- SYSRQ_KEY = 0x69;
- } else
-#endif /* CONFIG_MAC_ADBKEYCODES */
- {
- ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
- SYSRQ_KEY = 0x54;
- }
-#endif /* CONFIG_MAGIC_SYSRQ */
-#elif defined(CONFIG_ADB_KEYBOARD)
- ppc_md.kbd_setkeycode = mackbd_setkeycode;
- ppc_md.kbd_getkeycode = mackbd_getkeycode;
- ppc_md.kbd_translate = mackbd_translate;
- ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
- ppc_md.kbd_leds = mackbd_leds;
- ppc_md.kbd_init_hw = mackbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate;
- SYSRQ_KEY = 0x69;
-#endif /* CONFIG_MAGIC_SYSRQ */
-#endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */
-#endif /* CONFIG_VT */
-}
-
-void __init
-pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /* isa_io_base gets set in pmac_find_bridges */
- isa_mem_base = PMAC_ISA_MEM_BASE;
- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 1;
- DMA_MODE_WRITE = 2;
-
- ppc_md.setup_arch = pmac_setup_arch;
- ppc_md.show_cpuinfo = pmac_show_cpuinfo;
- ppc_md.show_percpuinfo = of_show_percpuinfo;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = pmac_pic_init;
- ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
- ppc_md.init = pmac_init2;
-
- ppc_md.pcibios_fixup = pmac_pcibios_fixup;
- ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
- ppc_md.pcibios_after_init = pmac_pcibios_after_init;
-
- ppc_md.restart = pmac_restart;
- ppc_md.power_off = pmac_power_off;
- ppc_md.halt = pmac_halt;
-
- ppc_md.time_init = pmac_time_init;
- ppc_md.set_rtc_time = pmac_set_rtc_time;
- ppc_md.get_rtc_time = pmac_get_rtc_time;
- ppc_md.calibrate_decr = pmac_calibrate_decr;
-
- ppc_md.find_end_of_memory = pmac_find_end_of_memory;
-
- select_adb_keyboard();
-
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
- ppc_ide_md.ide_check_region = pmac_ide_check_region;
- ppc_ide_md.ide_request_region = pmac_ide_request_region;
- ppc_ide_md.ide_release_region = pmac_ide_release_region;
- ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-#ifdef CONFIG_BOOTX_TEXT
- ppc_md.progress = pmac_progress;
-#endif /* CONFIG_BOOTX_TEXT */
-
- if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-extern void drawchar(char c);
-extern void drawstring(const char *c);
-extern boot_infos_t *disp_bi;
-void __init
-pmac_progress(char *s, unsigned short hex)
-{
- if (disp_bi == 0)
- return;
- btext_drawstring(s);
- btext_drawchar('\n');
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/kernel/pmac_smp.c b/arch/ppc/kernel/pmac_smp.c
deleted file mode 100644
index 9c28cdde79ee..000000000000
--- a/arch/ppc/kernel/pmac_smp.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- * SMP support for power macintosh.
- *
- * We support both the old "powersurge" SMP architecture
- * and the current Core99 (G4 PowerMac) machines.
- *
- * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
- * and Ben Herrenschmidt <benh@kernel.crashing.org>.
- *
- * Support for DayStar quad CPU cards
- * Copyright (C) XLR8, Inc. 1994-2000
- *
- * 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 <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/hardirq.h>
-#include <asm/softirq.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/feature.h>
-#include <asm/time.h>
-#include <asm/gemini.h>
-
-#include "open_pic.h"
-
-/*
- * Powersurge (old powermac SMP) support.
- */
-
-extern void __secondary_start_psurge(void);
-extern void __secondary_start_psurge2(void); /* Temporary horrible hack */
-extern void __secondary_start_psurge3(void); /* Temporary horrible hack */
-
-/* Addresses for powersurge registers */
-#define HAMMERHEAD_BASE 0xf8000000
-#define HHEAD_CONFIG 0x90
-#define HHEAD_SEC_INTR 0xc0
-
-/* register for interrupting the primary processor on the powersurge */
-/* N.B. this is actually the ethernet ROM! */
-#define PSURGE_PRI_INTR 0xf3019000
-
-/* register for storing the start address for the secondary processor */
-/* N.B. this is the PCI config space address register for the 1st bridge */
-#define PSURGE_START 0xf2800000
-
-/* Daystar/XLR8 4-CPU card */
-#define PSURGE_QUAD_REG_ADDR 0xf8800000
-
-#define PSURGE_QUAD_IRQ_SET 0
-#define PSURGE_QUAD_IRQ_CLR 1
-#define PSURGE_QUAD_IRQ_PRIMARY 2
-#define PSURGE_QUAD_CKSTOP_CTL 3
-#define PSURGE_QUAD_PRIMARY_ARB 4
-#define PSURGE_QUAD_BOARD_ID 6
-#define PSURGE_QUAD_WHICH_CPU 7
-#define PSURGE_QUAD_CKSTOP_RDBK 8
-#define PSURGE_QUAD_RESET_CTL 11
-
-#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
-#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
-#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
-#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
-
-/* virtual addresses for the above */
-static volatile u8 *hhead_base;
-static volatile u8 *quad_base;
-static volatile u32 *psurge_pri_intr;
-static volatile u8 *psurge_sec_intr;
-static volatile u32 *psurge_start;
-
-/* what sort of powersurge board we have */
-static int psurge_type;
-
-/* values for psurge_type */
-#define PSURGE_DUAL 0
-#define PSURGE_QUAD_OKEE 1
-#define PSURGE_QUAD_COTTON 2
-#define PSURGE_QUAD_ICEGRASS 3
-
-/* l2 cache stuff for dual G4 macs */
-extern void core99_init_l2(void);
-
-/*
- * Set and clear IPIs for powersurge.
- */
-static inline void psurge_set_ipi(int cpu)
-{
- if (cpu == 0)
- in_be32(psurge_pri_intr);
- else if (psurge_type == PSURGE_DUAL)
- out_8(psurge_sec_intr, 0);
- else
- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
-}
-
-static inline void psurge_clr_ipi(int cpu)
-{
- if (cpu > 0) {
- if (psurge_type == PSURGE_DUAL)
- out_8(psurge_sec_intr, ~0);
- else
- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
- }
-}
-
-/*
- * On powersurge (old SMP powermac architecture) we don't have
- * separate IPIs for separate messages like openpic does. Instead
- * we have a bitmap for each processor, where a 1 bit means that
- * the corresponding message is pending for that processor.
- * Ideally each cpu's entry would be in a different cache line.
- * -- paulus.
- */
-static unsigned long psurge_smp_message[NR_CPUS];
-
-void __pmac
-psurge_smp_message_recv(struct pt_regs *regs)
-{
- int cpu = smp_processor_id();
- int msg;
-
- /* clear interrupt */
- psurge_clr_ipi(cpu);
-
- if (smp_num_cpus < 2)
- return;
-
- /* make sure there is a message there */
- for (msg = 0; msg < 4; msg++)
- if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
- smp_message_recv(msg, regs);
-}
-
-void __pmac
-psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
-{
- psurge_smp_message_recv(regs);
-}
-
-static void __pmac
-smp_psurge_message_pass(int target, int msg, unsigned long data, int wait)
-{
- int i;
-
- if (smp_num_cpus < 2)
- return;
-
- for (i = 0; i < smp_num_cpus; i++) {
- if (target == MSG_ALL
- || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
- || target == i) {
- set_bit(msg, &psurge_smp_message[i]);
- psurge_set_ipi(i);
- }
- }
-}
-
-/*
- * Determine a quad card presence. We read the board ID register, we
- * force the data bus to change to something else, and we read it again.
- * It it's stable, then the register probably exist (ugh !)
- */
-static int __init psurge_quad_probe(void)
-{
- int type;
- unsigned int i;
-
- type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
- if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
- || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
- return PSURGE_DUAL;
-
- /* looks OK, try a slightly more rigorous test */
- /* bogus is not necessarily cacheline-aligned,
- though I don't suppose that really matters. -- paulus */
- for (i = 0; i < 100; i++) {
- volatile u32 bogus[8];
- bogus[(0+i)%8] = 0x00000000;
- bogus[(1+i)%8] = 0x55555555;
- bogus[(2+i)%8] = 0xFFFFFFFF;
- bogus[(3+i)%8] = 0xAAAAAAAA;
- bogus[(4+i)%8] = 0x33333333;
- bogus[(5+i)%8] = 0xCCCCCCCC;
- bogus[(6+i)%8] = 0xCCCCCCCC;
- bogus[(7+i)%8] = 0x33333333;
- wmb();
- asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
- mb();
- if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
- return PSURGE_DUAL;
- }
- return type;
-}
-
-static void __init psurge_quad_init(void)
-{
- int procbits;
-
- if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
- procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
- if (psurge_type == PSURGE_QUAD_ICEGRASS)
- PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
- else
- PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
- mdelay(33);
- out_8(psurge_sec_intr, ~0);
- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
- PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
- if (psurge_type != PSURGE_QUAD_ICEGRASS)
- PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
- PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
- mdelay(33);
- PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
- mdelay(33);
- PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
- mdelay(33);
-}
-
-static int __init smp_psurge_probe(void)
-{
- int i, ncpus;
-
- /* We don't do SMP on the PPC601 -- paulus */
- if (PVR_VER(mfspr(PVR)) == 1)
- return 1;
-
- /*
- * The powersurge cpu board can be used in the generation
- * of powermacs that have a socket for an upgradeable cpu card,
- * including the 7500, 8500, 9500, 9600.
- * The device tree doesn't tell you if you have 2 cpus because
- * OF doesn't know anything about the 2nd processor.
- * Instead we look for magic bits in magic registers,
- * in the hammerhead memory controller in the case of the
- * dual-cpu powersurge board. -- paulus.
- */
- if (find_devices("hammerhead") == NULL)
- return 1;
-
- hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
- quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
- psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
-
- psurge_type = psurge_quad_probe();
- if (psurge_type != PSURGE_DUAL) {
- psurge_quad_init();
- /* All released cards using this HW design have 4 CPUs */
- ncpus = 4;
- } else {
- iounmap((void *) quad_base);
- if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
- /* not a dual-cpu card */
- iounmap((void *) hhead_base);
- return 1;
- }
- ncpus = 2;
- }
-
- psurge_start = ioremap(PSURGE_START, 4);
- psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
-
- /* this is not actually strictly necessary -- paulus. */
- for (i = 1; i < ncpus; ++i)
- smp_hw_index[i] = i;
-
- if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
-
- return ncpus;
-}
-
-static void __init smp_psurge_kick_cpu(int nr)
-{
- void (*start)(void) = __secondary_start_psurge;
- unsigned long a;
-
- /* may need to flush here if secondary bats aren't setup */
- for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
- asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
- asm volatile("sync");
-
- if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
-
- /* setup entry point of secondary processor */
- switch (nr) {
- case 2:
- start = __secondary_start_psurge2;
- break;
- case 3:
- start = __secondary_start_psurge3;
- break;
- }
-
- out_be32(psurge_start, __pa(start));
- mb();
-
- psurge_set_ipi(nr);
- udelay(10);
- psurge_clr_ipi(nr);
-
- if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
-}
-
-/*
- * With the dual-cpu powersurge board, the decrementers and timebases
- * of both cpus are frozen after the secondary cpu is started up,
- * until we give the secondary cpu another interrupt. This routine
- * uses this to get the timebases synchronized.
- * -- paulus.
- */
-static void __init psurge_dual_sync_tb(int cpu_nr)
-{
- static volatile int sec_tb_reset = 0;
- int t;
-
- set_dec(tb_ticks_per_jiffy);
- set_tb(0, 0);
- last_jiffy_stamp(cpu_nr) = 0;
-
- if (cpu_nr > 0) {
- mb();
- sec_tb_reset = 1;
- return;
- }
-
- /* wait for the secondary to have reset its TB before proceeding */
- for (t = 10000000; t > 0 && !sec_tb_reset; --t)
- ;
-
- /* now interrupt the secondary, starting both TBs */
- psurge_set_ipi(1);
-
- smp_tb_synchronized = 1;
-}
-
-static void __init
-smp_psurge_setup_cpu(int cpu_nr)
-{
-
- if (cpu_nr == 0) {
- if (smp_num_cpus < 2)
- return;
- /* reset the entry point so if we get another intr we won't
- * try to startup again */
- out_be32(psurge_start, 0x100);
- if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
- printk(KERN_ERR "Couldn't get primary IPI interrupt");
- }
-
- if (psurge_type == PSURGE_DUAL)
- psurge_dual_sync_tb(cpu_nr);
-}
-
-static int __init
-smp_core99_probe(void)
-{
- struct device_node *cpus;
- int i, ncpus = 1;
-
- if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
- cpus = find_type_devices("cpu");
- if (cpus)
- while ((cpus = cpus->next) != NULL)
- ++ncpus;
- printk("smp_core99_probe: found %d cpus\n", ncpus);
- if (ncpus > 1) {
- openpic_request_IPIs();
- for (i = 1; i < ncpus; ++i)
- smp_hw_index[i] = i;
- }
-
- return ncpus;
-}
-
-static void __init
-smp_core99_kick_cpu(int nr)
-{
- unsigned long save_vector, new_vector;
- unsigned long flags;
-#if 1 /* New way... */
- volatile unsigned long *vector
- = ((volatile unsigned long *)(KERNELBASE+0x100));
- if (nr < 1 || nr > 3)
- return;
-#else
- volatile unsigned long *vector
- = ((volatile unsigned long *)(KERNELBASE+0x500));
- if (nr != 1)
- return;
-#endif
- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
-
- local_irq_save(flags);
- local_irq_disable();
-
- /* Save reset vector */
- save_vector = *vector;
-
- /* Setup fake reset vector that does
- * b __secondary_start_psurge - KERNELBASE
- */
- switch(nr) {
- case 1:
- new_vector = (unsigned long)__secondary_start_psurge;
- break;
- case 2:
- new_vector = (unsigned long)__secondary_start_psurge2;
- break;
- case 3:
- new_vector = (unsigned long)__secondary_start_psurge3;
- break;
- }
- *vector = 0x48000002 + new_vector - KERNELBASE;
-
- /* flush data cache and inval instruction cache */
- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
-
- /* Put some life in our friend */
- feature_core99_kick_cpu(nr);
-
- /* FIXME: We wait a bit for the CPU to take the exception, I should
- * instead wait for the entry code to set something for me. Well,
- * ideally, all that crap will be done in prom.c and the CPU left
- * in a RAM-based wait loop like CHRP.
- */
- mdelay(1);
-
- /* Restore our exception vector */
- *vector = save_vector;
- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
-
- local_irq_restore(flags);
- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
-}
-
-static void __init
-smp_core99_setup_cpu(int cpu_nr)
-{
- /* Setup openpic */
- do_openpic_setup_cpu();
-
- /* Setup L2 */
- if (cpu_nr != 0)
- core99_init_l2();
- else
- if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
-}
-
-/* PowerSurge-style Macs */
-struct smp_ops_t psurge_smp_ops __pmacdata = {
- smp_psurge_message_pass,
- smp_psurge_probe,
- smp_psurge_kick_cpu,
- smp_psurge_setup_cpu,
-};
-
-/* Core99 Macs (dual G4s) */
-struct smp_ops_t core99_smp_ops __pmacdata = {
- smp_openpic_message_pass,
- smp_core99_probe,
- smp_core99_kick_cpu,
- smp_core99_setup_cpu,
-};
diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c
deleted file mode 100644
index ba7260441eb2..000000000000
--- a/arch/ppc/kernel/pmac_time.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_time.c 1.16 09/08/01 15:47:42 paulus
- */
-/*
- * Support for periodic interrupts (100 per second) and for getting
- * the current time from the RTC on Power Macintoshes.
- *
- * We use the decrementer register for our periodic interrupts.
- *
- * Paul Mackerras August 1996.
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/hardirq.h>
-#include <asm/time.h>
-#include <asm/nvram.h>
-
-extern rwlock_t xtime_lock;
-
-/* Apparently the RTC stores seconds since 1 Jan 1904 */
-#define RTC_OFFSET 2082844800
-
-/*
- * Calibrate the decrementer frequency with the VIA timer 1.
- */
-#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
-
-/* VIA registers */
-#define RS 0x200 /* skip between registers */
-#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
-#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
-#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
-#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
-#define ACR (11*RS) /* Auxiliary control register */
-#define IFR (13*RS) /* Interrupt flag register */
-
-/* Bits in ACR */
-#define T1MODE 0xc0 /* Timer 1 mode */
-#define T1MODE_CONT 0x40 /* continuous interrupts */
-
-/* Bits in IFR and IER */
-#define T1_INT 0x40 /* Timer 1 interrupt */
-
-extern struct timezone sys_tz;
-
-long __init
-pmac_time_init(void)
-{
-#ifdef CONFIG_NVRAM
- s32 delta = 0;
- int dst;
-
- delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
- delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
- delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
- if (delta & 0x00800000UL)
- delta |= 0xFF000000UL;
- dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
- printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
- dst ? "on" : "off");
- return delta;
-#else
- return 0;
-#endif
-}
-
-unsigned long __pmac
-pmac_get_rtc_time(void)
-{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
- struct adb_request req;
- unsigned long now;
-#endif
-
- /* Get the time from the RTC */
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
- return 0;
- while (!req.complete)
- cuda_poll();
- if (req.reply_len != 7)
- printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
- req.reply_len);
- now = (req.reply[3] << 24) + (req.reply[4] << 16)
- + (req.reply[5] << 8) + req.reply[6];
- return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
- return 0;
- while (!req.complete)
- pmu_poll();
- if (req.reply_len != 5)
- printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
- req.reply_len);
- now = (req.reply[1] << 24) + (req.reply[2] << 16)
- + (req.reply[3] << 8) + req.reply[4];
- return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_PMU */
- default: ;
- }
- return 0;
-}
-
-int __pmac
-pmac_set_rtc_time(unsigned long nowtime)
-{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
- struct adb_request req;
-#endif
-
- nowtime += RTC_OFFSET;
-
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
- return 0;
- while (!req.complete)
- cuda_poll();
- if ((req.reply_len != 3) && (req.reply_len != 7))
- printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
- req.reply_len);
- return 1;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
- return 0;
- while (!req.complete)
- pmu_poll();
- if (req.reply_len != 0)
- printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
- req.reply_len);
- return 1;
-#endif /* CONFIG_ADB_PMU */
- default:
- return 0;
- }
-}
-
-/*
- * Calibrate the decrementer register using VIA timer 1.
- * This is used both on powermacs and CHRP machines.
- */
-int __init
-via_calibrate_decr(void)
-{
- struct device_node *vias;
- volatile unsigned char *via;
- int count = VIA_TIMER_FREQ_6 / HZ;
- unsigned int dstart, dend;
-
- vias = find_devices("via-cuda");
- if (vias == 0)
- vias = find_devices("via-pmu");
- if (vias == 0)
- vias = find_devices("via");
- if (vias == 0 || vias->n_addrs == 0)
- return 0;
- via = (volatile unsigned char *)
- ioremap(vias->addrs[0].address, vias->addrs[0].size);
-
- /* set timer 1 for continuous interrupts */
- out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
- /* set the counter to a small value */
- out_8(&via[T1CH], 2);
- /* set the latch to `count' */
- out_8(&via[T1LL], count);
- out_8(&via[T1LH], count >> 8);
- /* wait until it hits 0 */
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dstart = get_dec();
- /* clear the interrupt & wait until it hits 0 again */
- in_8(&via[T1CL]);
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dend = get_dec();
-
- tb_ticks_per_jiffy = (dstart - dend) / 6;
- tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
-
- printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
- tb_ticks_per_jiffy, dstart - dend);
-
- return 1;
-}
-
-#ifdef CONFIG_PMAC_PBOOK
-/*
- * Reset the time after a sleep.
- */
-static int __pmac
-time_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- static unsigned long time_diff;
- unsigned long flags;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- read_lock_irqsave(&xtime_lock, flags);
- time_diff = xtime.tv_sec - pmac_get_rtc_time();
- read_unlock_irqrestore(&xtime_lock, flags);
- break;
- case PBOOK_WAKE:
- write_lock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = pmac_get_rtc_time() + time_diff;
- set_dec(tb_ticks_per_jiffy);
- /* No currently-supported powerbook has a 601,
- so use get_tbl, not native */
- last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
- xtime.tv_usec = 0;
- last_rtc_update = xtime.tv_sec;
- write_unlock_irqrestore(&xtime_lock, flags);
- break;
- }
- return PBOOK_SLEEP_OK;
-}
-
-static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
- time_sleep_notify, SLEEP_LEVEL_MISC,
-};
-#endif /* CONFIG_PMAC_PBOOK */
-
-/*
- * Query the OF and get the decr frequency.
- * This was taken from the pmac time_init() when merging the prep/pmac
- * time functions.
- */
-void __init
-pmac_calibrate_decr(void)
-{
- struct device_node *cpu;
- unsigned int freq, *fp;
-
-#ifdef CONFIG_PMAC_PBOOK
- pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PMAC_PBOOK */
-
- /* We assume MacRISC2 machines have correct device-tree
- * calibration. That's better since the VIA itself seems
- * to be slightly off. --BenH
- */
- if (!machine_is_compatible("MacRISC2"))
- if (via_calibrate_decr())
- return;
-
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- cpu = find_type_devices("cpu");
- if (cpu == 0)
- panic("can't find cpu node in time_init");
- fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
- if (fp == 0)
- panic("can't get cpu timebase frequency");
- freq = *fp;
- printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
index 5ace6d58bc38..aa79ba92390b 100644
--- a/arch/ppc/kernel/ppc-stub.c
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.ppc-stub.c 1.6 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* ppc-stub.c: KGDB support for the Linux kernel.
@@ -61,7 +61,7 @@
*
* The following gdb commands are supported:
*
- * command function Return value
+ * command function Return value
*
* g return the value of the CPU registers hex data or ENN
* G set the value of the CPU registers OK or ENN
@@ -131,12 +131,16 @@ static int kgdb_started;
static u_int fault_jmp_buf[100];
static int kdebug;
+
static const char hexchars[]="0123456789abcdef";
/* Place where we save old trap entries for restoration - sparc*/
/* struct tt_entry kgdb_savettable[256]; */
/* typedef void (*trapfunc_t)(void); */
+static void kgdb_fault_handler(struct pt_regs *regs);
+static void handle_exception (struct pt_regs *regs);
+
#if 0
/* Install an exception handler for kgdb */
static void exceptionHandler(int tnum, unsigned int *tfunc)
@@ -188,14 +192,45 @@ static unsigned char *
mem2hex(char *mem, char *buf, int count)
{
unsigned char ch;
+ unsigned short tmp_s;
+ unsigned long tmp_l;
if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
debugger_fault_handler = kgdb_fault_handler;
- while (count-- > 0) {
- ch = *mem++;
- *buf++ = hexchars[ch >> 4];
- *buf++ = hexchars[ch & 0xf];
+
+ /* Accessing 16 bit and 32 bit objects in a single
+ ** load instruction is required to avoid bad side
+ ** effects for some IO registers.
+ */
+
+ if ((count == 2) && (((long)mem & 1) == 0)) {
+ tmp_s = *(unsigned short *)mem;
+ mem += 2;
+ *buf++ = hexchars[(tmp_s >> 12) & 0xf];
+ *buf++ = hexchars[(tmp_s >> 8) & 0xf];
+ *buf++ = hexchars[(tmp_s >> 4) & 0xf];
+ *buf++ = hexchars[tmp_s & 0xf];
+
+ } else if ((count == 4) && (((long)mem & 3) == 0)) {
+ tmp_l = *(unsigned int *)mem;
+ mem += 4;
+ *buf++ = hexchars[(tmp_l >> 28) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 24) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 20) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 16) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 12) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 8) & 0xf];
+ *buf++ = hexchars[(tmp_l >> 4) & 0xf];
+ *buf++ = hexchars[tmp_l & 0xf];
+
+ } else {
+ while (count-- > 0) {
+ ch = *mem++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
}
+
} else {
/* error condition */
}
@@ -210,17 +245,58 @@ mem2hex(char *mem, char *buf, int count)
static char *
hex2mem(char *buf, char *mem, int count)
{
- int i;
unsigned char ch;
+ int i;
+ char *orig_mem;
+ unsigned short tmp_s;
+ unsigned long tmp_l;
+
+ orig_mem = mem;
if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
debugger_fault_handler = kgdb_fault_handler;
- for (i=0; i<count; i++) {
- ch = hex(*buf++) << 4;
- ch |= hex(*buf++);
- *mem++ = ch;
+
+ /* Accessing 16 bit and 32 bit objects in a single
+ ** store instruction is required to avoid bad side
+ ** effects for some IO registers.
+ */
+
+ if ((count == 2) && (((long)mem & 1) == 0)) {
+ tmp_s = hex(*buf++) << 12;
+ tmp_s |= hex(*buf++) << 8;
+ tmp_s |= hex(*buf++) << 4;
+ tmp_s |= hex(*buf++);
+
+ *(unsigned short *)mem = tmp_s;
+ mem += 2;
+
+ } else if ((count == 4) && (((long)mem & 3) == 0)) {
+ tmp_l = hex(*buf++) << 28;
+ tmp_l |= hex(*buf++) << 24;
+ tmp_l |= hex(*buf++) << 20;
+ tmp_l |= hex(*buf++) << 16;
+ tmp_l |= hex(*buf++) << 12;
+ tmp_l |= hex(*buf++) << 8;
+ tmp_l |= hex(*buf++) << 4;
+ tmp_l |= hex(*buf++);
+
+ *(unsigned long *)mem = tmp_l;
+ mem += 4;
+
+ } else {
+ for (i=0; i<count; i++) {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ *mem++ = ch;
+ }
}
- flush_icache_range((int)mem, (int)mem+count);
+
+
+ /*
+ ** Flush the data cache, invalidate the instruction cache.
+ */
+ flush_icache_range((int)orig_mem, (int)orig_mem + count - 1);
+
} else {
/* error condition */
}
@@ -253,14 +329,14 @@ hexToInt(char **ptr, int *intValue)
(*ptr)++;
}
} else {
- /* error condition */
+ /* error condition */
}
debugger_fault_handler = 0;
return (numChars);
}
-/* scan for the sequence $<data>#<checksum> */
+/* scan for the sequence $<data>#<checksum> */
static void
getpacket(char *buffer)
{
@@ -316,14 +392,14 @@ getpacket(char *buffer)
} while (checksum != xmitcsum);
}
-/* send the packet in buffer. */
+/* send the packet in buffer. */
static void putpacket(unsigned char *buffer)
{
unsigned char checksum;
int count;
unsigned char ch, recv;
- /* $<packet info>#<checksum>. */
+ /* $<packet info>#<checksum>. */
do {
putDebugChar('$');
checksum = 0;
@@ -428,7 +504,7 @@ int kgdb_dabr_match(struct pt_regs *regs)
return 1;
}
-/* Convert the SPARC hardware trap type code to a unix signal number. */
+/* Convert the hardware trap type code to a unix signal number. */
/*
* This table contains the mapping between PowerPC hardware trap types, and
* signals, which are primarily what GDB understands.
@@ -438,20 +514,47 @@ static struct hard_trap_info
unsigned int tt; /* Trap type code for powerpc */
unsigned char signo; /* Signal that we map this trap into */
} hard_trap_info[] = {
- { 0x200, SIGSEGV }, /* machine check */
- { 0x300, SIGSEGV }, /* address error (store) */
- { 0x400, SIGBUS }, /* instruction bus error */
- { 0x500, SIGINT }, /* interrupt */
- { 0x600, SIGBUS }, /* alingment */
- { 0x700, SIGTRAP }, /* breakpoint trap */
- { 0x800, SIGFPE }, /* fpu unavail */
- { 0x900, SIGALRM }, /* decrementer */
- { 0xa00, SIGILL }, /* reserved */
- { 0xb00, SIGILL }, /* reserved */
- { 0xc00, SIGCHLD }, /* syscall */
- { 0xd00, SIGTRAP }, /* single-step/watch */
- { 0xe00, SIGFPE }, /* fp assist */
+#if defined(CONFIG_4xx)
+ { 0x100, SIGINT }, /* critical input interrupt */
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* data storage */
+ { 0x400, SIGBUS }, /* instruction storage */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alignment */
+ { 0x700, SIGILL }, /* program */
+ { 0x800, SIGILL }, /* reserved */
+ { 0x900, SIGILL }, /* reserved */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGILL }, /* reserved */
+ { 0xe00, SIGILL }, /* reserved */
+ { 0xf00, SIGILL }, /* reserved */
+ /*
+ ** 0x1000 PIT
+ ** 0x1010 FIT
+ ** 0x1020 watchdog
+ ** 0x1100 data TLB miss
+ ** 0x1200 instruction TLB miss
+ */
+ { 0x2000, SIGTRAP}, /* debug */
+#else
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* address error (store) */
+ { 0x400, SIGBUS }, /* instruction bus error */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alingment */
+ { 0x700, SIGTRAP }, /* breakpoint trap */
+ { 0x800, SIGFPE }, /* fpu unavail */
+ { 0x900, SIGALRM }, /* decrementer */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGTRAP }, /* single-step/watch */
+ { 0xe00, SIGFPE }, /* fp assist */
+#endif
{ 0, 0} /* Must be last */
+
};
static int computeSignal(unsigned int tt)
@@ -462,7 +565,7 @@ static int computeSignal(unsigned int tt)
if (ht->tt == tt)
return ht->signo;
- return SIGHUP; /* default for things we don't know about */
+ return SIGHUP; /* default for things we don't know about */
}
#define PC_REGNUM 64
@@ -493,7 +596,7 @@ handle_exception (struct pt_regs *regs)
#ifdef KGDB_DEBUG
printk("kgdb: entering handle_exception; trap [0x%x]\n",
- (unsigned int)regs->trap);
+ (unsigned int)regs->trap);
#endif
kgdb_interruptible(0);
@@ -510,7 +613,7 @@ handle_exception (struct pt_regs *regs)
sigval = computeSignal(regs->trap);
ptr = remcomOutBuffer;
-#if 0
+#if defined(CONFIG_4xx)
*ptr++ = 'S';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
@@ -533,6 +636,8 @@ handle_exception (struct pt_regs *regs)
*ptr++ = 0;
putpacket(remcomOutBuffer);
+ if (kdebug)
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
/* XXX We may want to add some features dealing with poking the
* XXX page tables, ... (look at sparc-stub.c for more info)
@@ -544,7 +649,7 @@ handle_exception (struct pt_regs *regs)
getpacket(remcomInBuffer);
switch (remcomInBuffer[0]) {
- case '?': /* report most recent signal */
+ case '?': /* report most recent signal */
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval & 0xf];
@@ -601,7 +706,7 @@ handle_exception (struct pt_regs *regs)
}
break;
- case 'G': /* set the value of the CPU registers */
+ case 'G': /* set the value of the CPU registers */
{
ptr = &remcomInBuffer[1];
@@ -639,15 +744,14 @@ handle_exception (struct pt_regs *regs)
ptr = &remcomInBuffer[1];
- if (hexToInt(&ptr, &addr)
- && *ptr++ == ','
- && hexToInt(&ptr, &length)) {
- if (mem2hex((char *)addr, remcomOutBuffer,length))
+ if (hexToInt(&ptr, &addr) && *ptr++ == ','
+ && hexToInt(&ptr, &length)) {
+ if (mem2hex((char *)addr, remcomOutBuffer,
+ length))
break;
- strcpy (remcomOutBuffer, "E03");
- } else {
- strcpy(remcomOutBuffer,"E01");
- }
+ strcpy(remcomOutBuffer, "E03");
+ } else
+ strcpy(remcomOutBuffer, "E01");
break;
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
@@ -655,50 +759,63 @@ handle_exception (struct pt_regs *regs)
ptr = &remcomInBuffer[1];
- if (hexToInt(&ptr, &addr)
- && *ptr++ == ','
- && hexToInt(&ptr, &length)
- && *ptr++ == ':') {
- if (hex2mem(ptr, (char *)addr, length)) {
+ if (hexToInt(&ptr, &addr) && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':') {
+ if (hex2mem(ptr, (char *)addr, length))
strcpy(remcomOutBuffer, "OK");
- } else {
+ else
strcpy(remcomOutBuffer, "E03");
- }
flush_icache_range(addr, addr+length);
- } else {
+ } else
strcpy(remcomOutBuffer, "E02");
- }
break;
- case 'k': /* kill the program, actually just continue */
- case 'c': /* cAA..AA Continue; address AA..AA optional */
+ case 'k': /* kill the program, actually just continue */
+ case 'c': /* cAA..AA Continue; address AA..AA optional */
/* try to read optional parameter, pc unchanged if no parm */
ptr = &remcomInBuffer[1];
- if (hexToInt(&ptr, &addr)) {
+ if (hexToInt(&ptr, &addr))
regs->nip = addr;
- }
/* Need to flush the instruction cache here, as we may have deposited a
* breakpoint, and the icache probably has no way of knowing that a data ref to
* some location may have changed something that is in the instruction cache.
*/
kgdb_flush_cache_all();
+#if defined(CONFIG_4xx)
+ strcpy(remcomOutBuffer, "OK");
+ putpacket(remcomOutBuffer);
+#endif
set_msr(msr);
+
kgdb_interruptible(1);
unlock_kernel();
kgdb_active = 0;
+ if (kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
return;
case 's':
kgdb_flush_cache_all();
+#if defined(CONFIG_4xx)
+ regs->msr |= MSR_DE;
+ regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC);
+ set_msr(msr);
+#else
regs->msr |= MSR_SE;
-#if 0
set_msr(msr | MSR_SE);
#endif
unlock_kernel();
kgdb_active = 0;
+ if (kdebug) {
+ printk("remcomInBuffer: %s\n", remcomInBuffer);
+ printk("remcomOutBuffer: %s\n", remcomOutBuffer);
+ }
return;
case 'r': /* Reset (if user process..exit ???)*/
@@ -729,7 +846,7 @@ breakpoint(void)
asm(" .globl breakinst
breakinst: .long 0x7d821008
- ");
+ ");
}
/* Output string in GDB O-packet format if GDB has connected. If nothing
@@ -739,24 +856,23 @@ kgdb_output_string (const char* s, unsigned int count)
{
char buffer[512];
- if (!kgdb_started)
- return 0;
+ if (!kgdb_started)
+ return 0;
- count = (count <= (sizeof(buffer) / 2 - 2))
+ count = (count <= (sizeof(buffer) / 2 - 2))
? count : (sizeof(buffer) / 2 - 2);
buffer[0] = 'O';
mem2hex (s, &buffer[1], count);
putpacket(buffer);
- return 1;
+ return 1;
}
-#ifndef CONFIG_8xx
+#if defined(CONFIG_6xx) || defined(CONFIG_POWER3) || defined(CONFIG_ISERIES)
-/* I don't know why other platforms don't need this. The function for
- * the 8xx is found in arch/ppc/8xx_io/uart.c. -- Dan
- */
+/* This is used on arches which don't have a serial driver that maps
+ * the ports for us */
void
kgdb_map_scc(void)
{
diff --git a/arch/ppc/kernel/ppc405_dma.c b/arch/ppc/kernel/ppc405_dma.c
new file mode 100755
index 000000000000..8cec3683a926
--- /dev/null
+++ b/arch/ppc/kernel/ppc405_dma.c
@@ -0,0 +1,511 @@
+/*
+ * linux/arch/ppc/kernel/ppc405_dma.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * IBM 405 DMA Controller Functions
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.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 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/ppc405_dma.h>
+
+
+/*
+ * Function prototypes
+ */
+
+int hw_init_dma_channel(unsigned int, ppc_dma_ch_t *);
+int init_dma_channel(unsigned int);
+int get_channel_config(unsigned int, ppc_dma_ch_t *);
+int set_channel_priority(unsigned int, unsigned int);
+unsigned int get_peripheral_width(unsigned int);
+int alloc_dma_handle(sgl_handle_t *, unsigned int, unsigned int);
+void free_dma_handle(sgl_handle_t);
+
+
+ppc_dma_ch_t dma_channels[MAX_405GP_DMA_CHANNELS];
+
+/*
+ * Configures a DMA channel, including the peripheral bus width, if a
+ * peripheral is attached to the channel, the polarity of the DMAReq and
+ * DMAAck signals, etc. This information should really be setup by the boot
+ * code, since most likely the configuration won't change dynamically.
+ * If the kernel has to call this function, it's recommended that it's
+ * called from platform specific init code. The driver should not need to
+ * call this function.
+ */
+int hw_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t *p_init)
+{
+ unsigned int polarity;
+ uint32_t control = 0;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+#ifdef DEBUG_405DMA
+ if (!p_init) {
+ printk("hw_init_dma_channel: NULL p_init\n");
+ return DMA_STATUS_NULL_POINTER;
+ }
+ if (dmanr >= MAX_405GP_DMA_CHANNELS) {
+ printk("hw_init_dma_channel: bad channel %d\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+#endif
+
+#if DCRN_POL > 0
+ polarity = mfdcr(DCRN_POL);
+#else
+ polarity = 0;
+#endif
+
+ /* Setup the control register based on the values passed to
+ * us in p_init. Then, over-write the control register with this
+ * new value.
+ */
+
+ control |= (
+ SET_DMA_CIE_ENABLE(p_init->int_enable) | /* interrupt enable */
+ SET_DMA_BEN(p_init->buffer_enable) | /* buffer enable */
+ SET_DMA_ETD(p_init->etd_output) | /* end of transfer pin */
+ SET_DMA_TCE(p_init->tce_enable) | /* terminal count enable */
+ SET_DMA_PL(p_init->pl) | /* peripheral location */
+ SET_DMA_DAI(p_init->dai) | /* dest addr increment */
+ SET_DMA_SAI(p_init->sai) | /* src addr increment */
+ SET_DMA_PRIORITY(p_init->cp) | /* channel priority */
+ SET_DMA_PW(p_init->pwidth) | /* peripheral/bus width */
+ SET_DMA_PSC(p_init->psc) | /* peripheral setup cycles */
+ SET_DMA_PWC(p_init->pwc) | /* peripheral wait cycles */
+ SET_DMA_PHC(p_init->phc) | /* peripheral hold cycles */
+ SET_DMA_PREFETCH(p_init->pf) /* read prefetch */
+ );
+
+ switch (dmanr) {
+ case 0:
+ /* clear all polarity signals and then "or" in new signal levels */
+ polarity &= ~(DMAReq0_ActiveLow | DMAAck0_ActiveLow | EOT0_ActiveLow);
+ polarity |= p_dma_ch->polarity;
+#if DCRN_POL > 0
+ mtdcr(DCRN_POL, polarity);
+#endif
+ mtdcr(DCRN_DMACR0, control);
+ break;
+ case 1:
+ polarity &= ~(DMAReq1_ActiveLow | DMAAck1_ActiveLow | EOT1_ActiveLow);
+ polarity |= p_dma_ch->polarity;
+#if DCRN_POL > 0
+ mtdcr(DCRN_POL, polarity);
+#endif
+ mtdcr(DCRN_DMACR1, control);
+ break;
+ case 2:
+ polarity &= ~(DMAReq2_ActiveLow | DMAAck2_ActiveLow | EOT2_ActiveLow);
+ polarity |= p_dma_ch->polarity;
+#if DCRN_POL > 0
+ mtdcr(DCRN_POL, polarity);
+#endif
+ mtdcr(DCRN_DMACR2, control);
+ break;
+ case 3:
+ polarity &= ~(DMAReq3_ActiveLow | DMAAck3_ActiveLow | EOT3_ActiveLow);
+ polarity |= p_dma_ch->polarity;
+#if DCRN_POL > 0
+ mtdcr(DCRN_POL, polarity);
+#endif
+ mtdcr(DCRN_DMACR3, control);
+ break;
+ default:
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ /* save these values in our dma channel structure */
+ memcpy(p_dma_ch, p_init, sizeof(ppc_dma_ch_t));
+
+ /*
+ * The peripheral width values written in the control register are:
+ * PW_8 0
+ * PW_16 1
+ * PW_32 2
+ * PW_64 3
+ *
+ * Since the DMA count register takes the number of "transfers",
+ * we need to divide the count sent to us in certain
+ * functions by the appropriate number. It so happens that our
+ * right shift value is equal to the peripheral width value.
+ */
+ p_dma_ch->shift = p_init->pwidth;
+
+ /*
+ * Save the control word for easy access.
+ */
+ p_dma_ch->control = control;
+
+ mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */
+ return DMA_STATUS_GOOD;
+}
+
+
+
+
+/*
+ * This function returns the channel configuration.
+ */
+int get_channel_config(unsigned int dmanr, ppc_dma_ch_t *p_dma_ch)
+{
+ unsigned int polarity;
+ unsigned int control;
+
+#if DCRN_POL > 0
+ polarity = mfdcr(DCRN_POL);
+#else
+ polarity = 0;
+#endif
+
+ switch (dmanr) {
+ case 0:
+ p_dma_ch->polarity =
+ polarity & (DMAReq0_ActiveLow | DMAAck0_ActiveLow | EOT0_ActiveLow);
+ control = mfdcr(DCRN_DMACR0);
+ break;
+ case 1:
+ p_dma_ch->polarity =
+ polarity & (DMAReq1_ActiveLow | DMAAck1_ActiveLow | EOT1_ActiveLow);
+ control = mfdcr(DCRN_DMACR1);
+ break;
+ case 2:
+ p_dma_ch->polarity =
+ polarity & (DMAReq2_ActiveLow | DMAAck2_ActiveLow | EOT2_ActiveLow);
+ control = mfdcr(DCRN_DMACR2);
+ break;
+ case 3:
+ p_dma_ch->polarity =
+ polarity & (DMAReq3_ActiveLow | DMAAck3_ActiveLow | EOT3_ActiveLow);
+ control = mfdcr(DCRN_DMACR3);
+ break;
+ default:
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ p_dma_ch->cp = GET_DMA_PRIORITY(control);
+ p_dma_ch->pwidth = GET_DMA_PW(control);
+ p_dma_ch->psc = GET_DMA_PSC(control);
+ p_dma_ch->pwc = GET_DMA_PWC(control);
+ p_dma_ch->phc = GET_DMA_PHC(control);
+ p_dma_ch->pf = GET_DMA_PREFETCH(control);
+ p_dma_ch->int_enable = GET_DMA_CIE_ENABLE(control);
+ p_dma_ch->shift = GET_DMA_PW(control);
+
+ return DMA_STATUS_GOOD;
+}
+
+/*
+ * Sets the priority for the DMA channel dmanr.
+ * Since this is setup by the hardware init function, this function
+ * can be used to dynamically change the priority of a channel.
+ *
+ * Acceptable priorities:
+ *
+ * PRIORITY_LOW
+ * PRIORITY_MID_LOW
+ * PRIORITY_MID_HIGH
+ * PRIORITY_HIGH
+ *
+ */
+int set_channel_priority(unsigned int dmanr, unsigned int priority)
+{
+ unsigned int control;
+
+#ifdef DEBUG_405DMA
+ if ( (priority != PRIORITY_LOW) &&
+ (priority != PRIORITY_MID_LOW) &&
+ (priority != PRIORITY_MID_HIGH) &&
+ (priority != PRIORITY_HIGH)) {
+ printk("set_channel_priority: bad priority: 0x%x\n", priority);
+ }
+#endif
+
+ switch (dmanr) {
+ case 0:
+ control = mfdcr(DCRN_DMACR0);
+ control|= SET_DMA_PRIORITY(priority);
+ mtdcr(DCRN_DMACR0, control);
+ break;
+ case 1:
+ control = mfdcr(DCRN_DMACR1);
+ control|= SET_DMA_PRIORITY(priority);
+ mtdcr(DCRN_DMACR1, control);
+ break;
+ case 2:
+ control = mfdcr(DCRN_DMACR2);
+ control|= SET_DMA_PRIORITY(priority);
+ mtdcr(DCRN_DMACR2, control);
+ break;
+ case 3:
+ control = mfdcr(DCRN_DMACR3);
+ control|= SET_DMA_PRIORITY(priority);
+ mtdcr(DCRN_DMACR3, control);
+ break;
+ default:
+#ifdef DEBUG_405DMA
+ printk("set_channel_priority: bad channel: %d\n", dmanr);
+#endif
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+ return DMA_STATUS_GOOD;
+}
+
+
+
+/*
+ * Returns the width of the peripheral attached to this channel. This assumes
+ * that someone who knows the hardware configuration, boot code or some other
+ * init code, already set the width.
+ *
+ * The return value is one of:
+ * PW_8
+ * PW_16
+ * PW_32
+ * PW_64
+ *
+ * The function returns 0 on error.
+ */
+unsigned int get_peripheral_width(unsigned int dmanr)
+{
+ unsigned int control;
+
+ switch (dmanr) {
+ case 0:
+ control = mfdcr(DCRN_DMACR0);
+ break;
+ case 1:
+ control = mfdcr(DCRN_DMACR1);
+ break;
+ case 2:
+ control = mfdcr(DCRN_DMACR2);
+ break;
+ case 3:
+ control = mfdcr(DCRN_DMACR3);
+ break;
+ default:
+#ifdef DEBUG_405DMA
+ printk("get_peripheral_width: bad channel: %d\n", dmanr);
+#endif
+ return 0;
+ }
+ return(GET_DMA_PW(control));
+}
+
+
+
+
+/*
+ * Create a scatter/gather list handle. This is simply a structure which
+ * describes a scatter/gather list.
+ *
+ * A handle is returned in "handle" which the driver should save in order to
+ * be able to access this list later. A chunk of memory will be allocated
+ * to be used by the API for internal management purposes, including managing
+ * the sg list and allocating memory for the sgl descriptors. One page should
+ * be more than enough for that purpose. Perhaps it's a bit wasteful to use
+ * a whole page for a single sg list, but most likely there will be only one
+ * sg list per channel.
+ *
+ * Interrupt notes:
+ * Each sgl descriptor has a copy of the DMA control word which the DMA engine
+ * loads in the control register. The control word has a "global" interrupt
+ * enable bit for that channel. Interrupts are further qualified by a few bits
+ * in the sgl descriptor count register. In order to setup an sgl, we have to
+ * know ahead of time whether or not interrupts will be enabled at the completion
+ * of the transfers. Thus, enable_dma_interrupt()/disable_dma_interrupt() MUST
+ * be called before calling alloc_dma_handle(). If the interrupt mode will never
+ * change after powerup, then enable_dma_interrupt()/disable_dma_interrupt()
+ * do not have to be called -- interrupts will be enabled or disabled based
+ * on how the channel was configured after powerup by the hw_init_dma_channel()
+ * function. Each sgl descriptor will be setup to interrupt if an error occurs;
+ * however, only the last descriptor will be setup to interrupt. Thus, an
+ * interrupt will occur (if interrupts are enabled) only after the complete
+ * sgl transfer is done.
+ */
+int alloc_dma_handle(sgl_handle_t *phandle, unsigned int mode, unsigned int dmanr)
+{
+ sgl_list_info_t *psgl;
+ dma_addr_t dma_addr;
+ ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+ uint32_t sg_command;
+ void *ret;
+
+#ifdef DEBUG_405DMA
+ if (!phandle) {
+ printk("alloc_dma_handle: null handle pointer\n");
+ return DMA_STATUS_NULL_POINTER;
+ }
+ switch (mode) {
+ case DMA_MODE_READ:
+ case DMA_MODE_WRITE:
+ case DMA_MODE_MM:
+ case DMA_MODE_MM_DEVATSRC:
+ case DMA_MODE_MM_DEVATDST:
+ break;
+ default:
+ printk("alloc_dma_handle: bad mode 0x%x\n", mode);
+ return DMA_STATUS_BAD_MODE;
+ }
+ if (dmanr >= MAX_405GP_DMA_CHANNELS) {
+ printk("alloc_dma_handle: invalid channel 0x%x\n", dmanr);
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+#endif
+
+ /* Get a page of memory, which is zeroed out by pci_alloc_consistent() */
+
+/* wrong not a pci device - armin */
+ /* psgl = (sgl_list_info_t *) pci_alloc_consistent(NULL, SGL_LIST_SIZE, &dma_addr);
+*/
+
+ ret = consistent_alloc(GFP_ATOMIC |GFP_DMA, SGL_LIST_SIZE, &dma_addr);
+ if (ret != NULL) {
+ memset(ret, 0,SGL_LIST_SIZE );
+ psgl = (sgl_list_info_t *) ret;
+ }
+
+
+ if (psgl == NULL) {
+ *phandle = (sgl_handle_t)NULL;
+ return DMA_STATUS_OUT_OF_MEMORY;
+ }
+
+ psgl->dma_addr = dma_addr;
+ psgl->dmanr = dmanr;
+
+ /*
+ * Modify and save the control word. These word will get written to each sgl
+ * descriptor. The DMA engine then loads this control word into the control
+ * register every time it reads a new descriptor.
+ */
+ psgl->control = p_dma_ch->control;
+ psgl->control &= ~(DMA_TM_MASK | DMA_TD); /* clear all "mode" bits first */
+ psgl->control |= (mode | DMA_CH_ENABLE); /* save the control word along with the mode */
+
+ if (p_dma_ch->int_enable) {
+ psgl->control |= DMA_CIE_ENABLE; /* channel interrupt enabled */
+ }
+ else {
+ psgl->control &= ~DMA_CIE_ENABLE;
+ }
+
+#if DCRN_ASGC > 0
+ sg_command = mfdcr(DCRN_ASGC);
+ switch (dmanr) {
+ case 0:
+ sg_command |= SSG0_MASK_ENABLE;
+ break;
+ case 1:
+ sg_command |= SSG1_MASK_ENABLE;
+ break;
+ case 2:
+ sg_command |= SSG2_MASK_ENABLE;
+ break;
+ case 3:
+ sg_command |= SSG3_MASK_ENABLE;
+ break;
+ default:
+#ifdef DEBUG_405DMA
+ printk("alloc_dma_handle: bad channel: %d\n", dmanr);
+#endif
+ free_dma_handle((sgl_handle_t)psgl);
+ *phandle = (sgl_handle_t)NULL;
+ return DMA_STATUS_BAD_CHANNEL;
+ }
+
+ mtdcr(DCRN_ASGC, sg_command); /* enable writing to this channel's sgl control bits */
+#else
+ (void)sg_command;
+#endif
+ psgl->sgl_control = SG_ERI_ENABLE | SG_LINK; /* sgl descriptor control bits */
+
+ if (p_dma_ch->int_enable) {
+ if (p_dma_ch->tce_enable)
+ psgl->sgl_control |= SG_TCI_ENABLE;
+ else
+ psgl->sgl_control |= SG_ETI_ENABLE;
+ }
+
+ *phandle = (sgl_handle_t)psgl;
+ return DMA_STATUS_GOOD;
+}
+
+
+
+/*
+ * Destroy a scatter/gather list handle that was created by alloc_dma_handle().
+ * The list must be empty (contain no elements).
+ */
+void free_dma_handle(sgl_handle_t handle)
+{
+ sgl_list_info_t *psgl = (sgl_list_info_t *)handle;
+
+ if (!handle) {
+#ifdef DEBUG_405DMA
+ printk("free_dma_handle: got NULL\n");
+#endif
+ return;
+ }
+ else if (psgl->phead) {
+#ifdef DEBUG_405DMA
+ printk("free_dma_handle: list not empty\n");
+#endif
+ return;
+ }
+ else if (!psgl->dma_addr) { /* should never happen */
+#ifdef DEBUG_405DMA
+ printk("free_dma_handle: no dma address\n");
+#endif
+ return;
+ }
+
+ /* wrong not a PCI device -armin */
+ /* pci_free_consistent(NULL, SGL_LIST_SIZE, (void *)psgl, psgl->dma_addr); */
+ // free_pages((unsigned long)psgl, get_order(SGL_LIST_SIZE));
+ consistent_free((void *)psgl);
+
+
+}
+
+
+EXPORT_SYMBOL(hw_init_dma_channel);
+EXPORT_SYMBOL(get_channel_config);
+EXPORT_SYMBOL(set_channel_priority);
+EXPORT_SYMBOL(get_peripheral_width);
+EXPORT_SYMBOL(alloc_dma_handle);
+EXPORT_SYMBOL(free_dma_handle);
+EXPORT_SYMBOL(dma_channels);
diff --git a/arch/ppc/kernel/ppc405_pci.c b/arch/ppc/kernel/ppc405_pci.c
new file mode 100755
index 000000000000..2e0bd345f4c9
--- /dev/null
+++ b/arch/ppc/kernel/ppc405_pci.c
@@ -0,0 +1,207 @@
+/*
+ * FILE NAME: ppc405_pci.c
+ *
+ * BRIEF MODULE DESCRIPTION:
+ * Based on arch/ppc/kernel/indirect.c, Copyright (C) 1998 Gabriel Paubert.
+ *
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ * Frank Rowand <frank_rowand@mvista.com>
+ * Debbie Chu <debbie_chu@mvista.com>
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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/pci.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <linux/init.h>
+#include <asm/ibm4xx.h>
+#include <asm/pci-bridge.h>
+#include <platforms/ibm_ocp.h>
+
+#ifdef CONFIG_DEBUG_BRINGUP
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern void bios_fixup(struct pci_controller *, void *);
+extern int ppc405_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin);
+extern struct pcil0_regs *PCIL_ADDR[];
+
+void
+ppc405_pcibios_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+ unsigned long max_host_addr;
+ unsigned long min_host_addr;
+ struct resource *res;
+
+ /*
+ * openbios puts some graphics cards in the same range as the host
+ * controller uses to map to SDRAM. Fix it.
+ */
+
+ min_host_addr = 0;
+ max_host_addr = PPC405_PCI_MEM_BASE - 1;
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ res = dev->resource + i;
+ if (!res->start)
+ continue;
+ if ((res->flags & IORESOURCE_MEM) &&
+ (((res->start >= min_host_addr)
+ && (res->start <= max_host_addr))
+ || ((res->end >= min_host_addr)
+ && (res->end <= max_host_addr))
+ || ((res->start < min_host_addr)
+ && (res->end > max_host_addr))
+ )
+ ) {
+
+ DBG(KERN_ERR "PCI: 0x%lx <= resource[%d] <= 0x%lx"
+ ", bus 0x%x dev 0x%2.2x.%1.1x,\n"
+ KERN_ERR " %s\n"
+ KERN_ERR " fixup will be attempted later\n",
+ min_host_addr, i, max_host_addr,
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), dev->name);
+
+ /* force pcibios_assign_resources() to assign a new address */
+ res->end -= res->start;
+ res->start = 0;
+ }
+ }
+}
+
+static int
+ppc4xx_exclude_device(unsigned char bus, unsigned char devfn)
+{
+ /* We prevent us from seeing ourselves to avoid having
+ * the kernel try to remap our BAR #1 and fuck up bus
+ * master from external PCI devices
+ */
+ return (bus == 0 && devfn == 0);
+}
+
+void
+ppc4xx_find_bridges(void)
+{
+ struct pci_controller *hose_a;
+ struct pcil0_regs *pcip;
+ unsigned int tmp_addr;
+ unsigned int tmp_size;
+ unsigned int reg_index;
+ unsigned int new_pmm_max;
+ unsigned int new_pmm_min;
+
+ isa_io_base = 0;
+ isa_mem_base = 0;
+ pci_dram_offset = 0;
+
+ /* Check if running in slave mode */
+ if ((mfdcr(DCRN_CHPSR) & PSR_PCI_ARBIT_EN) == 0) {
+ printk("Running as PCI slave, kernel PCI disabled !\n");
+ return;
+ }
+ /* Setup PCI32 hose */
+ hose_a = pcibios_alloc_controller();
+ if (!hose_a)
+ return;
+ setup_indirect_pci(hose_a, PPC405_PCI_CONFIG_ADDR,
+ PPC405_PCI_CONFIG_DATA);
+ pcip = ioremap((unsigned long) PCIL_ADDR[0], PAGE_SIZE);
+ if (pcip != NULL) {
+
+#if defined(CONFIG_BIOS_FIXUP)
+ bios_fixup(hose_a, pcip);
+#endif
+ new_pmm_min = 0xffffffff;
+ for (reg_index = 0; reg_index < 3; reg_index++) {
+ tmp_size = in_le32((void *) &(pcip->pmm[reg_index].ma)); // *_PMM0MA
+ if (tmp_size & 0x1) {
+ tmp_addr = in_le32((void *) &(pcip->pmm[reg_index].pcila)); // *_PMM0PCILA
+ if (tmp_addr < PPC405_PCI_PHY_MEM_BASE) {
+ printk(KERN_DEBUG
+ "Disabling mapping to PCI mem addr 0x%8.8x\n",
+ tmp_addr);
+ out_le32((void *) &(pcip->pmm[reg_index].ma), tmp_size & ~1); // *_PMMOMA
+ } else {
+ tmp_addr = in_le32((void *) &(pcip->pmm[reg_index].la)); // *_PMMOLA
+ if (tmp_addr < new_pmm_min)
+ new_pmm_min = tmp_addr;
+ tmp_addr =
+ tmp_addr + (0xffffffff -
+ (tmp_size &
+ 0xffffc000));
+ if (tmp_addr > PPC405_PCI_UPPER_MEM) {
+ new_pmm_max = tmp_addr; // PPC405_PCI_UPPER_MEM
+ } else {
+ new_pmm_max =
+ PPC405_PCI_UPPER_MEM;
+ }
+ }
+ }
+
+ } // for
+
+ iounmap(pcip);
+ }
+ hose_a->first_busno = 0;
+ hose_a->last_busno = 0xff;
+ hose_a->pci_mem_offset = 0;
+
+ /* Setup bridge memory/IO ranges & resources
+ * TODO: Handle firmwares setting up a legacy ISA mem base
+ */
+ hose_a->io_space.start = PPC405_PCI_LOWER_IO;
+ hose_a->io_space.end = PPC405_PCI_UPPER_IO;
+ hose_a->mem_space.start = new_pmm_min;
+ hose_a->mem_space.end = new_pmm_max;
+ hose_a->io_base_phys = PPC405_PCI_PHY_IO_BASE;
+ hose_a->io_base_virt = ioremap(hose_a->io_base_phys, 0x10000);
+ hose_a->io_resource.start = 0;
+ hose_a->io_resource.end = PPC405_PCI_UPPER_IO-PPC405_PCI_LOWER_IO;
+ hose_a->io_resource.flags = IORESOURCE_IO;
+ hose_a->io_resource.name = "PCI I/O";
+ hose_a->mem_resources[0].start = new_pmm_min;
+ hose_a->mem_resources[0].end = new_pmm_max;
+ hose_a->mem_resources[0].flags = IORESOURCE_MEM;
+ hose_a->mem_resources[0].name = "PCI Memory";
+ isa_io_base = (int)hose_a->io_base_virt;
+ isa_mem_base = 0; /* ISA not implemented */
+ ISA_DMA_THRESHOLD = 0x00ffffff; /* ??? ISA not implemented */
+
+ /* Scan busses & initial setup by pci_auto */
+ hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+ hose_a->last_busno = 0;
+
+ /* Setup ppc_md */
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pci_exclude_device = ppc4xx_exclude_device;
+ ppc_md.pcibios_fixup_resources = ppc405_pcibios_fixup_resources;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ppc405_map_irq;
+}
diff --git a/arch/ppc/kernel/ppc4xx_kgdb.c b/arch/ppc/kernel/ppc4xx_kgdb.c
new file mode 100644
index 000000000000..810a0310a1e8
--- /dev/null
+++ b/arch/ppc/kernel/ppc4xx_kgdb.c
@@ -0,0 +1,124 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/ibm4xx.h>
+#include <linux/kernel.h>
+
+
+
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+#include <platforms/ibm_ocp.h>
+
+extern struct NS16550* COM_PORTS[];
+#ifndef NULL
+#define NULL 0x00
+#endif
+
+static volatile struct NS16550 *kgdb_debugport = NULL;
+
+volatile struct NS16550 *
+NS16550_init(int chan)
+{
+ volatile struct NS16550 *com_port;
+ int quot;
+#ifdef BASE_BAUD
+ quot = BASE_BAUD / 9600;
+#else
+ quot = 0x000c; /* 0xc = 9600 baud (on a pc) */
+#endif
+
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+
+ com_port->lcr = 0x00;
+ com_port->ier = 0xFF;
+ com_port->ier = 0x00;
+ com_port->lcr = com_port->lcr | 0x80; /* Access baud rate */
+ com_port->dll = ( quot & 0x00ff ); /* 0xc = 9600 baud */
+ com_port->dlm = ( quot & 0xff00 ) >> 8;
+ com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
+ com_port->mcr = 0x00; /* RTS/DTR */
+ com_port->fcr = 0x07; /* Clear & enable FIFOs */
+
+ return( com_port );
+}
+
+
+void
+NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ while ((com_port->lsr & LSR_THRE) == 0)
+ ;
+ com_port->thr = c;
+ return;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0)
+ ;
+ return (com_port->rbr);
+}
+
+unsigned char
+NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#elif defined(CONFIG_KGDB_TTYS2)
+#define KGDB_PORT 2
+#elif defined(CONFIG_KGDB_TTYS3)
+#define KGDB_PORT 3
+#else
+#error "invalid kgdb_tty port"
+#endif
+
+void putDebugChar( unsigned char c )
+{
+ if ( kgdb_debugport == NULL )
+ kgdb_debugport = NS16550_init(KGDB_PORT);
+ NS16550_putc( kgdb_debugport, c );
+}
+
+int getDebugChar( void )
+{
+ if (kgdb_debugport == NULL)
+ kgdb_debugport = NS16550_init(KGDB_PORT);
+
+ return(NS16550_getc(kgdb_debugport));
+}
+
+void kgdb_interruptible(int enable)
+{
+ return;
+}
+
+void putDebugString(char* str)
+{
+ while (*str != '\0') {
+ putDebugChar(*str);
+ str++;
+ }
+ putDebugChar('\r');
+ return;
+}
+
+void
+kgdb_map_scc(void)
+{
+ printk("kgdb init \n");
+ kgdb_debugport = NS16550_init(KGDB_PORT);
+}
diff --git a/arch/ppc/kernel/ppc4xx_pic.c b/arch/ppc/kernel/ppc4xx_pic.c
index e4fcd971717f..ae96d1c722e9 100644
--- a/arch/ppc/kernel/ppc4xx_pic.c
+++ b/arch/ppc/kernel/ppc4xx_pic.c
@@ -1,7 +1,4 @@
/*
- * BK Id: SCCS/s.ppc4xx_pic.c 1.5 05/17/01 18:14:21 cort
- */
-/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
*
@@ -33,25 +30,29 @@
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/irq.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-
+#include <asm/ibm4xx.h>
+#include <asm/ppc4xx_pic.h>
/* Global Variables */
struct hw_interrupt_type *ppc4xx_pic;
+/* Six of one, half dozen of the other....#ifdefs, separate files,
+ * other tricks.....
+ *
+ * There are basically two types of interrupt controllers, the 403 AIC
+ * and the "others" with UIC. I just kept them both here separated
+ * with #ifdefs, but it seems to change depending upon how supporting
+ * files (like ppc4xx.h) change. -- Dan.
+ */
-/* Function Prototypes */
+#ifdef CONFIG_403
-static void ppc403_aic_enable(unsigned int irq);
-static void ppc403_aic_disable(unsigned int irq);
-static void ppc403_aic_disable_and_ack(unsigned int irq);
+/* Function Prototypes */
-static void ppc405_uic_enable(unsigned int irq);
-static void ppc405_uic_disable(unsigned int irq);
-static void ppc405_uic_disable_and_ack(unsigned int irq);
+static void ppc403_aic_enable(unsigned int irq);
+static void ppc403_aic_disable(unsigned int irq);
+static void ppc403_aic_disable_and_ack(unsigned int irq);
static struct hw_interrupt_type ppc403_aic = {
"403GC AIC",
@@ -63,55 +64,11 @@ static struct hw_interrupt_type ppc403_aic = {
0
};
-static struct hw_interrupt_type ppc405_uic = {
- "405GP UIC",
- NULL,
- NULL,
- ppc405_uic_enable,
- ppc405_uic_disable,
- ppc405_uic_disable_and_ack,
- 0
-};
-
-/*
- * Document me.
- */
-void __init
-ppc4xx_pic_init(void)
-{
- unsigned long ver = PVR_VER(mfspr(SPRN_PVR));
-
- switch (ver) {
-
- case PVR_VER(PVR_403GC):
- /*
- * Disable all external interrupts until they are
- * explicity requested.
- */
- ppc_cached_irq_mask[0] = 0;
- mtdcr(DCRN_EXIER, 0);
-
- ppc4xx_pic = &ppc403_aic;
- break;
-
- case PVR_VER(PVR_405GP):
- ppc4xx_pic = &ppc405_uic;
- break;
- }
-
- return;
-}
-
-/*
- * XXX - Currently 403-specific!
- *
- * Document me.
- */
int
-ppc4xx_pic_get_irq(struct pt_regs *regs)
+ppc403_pic_get_irq(struct pt_regs *regs)
{
int irq;
- unsigned long bits, mask = (1 << 31);
+ unsigned long bits;
/*
* Only report the status of those interrupts that are actually
@@ -123,19 +80,17 @@ ppc4xx_pic_get_irq(struct pt_regs *regs)
/*
* Walk through the interrupts from highest priority to lowest, and
* report the first pending interrupt found.
+ * We want PPC, not C bit numbering, so just subtract the ffs()
+ * result from 32.
*/
+ irq = 32 - ffs(bits);
- for (irq = 0; irq < NR_IRQS; irq++, mask >>= 1) {
- if (bits & mask)
- break;
- }
+ if (irq == NR_AIC_IRQS)
+ irq = -1;
return (irq);
}
-/*
- * Document me.
- */
static void
ppc403_aic_enable(unsigned int irq)
{
@@ -148,9 +103,6 @@ ppc403_aic_enable(unsigned int irq)
mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
}
-/*
- * Document me.
- */
static void
ppc403_aic_disable(unsigned int irq)
{
@@ -163,9 +115,6 @@ ppc403_aic_disable(unsigned int irq)
mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
}
-/*
- * Document me.
- */
static void
ppc403_aic_disable_and_ack(unsigned int irq)
{
@@ -179,29 +128,131 @@ ppc403_aic_disable_and_ack(unsigned int irq)
mtdcr(DCRN_EXISR, (1 << (31 - bit)));
}
-/*
- * Document me.
- */
+#else /* !CONFIG_403 */
+
static void
ppc405_uic_enable(unsigned int irq)
{
- /* XXX - Implement me. */
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] |= 1 << (31 - bit);
+ mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]);
}
-/*
- * Document me.
- */
static void
ppc405_uic_disable(unsigned int irq)
{
- /* XXX - Implement me. */
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]);
}
-/*
- * Document me.
- */
static void
ppc405_uic_disable_and_ack(unsigned int irq)
{
- /* XXX - Implement me. */
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]);
+ mtdcr(DCRN_UIC0_SR, (1 << (31 - bit)));
+}
+
+static void
+ppc405_uic_end(unsigned int irq)
+{
+ int bit, word;
+ unsigned int tr_bits;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ tr_bits = mfdcr(DCRN_UIC0_TR);
+ if ((tr_bits & (1 << (31 - bit))) == 0) {
+ /* level trigger */
+ mtdcr(DCRN_UIC0_SR, 1 << (31 - bit));
+ }
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ ppc_cached_irq_mask[word] |= 1 << (31 - bit);
+ mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[word]);
+ }
+}
+
+static struct hw_interrupt_type ppc405_uic = {
+#if defined (CONFIG_405GP)
+ "405GP UIC",
+#else
+ "NP405 UIC",
+#endif
+ NULL,
+ NULL,
+ ppc405_uic_enable,
+ ppc405_uic_disable,
+ ppc405_uic_disable_and_ack,
+ ppc405_uic_end,
+ 0
+};
+
+int
+ppc405_pic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits;
+
+ /*
+ * Only report the status of those interrupts that are actually
+ * enabled.
+ */
+
+ bits = mfdcr(DCRN_UIC0_MSR);
+
+ /*
+ * Walk through the interrupts from highest priority to lowest, and
+ * report the first pending interrupt found.
+ * We want PPC, not C bit numbering, so just subtract the ffs()
+ * result from 32.
+ */
+ irq = 32 - ffs(bits);
+
+ if (irq == NR_AIC_IRQS)
+ irq = -1;
+
+ return (irq);
+}
+#endif
+
+void __init
+ppc4xx_pic_init(void)
+{
+ /*
+ * Disable all external interrupts until they are
+ * explicity requested.
+ */
+ ppc_cached_irq_mask[0] = 0;
+
+#ifdef CONFIG_403
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]);
+
+ ppc4xx_pic = &ppc403_aic;
+ ppc_md.get_irq = ppc403_pic_get_irq;
+#else
+ mtdcr(DCRN_UIC0_ER, ppc_cached_irq_mask[0]);
+
+ /* Set all interrupts to non-critical.
+ */
+ mtdcr(DCRN_UIC0_CR, 0);
+
+ ppc4xx_pic = &ppc405_uic;
+ ppc_md.get_irq = ppc405_pic_get_irq;
+#endif
}
diff --git a/arch/ppc/kernel/ppc4xx_pic.h b/arch/ppc/kernel/ppc4xx_pic.h
deleted file mode 100644
index ebb63a7f36d4..000000000000
--- a/arch/ppc/kernel/ppc4xx_pic.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * BK Id: SCCS/s.ppc4xx_pic.h 1.8 06/15/01 13:56:56 paulus
- */
-/*
- *
- * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: ppc4xx_pic.h
- *
- * Description:
- * Interrupt controller driver for PowerPC 4xx-based processors.
- */
-
-#ifndef __PPC4XX_PIC_H__
-#define __PPC4XX_PIC_H__
-
-#include <linux/config.h>
-#include "local_irq.h"
-
-/* External Global Variables */
-
-extern struct hw_interrupt_type *ppc4xx_pic;
-
-
-/* Function Prototypes */
-
-extern void ppc4xx_pic_init(void);
-extern int ppc4xx_pic_get_irq(struct pt_regs *regs);
-
-#endif /* __PPC4XX_PIC_H__ */
diff --git a/arch/ppc/kernel/ppc4xx_pm.c b/arch/ppc/kernel/ppc4xx_pm.c
new file mode 100644
index 000000000000..1f49c1f5e1f6
--- /dev/null
+++ b/arch/ppc/kernel/ppc4xx_pm.c
@@ -0,0 +1,75 @@
+/*
+ * file: ppc4xx_pm.c
+ *
+ * This an attempt to get Power Management going for the IBM 4xx processor.
+ * This was derived from the ppc4xx._setup.c file
+ *
+ * Armin Kuster akuster@mvista.com
+ * Jan 2002
+ *
+ *
+ * Copyright 2002 MontaVista Softare Inc.
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.
+ *
+ * Version 1.0 (02/14/01) - A. Kuster
+ * Initial version - moved pm code from ppc4xx_setup.c
+ *
+ * 1.1 02/21/01 - A. Kuster
+ * minor fixes, init value to 0 & += to &=
+ * added stb03 ifdef for 2nd i2c device
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/ibm4xx.h>
+
+void __init
+ppc4xx_pm_init(void)
+{
+
+ unsigned int value = 0;
+
+ /* turn off unused hardware to save power */
+#ifdef CONFIG_405GP
+ value |= CPM_DCP; /* CodePack */
+#endif
+
+#if !defined(CONFIG_IBM_OCP_GPIO)
+ value |= CPM_GPIO0;
+#endif
+
+#if !defined(CONFIG_PPC405_I2C_ADAP)
+ value |= CPM_IIC0;
+#ifdef CONFIG_STB03xxx
+ value |= CPM_IIC1;
+#endif
+#endif
+
+
+#if !defined(CONFIG_405_DMA)
+ value |= CPM_DMA;
+#endif
+
+ mtdcr(DCRN_CPMFR, value);
+
+}
diff --git a/arch/ppc/kernel/ppc4xx_serial.c b/arch/ppc/kernel/ppc4xx_serial.c
new file mode 100755
index 000000000000..54defaf2a92c
--- /dev/null
+++ b/arch/ppc/kernel/ppc4xx_serial.c
@@ -0,0 +1,190 @@
+
+/*
+ * linux/arch/ppc/kernel/ppc405_serial.c
+ *
+ * This is a fairly standard 165xx type device that will eventually
+ * be merged with other similar processor/boards. -- Dan
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Console I/O support for Early kernel bringup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * frank_rowand@mvista.com or source@mvista.com
+ * debbie_chu@mvista.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 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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/config.h>
+
+#if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR)
+
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#include <linux/init.h>
+#endif
+
+#ifdef CONFIG_DEBUG_BRINGUP
+
+#include <linux/console.h>
+
+extern void ftr_reset_preferred_console(void);
+
+
+static int ppc405_sercons_setup(struct console *co, char *options)
+{
+#ifdef CONFIG_UART0_DEBUG_CONSOLE
+ volatile unsigned char *uart_dll = (char *)0xef600300;
+ volatile unsigned char *uart_fcr = (char *)0xef600302;
+ volatile unsigned char *uart_lcr = (char *)0xef600303;
+#endif
+
+#ifdef CONFIG_UART1_DEBUG_CONSOLE
+ volatile unsigned char *uart_dll = (char *)0xef600400;
+ volatile unsigned char *uart_fcr = (char *)0xef600402;
+ volatile unsigned char *uart_lcr = (char *)0xef600403;
+#endif
+
+ *uart_lcr = *uart_lcr | 0x80; /* DLAB on */
+
+/* ftr revisit - there is no config option for this
+** also see include/asm-ppc/ppc405_serial.h
+**
+** #define CONFIG_IBM405GP_INTERNAL_CLOCK
+*/
+
+
+#ifdef CONFIG_IBM405GP_INTERNAL_CLOCK
+ /* ftr revisit
+ ** why is bit 19 of chcr0 (0x1000) being set?
+ */
+ /* 0x2a results in data corruption, kgdb works with 0x28 */
+ *uart_dll = 0x28; /* 9600 baud */
+ _put_CHCR0((_get_CHCR0() & 0xffffe000) | 0x103e);
+#else
+ *uart_dll = 0x48; /* 9600 baud */
+#endif
+ *uart_lcr = *uart_lcr & 0x7f; /* DLAB off */
+
+ return 0;
+}
+
+
+/*
+ * This is a bringup hack, writing directly to uart0 or uart1
+ */
+
+static void
+ppc405_sercons_write(struct console *co, const char *ptr,
+ unsigned nb)
+{
+ int i;
+
+#ifdef CONFIG_UART0_DEBUG_CONSOLE
+ volatile unsigned char *uart_xmit = (char *)0xef600300;
+ volatile unsigned char *uart_lsr = (char *)0xef600305;
+#endif
+
+#ifdef CONFIG_UART1_DEBUG_CONSOLE
+ volatile unsigned char *uart_xmit = (char *)0xef600400;
+ volatile unsigned char *uart_lsr = (char *)0xef600405;
+#endif
+
+ for (i = 0; i < nb; ++i) {
+
+ /* wait for transmit reg (possibly fifo) to empty */
+ while ((*uart_lsr & 0x40) == 0)
+ ;
+
+ *uart_xmit = (ptr[i] & 0xff);
+
+ if (ptr[i] == '\n') {
+
+ /* add a carriage return */
+
+ /* wait for transmit reg (possibly fifo) to empty */
+ while ((*uart_lsr & 0x40) == 0)
+ ;
+
+ *uart_xmit = '\r';
+ }
+ }
+
+ return;
+}
+
+
+static int
+ppc405_sercons_read(struct console *co, char *ptr, unsigned nb)
+{
+#ifdef CONFIG_UART0_DEBUG_CONSOLE
+ volatile unsigned char *uart_rcv = (char *)0xef600300;
+ volatile unsigned char *uart_lsr = (char *)0xef600305;
+#endif
+
+#ifdef CONFIG_UART1_DEBUG_CONSOLE
+ volatile unsigned char *uart_rcv = (char *)0xef600400;
+ volatile unsigned char *uart_lsr = (char *)0xef600405;
+#endif
+
+
+ /* ftr revisit: not tested */
+
+ if (nb == 0)
+ return(0);
+
+ if (!ptr)
+ return(-1);
+
+ /* wait for receive reg (possibly fifo) to contain data */
+ while ((*uart_lsr & 0x01) == 0)
+ ;
+
+ *ptr = *uart_rcv;
+
+ return(1);
+}
+
+static struct console ppc405_sercons = {
+ name: "dbg_cons",
+ write: ppc405_console_write,
+ setup: ppc405_console_setup,
+ flags: CON_PRINTBUFFER,
+ index: -1,
+};
+
+void
+register_debug_console(void)
+{
+ register_console(&ppc405_sercons);
+}
+
+void
+unregister_debug_console(void)
+{
+ unregister_console(&ppc405_sercons);
+}
+
+#endif /* CONFIG_DEBUG_BRINGUP */
+
+#endif /* #if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR) */
diff --git a/arch/ppc/kernel/ppc4xx_setup.c b/arch/ppc/kernel/ppc4xx_setup.c
new file mode 100755
index 000000000000..f086c14e7907
--- /dev/null
+++ b/arch/ppc/kernel/ppc4xx_setup.c
@@ -0,0 +1,415 @@
+/*
+ *
+ * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Copyright 2000-2001 MontaVista Software Inc.
+ * Completed implementation.
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ * Frank Rowand <frank_rowand@mvista.com>
+ * Debbie Chu <debbie_chu@mvista.com>
+ *
+ * Module name: ppc4xx_setup.c
+ *
+ * Description:
+ * Architecture- / platform-specific boot-time initialization code for
+ * IBM PowerPC 4xx based boards. Adapted from original
+ * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ * <dan@net4x.com>.
+ *
+ * History: 11/09/2001 - armin
+ * rename board_setup_nvram_access to board_init. board_init is
+ * used for all other board specific instructions needed during
+ * platform_init.
+ * moved RTC to board.c files
+ * moved VT/FB to board.c files
+ * moved r/w4 ide to redwood.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/reboot.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+#include <linux/console.h>
+#include <linux/ide.h>
+#include <linux/serial_reg.h>
+#include <linux/seq_file.h>
+
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/kgdb.h>
+#include <asm/ibm4xx.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/pci-bridge.h>
+#include <asm/bootinfo.h>
+
+/* Function Prototypes */
+extern void abort(void);
+extern void ppc4xx_find_bridges(void);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+
+extern int nonpci_ide_default_irq(ide_ioreg_t base);
+extern void nonpci_ide_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq);
+
+extern void ppc4xx_wdt_heartbeat(void);
+extern int wdt_enable;
+extern unsigned long wdt_period;
+
+/* Board specific functions */
+extern void board_setup_arch(void);
+extern void board_io_mapping(void);
+extern void board_setup_irq(void);
+extern void board_init(void);
+
+/* Global Variables */
+unsigned char __res[sizeof (bd_t)];
+
+static void __init
+ppc4xx_setup_arch(void)
+{
+
+ /* Setup PCI host bridges */
+
+#ifdef CONFIG_PCI
+ ppc4xx_find_bridges();
+#endif
+
+#if defined(CONFIG_FB)
+ conswitchp = &dummy_con;
+#endif
+
+ board_setup_arch();
+}
+
+/*
+ * This routine pretty-prints the platform's internal CPU clock
+ * frequencies into the buffer for usage in /proc/cpuinfo.
+ */
+
+static int
+ppc4xx_show_percpuinfo(struct seq_file *m, int i)
+{
+ bd_t *bip = (bd_t *) __res;
+
+ seq_printf(m, "clock\t\t: %ldMHz\n", (long) bip->bi_intfreq / 1000000);
+
+ return 0;
+}
+
+/*
+ * This routine pretty-prints the platform's internal bus clock
+ * frequencies into the buffer for usage in /proc/cpuinfo.
+ */
+static int
+ppc4xx_show_cpuinfo(struct seq_file *m)
+{
+ bd_t *bip = (bd_t *) __res;
+
+ seq_printf(m, "machine\t\t: %s\n", PPC4xx_MACHINE_NAME);
+ seq_printf(m, "plb bus clock\t: %ldMHz\n",
+ (long) bip->bi_busfreq / 1000000);
+#ifdef CONFIG_PCI
+ seq_printf(m, "pci bus clock\t: %dMHz\n",
+ bip->bi_pci_busfreq / 1000000);
+#endif
+
+ return 0;
+}
+
+/*
+ * Return the virtual address representing the top of physical RAM.
+ */
+static unsigned long __init
+ppc4xx_find_end_of_memory(void)
+{
+ bd_t *bip = (bd_t *) __res;
+
+ return ((unsigned long) bip->bi_memsize);
+}
+
+static void __init
+m4xx_map_io(void)
+{
+ io_block_mapping(PPC4xx_ONB_IO_VADDR,
+ PPC4xx_ONB_IO_PADDR, PPC4xx_ONB_IO_SIZE, _PAGE_IO);
+#ifdef CONFIG_PCI
+ io_block_mapping(PPC4xx_PCI_IO_VADDR,
+ PPC4xx_PCI_IO_PADDR, PPC4xx_PCI_IO_SIZE, _PAGE_IO);
+ io_block_mapping(PPC4xx_PCI_CFG_VADDR,
+ PPC4xx_PCI_CFG_PADDR, PPC4xx_PCI_CFG_SIZE, _PAGE_IO);
+ io_block_mapping(PPC4xx_PCI_LCFG_VADDR,
+ PPC4xx_PCI_LCFG_PADDR, PPC4xx_PCI_LCFG_SIZE, _PAGE_IO);
+#endif
+ board_io_mapping();
+}
+
+static void __init
+ppc4xx_init_IRQ(void)
+{
+ int i;
+
+ ppc4xx_pic_init();
+
+ for (i = 0; i < NR_IRQS; i++)
+ irq_desc[i].handler = ppc4xx_pic;
+
+ /* give board specific code a chance to setup things */
+ board_setup_irq();
+ return;
+}
+
+static void
+ppc4xx_restart(char *cmd)
+{
+ printk("%s\n", cmd);
+ abort();
+}
+
+static void
+ppc4xx_power_off(void)
+{
+ printk("System Halted\n");
+ __cli();
+ while (1) ;
+}
+
+static void
+ppc4xx_halt(void)
+{
+ printk("System Halted\n");
+ __cli();
+ while (1) ;
+}
+
+/*
+ * This routine retrieves the internal processor frequency from the board
+ * information structure, sets up the kernel timer decrementer based on
+ * that value, enables the 4xx programmable interval timer (PIT) and sets
+ * it up for auto-reload.
+ */
+static void __init
+ppc4xx_calibrate_decr(void)
+{
+ unsigned int freq;
+ bd_t *bip = (bd_t *) __res;
+
+#if defined(CONFIG_WALNUT) || defined(CONFIG_CEDER)
+ /* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */
+ mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE);
+#endif
+#ifdef CONFIG_REDWOOD_5
+ freq = bip->bi_tbfreq;
+#else
+ freq = bip->bi_intfreq;
+
+#endif
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ /* Set the time base to zero.
+ ** At 200 Mhz, time base will rollover in ~2925 years.
+ */
+
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ /* Clear any pending timer interrupts */
+
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+ mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+ /* Set the PIT reload value and just let it run. */
+ mtspr(SPRN_PIT, tb_ticks_per_jiffy);
+}
+
+#ifdef CONFIG_DEBUG_TEXT
+static void
+ppc4xx_progress(char *s, unsigned short hex)
+{
+ printk("%s\n\r", s);
+}
+#endif
+
+/*
+ * IDE stuff.
+ * should be generic for every IDE PCI chipset
+ */
+#if defined(CONFIG_BLK_DEV_IDE)
+static int
+ppc4xx_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return check_region(from, extent);
+}
+
+static void
+ppc4xx_ide_request_region(ide_ioreg_t from, unsigned int extent,
+ const char *name)
+{
+ request_region(from, extent, name);
+ return;
+}
+
+static void
+ppc4xx_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+ release_region(from, extent);
+ return;
+}
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDEPCI)
+static void
+ppc4xx_ide_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
+{
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+ hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+}
+#endif
+
+TODC_ALLOC();
+
+/*
+ * Input(s):
+ * r3 - Optional pointer to a board information structure.
+ * r4 - Optional pointer to the physical starting address of the init RAM
+ * disk.
+ * r5 - Optional pointer to the physical ending address of the init RAM
+ * disk.
+ * r6 - Optional pointer to the physical starting address of any kernel
+ * command-line parameters.
+ * r7 - Optional pointer to the physical ending address of any kernel
+ * command-line parameters.
+ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+ sizeof (bd_t));
+
+ }
+#if defined(CONFIG_BLK_DEV_INITRD)
+ /*
+ * If the init RAM disk has been configured in, and there's a valid
+ * starting address for it, set it up.
+ */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Copy the kernel command line arguments to a safe place. */
+
+ if (r6) {
+ *(char *) (r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+ }
+#if defined(CONFIG_PPC405_WDT)
+/* Look for wdt= option on command line */
+ if (strstr(cmd_line, "wdt=")) {
+ int valid_wdt = 0;
+ char *p, *q;
+ for (q = cmd_line; (p = strstr(q, "wdt=")) != 0;) {
+ q = p + 4;
+ if (p > cmd_line && p[-1] != ' ')
+ continue;
+ wdt_period = simple_strtoul(q, &q, 0);
+ valid_wdt = 1;
+ ++q;
+ }
+ wdt_enable = valid_wdt;
+ }
+#endif
+
+ /* Initialize machine-dependency vectors */
+
+ ppc_md.setup_arch = ppc4xx_setup_arch;
+ ppc_md.show_percpuinfo = ppc4xx_show_percpuinfo;
+ ppc_md.show_cpuinfo = ppc4xx_show_cpuinfo;
+ ppc_md.init_IRQ = ppc4xx_init_IRQ;
+
+ ppc_md.restart = ppc4xx_restart;
+ ppc_md.power_off = ppc4xx_power_off;
+ ppc_md.halt = ppc4xx_halt;
+
+ ppc_md.calibrate_decr = ppc4xx_calibrate_decr;
+
+#ifdef CONFIG_PPC405_WDT
+ ppc_md.heartbeat = ppc4xx_wdt_heartbeat;
+#endif
+ ppc_md.heartbeat_count = 0;
+
+ ppc_md.find_end_of_memory = ppc4xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = m4xx_map_io;
+
+#ifdef CONFIG_DEBUG_TEXT
+ ppc_md.progress = ppc4xx_progress;
+#endif
+
+#if defined(CONFIG_VT) && defined(CONFIG_PC_KEYBOARD)
+#if defined(CONFIG_REDWOOD_4) && defined(CONFIG_STB_KB)
+ redwood_irkb_init();
+#else
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#endif
+#endif
+
+/*
+** m8xx_setup.c, prep_setup.c use
+** defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+*/
+#if defined (CONFIG_IDE)
+ ppc_ide_md.ide_request_region = ppc4xx_ide_request_region;
+ ppc_ide_md.ide_release_region = ppc4xx_ide_release_region;
+ ppc_ide_md.ide_check_region = ppc4xx_ide_check_region;
+#if defined(CONFIG_BLK_DEV_IDEPCI)
+ ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports;
+#elif defined (CONFIG_DMA_NONPCI) /* ON board IDE */
+ ppc_ide_md.default_irq = nonpci_ide_default_irq;
+ ppc_ide_md.ide_init_hwif = nonpci_ide_init_hwif_ports;
+#endif
+#endif
+ board_init();
+
+ return;
+}
diff --git a/arch/ppc/kernel/ppc8260_pic.c b/arch/ppc/kernel/ppc8260_pic.c
index b829116f78a0..b2ae5e951aef 100644
--- a/arch/ppc/kernel/ppc8260_pic.c
+++ b/arch/ppc/kernel/ppc8260_pic.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.ppc8260_pic.c 1.5 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
#include <linux/stddef.h>
@@ -85,6 +85,22 @@ static void m8260_mask_and_ack(unsigned int irq_nr)
sipnr[word] = 1 << (31 - bit);
}
+static void m8260_end_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+ }
+}
+
struct hw_interrupt_type ppc8260_pic = {
" 8260 SIU ",
NULL,
@@ -92,6 +108,7 @@ struct hw_interrupt_type ppc8260_pic = {
m8260_unmask_irq,
m8260_mask_irq,
m8260_mask_and_ack,
+ m8260_end_irq,
0
};
@@ -106,6 +123,9 @@ m8260_get_irq(struct pt_regs *regs)
* to get the irq number. */
bits = immr->im_intctl.ic_sivec;
irq = bits >> 26;
+
+ if (irq == 0)
+ return(-1);
#if 0
irq += ppc8260_pic.irq_offset;
#endif
diff --git a/arch/ppc/kernel/ppc8260_pic.h b/arch/ppc/kernel/ppc8260_pic.h
index dd415f4995bf..40e70f82a8b8 100644
--- a/arch/ppc/kernel/ppc8260_pic.h
+++ b/arch/ppc/kernel/ppc8260_pic.h
@@ -1,11 +1,11 @@
/*
- * BK Id: SCCS/s.ppc8260_pic.h 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
#ifndef _PPC_KERNEL_PPC8260_H
#define _PPC_KERNEL_PPC8260_H
-#include "local_irq.h"
+#include <linux/irq.h>
extern struct hw_interrupt_type ppc8260_pic;
diff --git a/arch/ppc/kernel/ppc8xx_pic.c b/arch/ppc/kernel/ppc8xx_pic.c
index b01669fe60df..a952d85ea01a 100644
--- a/arch/ppc/kernel/ppc8xx_pic.c
+++ b/arch/ppc/kernel/ppc8xx_pic.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.ppc8xx_pic.c 1.10 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
#include <linux/config.h>
#include <linux/stddef.h>
@@ -44,6 +44,21 @@ static void m8xx_unmask_irq(unsigned int irq_nr)
ppc_cached_irq_mask[word];
}
+static void m8xx_end_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+ int bit, word;
+
+ bit = irq_nr & 0x1f;
+ word = irq_nr >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31-bit));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
+ ppc_cached_irq_mask[word];
+ }
+}
+
+
static void m8xx_mask_and_ack(unsigned int irq_nr)
{
int bit, word;
@@ -64,6 +79,7 @@ struct hw_interrupt_type ppc8xx_pic = {
m8xx_unmask_irq,
m8xx_mask_irq,
m8xx_mask_and_ack,
+ m8xx_end_irq,
0
};
@@ -97,19 +113,26 @@ m8xx_do_IRQ(struct pt_regs *regs,
#endif
+/*
+ * We either return a valid interrupt or -1 if there is nothing pending
+ */
int
m8xx_get_irq(struct pt_regs *regs)
{
int irq;
- unsigned long bits = 0;
- /* For MPC8xx, read the SIVEC register and shift the bits down
- * to get the irq number. */
- bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
- irq = bits >> 26;
-#if 0
- irq += ppc8xx_pic.irq_offset;
-#endif
+ /* For MPC8xx, read the SIVEC register and shift the bits down
+ * to get the irq number.
+ */
+ irq = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26;
+
+ /*
+ * When we read the sivec without an interrupt to process, we will
+ * get back SIU_LEVEL7. In this case, return -1
+ */
+ if (irq == SIU_LEVEL7)
+ return -1;
+
return irq;
}
diff --git a/arch/ppc/kernel/ppc8xx_pic.h b/arch/ppc/kernel/ppc8xx_pic.h
index 1253d31c28a3..9cbf0d6eec4a 100644
--- a/arch/ppc/kernel/ppc8xx_pic.h
+++ b/arch/ppc/kernel/ppc8xx_pic.h
@@ -1,11 +1,11 @@
/*
- * BK Id: SCCS/s.ppc8xx_pic.h 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
#ifndef _PPC_KERNEL_PPC8xx_H
#define _PPC_KERNEL_PPC8xx_H
#include <linux/config.h>
-#include "local_irq.h"
+#include <linux/irq.h>
extern struct hw_interrupt_type ppc8xx_pic;
@@ -15,7 +15,7 @@ void m8xx_do_IRQ(struct pt_regs *regs,
int m8xx_get_irq(struct pt_regs *regs);
#ifdef CONFIG_MBX
-#include "i8259.h"
+#include <asm/i8259.h>
#include <asm/io.h>
void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs);
#endif
diff --git a/arch/ppc/kernel/ppc_asm.h b/arch/ppc/kernel/ppc_asm.h
deleted file mode 100644
index ea28f75d9acc..000000000000
--- a/arch/ppc/kernel/ppc_asm.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * BK Id: SCCS/s.ppc_asm.h 1.18 10/18/01 15:02:09 trini
- */
-/*
- * arch/ppc/kernel/ppc_asm.h
- *
- * Definitions used by various bits of low-level assembly code on PowerPC.
- *
- * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
- *
- * 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 <linux/config.h>
-
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
-
-/*
- * Macros for storing registers into and loading registers from
- * exception frames.
- */
-#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
-#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
-#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
-#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
-#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
-#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
-#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
-#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
-#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
-#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
-
-#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base)
-#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
-#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
-#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
-#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
-#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
-#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base)
-#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
-#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
-#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
-#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
-#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
-
-/*
- * Once a version of gas that understands the AltiVec instructions
- * is freely available, we can do this the normal way... - paulus
- */
-#define LVX(r,a,b) .long (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(103<<1)
-#define STVX(r,a,b) .long (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(231<<1)
-#define MFVSCR(r) .long (4<<26)+((r)<<21)+(770<<1)
-#define MTVSCR(r) .long (4<<26)+((r)<<11)+(802<<1)
-
-#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); STVX(n,b,base)
-#define SAVE_2VR(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
-#define SAVE_4VR(n,b,base) SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base)
-#define SAVE_8VR(n,b,base) SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base)
-#define SAVE_16VR(n,b,base) SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base)
-#define SAVE_32VR(n,b,base) SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base)
-#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); LVX(n,b,base)
-#define REST_2VR(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
-#define REST_4VR(n,b,base) REST_2VR(n,b,base); REST_2VR(n+2,b,base)
-#define REST_8VR(n,b,base) REST_4VR(n,b,base); REST_4VR(n+4,b,base)
-#define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n+8,b,base)
-#define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base)
-
-#ifdef CONFIG_PPC601_SYNC_FIX
-#define SYNC \
-BEGIN_FTR_SECTION \
- sync; \
- isync; \
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-#define SYNC_601 \
-BEGIN_FTR_SECTION \
- sync; \
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-#define ISYNC_601 \
-BEGIN_FTR_SECTION \
- isync; \
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-#else
-#define SYNC
-#define SYNC_601
-#define ISYNC_601
-#endif
-
-#ifndef CONFIG_SMP
-#define TLBSYNC
-#else /* CONFIG_SMP */
-/* tlbsync is not implemented on 601 */
-#define TLBSYNC \
-BEGIN_FTR_SECTION \
- tlbsync; \
- sync; \
-END_FTR_SECTION_IFCLR(CPU_FTR_601)
-#endif
-
-/*
- * This instruction is not implemented on the PPC 603 or 601; however, on
- * the 403GCX and 405GP tlbia IS defined and tlbie is not.
- * All of these instructions exist in the 8xx, they have magical powers,
- * and they must be used.
- */
-
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-#define tlbia \
- li r4,1024; \
- mtctr r4; \
- lis r4,KERNELBASE@h; \
-0: tlbie r4; \
- addi r4,r4,0x1000; \
- bdnz 0b
-#endif
-
-/*
- * On APUS (Amiga PowerPC cpu upgrade board), we don't know the
- * physical base address of RAM at compile time.
- */
-#define tophys(rd,rs) \
-0: addis rd,rs,-KERNELBASE@h; \
- .section ".vtop_fixup","aw"; \
- .align 1; \
- .long 0b; \
- .previous
-
-#define tovirt(rd,rs) \
-0: addis rd,rs,KERNELBASE@h; \
- .section ".ptov_fixup","aw"; \
- .align 1; \
- .long 0b; \
- .previous
-
-/*
- * On 64-bit cpus, we use the rfid instruction instead of rfi, but
- * we then have to make sure we preserve the top 32 bits except for
- * the 64-bit mode bit, which we clear.
- */
-#ifdef CONFIG_PPC64BRIDGE
-#define FIX_SRR1(ra, rb) \
- mr rb,ra; \
- mfmsr ra; \
- clrldi ra,ra,1; /* turn off 64-bit mode */ \
- rldimi ra,rb,0,32
-#define RFI .long 0x4c000024 /* rfid instruction */
-#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* mtmsrd */
-#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */
-
-#else
-#define FIX_SRR1(ra, rb)
-#define RFI rfi
-#define MTMSRD(r) mtmsr r
-#define CLR_TOP32(r)
-#endif /* CONFIG_PPC64BRIDGE */
diff --git a/arch/ppc/kernel/ppc_asm.tmpl b/arch/ppc/kernel/ppc_asm.tmpl
deleted file mode 100644
index c35192bb4fe6..000000000000
--- a/arch/ppc/kernel/ppc_asm.tmpl
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Condition Register Bit Fields */
-
-#define cr0 0
-#define cr1 1
-#define cr2 2
-#define cr3 3
-#define cr4 4
-#define cr5 5
-#define cr6 6
-#define cr7 7
-
-
-/* General Purpose Registers (GPRs) */
-
-#define r0 0
-#define r1 1
-#define r2 2
-#define r3 3
-#define r4 4
-#define r5 5
-#define r6 6
-#define r7 7
-#define r8 8
-#define r9 9
-#define r10 10
-#define r11 11
-#define r12 12
-#define r13 13
-#define r14 14
-#define r15 15
-#define r16 16
-#define r17 17
-#define r18 18
-#define r19 19
-#define r20 20
-#define r21 21
-#define r22 22
-#define r23 23
-#define r24 24
-#define r25 25
-#define r26 26
-#define r27 27
-#define r28 28
-#define r29 29
-#define r30 30
-#define r31 31
-
-
-/* Floating Point Registers (FPRs) */
-
-#define fr0 0
-#define fr1 1
-#define fr2 2
-#define fr3 3
-#define fr4 4
-#define fr5 5
-#define fr6 6
-#define fr7 7
-#define fr8 8
-#define fr9 9
-#define fr10 10
-#define fr11 11
-#define fr12 12
-#define fr13 13
-#define fr14 14
-#define fr15 15
-#define fr16 16
-#define fr17 17
-#define fr18 18
-#define fr19 19
-#define fr20 20
-#define fr21 21
-#define fr22 22
-#define fr23 23
-#define fr24 24
-#define fr25 25
-#define fr26 26
-#define fr27 27
-#define fr28 28
-#define fr29 29
-#define fr30 30
-#define fr31 31
-
-#define vr0 0
-#define vr1 1
-#define vr2 2
-#define vr3 3
-#define vr4 4
-#define vr5 5
-#define vr6 6
-#define vr7 7
-#define vr8 8
-#define vr9 9
-#define vr10 10
-#define vr11 11
-#define vr12 12
-#define vr13 13
-#define vr14 14
-#define vr15 15
-#define vr16 16
-#define vr17 17
-#define vr18 18
-#define vr19 19
-#define vr20 20
-#define vr21 21
-#define vr22 22
-#define vr23 23
-#define vr24 24
-#define vr25 25
-#define vr26 26
-#define vr27 27
-#define vr28 28
-#define vr29 29
-#define vr30 30
-#define vr31 31
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 805c7fbd1383..2649b327c7f2 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.ppc_ksyms.c 1.59 11/04/01 22:58:20 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
#include <linux/config.h>
#include <linux/module.h>
@@ -12,18 +12,17 @@
#include <linux/tty.h>
#include <linux/vt_kern.h>
#include <linux/nvram.h>
-#include <linux/spinlock.h>
#include <linux/console.h>
#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/ide.h>
#include <asm/page.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <linux/ide.h>
#include <asm/ide.h>
#include <asm/atomic.h>
#include <asm/bitops.h>
@@ -36,7 +35,7 @@
#include <asm/system.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
-#include <asm/feature.h>
+#include <asm/pmac_feature.h>
#include <asm/dma.h>
#include <asm/machdep.h>
#include <asm/hw_irq.h>
@@ -60,7 +59,7 @@
extern void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
extern void transfer_to_handler(void);
-extern void syscall_trace(void);
+extern void do_syscall_trace(void);
extern void do_IRQ(struct pt_regs *regs);
extern void MachineCheckException(struct pt_regs *regs);
extern void AlignmentException(struct pt_regs *regs);
@@ -82,7 +81,7 @@ extern unsigned long mm_ptov (unsigned long paddr);
EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_signal);
-EXPORT_SYMBOL(syscall_trace);
+EXPORT_SYMBOL(do_syscall_trace);
EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
EXPORT_SYMBOL(MachineCheckException);
@@ -161,14 +160,18 @@ EXPORT_SYMBOL(_insw_ns);
EXPORT_SYMBOL(_outsw_ns);
EXPORT_SYMBOL(_insl_ns);
EXPORT_SYMBOL(_outsl_ns);
+EXPORT_SYMBOL(iopa);
+EXPORT_SYMBOL(mm_ptov);
+#ifndef CONFIG_PPC_ISERIES
EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(iopa);
-EXPORT_SYMBOL(mm_ptov);
+#endif
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
EXPORT_SYMBOL(ppc_ide_md);
EXPORT_SYMBOL(ppc_generic_ide_fix_driveid);
+#endif
#ifdef CONFIG_PCI
EXPORT_SYMBOL_NOVERS(isa_io_base);
@@ -176,19 +179,32 @@ EXPORT_SYMBOL_NOVERS(isa_mem_base);
EXPORT_SYMBOL_NOVERS(pci_dram_offset);
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
+EXPORT_SYMBOL(pci_bus_io_base);
+EXPORT_SYMBOL(pci_bus_io_base_phys);
+EXPORT_SYMBOL(pci_bus_mem_base_phys);
+EXPORT_SYMBOL(pci_bus_to_hose);
+EXPORT_SYMBOL(pci_resource_to_bus);
+EXPORT_SYMBOL(pci_phys_to_bus);
+EXPORT_SYMBOL(pci_bus_to_phys);
#endif /* CONFIG_PCI */
+#ifdef CONFIG_NOT_COHERENT_CACHE
+EXPORT_SYMBOL(consistent_alloc);
+EXPORT_SYMBOL(consistent_free);
+EXPORT_SYMBOL(consistent_sync);
+#endif
+
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
-/*EXPORT_SYMBOL(__restore_flags);*/
-/*EXPORT_SYMBOL(_disable_interrupts);
- EXPORT_SYMBOL(_enable_interrupts);*/
EXPORT_SYMBOL(flush_instruction_cache);
EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(enable_kernel_fp);
EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(flush_dcache_range);
+EXPORT_SYMBOL(flush_icache_user_range);
+EXPORT_SYMBOL(flush_icache_page);
+EXPORT_SYMBOL(flush_dcache_page);
EXPORT_SYMBOL(xchg_u32);
#ifdef CONFIG_ALTIVEC
EXPORT_SYMBOL(last_task_used_altivec);
@@ -196,7 +212,6 @@ EXPORT_SYMBOL(giveup_altivec);
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SMP
EXPORT_SYMBOL(global_irq_lock);
-EXPORT_SYMBOL(global_irq_count);
EXPORT_SYMBOL(global_irq_holder);
EXPORT_SYMBOL(__global_cli);
EXPORT_SYMBOL(__global_sti);
@@ -247,26 +262,11 @@ EXPORT_SYMBOL(device_is_compatible);
EXPORT_SYMBOL(machine_is_compatible);
EXPORT_SYMBOL(find_all_nodes);
EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(pci_bus_io_base);
-EXPORT_SYMBOL(pci_bus_io_base_phys);
-EXPORT_SYMBOL(pci_bus_mem_base_phys);
+EXPORT_SYMBOL(request_OF_resource);
+EXPORT_SYMBOL(release_OF_resource);
EXPORT_SYMBOL(pci_device_to_OF_node);
EXPORT_SYMBOL(pci_device_from_OF_node);
-EXPORT_SYMBOL(pci_bus_to_hose);
-EXPORT_SYMBOL(pci_resource_to_bus);
-EXPORT_SYMBOL(pci_phys_to_bus);
-EXPORT_SYMBOL(pci_bus_to_phys);
EXPORT_SYMBOL(pmac_newworld);
-EXPORT_SYMBOL(feature_set);
-EXPORT_SYMBOL(feature_clear);
-EXPORT_SYMBOL(feature_test);
-EXPORT_SYMBOL(feature_set_gmac_power);
-EXPORT_SYMBOL(feature_gmac_phy_reset);
-EXPORT_SYMBOL(feature_set_usb_power);
-EXPORT_SYMBOL(feature_set_firewire_power);
-EXPORT_SYMBOL(feature_set_firewire_cable_power);
-EXPORT_SYMBOL(feature_set_modem_power);
-EXPORT_SYMBOL(feature_set_airport_power);
#endif /* defined(CONFIG_ALL_PPC) */
#if defined(CONFIG_BOOTX_TEXT)
EXPORT_SYMBOL(btext_update_display);
@@ -293,14 +293,16 @@ EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memmove);
EXPORT_SYMBOL_NOVERS(memscan);
EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL_NOVERS(memchr);
EXPORT_SYMBOL(abs);
-#ifdef CONFIG_VGA_CONSOLE
+#if defined(CONFIG_FB_VGA16_MODULE)
EXPORT_SYMBOL(screen_info);
#endif
EXPORT_SYMBOL(__delay);
+#ifndef INLINE_IRQS
EXPORT_SYMBOL(__sti);
EXPORT_SYMBOL(__sti_end);
EXPORT_SYMBOL(__cli);
@@ -309,6 +311,7 @@ EXPORT_SYMBOL(__save_flags_ptr);
EXPORT_SYMBOL(__save_flags_ptr_end);
EXPORT_SYMBOL(__restore_flags);
EXPORT_SYMBOL(__restore_flags_end);
+#endif
EXPORT_SYMBOL(timer_interrupt_intercept);
EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(do_IRQ_intercept);
@@ -319,7 +322,9 @@ EXPORT_SYMBOL(tb_ticks_per_jiffy);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
#ifdef CONFIG_XMON
+extern void xmon_printf(char *fmt, ...);
EXPORT_SYMBOL(xmon);
+EXPORT_SYMBOL(xmon_printf);
#endif
EXPORT_SYMBOL(__up);
EXPORT_SYMBOL(__down);
@@ -343,10 +348,12 @@ EXPORT_SYMBOL(debugger_fault_handler);
#ifdef CONFIG_8xx
EXPORT_SYMBOL(__res);
-EXPORT_SYMBOL(request_8xxirq);
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
#endif /* CONFIG_8xx */
+#if defined(CONFIG_8xx) || defined(CONFIG_8260)
+EXPORT_SYMBOL(request_8xxirq);
+#endif
EXPORT_SYMBOL(ret_to_user_hook);
EXPORT_SYMBOL(next_mmu_context);
@@ -361,3 +368,7 @@ EXPORT_SYMBOL(intercept_table);
extern long *ret_from_intercept;
EXPORT_SYMBOL(ret_from_intercept);
EXPORT_SYMBOL(cur_cpu_spec);
+#if defined(CONFIG_ALL_PPC)
+extern unsigned long agp_special_page;
+EXPORT_SYMBOL_NOVERS(agp_special_page);
+#endif /* defined(CONFIG_ALL_PPC) */
diff --git a/arch/ppc/kernel/pplus_common.c b/arch/ppc/kernel/pplus_common.c
new file mode 100644
index 000000000000..df3c2ca61f1d
--- /dev/null
+++ b/arch/ppc/kernel/pplus_common.c
@@ -0,0 +1,317 @@
+/*
+ * arch/ppc/kernel/pplus_common.c
+ *
+ * Common Motorola PowerPlus Platform--really Falcon/Raven or HAWK.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+#include <asm/pplus.h>
+
+/*
+ * The Falcon/Raven and HAWK has 4 sets of registers:
+ * 1) PPC Registers which define the mappings from PPC bus to PCI bus,
+ * etc.
+ * 2) PCI Registers which define the mappings from PCI bus to PPC bus and the
+ * MPIC base address.
+ * 3) MPIC registers.
+ * 4) System Memory Controller (SMC) registers.
+ */
+
+/*
+ * Initialize the Motorola MCG Raven or HAWK host bridge.
+ *
+ * This means setting up the PPC bus to PCI memory and I/O space mappings,
+ * setting the PCI memory space address of the MPIC (mapped straight
+ * through), and ioremap'ing the mpic registers.
+ * This routine will set the PCI_CONFIG_ADDR or PCI_CONFIG_DATA
+ * addresses based on the PCI I/O address that is passed in.
+ * 'OpenPIC_Addr' will be set correctly by this routine.
+ */
+int __init
+pplus_init(struct pci_controller *hose,
+ uint ppc_reg_base,
+ ulong processor_pci_mem_start,
+ ulong processor_pci_mem_end,
+ ulong processor_pci_io_start,
+ ulong processor_pci_io_end,
+ ulong processor_mpic_base)
+{
+ uint addr, offset;
+
+ /*
+ * Some sanity checks...
+ */
+ if (((processor_pci_mem_start&0xffff0000) != processor_pci_mem_start) ||
+ ((processor_pci_io_start &0xffff0000) != processor_pci_io_start)) {
+ printk("pplus_init: %s\n",
+ "PPC to PCI mappings must start on 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end &0x0000ffff) != 0x0000ffff) ||
+ ((processor_pci_io_end &0x0000ffff) != 0x0000ffff)) {
+ printk("pplus_init: PPC to PCI mappings %s\n",
+ "must end just before a 64 KB boundaries");
+ return -1;
+ }
+
+ if (((processor_pci_mem_end - processor_pci_mem_start) !=
+ (hose->mem_space.end - hose->mem_space.start)) ||
+ ((processor_pci_io_end - processor_pci_io_start) !=
+ (hose->io_space.end - hose->io_space.start))) {
+ printk("pplus_init: %s\n",
+ "PPC and PCI memory or I/O space sizes don't match");
+ return -1;
+ }
+
+ if ((processor_mpic_base & 0xfffc0000) != processor_mpic_base) {
+ printk("pplus_init: %s\n",
+ "MPIC address must start on 256 MB boundary");
+ return -1;
+ }
+
+ if ((pci_dram_offset & 0xffff0000) != pci_dram_offset) {
+ printk("pplus_init: %s\n",
+ "pci_dram_offset must be multiple of 64 KB");
+ return -1;
+ }
+
+ /*
+ * Disable previous PPC->PCI mappings.
+ */
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF0_OFF), 0x00000000);
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF1_OFF), 0x00000000);
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF2_OFF), 0x00000000);
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF3_OFF), 0x00000000);
+
+ /*
+ * Program the XSADD/XSOFF registers to set up the PCI Mem & I/O
+ * space mappings. These are the mappings going from the processor to
+ * the PCI bus.
+ *
+ * Note: Don't need to 'AND' start/end addresses with 0xffff0000
+ * because sanity check above ensures that they are properly
+ * aligned.
+ */
+
+ /* Set up PPC->PCI Mem mapping */
+ addr = processor_pci_mem_start | (processor_pci_mem_end >> 16);
+ offset = (hose->mem_space.start - processor_pci_mem_start) | 0xd2;
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSADD0_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF0_OFF), offset);
+
+ /* Set up PPC->MPIC mapping on the bridge */
+ addr = processor_mpic_base |
+ (((processor_mpic_base + PPLUS_MPIC_SIZE) >> 16) - 1);
+ offset = 0xc2; /* No write posting for this PCI Mem space */
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSADD1_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF1_OFF), offset);
+
+ /* Set up PPC->PCI I/O mapping -- Contiguous I/O space */
+ addr = processor_pci_io_start | (processor_pci_io_end >> 16);
+ offset = (hose->io_space.start - processor_pci_io_start) | 0xc0;
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSADD3_OFF), addr);
+ out_be32((uint *)(ppc_reg_base + PPLUS_PPC_XSOFF3_OFF), offset);
+
+ hose->io_base_virt = (void *)ioremap(processor_pci_io_start,
+ (processor_pci_io_end - processor_pci_io_start + 1));
+
+ /*
+ * Set up the indirect method of accessing PCI config space.
+ * The PCI config addr/data pair based on start addr of PCI I/O space.
+ */
+ setup_indirect_pci(hose,
+ processor_pci_io_start + PPLUS_PCI_CONFIG_ADDR_OFF,
+ processor_pci_io_start + PPLUS_PCI_CONFIG_DATA_OFF);
+
+ /*
+ * Disable previous PCI->PPC mappings.
+ */
+
+ /* XXXX Put in mappings from PCI bus to processor bus XXXX */
+
+ /*
+ * Disable MPIC response to PCI I/O space (BAR 0).
+ * Make MPIC respond to PCI Mem space at specified address.
+ * (BAR 1).
+ */
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_BASE_ADDRESS_0,
+ 0x00000000 | 0x1);
+
+ early_write_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_BASE_ADDRESS_1,
+ processor_mpic_base | 0x0);
+
+ /* Map MPIC into vitual memory */
+ OpenPIC_Addr = ioremap(processor_mpic_base, PPLUS_MPIC_SIZE);
+
+ return 0;
+}
+
+/*
+ * Find the amount of RAM present.
+ * This assumes that PPCBug has initialized the memory controller (SMC)
+ * on the Falcon/HAWK correctly (i.e., it does no sanity checking).
+ * It also assumes that the memory base registers are set to configure the
+ * memory as contigous starting with "RAM A BASE", "RAM B BASE", etc.
+ * however, RAM base registers can be skipped (e.g. A, B, C are set,
+ * D is skipped but E is set is okay).
+ */
+#define MB (1024*1024)
+
+static uint reg_offset_table[] __initdata = {
+ PPLUS_SMC_RAM_A_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_B_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_C_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_D_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_E_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_F_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_G_SIZE_REG_OFF,
+ PPLUS_SMC_RAM_H_SIZE_REG_OFF
+};
+
+static uint falcon_size_table[] __initdata = {
+ 0 * MB, /* 0 ==> 0 MB */
+ 16 * MB, /* 1 ==> 16 MB */
+ 32 * MB, /* 2 ==> 32 MB */
+ 64 * MB, /* 3 ==> 64 MB */
+ 128 * MB, /* 4 ==> 128 MB */
+ 256 * MB, /* 5 ==> 256 MB */
+ 1024 * MB, /* 6 ==> 1024 MB (1 GB) */
+};
+
+static uint hawk_size_table[] __initdata = {
+ 0 * MB, /* 0 ==> 0 MB */
+ 32 * MB, /* 1 ==> 32 MB */
+ 64 * MB, /* 2 ==> 64 MB */
+ 64 * MB, /* 3 ==> 64 MB */
+ 128 * MB, /* 4 ==> 128 MB */
+ 128 * MB, /* 5 ==> 128 MB */
+ 128 * MB, /* 6 ==> 128 MB */
+ 256 * MB, /* 7 ==> 256 MB */
+ 256 * MB, /* 8 ==> 256 MB */
+ 512 * MB, /* 9 ==> 512 MB */
+};
+
+/*
+ * *** WARNING: You MUST have a BAT set up to map in the SMC regs ***
+ *
+ * Read the memory controller's registers to determine the amount of system
+ * memory. Assumes that the memory controller registers are already mapped
+ * into virtual memory--too early to use ioremap().
+ */
+unsigned long __init
+pplus_get_mem_size(uint smc_base)
+{
+ unsigned long total;
+ int i, size_table_entries, reg_limit;
+ uint vend_dev_id;
+ uint *size_table;
+ u_char val;
+
+
+ vend_dev_id = in_be32((uint *)smc_base + PCI_VENDOR_ID);
+
+ if (((vend_dev_id & 0xffff0000) >> 16) != PCI_VENDOR_ID_MOTOROLA) {
+ printk("pplus_get_mem_size: %s (0x%x)\n",
+ "Not a Motorola Memory Controller", vend_dev_id);
+ return 0;
+ }
+
+ vend_dev_id &= 0x0000ffff;
+
+ if (vend_dev_id == PCI_DEVICE_ID_MOTOROLA_FALCON) {
+ size_table = falcon_size_table;
+ size_table_entries = sizeof(falcon_size_table) /
+ sizeof(falcon_size_table[0]);
+
+ reg_limit = PPLUS_FALCON_SMC_REG_COUNT;
+ }
+ else if (vend_dev_id == PCI_DEVICE_ID_MOTOROLA_HAWK) {
+ size_table = hawk_size_table;
+ size_table_entries = sizeof(hawk_size_table) /
+ sizeof(hawk_size_table[0]);
+ reg_limit = PPLUS_HAWK_SMC_REG_COUNT;
+ }
+ else {
+ printk("pplus_get_mem_size: %s (0x%x)\n",
+ "Not a Falcon or HAWK", vend_dev_id);
+ return 0;
+ }
+
+ total = 0;
+
+ /* Check every reg because PPCBug may skip some */
+ for (i=0; i<reg_limit; i++) {
+ val = in_8((u_char *)(smc_base + reg_offset_table[i]));
+
+ if (val & 0x80) { /* If enabled */
+ val &= 0x0f;
+
+ /* Don't go past end of size_table */
+ if (val < size_table_entries) {
+ total += size_table[val];
+ }
+ else { /* Register not set correctly */
+ break;
+ }
+ }
+ }
+
+ return total;
+}
+
+int __init
+pplus_mpic_init(unsigned int pci_mem_offset)
+{
+ unsigned short devid;
+ unsigned int pci_membase;
+
+ /* Check the first PCI device to see if it is a Raven or Hawk. */
+ early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid);
+
+ switch (devid) {
+ case PCI_DEVICE_ID_MOTOROLA_RAVEN:
+ case PCI_DEVICE_ID_MOTOROLA_HAWK:
+ break;
+ default:
+ OpenPIC_Addr = NULL;
+ return 1;
+ }
+
+ /* Read the memory base register. */
+ early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+ if (pci_membase == 0) {
+ OpenPIC_Addr = NULL;
+ return 1;
+ }
+
+ /* Map the MPIC registers to virtual memory. */
+ OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000);
+
+ return 0;
+}
diff --git a/arch/ppc/kernel/prep_nvram.c b/arch/ppc/kernel/prep_nvram.c
deleted file mode 100644
index 0049e1b0ffb9..000000000000
--- a/arch/ppc/kernel/prep_nvram.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_nvram.c 1.12 09/08/01 15:47:42 paulus
- */
-/*
- * linux/arch/ppc/kernel/prep_nvram.c
- *
- * Copyright (C) 1998 Corey Minyard
- *
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-
-#include <asm/sections.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/machdep.h>
-#include <asm/prep_nvram.h>
-
-static char nvramData[MAX_PREP_NVRAM];
-static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
-
-unsigned char __prep prep_nvram_read_val(int addr)
-{
- outb(addr, PREP_NVRAM_AS0);
- outb(addr>>8, PREP_NVRAM_AS1);
- return inb(PREP_NVRAM_DATA);
-}
-
-void __prep prep_nvram_write_val(int addr,
- unsigned char val)
-{
- outb(addr, PREP_NVRAM_AS0);
- outb(addr>>8, PREP_NVRAM_AS1);
- outb(val, PREP_NVRAM_DATA);
-}
-
-void __init init_prep_nvram(void)
-{
- unsigned char *nvp;
- int i;
- int nvramSize;
-
- /*
- * The following could fail if the NvRAM were corrupt but
- * we expect the boot firmware to have checked its checksum
- * before boot
- */
- nvp = (char *) &nvram->Header;
- for (i=0; i<sizeof(HEADER); i++)
- {
- *nvp = ppc_md.nvram_read_val(i);
- nvp++;
- }
-
- /*
- * The PReP NvRAM may be any size so read in the header to
- * determine how much we must read in order to get the complete
- * GE area
- */
- nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
- if(nvramSize>MAX_PREP_NVRAM)
- {
- /*
- * NvRAM is too large
- */
- nvram->Header.GELength=0;
- return;
- }
-
- /*
- * Read the remainder of the PReP NvRAM
- */
- nvp = (char *) &nvram->GEArea[0];
- for (i=sizeof(HEADER); i<nvramSize; i++)
- {
- *nvp = ppc_md.nvram_read_val(i);
- nvp++;
- }
-}
-
-__prep
-char __prep *prep_nvram_get_var(const char *name)
-{
- char *cp;
- int namelen;
-
- namelen = strlen(name);
- cp = prep_nvram_first_var();
- while (cp != NULL) {
- if ((strncmp(name, cp, namelen) == 0)
- && (cp[namelen] == '='))
- {
- return cp+namelen+1;
- }
- cp = prep_nvram_next_var(cp);
- }
-
- return NULL;
-}
-
-__prep
-char __prep *prep_nvram_first_var(void)
-{
- if (nvram->Header.GELength == 0) {
- return NULL;
- } else {
- return (((char *)nvram)
- + ((unsigned int) nvram->Header.GEAddress));
- }
-}
-
-__prep
-char __prep *prep_nvram_next_var(char *name)
-{
- char *cp;
-
-
- cp = name;
- while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
- && (*cp != '\0'))
- {
- cp++;
- }
-
- /* Skip over any null characters. */
- while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
- && (*cp == '\0'))
- {
- cp++;
- }
-
- if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
- return cp;
- } else {
- return NULL;
- }
-}
-
-
-
diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c
deleted file mode 100644
index 0db1fde7c06e..000000000000
--- a/arch/ppc/kernel/prep_pci.c
+++ /dev/null
@@ -1,1249 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_pci.c 1.31 10/05/01 17:48:18 trini
- */
-/*
- * PReP pci functions.
- * Originally by Gary Thomas
- * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
- *
- * The motherboard routes/maps will disappear shortly. -- Cort
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/sections.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/ptrace.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/residual.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-#include "open_pic.h"
-
-#define MAX_DEVNR 22
-
-/* Which PCI interrupt line does a given device [slot] use? */
-/* Note: This really should be two dimensional based in slot/pin used */
-static unsigned char *Motherboard_map;
-unsigned char *Motherboard_map_name;
-
-/* How is the 82378 PIRQ mapping setup? */
-static unsigned char *Motherboard_routes;
-
-static void (*Motherboard_non0)(struct pci_dev *);
-
-static void Powerplus_Map_Non0(struct pci_dev *);
-
-/* Used for Motorola to store system config register */
-static unsigned long *ProcInfo;
-
-/* Tables for known hardware */
-
-/* Motorola PowerStackII - Utah */
-static char Utah_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 5, /* Slot 2 - SCSI - NCR825A */
- 0, /* Slot 3 - unused */
- 1, /* Slot 4 - Ethernet - DEC2114x */
- 0, /* Slot 5 - unused */
- 3, /* Slot 6 - PCI Card slot #1 */
- 4, /* Slot 7 - PCI Card slot #2 */
- 5, /* Slot 8 - PCI Card slot #3 */
- 5, /* Slot 9 - PCI Bridge */
- /* added here in case we ever support PCI bridges */
- /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 5, /* Slot 12 - SCSI - NCR825A */
- 0, /* Slot 13 - unused */
- 3, /* Slot 14 - enet */
- 0, /* Slot 15 - unused */
- 2, /* Slot 16 - unused */
- 3, /* Slot 17 - unused */
- 5, /* Slot 18 - unused */
- 0, /* Slot 19 - unused */
- 0, /* Slot 20 - unused */
- 0, /* Slot 21 - unused */
- 0, /* Slot 22 - unused */
-};
-
-static char Utah_pci_IRQ_routes[] __prepdata =
-{
- 0, /* Line 0 - Unused */
- 9, /* Line 1 */
- 10, /* Line 2 */
- 11, /* Line 3 */
- 14, /* Line 4 */
- 15, /* Line 5 */
-};
-
-/* Motorola PowerStackII - Omaha */
-/* no integrated SCSI or ethernet */
-static char Omaha_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 3, /* Slot 2 - Winbond EIDE */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 1, /* Slot 6 - PCI slot 1 */
- 2, /* Slot 7 - PCI slot 2 */
- 3, /* Slot 8 - PCI slot 3 */
- 4, /* Slot 9 - PCI slot 4 */ /* needs indirect access */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 0, /* Slot 12 - unused */
- 0, /* Slot 13 - unused */
- 0, /* Slot 14 - unused */
- 0, /* Slot 15 - unused */
- 1, /* Slot 16 - PCI slot 1 */
- 2, /* Slot 17 - PCI slot 2 */
- 3, /* Slot 18 - PCI slot 3 */
- 4, /* Slot 19 - PCI slot 4 */ /* needs indirect access */
- 0,
- 0,
- 0,
-};
-
-static char Omaha_pci_IRQ_routes[] __prepdata =
-{
- 0, /* Line 0 - Unused */
- 9, /* Line 1 */
- 11, /* Line 2 */
- 14, /* Line 3 */
- 15 /* Line 4 */
-};
-
-/* Motorola PowerStack */
-static char Blackhawk_pci_IRQ_map[19] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI */
- 0, /* Slot 13 - unused */
- 1, /* Slot 14 - Ethernet */
- 0, /* Slot 15 - unused */
- 1, /* Slot P7 */
- 2, /* Slot P6 */
- 3, /* Slot P5 */
-};
-
-static char Blackhawk_pci_IRQ_routes[] __prepdata =
-{
- 0, /* Line 0 - Unused */
- 9, /* Line 1 */
- 11, /* Line 2 */
- 15, /* Line 3 */
- 15 /* Line 4 */
-};
-
-/* Motorola Mesquite */
-static char Mesquite_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 0, /* Slot 12 - unused */
- 0, /* Slot 13 - unused */
- 2, /* Slot 14 - Ethernet */
- 0, /* Slot 15 - unused */
- 3, /* Slot 16 - PMC */
- 0, /* Slot 17 - unused */
- 0, /* Slot 18 - unused */
- 0, /* Slot 19 - unused */
- 0, /* Slot 20 - unused */
- 0, /* Slot 21 - unused */
- 0, /* Slot 22 - unused */
-};
-
-/* Motorola Sitka */
-static char Sitka_pci_IRQ_map[21] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 0, /* Slot 12 - unused */
- 0, /* Slot 13 - unused */
- 2, /* Slot 14 - Ethernet */
- 0, /* Slot 15 - unused */
- 9, /* Slot 16 - PMC 1 */
- 12, /* Slot 17 - PMC 2 */
- 0, /* Slot 18 - unused */
- 0, /* Slot 19 - unused */
- 4, /* Slot 20 - NT P2P bridge */
-};
-
-/* Motorola MTX */
-static char MTX_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI */
- 0, /* Slot 13 - unused */
- 2, /* Slot 14 - Ethernet */
- 0, /* Slot 15 - unused */
- 9, /* Slot 16 - PCI/PMC slot 1 */
- 10, /* Slot 17 - PCI/PMC slot 2 */
- 11, /* Slot 18 - PCI slot 3 */
- 0, /* Slot 19 - unused */
- 0, /* Slot 20 - unused */
- 0, /* Slot 21 - unused */
- 0, /* Slot 22 - unused */
-};
-
-/* Motorola MTX Plus */
-/* Secondary bus interrupt routing is not supported yet */
-static char MTXplus_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI */
- 0, /* Slot 13 - unused */
- 2, /* Slot 14 - Ethernet 1 */
- 0, /* Slot 15 - unused */
- 9, /* Slot 16 - PCI slot 1P */
- 10, /* Slot 17 - PCI slot 2P */
- 11, /* Slot 18 - PCI slot 3P */
- 10, /* Slot 19 - Ethernet 2 */
- 0, /* Slot 20 - P2P Bridge */
- 0, /* Slot 21 - unused */
- 0, /* Slot 22 - unused */
-};
-
-static char Raven_pci_IRQ_routes[] __prepdata =
-{
- 0, /* This is a dummy structure */
-};
-
-/* Motorola MVME16xx */
-static char Genesis_pci_IRQ_map[16] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI */
- 0, /* Slot 13 - unused */
- 1, /* Slot 14 - Ethernet */
- 0, /* Slot 15 - unused */
-};
-
-static char Genesis_pci_IRQ_routes[] __prepdata =
-{
- 0, /* Line 0 - Unused */
- 10, /* Line 1 */
- 11, /* Line 2 */
- 14, /* Line 3 */
- 15 /* Line 4 */
-};
-
-static char Genesis2_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - Ethernet */
- 0, /* Slot 11 - Universe PCI - VME Bridge */
- 3, /* Slot 12 - unused */
- 0, /* Slot 13 - unused */
- 2, /* Slot 14 - SCSI */
- 0, /* Slot 15 - unused */
- 9, /* Slot 16 - PMC 1 */
- 12, /* Slot 17 - pci */
- 11, /* Slot 18 - pci */
- 10, /* Slot 19 - pci */
- 0, /* Slot 20 - pci */
- 0, /* Slot 21 - unused */
- 0, /* Slot 22 - unused */
-};
-
-/* Motorola Series-E */
-static char Comet_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI */
- 0, /* Slot 13 - unused */
- 1, /* Slot 14 - Ethernet */
- 0, /* Slot 15 - unused */
- 1, /* Slot 16 - PCI slot 1 */
- 2, /* Slot 17 - PCI slot 2 */
- 3, /* Slot 18 - PCI slot 3 */
- 4, /* Slot 19 - PCI bridge */
- 0,
- 0,
- 0,
-};
-
-static char Comet_pci_IRQ_routes[] __prepdata =
-{
- 0, /* Line 0 - Unused */
- 10, /* Line 1 */
- 11, /* Line 2 */
- 14, /* Line 3 */
- 15 /* Line 4 */
-};
-
-/* Motorola Series-EX */
-static char Comet2_pci_IRQ_map[23] __prepdata =
-{
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 3, /* Slot 2 - SCSI - NCR825A */
- 0, /* Slot 3 - unused */
- 1, /* Slot 4 - Ethernet - DEC2104X */
- 0, /* Slot 5 - unused */
- 1, /* Slot 6 - PCI slot 1 */
- 2, /* Slot 7 - PCI slot 2 */
- 3, /* Slot 8 - PCI slot 3 */
- 4, /* Slot 9 - PCI bridge */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI - NCR825A */
- 0, /* Slot 13 - unused */
- 1, /* Slot 14 - Ethernet - DEC2104X */
- 0, /* Slot 15 - unused */
- 1, /* Slot 16 - PCI slot 1 */
- 2, /* Slot 17 - PCI slot 2 */
- 3, /* Slot 18 - PCI slot 3 */
- 4, /* Slot 19 - PCI bridge */
- 0,
- 0,
- 0,
-};
-
-static char Comet2_pci_IRQ_routes[] __prepdata =
-{
- 0, /* Line 0 - Unused */
- 10, /* Line 1 */
- 11, /* Line 2 */
- 14, /* Line 3 */
- 15, /* Line 4 */
-};
-
-/*
- * ibm 830 (and 850?).
- * This is actually based on the Carolina motherboard
- * -- Cort
- */
-static char ibm8xx_pci_IRQ_map[23] __prepdata = {
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - FireCoral */
- 4, /* Slot 12 - Ethernet PCIINTD# */
- 2, /* Slot 13 - PCI Slot #2 */
- 2, /* Slot 14 - S3 Video PCIINTD# */
- 0, /* Slot 15 - onboard SCSI (INDI) [1] */
- 3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */
- 0, /* Slot 17 - unused */
- 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
- 0, /* Slot 19 - unused */
- 0, /* Slot 20 - unused */
- 0, /* Slot 21 - unused */
- 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
-};
-
-static char ibm8xx_pci_IRQ_routes[] __prepdata = {
- 0, /* Line 0 - unused */
- 15, /* Line 1 */
- 15, /* Line 2 */
- 15, /* Line 3 */
- 15, /* Line 4 */
-};
-
-/*
- * a 6015 ibm board
- * -- Cort
- */
-static char ibm6015_pci_IRQ_map[23] __prepdata = {
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - */
- 1, /* Slot 12 - SCSI */
- 2, /* Slot 13 - */
- 2, /* Slot 14 - */
- 1, /* Slot 15 - */
- 1, /* Slot 16 - */
- 0, /* Slot 17 - */
- 2, /* Slot 18 - */
- 0, /* Slot 19 - */
- 0, /* Slot 20 - */
- 0, /* Slot 21 - */
- 2, /* Slot 22 - */
-};
-
-static char ibm6015_pci_IRQ_routes[] __prepdata = {
- 0, /* Line 0 - unused */
- 13, /* Line 1 */
- 15, /* Line 2 */
- 15, /* Line 3 */
- 15, /* Line 4 */
-};
-
-
-/* IBM Nobis and Thinkpad 850 */
-static char Nobis_pci_IRQ_map[23] __prepdata ={
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - unused */
- 3, /* Slot 12 - SCSI */
- 0, /* Slot 13 - unused */
- 0, /* Slot 14 - unused */
- 0, /* Slot 15 - unused */
-};
-
-static char Nobis_pci_IRQ_routes[] __prepdata = {
- 0, /* Line 0 - Unused */
- 13, /* Line 1 */
- 13, /* Line 2 */
- 13, /* Line 3 */
- 13 /* Line 4 */
-};
-
-/*
- * IBM RS/6000 43p/140 -- paulus
- * XXX we should get all this from the residual data
- */
-static char ibm43p_pci_IRQ_map[23] __prepdata = {
- 0, /* Slot 0 - unused */
- 0, /* Slot 1 - unused */
- 0, /* Slot 2 - unused */
- 0, /* Slot 3 - unused */
- 0, /* Slot 4 - unused */
- 0, /* Slot 5 - unused */
- 0, /* Slot 6 - unused */
- 0, /* Slot 7 - unused */
- 0, /* Slot 8 - unused */
- 0, /* Slot 9 - unused */
- 0, /* Slot 10 - unused */
- 0, /* Slot 11 - FireCoral ISA bridge */
- 6, /* Slot 12 - Ethernet */
- 0, /* Slot 13 - openpic */
- 0, /* Slot 14 - unused */
- 0, /* Slot 15 - unused */
- 7, /* Slot 16 - NCR58C825a onboard scsi */
- 0, /* Slot 17 - unused */
- 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
- 0, /* Slot 19 - unused */
- 0, /* Slot 20 - unused */
- 0, /* Slot 21 - unused */
- 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
-};
-
-static char ibm43p_pci_IRQ_routes[] __prepdata = {
- 0, /* Line 0 - unused */
- 15, /* Line 1 */
- 15, /* Line 2 */
- 15, /* Line 3 */
- 15, /* Line 4 */
-};
-
-/* Motorola PowerPlus architecture PCI IRQ tables */
-/* Interrupt line values for INTA-D on primary/secondary MPIC inputs */
-
-struct powerplus_irq_list
-{
- unsigned char primary[4]; /* INT A-D */
- unsigned char secondary[4]; /* INT A-D */
-};
-
-/*
- * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to
- * OpenPIC inputs 9-12. PCI INTs A-D from the on board P2P bridge
- * are routed to OpenPIC inputs 5-8. These values are offset by
- * 16 in the table to reflect the Linux kernel interrupt value.
- */
-struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
-{
- {25, 26, 27, 28},
- {21, 22, 23, 24}
-};
-
-/*
- * For the MCP750 (system slot board), cPCI INTs A-D are routed to
- * OpenPIC inputs 8-11 and the PMC INTs A-D are routed to OpenPIC
- * input 3. On a hot swap MCP750, the companion card PCI INTs A-D
- * are routed to OpenPIC inputs 12-15. These values are offset by
- * 16 in the table to reflect the Linux kernel interrupt value.
- */
-struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
-{
- {24, 25, 26, 27},
- {28, 29, 30, 31}
-};
-
-/*
- * This table represents the standard PCI swizzle defined in the
- * PCI bus specification.
- */
-static unsigned char prep_pci_intpins[4][4] __prepdata =
-{
- { 1, 2, 3, 4}, /* Buses 0, 4, 8, ... */
- { 2, 3, 4, 1}, /* Buses 1, 5, 9, ... */
- { 3, 4, 1, 2}, /* Buses 2, 6, 10 ... */
- { 4, 1, 2, 3}, /* Buses 3, 7, 11 ... */
-};
-
-/* We have to turn on LEVEL mode for changed IRQ's */
-/* All PCI IRQ's need to be level mode, so this should be something
- * other than hard-coded as well... IRQ's are individually mappable
- * to either edge or level.
- */
-
-/*
- * 8259 edge/level control definitions
- */
-#define ISA8259_M_ELCR 0x4d0
-#define ISA8259_S_ELCR 0x4d1
-
-#define ELCRS_INT15_LVL 0x80
-#define ELCRS_INT14_LVL 0x40
-#define ELCRS_INT12_LVL 0x10
-#define ELCRS_INT11_LVL 0x08
-#define ELCRS_INT10_LVL 0x04
-#define ELCRS_INT9_LVL 0x02
-#define ELCRS_INT8_LVL 0x01
-#define ELCRM_INT7_LVL 0x80
-#define ELCRM_INT5_LVL 0x20
-
-#define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset)
-#define DEVNO(dev) (dev>>3)
-
-#define cfg_read(val, addr, type, op) *val = op((type)(addr))
-#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
-
-#define cfg_read_bad(val, size) *val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte 0xff
-#define bad_word 0xffff
-#define bad_dword 0xffffffffU
-
-#define PREP_PCI_OP(rw, size, type, op) \
-static int __prep \
-prep_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- if ((dev->bus->number != 0) || (DEVNO(dev->devfn) > MAX_DEVNR)) \
- { \
- cfg_##rw##_bad(val, size) \
- return PCIBIOS_DEVICE_NOT_FOUND; \
- } \
- cfg_##rw(val, CFGPTR(dev->devfn), type, op); \
- return PCIBIOS_SUCCESSFUL; \
-}
-
-PREP_PCI_OP(read, byte, u8 *, in_8)
-PREP_PCI_OP(read, word, u16 *, in_le16)
-PREP_PCI_OP(read, dword, u32 *, in_le32)
-PREP_PCI_OP(write, byte, u8, out_8)
-PREP_PCI_OP(write, word, u16, out_le16)
-PREP_PCI_OP(write, dword, u32, out_le32)
-
-static struct pci_ops prep_pci_ops =
-{
- prep_read_config_byte,
- prep_read_config_word,
- prep_read_config_dword,
- prep_write_config_byte,
- prep_write_config_word,
- prep_write_config_dword
-};
-
-#define MOTOROLA_CPUTYPE_REG 0x800
-#define MOTOROLA_BASETYPE_REG 0x803
-#define MPIC_RAVEN_ID 0x48010000
-#define MPIC_HAWK_ID 0x48030000
-#define MOT_PROC2_BIT 0x800
-
-static u_char mvme2600_openpic_initsenses[] __initdata = {
- 1, /* MVME2600_INT_SIO */
- 0, /* MVME2600_INT_FALCN_ECC_ERR */
- 1, /* MVME2600_INT_PCI_ETHERNET */
- 1, /* MVME2600_INT_PCI_SCSI */
- 1, /* MVME2600_INT_PCI_GRAPHICS */
- 1, /* MVME2600_INT_PCI_VME0 */
- 1, /* MVME2600_INT_PCI_VME1 */
- 1, /* MVME2600_INT_PCI_VME2 */
- 1, /* MVME2600_INT_PCI_VME3 */
- 1, /* MVME2600_INT_PCI_INTA */
- 1, /* MVME2600_INT_PCI_INTB */
- 1, /* MVME2600_INT_PCI_INTC */
- 1, /* MVME2600_INT_PCI_INTD */
- 1, /* MVME2600_INT_LM_SIG0 */
- 1, /* MVME2600_INT_LM_SIG1 */
-};
-
-#define MOT_RAVEN_PRESENT 0x1
-#define MOT_HAWK_PRESENT 0x2
-
-int mot_entry = -1;
-int prep_keybd_present = 1;
-int MotMPIC;
-int mot_multi;
-
-int __init
-raven_init(void)
-{
- unsigned int devid;
- unsigned int pci_membase;
- unsigned char base_mod;
-
- /* Check to see if the Raven chip exists. */
- if ( _prep_type != _PREP_Motorola) {
- OpenPIC_Addr = NULL;
- return 0;
- }
-
- /* Check to see if this board is a type that might have a Raven. */
- if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
- OpenPIC_Addr = NULL;
- return 0;
- }
-
- /* Check the first PCI device to see if it is a Raven. */
- early_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &devid);
-
- switch (devid & 0xffff0000) {
- case MPIC_RAVEN_ID:
- MotMPIC = MOT_RAVEN_PRESENT;
- break;
- case MPIC_HAWK_ID:
- MotMPIC = MOT_HAWK_PRESENT;
- break;
- default:
- OpenPIC_Addr = NULL;
- return 0;
- }
-
-
- /* Read the memory base register. */
- early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
-
- if (pci_membase == 0) {
- OpenPIC_Addr = NULL;
- return 0;
- }
-
- /* Map the Raven MPIC registers to virtual memory. */
- OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000);
-
- OpenPIC_InitSenses = mvme2600_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
-
- ppc_md.get_irq = openpic_get_irq;
-
- /* If raven is present on Motorola store the system config register
- * for later use.
- */
- ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
-
- /* Indicate to system if this is a multiprocessor board */
- if (!(*ProcInfo & MOT_PROC2_BIT)) {
- mot_multi = 1;
- }
-
- /* This is a hack. If this is a 2300 or 2400 mot board then there is
- * no keyboard controller and we have to indicate that.
- */
- base_mod = inb(MOTOROLA_BASETYPE_REG);
- if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
- (base_mod == 0xFA) || (base_mod == 0xE1))
- prep_keybd_present = 0;
-
- return 1;
-}
-
-struct mot_info {
- int cpu_type; /* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
- /* 0x200 if this board has a Hawk chip. */
- int base_type;
- int max_cpu; /* ored with 0x80 if this board should be checked for multi CPU */
- const char *name;
- unsigned char *map;
- unsigned char *routes;
- void (*map_non0_bus)(struct pci_dev *); /* For boards with more than bus 0 devices. */
- struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
- unsigned char secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
-} mot_info[] __prepdata = {
- {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
- {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes, NULL, NULL, 0x00},
- {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00},
- {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes, NULL, NULL, 0x00},
- {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes, NULL, NULL, 0x00},
- {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes, NULL, NULL, 0x00},
- {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xFF},
- {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0},
- {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
- {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
- {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
- {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
- {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
- {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
- {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
- {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
- {0x000, 0x00, 0x00, "", NULL, NULL, NULL, NULL, 0x00}
-};
-
-void __init
-ibm_prep_init(void)
-{
- u32 addr;
-#ifdef CONFIG_PREP_RESIDUAL
- PPC_DEVICE *mpic;
-#endif
-
- if (inb(0x0852) == 0xd5) {
- /* This is for the 43p-140 */
- early_read_config_dword(0, 0, PCI_DEVFN(13, 0),
- PCI_BASE_ADDRESS_0, &addr);
- if (addr != 0xffffffff
- && !(addr & PCI_BASE_ADDRESS_SPACE_IO)
- && (addr &= PCI_BASE_ADDRESS_MEM_MASK) != 0) {
- addr += PREP_ISA_MEM_BASE;
- OpenPIC_Addr = ioremap(addr, 0x40000);
- ppc_md.get_irq = openpic_get_irq;
- }
- }
-
-#ifdef CONFIG_PREP_RESIDUAL
- mpic = residual_find_device(-1, NULL, SystemPeripheral,
- ProgrammableInterruptController, MPIC, 0);
- if (mpic != NULL)
- printk("mpic = %p\n", mpic);
-#endif
-}
-
-static void __init
-ibm43p_pci_map_non0(struct pci_dev *dev)
-{
- unsigned char intpin;
- static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 };
-
- if (dev == NULL)
- return;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
- if (intpin < 1 || intpin > 4)
- return;
- intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3;
- dev->irq = openpic_to_irq(bridge_intrs[intpin]);
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-}
-
-void __init
-prep_route_pci_interrupts(void)
-{
- unsigned char *ibc_pirq = (unsigned char *)0x80800860;
- unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
- int i;
-
- if ( _prep_type == _PREP_Motorola)
- {
- unsigned short irq_mode;
- unsigned char cpu_type;
- unsigned char base_mod;
- int entry;
-
- cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
- base_mod = inb(MOTOROLA_BASETYPE_REG);
-
- for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
- if (mot_info[entry].cpu_type & 0x200) { /* Check for Hawk chip */
- if (!(MotMPIC & MOT_HAWK_PRESENT))
- continue;
- } else { /* Check non hawk boards */
- if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
- continue;
-
- if (mot_info[entry].base_type == 0) {
- mot_entry = entry;
- break;
- }
-
- if (mot_info[entry].base_type != base_mod)
- continue;
- }
-
- if (!(mot_info[entry].max_cpu & 0x80)) {
- mot_entry = entry;
- break;
- }
-
- /* processor 1 not present and max processor zero indicated */
- if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
- mot_entry = entry;
- break;
- }
-
- /* processor 1 present and max processor zero indicated */
- if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
- mot_entry = entry;
- break;
- }
- }
-
- if (mot_entry == -1) /* No particular cpu type found - assume Blackhawk */
- mot_entry = 3;
-
- Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
- Motherboard_map = mot_info[mot_entry].map;
- Motherboard_routes = mot_info[mot_entry].routes;
- Motherboard_non0 = mot_info[mot_entry].map_non0_bus;
-
- if (!(mot_info[entry].cpu_type & 0x100)) {
- /* AJF adjust level/edge control according to routes */
- irq_mode = 0;
- for (i = 1; i <= 4; i++)
- irq_mode |= ( 1 << Motherboard_routes[i] );
- outb( irq_mode & 0xff, 0x4d0 );
- outb( (irq_mode >> 8) & 0xff, 0x4d1 );
- }
- } else if ( _prep_type == _PREP_IBM ) {
- unsigned char planar_id = inb(0x0852);
- unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
-
- printk("IBM ID: %08x\n", planar_id);
- switch(planar_id) {
- case 0xff:
- Motherboard_map_name = "IBM Thinkpad 850/860";
- Motherboard_map = Nobis_pci_IRQ_map;
- Motherboard_routes = Nobis_pci_IRQ_routes;
- irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
- irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
- break;
- case 0xfc:
- Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
- Motherboard_map = ibm6015_pci_IRQ_map;
- Motherboard_routes = ibm6015_pci_IRQ_routes;
- irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
- irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
- break;
- case 0xd5:
- Motherboard_map_name = "IBM 43P-140 (Tiger1)";
- Motherboard_map = ibm43p_pci_IRQ_map;
- Motherboard_routes = ibm43p_pci_IRQ_routes;
- Motherboard_non0 = ibm43p_pci_map_non0;
- irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
- irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
- break;
- default:
- printk(KERN_ERR "Unknown IBM motherboard! Defaulting to Carolina.\n");
- case 0xf0: /* PowerSeries 830/850 */
- case 0xf1: /* PowerSeries 830/850 */
- case 0xf2: /* PowerSeries 830/850 */
- case 0xf4: /* 7248-43P */
- case 0xf5: /* 7248-43P */
- case 0xf6: /* 7248-43P */
- case 0xf7: /* 7248-43P (missing from Carolina Tech Spec) */
- Motherboard_map_name = "IBM PS830/PS850/7248 (Carolina)";
- Motherboard_map = ibm8xx_pci_IRQ_map;
- Motherboard_routes = ibm8xx_pci_IRQ_routes;
- irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
- irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
- break;
- }
-
- outb(inb(0x04d0)|irq_edge_mask_lo, 0x04d0); /* primary 8259 */
- outb(inb(0x04d1)|irq_edge_mask_hi, 0x04d1); /* cascaded 8259 */
- } else {
- printk("No known machine pci routing!\n");
- return;
- }
-
- /* Set up mapping from slots */
- for (i = 1; i <= 4; i++)
- ibc_pirq[i-1] = Motherboard_routes[i];
- /* Enable PCI interrupts */
- *ibc_pcicon |= 0x20;
-}
-
-void __init
-prep_pib_init(void)
-{
- unsigned char reg;
- unsigned short short_reg;
-
- struct pci_dev *dev = NULL;
-
- if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) {
- /*
- * Perform specific configuration for the Via Tech or
- * or Winbond PCI-ISA-Bridge part.
- */
- if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_1, dev))) {
- /*
- * PPCBUG does not set the enable bits
- * for the IDE device. Force them on here.
- */
- pci_read_config_byte(dev, 0x40, &reg);
-
- reg |= 0x03; /* IDE: Chip Enable Bits */
- pci_write_config_byte(dev, 0x40, reg);
- }
- if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C586_2,
- dev)) && (dev->devfn = 0x5a)) {
- /* Force correct USB interrupt */
- dev->irq = 11;
- pci_write_config_byte(dev,
- PCI_INTERRUPT_LINE,
- dev->irq);
- }
- if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
- PCI_DEVICE_ID_WINBOND_83C553, dev))) {
- /* Clear PCI Interrupt Routing Control Register. */
- short_reg = 0x0000;
- pci_write_config_word(dev, 0x44, short_reg);
- if (OpenPIC_Addr){
- /* Route IDE interrupts to IRQ 14 */
- reg = 0xEE;
- pci_write_config_byte(dev, 0x43, reg);
- }
- }
- }
-
- if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
- PCI_DEVICE_ID_WINBOND_82C105, dev))){
- if (OpenPIC_Addr){
- /*
- * Disable LEGIRQ mode so PCI INTS are routed
- * directly to the 8259 and enable both channels
- */
- pci_write_config_dword(dev, 0x40, 0x10ff0033);
-
- /* Force correct IDE interrupt */
- dev->irq = 14;
- pci_write_config_byte(dev,
- PCI_INTERRUPT_LINE,
- dev->irq);
- } else {
- /* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */
- pci_write_config_dword(dev, 0x40, 0x10ff08a1);
- }
- }
-}
-
-static void __init
-Powerplus_Map_Non0(struct pci_dev *dev)
-{
- struct pci_bus *pbus; /* Parent bus structure pointer */
- struct pci_dev *tdev = dev; /* Temporary device structure */
- unsigned int devnum; /* Accumulated device number */
- unsigned char intline; /* Linux interrupt value */
- unsigned char intpin; /* PCI interrupt pin */
-
- /* Check for valid PCI dev pointer */
- if (dev == NULL) return;
-
- /* Initialize bridge IDSEL variable */
- devnum = PCI_SLOT(tdev->devfn);
-
- /* Read the interrupt pin of the device and adjust for indexing */
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &intpin);
-
- /* If device doesn't request an interrupt, return */
- if ( (intpin < 1) || (intpin > 4) )
- return;
-
- intpin--;
-
- /*
- * Walk up to bus 0, adjusting the interrupt pin for the standard
- * PCI bus swizzle.
- */
- do {
- intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
- pbus = tdev->bus; /* up one level */
- tdev = pbus->self;
- devnum = PCI_SLOT(tdev->devfn);
- } while(tdev->bus->number);
-
- /* Use the primary interrupt inputs by default */
- intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
-
- /*
- * If the board has secondary interrupt inputs, walk the bus and
- * note the devfn of the bridge from bus 0. If it is the same as
- * the devfn of the bus bridge with secondary inputs, use those.
- * Otherwise, assume it's a PMC site and get the interrupt line
- * value from the interrupt routing table.
- */
- if (mot_info[mot_entry].secondary_bridge_devfn) {
- pbus = dev->bus;
-
- while (pbus->primary != 0)
- pbus = pbus->parent;
-
- if ((pbus->self)->devfn != 0xA0) {
- if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn)
- intline = mot_info[mot_entry].pci_irq_list->secondary[intpin];
- else {
- if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map)
- intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16;
- else {
- int i;
- for (i=0;i<3;i++)
- intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
- intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
- }
- }
- }
- }
-
- /* Write calculated interrupt value to header and device list */
- dev->irq = intline;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq);
-}
-
-void __init
-prep_pcibios_fixup(void)
-{
- struct pci_dev *dev;
- extern unsigned char *Motherboard_map;
- extern unsigned char *Motherboard_routes;
- unsigned char i;
-
- prep_route_pci_interrupts();
-
- printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
- if (OpenPIC_Addr) {
- /* PCI interrupts are controlled by the OpenPIC */
- pci_for_each_dev(dev) {
- if (dev->bus->number == 0) {
- dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
- pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq);
- } else {
- if (Motherboard_non0 != NULL)
- Motherboard_non0(dev);
- }
- }
-
- /* Setup the Winbond or Via PIB */
- prep_pib_init();
-
- return;
- }
-
- pci_for_each_dev(dev) {
- /*
- * Use our old hard-coded kludge to figure out what
- * irq this device uses. This is necessary on things
- * without residual data. -- Cort
- */
- unsigned char d = PCI_SLOT(dev->devfn);
- dev->irq = Motherboard_routes[Motherboard_map[d]];
-
- for ( i = 0 ; i <= 5 ; i++ ) {
- /*
- * Relocate PCI I/O resources if necessary so the
- * standard 256MB BAT covers them.
- */
- if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) &&
- (dev->resource[i].start > 0x10000000)) {
- printk("Relocating PCI address %lx -> %lx\n",
- dev->resource[i].start,
- (dev->resource[i].start &
- 0x00FFFFFF)| 0x01000000);
- dev->resource[i].start =
- (dev->resource[i].start & 0x00FFFFFF)
- | 0x01000000;
- pci_write_config_dword(dev,
- PCI_BASE_ADDRESS_0 + (i*0x4),
- dev->resource[i].start);
- dev->resource[i].end =
- (dev->resource[i].end & 0x00FFFFFF)
- | 0x01000000;
- }
- }
-#if 0
- /*
- * If we have residual data and if it knows about this
- * device ask it what the irq is.
- * -- Cort
- */
- ppcd = residual_find_device_id( ~0L, dev->device,
- -1,-1,-1, 0);
-#endif
- }
-}
-
-static void __init
-prep_init_resource(struct resource *res, unsigned long start,
- unsigned long end, int flags)
-{
- res->flags = flags;
- res->start = start;
- res->end = end;
- res->name = "PCI host bridge";
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
-}
-
-void __init
-prep_find_bridges(void)
-{
- struct pci_controller* hose;
-
- hose = pcibios_alloc_controller();
- if (!hose)
- return;
-
- hose->first_busno = 0;
- hose->last_busno = 0xff;
- hose->pci_mem_offset = PREP_ISA_MEM_BASE;
- hose->io_base_phys = PREP_ISA_IO_BASE;
- hose->io_base_virt = (void *)0x80000000; /* see prep_map_io() */
- prep_init_resource(&hose->io_resource, 0, 0x0fffffff, IORESOURCE_IO);
- prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff,
- IORESOURCE_MEM);
-
- printk("PReP architecture\n");
- {
-#ifdef CONFIG_PREP_RESIDUAL
- PPC_DEVICE *hostbridge;
-
- hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
- BridgeController, PCIBridge, -1, 0);
- if (hostbridge &&
- hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
- PnP_TAG_PACKET * pkt;
- pkt = PnP_find_large_vendor_packet(
- res->DevicePnPHeap+hostbridge->AllocatedOffset,
- 3, 0);
- if(pkt) {
-#define p pkt->L4_Pack.L4_Data.L4_PPCPack
- setup_indirect_pci(hose,
- ld_le32((unsigned *) (p.PPCData)),
- ld_le32((unsigned *) (p.PPCData+8)));
- } else
- setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
- } else
-#endif /* CONFIG_PREP_RESIDUAL */
- hose->ops = &prep_pci_ops;
- }
-
- ppc_md.pcibios_fixup = prep_pcibios_fixup;
-}
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
deleted file mode 100644
index cf8ecaae9bcb..000000000000
--- a/arch/ppc/kernel/prep_setup.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_setup.c 1.44 11/13/01 21:26:07 paulus
- */
-/*
- * linux/arch/ppc/kernel/setup.c
- *
- * Copyright (C) 1995 Linus Torvalds
- * Adapted from 'alpha' version by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- *
- * Support for PReP (Motorola MTX/MVME)
- * by Troy Benjegerdes (hozer@drgw.net)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/blk.h>
-#include <linux/ioport.h>
-#include <linux/console.h>
-#include <linux/timex.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-
-#include <asm/sections.h>
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/residual.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/cache.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/mk48t59.h>
-#include <asm/prep_nvram.h>
-#include <asm/raven.h>
-#include <asm/keyboard.h>
-#include <asm/vga.h>
-#include <asm/time.h>
-
-#include "local_irq.h"
-#include "i8259.h"
-#include "open_pic.h"
-
-#if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
-#include <../drivers/sound/sound_config.h>
-#include <../drivers/sound/dev_table.h>
-#endif
-
-unsigned char ucSystemType;
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
-extern unsigned long mc146818_get_rtc_time(void);
-extern int mc146818_set_rtc_time(unsigned long nowtime);
-extern unsigned long mk48t59_get_rtc_time(void);
-extern int mk48t59_set_rtc_time(unsigned long nowtime);
-
-extern unsigned char prep_nvram_read_val(int addr);
-extern void prep_nvram_write_val(int addr,
- unsigned char val);
-extern unsigned char rs_nvram_read_val(int addr);
-extern void rs_nvram_write_val(int addr,
- unsigned char val);
-extern void ibm_prep_init(void);
-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[];
-
-extern void prep_find_bridges(void);
-extern char saved_command_line[];
-
-int _prep_type;
-
-#define cached_21 (((char *)(ppc_cached_irq_mask))[3])
-#define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
-
-/* for the mac fs */
-kdev_t boot_dev;
-/* used in nasty hack for sound - see prep_setup_arch() -- Cort */
-long ppc_cs4232_dma, ppc_cs4232_dma2;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-
-#ifdef CONFIG_SOUND_MODULE
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
-
-static int __prep
-prep_show_cpuinfo(struct seq_file *m)
-{
- extern char *Motherboard_map_name;
- int cachew;
-#ifdef CONFIG_PREP_RESIDUAL
- int i;
-#endif
-
- seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
-
- switch ( _prep_type ) {
- case _PREP_IBM:
- cachew = inw(0x80c);
- if (cachew & (1<<6))
- seq_printf(m, "Upgrade CPU\n");
- seq_printf(m, "L2\t\t: ");
- if (cachew & (1<<7)) {
- seq_printf(m, "not present\n");
- goto no_l2;
- }
- seq_printf(m, "%sKb,", (cachew & (1 << 10))? "512" : "256");
- seq_printf(m, "%ssync\n", (cachew & (1 << 15))? "" : "a");
- break;
- case _PREP_Motorola:
- cachew = *((unsigned char *)CACHECRBA);
- seq_printf(m, "L2\t\t: ");
- switch (cachew & L2CACHE_MASK) {
- case L2CACHE_512KB:
- seq_printf(m, "512Kb");
- break;
- case L2CACHE_256KB:
- seq_printf(m, "256Kb");
- break;
- case L2CACHE_1MB:
- seq_printf(m, "1MB");
- break;
- case L2CACHE_NONE:
- seq_printf(m, "none\n");
- goto no_l2;
- break;
- default:
- seq_printf(m, "%x\n", cachew);
- }
-
- seq_printf(m, ", parity %s",
- (cachew & L2CACHE_PARITY)? "enabled" : "disabled");
-
- seq_printf(m, " SRAM:");
-
- switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
- case 1: seq_printf(m, "synchronous,parity,flow-through\n");
- break;
- case 2: seq_printf(m, "asynchronous,no parity\n");
- break;
- case 3: seq_printf(m, "asynchronous,parity\n");
- break;
- default:seq_printf(m, "synchronous,pipelined,no parity\n");
- break;
- }
- break;
- default:
- break;
- }
-
-no_l2:
-#ifdef CONFIG_PREP_RESIDUAL
- if (res->ResidualLength == 0) {
- /* print info about SIMMs */
- seq_printf(m, "simms\t\t: ");
- for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
- if (res->Memories[i].SIMMSize != 0)
- seq_printf(m, "%d:%ldM ", i,
- (res->Memories[i].SIMMSize > 1024) ?
- res->Memories[i].SIMMSize>>20 :
- res->Memories[i].SIMMSize);
- }
- seq_printf(m, "\n");
- }
-#endif
-
- return 0;
-}
-
-static int __prep
-prep_show_percpuinfo(struct seq_file *m, int i)
-{
- int len = 0;
-
- /* PREP's without residual data will give incorrect values here */
- seq_printf(m, "clock\t\t: ");
-#ifdef CONFIG_PREP_RESIDUAL
- if (res->ResidualLength)
- seq_printf(m, "%ldMHz\n",
- (res->VitalProductData.ProcessorHz > 1024) ?
- res->VitalProductData.ProcessorHz>>20 :
- res->VitalProductData.ProcessorHz);
- else
-#endif /* CONFIG_PREP_RESIDUAL */
- seq_printf(m, "???\n");
-
- return 0;
-}
-
-static void __init
-prep_setup_arch(void)
-{
- unsigned char reg;
-#if 0 /* unused?? */
- unsigned char ucMothMemType;
- unsigned char ucEquipPres1;
-#endif
-
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000;
-
- /* Lookup PCI host bridges */
- prep_find_bridges();
-
- /* Set up floppy in PS/2 mode */
- outb(0x09, SIO_CONFIG_RA);
- reg = inb(SIO_CONFIG_RD);
- reg = (reg & 0x3F) | 0x40;
- outb(reg, SIO_CONFIG_RD);
- outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
-
- /*
- * We need to set up the NvRAM access routines early as prep_init
- * has yet to be called
- */
- ppc_md.nvram_read_val = prep_nvram_read_val;
- ppc_md.nvram_write_val = prep_nvram_write_val;
-
- /* we should determine this according to what we find! -- Cort */
- switch ( _prep_type )
- {
- case _PREP_IBM:
- /* Enable L2. Assume we don't need to flush -- Cort*/
- *(unsigned char *)(0x8000081c) |= 3;
- ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
- break;
- case _PREP_Motorola:
- /* Enable L2. Assume we don't need to flush -- Cort*/
- *(unsigned char *)(0x8000081c) |= 3;
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = to_kdev_t(0x00ff); /* /dev/nfs */
-#else
- ROOT_DEV = to_kdev_t(0x0802); /* /dev/sda2 */
-#endif
- break;
- }
-
- /* Read in NVRAM data */
- init_prep_nvram();
-
- /* if no bootargs, look in NVRAM */
- if ( cmd_line[0] == '\0' ) {
- char *bootargs;
- bootargs = prep_nvram_get_var("bootargs");
- if (bootargs != NULL) {
- strcpy(cmd_line, bootargs);
- /* again.. */
- strcpy(saved_command_line, cmd_line);
- }
- }
-
-#ifdef CONFIG_SOUND_CS4232
- /*
- * setup proper values for the cs4232 driver so we don't have
- * to recompile for the motorola or ibm workstations sound systems.
- * This is a really nasty hack, but unless we change the driver
- * it's the only way to support both addrs from one binary.
- * -- Cort
- */
- if ( _machine == _MACH_prep )
- {
- extern struct card_info snd_installed_cards[];
- struct card_info *snd_ptr;
-
- for ( snd_ptr = snd_installed_cards;
- snd_ptr < &snd_installed_cards[num_sound_cards];
- snd_ptr++ )
- {
- if ( snd_ptr->card_type == SNDCARD_CS4232 )
- {
- if ( _prep_type == _PREP_Motorola )
- {
- snd_ptr->config.io_base = 0x830;
- snd_ptr->config.irq = 10;
- snd_ptr->config.dma = ppc_cs4232_dma = 6;
- snd_ptr->config.dma2 = ppc_cs4232_dma2 = 7;
- }
- if ( _prep_type == _PREP_IBM )
- {
- snd_ptr->config.io_base = 0x530;
- snd_ptr->config.irq = 5;
- snd_ptr->config.dma = ppc_cs4232_dma = 1;
- /* this is wrong - but leave it for now */
- snd_ptr->config.dma2 = ppc_cs4232_dma2 = 7;
- }
- }
- }
- }
-#endif /* CONFIG_SOUND_CS4232 */
-
- /*print_residual_device_info();*/
-
- switch (_prep_type) {
- case _PREP_Motorola:
- raven_init();
- break;
- case _PREP_IBM:
- ibm_prep_init();
- break;
- }
-
-#ifdef CONFIG_VGA_CONSOLE
- /* remap the VGA memory */
- vgacon_remap_base = 0xf0000000;
- /*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
- conswitchp = &vga_con;
-#elif defined(CONFIG_DUMMY_CONSOLE)
- conswitchp = &dummy_con;
-#endif
-}
-
-/*
- * Determine the decrementer frequency from the residual data
- * This allows for a faster boot as we do not need to calibrate the
- * decrementer against another clock. This is important for embedded systems.
- */
-static int __init
-prep_res_calibrate_decr(void)
-{
-#ifdef CONFIG_PREP_RESIDUAL
- unsigned long freq, divisor = 4;
-
- if ( res->VitalProductData.ProcessorBusHz ) {
- freq = res->VitalProductData.ProcessorBusHz;
- printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
- (freq/divisor)/1000000,
- (freq/divisor)%1000000);
- tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
- tb_ticks_per_jiffy = freq / HZ / divisor;
- return 0;
- } else
-#endif
- return 1;
-}
-
-/*
- * Uses the on-board timer to calibrate the on-chip decrementer register
- * for prep systems. On the pmac the OF tells us what the frequency is
- * but on prep we have to figure it out.
- * -- Cort
- */
-/* Done with 3 interrupts: the first one primes the cache and the
- * 2 following ones measure the interval. The precision of the method
- * is still doubtful due to the short interval sampled.
- */
-static volatile int calibrate_steps __initdata = 3;
-static unsigned tbstamp __initdata = 0;
-
-static void __init
-prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs)
-{
- unsigned long t, freq;
- int step=--calibrate_steps;
-
- t = get_tbl();
- if (step > 0) {
- tbstamp = t;
- } else {
- freq = (t - tbstamp)*HZ;
- printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
- }
-}
-
-static void __init
-prep_calibrate_decr(void)
-{
- int res;
-
- /* Try and get this from the residual data. */
- res = prep_res_calibrate_decr();
-
- /* If we didn't get it from the residual data, try this. */
- if ( res ) {
- unsigned long flags;
-
- save_flags(flags);
-
-#define TIMER0_COUNT 0x40
-#define TIMER_CONTROL 0x43
- /* set timer to periodic mode */
- outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
- /* set the clock to ~100 Hz */
- outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
- outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
-
- if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
- panic("Could not allocate timer IRQ!");
- __sti();
- /* wait for calibrate */
- while ( calibrate_steps )
- ;
- restore_flags(flags);
- free_irq( 0, NULL);
- }
-}
-
-static long __init
-mk48t59_init(void) {
- unsigned char tmp;
-
- tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
- if (tmp & MK48T59_RTC_CB_STOP) {
- printk("Warning: RTC was stopped, date will be wrong.\n");
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB,
- tmp & ~MK48T59_RTC_CB_STOP);
- /* Low frequency crystal oscillators may take a very long
- * time to startup and stabilize. For now just ignore the
- * the issue, but attempting to calibrate the decrementer
- * from the RTC just after this wakeup is likely to be very
- * inaccurate. Firmware should not allow to load
- * the OS with the clock stopped anyway...
- */
- }
- /* Ensure that the clock registers are updated */
- tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
- tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE);
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp);
- return 0;
-}
-
-/* We use the NVRAM RTC to time a second to calibrate the decrementer,
- * the RTC registers have just been set up in the right state by the
- * preceding routine.
- */
-static void __init
-mk48t59_calibrate_decr(void)
-{
- unsigned long freq;
- unsigned long t1;
- unsigned char save_control;
- long i;
- unsigned char sec;
-
-
- /* Make sure the time is not stopped. */
- save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
-
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
- (save_control & (~MK48T59_RTC_CB_STOP)));
-
- /* Now make sure the read bit is off so the value will change. */
- save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
- save_control &= ~MK48T59_RTC_CA_READ;
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-
-
- /* Read the seconds value to see when it changes. */
- sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
- /* Actually this is bad for precision, we should have a loop in
- * which we only read the seconds counter. nvram_read_val writes
- * the address bytes on every call and this takes a lot of time.
- * Perhaps an nvram_wait_change method returning a time
- * stamp with a loop count as parameter would be the solution.
- */
- for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
- t1 = get_tbl();
- if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
- break;
- }
- }
-
- sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
- for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */
- freq = get_tbl()-t1;
- if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec)
- break;
- }
-
- printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
-
-static void __prep
-prep_restart(char *cmd)
-{
- unsigned long i = 10000;
-
- __cli();
-
- /* set exception prefix high - to the prom */
- _nmask_and_or_msr(0, MSR_IP);
-
- /* make sure bit 0 (reset) is a 0 */
- outb( inb(0x92) & ~1L , 0x92 );
- /* signal a reset to system control port A - soft reset */
- outb( inb(0x92) | 1 , 0x92 );
-
- while ( i != 0 ) i++;
- panic("restart failed\n");
-}
-
-static void __prep
-prep_halt(void)
-{
- unsigned long flags;
- __cli();
- /* set exception prefix high - to the prom */
- save_flags( flags );
- restore_flags( flags|MSR_IP );
-
- /* make sure bit 0 (reset) is a 0 */
- outb( inb(0x92) & ~1L , 0x92 );
- /* signal a reset to system control port A - soft reset */
- outb( inb(0x92) | 1 , 0x92 );
-
- while ( 1 ) ;
- /*
- * Not reached
- */
-}
-
-/*
- * On IBM PReP's, power management is handled by a Signetics 87c750 behind the
- * Utah component on the ISA bus. To access the 750 you must write a series of
- * nibbles to port 0x82a (decoded by the Utah). This is described somewhat in
- * the IBM Carolina Technical Specification.
- * -Hollis
- */
-static void __prep
-utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
-{
- /*
- * byte1: 0 0 0 1 0 d a5 a4
- * byte2: 0 0 0 1 a3 a2 a1 a0
- *
- * d = the bit's value, enabled or disabled
- * (a5 a4 a3) = the byte number, minus 20
- * (a2 a1 a0) = the bit number
- *
- * example: set the 5th bit of byte 21 (21.5)
- * a5 a4 a3 = 001 (byte 1)
- * a2 a1 a0 = 101 (bit 5)
- *
- * byte1 = 0001 0100 (0x14)
- * byte2 = 0001 1101 (0x1d)
- */
- unsigned char byte1=0x10, byte2=0x10;
- const unsigned int pm_reg_1=0x82a; /* ISA address */
-
- /* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
- bytenum -= 20;
-
- byte1 |= (!!value) << 2; /* set d */
- byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */
-
- byte2 |= (bytenum & 0x1) << 3; /* set a3 */
- byte2 |= bitnum & 0x7; /* set a2, a1, a0 */
-
- outb(byte1, pm_reg_1); /* first nibble */
- mb();
- udelay(100); /* important: let controller recover */
-
- outb(byte2, pm_reg_1); /* second nibble */
- mb();
- udelay(100); /* important: let controller recover */
-}
-
-static void __prep
-prep_power_off(void)
-{
- if ( _prep_type == _PREP_IBM) {
- /* tested on:
- * Carolina's: 7248-43P, 6070 (PowerSeries 850)
- * should work on:
- * Carolina: 6050 (PowerSeries 830)
- * 7043-140 (Tiger 1)
- */
- unsigned long flags;
- __cli();
- /* set exception prefix high - to the prom */
- save_flags( flags );
- restore_flags( flags|MSR_IP );
-
- utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
-
- while ( 1 ) ;
- /* not reached */
- } else {
- prep_halt();
- }
-}
-
-static unsigned int __prep
-prep_irq_cannonicalize(u_int irq)
-{
- if (irq == 2)
- {
- return 9;
- }
- else
- {
- return irq;
- }
-}
-
-static int __prep
-prep_get_irq(struct pt_regs *regs)
-{
- return i8259_irq(smp_processor_id());
-}
-
-static void __init
-prep_init_IRQ(void)
-{
- int i;
-
- if (OpenPIC_Addr != NULL)
- openpic_init(1, NUM_8259_INTERRUPTS, 0, -1);
- for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
- irq_desc[i].handler = &i8259_pic;
- i8259_init();
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-static int __prep
-prep_ide_default_irq(ide_ioreg_t base)
-{
- switch (base) {
- case 0x1f0: return 13;
- case 0x170: return 13;
- case 0x1e8: return 11;
- case 0x168: return 10;
- case 0xfff0: return 14; /* MCP(N)750 ide0 */
- case 0xffe0: return 15; /* MCP(N)750 ide1 */
- default: return 0;
- }
-}
-
-static ide_ioreg_t __prep
-prep_ide_default_io_base(int index)
-{
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- case 2: return 0x1e8;
- case 3: return 0x168;
- default:
- return 0;
- }
-}
-
-static int __prep
-prep_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
- return check_region(from, extent);
-}
-
-static void __prep
-prep_ide_request_region(ide_ioreg_t from,
- unsigned int extent,
- const char *name)
-{
- request_region(from, extent, name);
-}
-
-static void __prep
-prep_ide_release_region(ide_ioreg_t from,
- unsigned int extent)
-{
- release_region(from, extent);
-}
-
-static void __init
-prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
-{
- ide_ioreg_t reg = data_port;
- int i;
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
- }
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
- hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
- }
- if (irq != NULL)
- *irq = 0;
-}
-#endif
-
-#ifdef CONFIG_SMP
-/* PReP (MTX) support */
-static int __init
-smp_prep_probe(void)
-{
- extern int mot_multi;
-
- if (mot_multi) {
- openpic_request_IPIs();
- smp_hw_index[1] = 1;
- return 2;
- }
-
- return 1;
-}
-
-static void __init
-smp_prep_kick_cpu(int nr)
-{
- *(unsigned long *)KERNELBASE = nr;
- asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
- printk("CPU1 reset, waiting\n");
-}
-
-static void __init
-smp_prep_setup_cpu(int cpu_nr)
-{
- if (OpenPIC_Addr)
- do_openpic_setup_cpu();
-}
-
-static struct smp_ops_t prep_smp_ops __prepdata = {
- smp_openpic_message_pass,
- smp_prep_probe,
- smp_prep_kick_cpu,
- smp_prep_setup_cpu,
-};
-#endif /* CONFIG_SMP */
-
-/*
- * This finds the amount of physical ram and does necessary
- * setup for prep. This is pretty architecture specific so
- * this will likely stay separate from the pmac.
- * -- Cort
- */
-static unsigned long __init
-prep_find_end_of_memory(void)
-{
- unsigned long total = 0;
- extern unsigned int boot_mem_size;
-
-#ifdef CONFIG_PREP_RESIDUAL
- total = res->TotalMemory;
-#endif
-
- if (total == 0 && boot_mem_size != 0)
- total = boot_mem_size;
- else if (total == 0) {
- /*
- * I need a way to probe the amount of memory if the residual
- * data doesn't contain it. -- Cort
- */
- total = 0x02000000;
- printk(KERN_INFO "Ramsize from residual data was 0"
- " -- defaulting to %ldM\n", total>>20);
- }
-
- return (total);
-}
-
-/*
- * Setup the bat mappings we're going to load that cover
- * the io areas. RAM was mapped by mapin_ram().
- * -- Cort
- */
-static void __init
-prep_map_io(void)
-{
- io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO);
- io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO);
-}
-
-static void __init
-prep_init2(void)
-{
-#ifdef CONFIG_NVRAM
- request_region(PREP_NVRAM_AS0, 0x8, "nvram");
-#endif
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
-}
-
-void __init
-prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
-#ifdef CONFIG_PREP_RESIDUAL
- /* make a copy of residual data */
- if ( r3 ) {
- memcpy((void *)res,(void *)(r3+KERNELBASE),
- sizeof(RESIDUAL));
- }
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy cmd_line parameters */
- if ( r6 )
- {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- isa_io_base = PREP_ISA_IO_BASE;
- isa_mem_base = PREP_ISA_MEM_BASE;
- pci_dram_offset = PREP_PCI_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = 0x00ffffff;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-
- /* figure out what kind of prep workstation we are */
-#ifdef CONFIG_PREP_RESIDUAL
- if ( res->ResidualLength != 0 )
- {
- if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
- _prep_type = _PREP_IBM;
- else
- _prep_type = _PREP_Motorola;
- }
- else /* assume motorola if no residual (netboot?) */
-#endif
- {
- _prep_type = _PREP_Motorola;
- }
-
- ppc_md.setup_arch = prep_setup_arch;
- ppc_md.show_percpuinfo = prep_show_percpuinfo;
- ppc_md.show_cpuinfo = prep_show_cpuinfo;
- ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
- ppc_md.init_IRQ = prep_init_IRQ;
- /* this gets changed later on if we have an OpenPIC -- Cort */
- ppc_md.get_irq = prep_get_irq;
- ppc_md.init = prep_init2;
-
- ppc_md.restart = prep_restart;
- ppc_md.power_off = prep_power_off;
- ppc_md.halt = prep_halt;
-
- ppc_md.time_init = NULL;
- if (_prep_type == _PREP_IBM) {
- ppc_md.set_rtc_time = mc146818_set_rtc_time;
- ppc_md.get_rtc_time = mc146818_get_rtc_time;
- ppc_md.calibrate_decr = prep_calibrate_decr;
- } else {
- ppc_md.set_rtc_time = mk48t59_set_rtc_time;
- ppc_md.get_rtc_time = mk48t59_get_rtc_time;
- ppc_md.calibrate_decr = mk48t59_calibrate_decr;
- ppc_md.time_init = mk48t59_init;
- }
-
- ppc_md.find_end_of_memory = prep_find_end_of_memory;
- ppc_md.setup_io_mappings = prep_map_io;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
- ppc_ide_md.default_irq = prep_ide_default_irq;
- ppc_ide_md.default_io_base = prep_ide_default_io_base;
- ppc_ide_md.ide_check_region = prep_ide_check_region;
- ppc_ide_md.ide_request_region = prep_ide_request_region;
- ppc_ide_md.ide_release_region = prep_ide_release_region;
- ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
-#endif
-
-#ifdef CONFIG_VT
- ppc_md.kbd_setkeycode = pckbd_setkeycode;
- ppc_md.kbd_getkeycode = pckbd_getkeycode;
- ppc_md.kbd_translate = pckbd_translate;
- ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
- ppc_md.kbd_leds = pckbd_leds;
- ppc_md.kbd_init_hw = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
- SYSRQ_KEY = 0x54;
-#endif
-#endif
-
-#ifdef CONFIG_SMP
- ppc_md.smp_ops = &prep_smp_ops;
-#endif /* CONFIG_SMP */
-}
diff --git a/arch/ppc/kernel/prep_time.c b/arch/ppc/kernel/prep_time.c
deleted file mode 100644
index 2e51b272ddf7..000000000000
--- a/arch/ppc/kernel/prep_time.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_time.c 1.10 09/08/01 15:47:42 paulus
- */
-/*
- * linux/arch/i386/kernel/time.c
- *
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * Adapted for PowerPC (PreP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- * copied and modified from intel version
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-
-#include <asm/sections.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/machdep.h>
-#include <asm/prep_nvram.h>
-#include <asm/mk48t59.h>
-
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-/*
- * The motorola uses the m48t18 rtc (includes DS1643) whose registers
- * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
- * rtc (ds1386) which has regs at addr 0-d). The intel gets
- * past this because the bios emulates the mc146818.
- *
- * Why in the world did they have to use different clocks?
- *
- * Right now things are hacked to check which machine we're on then
- * use the appropriate macro. This is very very ugly and I should
- * probably have a function that checks which machine we're on then
- * does things correctly transparently or a function pointer which
- * is setup at boot time to use the correct addresses.
- * -- Cort
- */
-
-/*
- * Set the hardware clock. -- Cort
- */
-__prep
-int mc146818_set_rtc_time(unsigned long nowtime)
-{
- unsigned char save_control, save_freq_select;
- struct rtc_time tm;
-
- spin_lock(&rtc_lock);
- to_tm(nowtime, &tm);
-
- /* tell the clock it's being set */
- save_control = CMOS_READ(RTC_CONTROL);
-
- CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-
- /* stop and reset prescaler */
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-
- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year = (tm.tm_year - 1900) % 100;
- if (!(save_control & RTC_DM_BINARY) || 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);
- }
- CMOS_WRITE(tm.tm_sec, RTC_SECONDS);
- CMOS_WRITE(tm.tm_min, RTC_MINUTES);
- CMOS_WRITE(tm.tm_hour, RTC_HOURS);
- CMOS_WRITE(tm.tm_mon, RTC_MONTH);
- CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
- CMOS_WRITE(tm.tm_year, RTC_YEAR);
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_WRITE(save_control, RTC_CONTROL);
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- spin_unlock(&rtc_lock);
-
- return 0;
-}
-
-__prep
-unsigned long mc146818_get_rtc_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- int uip, i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for ( i = 0; i<1000000; i++) {
- uip = CMOS_READ(RTC_FREQ_SELECT);
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- uip |= CMOS_READ(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0) break;
- }
-
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
- || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-__prep
-int mk48t59_set_rtc_time(unsigned long nowtime)
-{
- unsigned char save_control;
- struct rtc_time tm;
-
- spin_lock(&rtc_lock);
- to_tm(nowtime, &tm);
-
- /* tell the clock it's being written */
- save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
-
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
- (save_control | MK48T59_RTC_CA_WRITE));
-
- tm.tm_year = (tm.tm_year - 1900) % 100;
- 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);
-
- ppc_md.nvram_write_val(MK48T59_RTC_SECONDS, tm.tm_sec);
- ppc_md.nvram_write_val(MK48T59_RTC_MINUTES, tm.tm_min);
- ppc_md.nvram_write_val(MK48T59_RTC_HOURS, tm.tm_hour);
- ppc_md.nvram_write_val(MK48T59_RTC_MONTH, tm.tm_mon);
- ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
- ppc_md.nvram_write_val(MK48T59_RTC_YEAR, tm.tm_year);
-
- /* Turn off the write bit. */
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
- spin_unlock(&rtc_lock);
-
- return 0;
-}
-
-__prep
-unsigned long mk48t59_get_rtc_time(void)
-{
- unsigned char save_control;
- unsigned int year, mon, day, hour, min, sec;
-
- /* Simple: freeze the clock, read it and allow updates again */
- save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
- save_control &= ~MK48T59_RTC_CA_READ;
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-
- /* Set the register to read the value. */
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
- (save_control | MK48T59_RTC_CA_READ));
-
- sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
- min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
- hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
- day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
- mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
- year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
-
- /* Let the time values change again. */
- ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
-
- year = year + 1900;
- if (year < 1970) {
- year += 100;
- }
-
- return mktime(year, mon, day, hour, min, sec);
-}
diff --git a/arch/ppc/kernel/proc_rtas.c b/arch/ppc/kernel/proc_rtas.c
deleted file mode 100644
index b893044fdb5d..000000000000
--- a/arch/ppc/kernel/proc_rtas.c
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- * BK Id: SCCS/s.proc_rtas.c 1.5 05/17/01 18:14:22 cort
- */
-/*
- * arch/ppc/kernel/proc_rtas.c
- * Copyright (C) 2000 Tilmann Bitterberg
- * (tilmann@bitterberg.de)
- *
- * RTAS (Runtime Abstraction Services) stuff
- * Intention is to provide a clean user interface
- * to use the RTAS.
- *
- * TODO:
- * Split off a header file and maybe move it to a different
- * location. Write Documentation on what the /proc/rtas/ entries
- * actually do.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <linux/time.h>
-#include <linux/string.h>
-
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h> /* for ppc_md */
-#include <asm/time.h>
-
-/* Token for Sensors */
-#define KEY_SWITCH 0x0001
-#define ENCLOSURE_SWITCH 0x0002
-#define THERMAL_SENSOR 0x0003
-#define LID_STATUS 0x0004
-#define POWER_SOURCE 0x0005
-#define BATTERY_VOLTAGE 0x0006
-#define BATTERY_REMAINING 0x0007
-#define BATTERY_PERCENTAGE 0x0008
-#define EPOW_SENSOR 0x0009
-#define BATTERY_CYCLESTATE 0x000a
-#define BATTERY_CHARGING 0x000b
-
-/* IBM specific sensors */
-#define IBM_SURVEILLANCE 0x2328 /* 9000 */
-#define IBM_FANRPM 0x2329 /* 9001 */
-#define IBM_VOLTAGE 0x232a /* 9002 */
-#define IBM_DRCONNECTOR 0x232b /* 9003 */
-#define IBM_POWERSUPPLY 0x232c /* 9004 */
-#define IBM_INTQUEUE 0x232d /* 9005 */
-
-/* Status return values */
-#define SENSOR_CRITICAL_HIGH 13
-#define SENSOR_WARNING_HIGH 12
-#define SENSOR_NORMAL 11
-#define SENSOR_WARNING_LOW 10
-#define SENSOR_CRITICAL_LOW 9
-#define SENSOR_SUCCESS 0
-#define SENSOR_HW_ERROR -1
-#define SENSOR_BUSY -2
-#define SENSOR_NOT_EXIST -3
-#define SENSOR_DR_ENTITY -9000
-
-/* Location Codes */
-#define LOC_SCSI_DEV_ADDR 'A'
-#define LOC_SCSI_DEV_LOC 'B'
-#define LOC_CPU 'C'
-#define LOC_DISKETTE 'D'
-#define LOC_ETHERNET 'E'
-#define LOC_FAN 'F'
-#define LOC_GRAPHICS 'G'
-/* reserved / not used 'H' */
-#define LOC_IO_ADAPTER 'I'
-/* reserved / not used 'J' */
-#define LOC_KEYBOARD 'K'
-#define LOC_LCD 'L'
-#define LOC_MEMORY 'M'
-#define LOC_NV_MEMORY 'N'
-#define LOC_MOUSE 'O'
-#define LOC_PLANAR 'P'
-#define LOC_OTHER_IO 'Q'
-#define LOC_PARALLEL 'R'
-#define LOC_SERIAL 'S'
-#define LOC_DEAD_RING 'T'
-#define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */
-#define LOC_VOLTAGE 'V'
-#define LOC_SWITCH_ADAPTER 'W'
-#define LOC_OTHER 'X'
-#define LOC_FIRMWARE 'Y'
-#define LOC_SCSI 'Z'
-
-/* Tokens for indicators */
-#define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/
-#define TONE_VOLUME 0x0002 /* 0 - 100 (%) */
-#define SYSTEM_POWER_STATE 0x0003
-#define WARNING_LIGHT 0x0004
-#define DISK_ACTIVITY_LIGHT 0x0005
-#define HEX_DISPLAY_UNIT 0x0006
-#define BATTERY_WARNING_TIME 0x0007
-#define CONDITION_CYCLE_REQUEST 0x0008
-#define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */
-#define DR_ACTION 0x2329 /* 9001 */
-#define DR_INDICATOR 0x232a /* 9002 */
-/* 9003 - 9004: Vendor specific */
-#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */
-/* 9006 - 9999: Vendor specific */
-
-/* other */
-#define MAX_SENSORS 17 /* I only know of 17 sensors */
-#define MAX_LINELENGTH 256
-#define SENSOR_PREFIX "ibm,sensor-"
-#define cel_to_fahr(x) ((x*9/5)+32)
-
-
-/* Globals */
-static struct proc_dir_entry *proc_rtas;
-static struct rtas_sensors sensors;
-static struct device_node *rtas;
-static unsigned long power_on_time = 0; /* Save the time the user set */
-static char progress_led[MAX_LINELENGTH];
-
-static unsigned long rtas_tone_frequency = 1000;
-static unsigned long rtas_tone_volume = 0;
-
-/* ****************STRUCTS******************************************* */
-struct individual_sensor {
- unsigned int token;
- unsigned int quant;
-};
-
-struct rtas_sensors {
- struct individual_sensor sensor[MAX_SENSORS];
- unsigned int quant;
-};
-
-/* ****************************************************************** */
-/* Declarations */
-static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
- int count, int *eof, void *data);
-static ssize_t ppc_rtas_clock_read(struct file * file, char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-
-static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
- size_t count, loff_t *ppos);
-
-struct file_operations ppc_rtas_poweron_operations = {
- read: ppc_rtas_poweron_read,
- write: ppc_rtas_poweron_write
-};
-struct file_operations ppc_rtas_progress_operations = {
- read: ppc_rtas_progress_read,
- write: ppc_rtas_progress_write
-};
-
-struct file_operations ppc_rtas_clock_operations = {
- read: ppc_rtas_clock_read,
- write: ppc_rtas_clock_write
-};
-
-struct file_operations ppc_rtas_tone_freq_operations = {
- read: ppc_rtas_tone_freq_read,
- write: ppc_rtas_tone_freq_write
-};
-struct file_operations ppc_rtas_tone_volume_operations = {
- read: ppc_rtas_tone_volume_read,
- write: ppc_rtas_tone_volume_write
-};
-
-int ppc_rtas_find_all_sensors (void);
-int ppc_rtas_process_sensor(struct individual_sensor s, int state,
- int error, char * buf);
-char * ppc_rtas_process_error(int error);
-int get_location_code(struct individual_sensor s, char * buf);
-int check_location_string (char *c, char * buf);
-int check_location (char *c, int idx, char * buf);
-
-/* ****************************************************************** */
-/* MAIN */
-/* ****************************************************************** */
-void proc_rtas_init(void)
-{
- struct proc_dir_entry *entry;
-
- rtas = find_devices("rtas");
- if ((rtas == 0) || (_machine != _MACH_chrp)) {
- return;
- }
-
- proc_rtas = proc_mkdir("rtas", 0);
- if (proc_rtas == 0)
- return;
-
- /* /proc/rtas entries */
-
- entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas);
- if (entry) entry->proc_fops = &ppc_rtas_progress_operations;
-
- entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas);
- if (entry) entry->proc_fops = &ppc_rtas_clock_operations;
-
- entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas);
- if (entry) entry->proc_fops = &ppc_rtas_poweron_operations;
-
- create_proc_read_entry("sensors", S_IRUGO, proc_rtas,
- ppc_rtas_sensor_read, NULL);
-
- entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas);
- if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations;
-
- entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas);
- if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
-}
-
-/* ****************************************************************** */
-/* POWER-ON-TIME */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- struct rtc_time tm;
- unsigned long nowtime;
- char *dest;
- int error;
-
- nowtime = simple_strtoul(buf, &dest, 10);
- if (*dest != '\0' && *dest != '\n') {
- printk("ppc_rtas_poweron_write: Invalid time\n");
- return count;
- }
- power_on_time = nowtime; /* save the time */
-
- to_tm(nowtime, &tm);
-
- error = call_rtas("set-time-for-power-on", 7, 1, NULL,
- tm.tm_year, tm.tm_mon, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
- if (error != 0)
- printk(KERN_WARNING "error: setting poweron time returned: %s\n",
- ppc_rtas_process_error(error));
- return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- int n;
- if (power_on_time == 0)
- n = sprintf(buf, "Power on time not set\n");
- else
- n = sprintf(buf, "%lu\n", power_on_time);
-
- if (*ppos >= strlen(buf))
- return 0;
- if (n > strlen(buf) - *ppos)
- n = strlen(buf) - *ppos;
- if (n > count)
- n = count;
- *ppos += n;
- return n;
-}
-
-/* ****************************************************************** */
-/* PROGRESS */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- unsigned long hex;
-
- strcpy(progress_led, buf); /* save the string */
- /* Lets see if the user passed hexdigits */
- hex = simple_strtoul(buf, NULL, 10);
-
- ppc_md.progress ((char *)buf, hex);
- return count;
-
- /* clear the line */ /* ppc_md.progress(" ", 0xffff);*/
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- int n = 0;
- if (progress_led != NULL)
- n = sprintf (buf, "%s\n", progress_led);
- if (*ppos >= strlen(buf))
- return 0;
- if (n > strlen(buf) - *ppos)
- n = strlen(buf) - *ppos;
- if (n > count)
- n = count;
- *ppos += n;
- return n;
-}
-
-/* ****************************************************************** */
-/* CLOCK */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- struct rtc_time tm;
- unsigned long nowtime;
- char *dest;
- int error;
-
- nowtime = simple_strtoul(buf, &dest, 10);
- if (*dest != '\0' && *dest != '\n') {
- printk("ppc_rtas_clock_write: Invalid time\n");
- return count;
- }
-
- to_tm(nowtime, &tm);
- error = call_rtas("set-time-of-day", 7, 1, NULL,
- tm.tm_year, tm.tm_mon, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
- if (error != 0)
- printk(KERN_WARNING "error: setting the clock returned: %s\n",
- ppc_rtas_process_error(error));
- return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_clock_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- unsigned int year, mon, day, hour, min, sec;
- unsigned long *ret = kmalloc(4*8, GFP_KERNEL);
- int n, error;
-
- error = call_rtas("get-time-of-day", 0, 8, ret);
-
- year = ret[0]; mon = ret[1]; day = ret[2];
- hour = ret[3]; min = ret[4]; sec = ret[5];
-
- if (error != 0){
- printk(KERN_WARNING "error: reading the clock returned: %s\n",
- ppc_rtas_process_error(error));
- n = sprintf (buf, "0");
- } else {
- n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec));
- }
- kfree(ret);
-
- if (*ppos >= strlen(buf))
- return 0;
- if (n > strlen(buf) - *ppos)
- n = strlen(buf) - *ppos;
- if (n > count)
- n = count;
- *ppos += n;
- return n;
-}
-
-/* ****************************************************************** */
-/* SENSOR STUFF */
-/* ****************************************************************** */
-static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
- int count, int *eof, void *data)
-{
- int i,j,n;
- unsigned long ret;
- int state, error;
- char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */
-
- if (count < 0)
- return -EINVAL;
-
- n = sprintf ( buffer , "RTAS (RunTime Abstraction Services) Sensor Information\n");
- n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n");
- n += sprintf ( buffer+n, "********************************************************\n");
-
- if (ppc_rtas_find_all_sensors() != 0) {
- n += sprintf ( buffer+n, "\nNo sensors are available\n");
- goto return_string;
- }
-
- for (i=0; i<sensors.quant; i++) {
- j = sensors.sensor[i].quant;
- /* A sensor may have multiple instances */
- while (j >= 0) {
- error = call_rtas("get-sensor-state", 2, 2, &ret,
- sensors.sensor[i].token, sensors.sensor[i].quant-j);
- state = (int) ret;
- n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n );
- n += sprintf (buffer+n, "\n");
- j--;
- } /* while */
- } /* for */
-
-return_string:
- if (off >= strlen(buffer)) {
- *eof = 1;
- return 0;
- }
- if (n > strlen(buffer) - off)
- n = strlen(buffer) - off;
- if (n > count)
- n = count;
- else
- *eof = 1;
- memcpy(buf, buffer + off, n);
- *start = buf;
- return n;
-}
-
-/* ****************************************************************** */
-
-int ppc_rtas_find_all_sensors (void)
-{
- unsigned long *utmp;
- int len, i, j;
-
- utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len);
- if (utmp == NULL) {
- printk (KERN_ERR "error: could not get rtas-sensors\n");
- return 1;
- }
-
- sensors.quant = len / 8; /* int + int */
-
- for (i=0, j=0; j<sensors.quant; i+=2, j++) {
- sensors.sensor[j].token = utmp[i];
- sensors.sensor[j].quant = utmp[i+1];
- }
- return 0;
-}
-
-/* ****************************************************************** */
-/*
- * Builds a string of what rtas returned
- */
-char * ppc_rtas_process_error(int error)
-{
- switch (error) {
- case SENSOR_CRITICAL_HIGH:
- return "(critical high)";
- case SENSOR_WARNING_HIGH:
- return "(warning high)";
- case SENSOR_NORMAL:
- return "(normal)";
- case SENSOR_WARNING_LOW:
- return "(warning low)";
- case SENSOR_CRITICAL_LOW:
- return "(critical low)";
- case SENSOR_SUCCESS:
- return "(read ok)";
- case SENSOR_HW_ERROR:
- return "(hardware error)";
- case SENSOR_BUSY:
- return "(busy)";
- case SENSOR_NOT_EXIST:
- return "(non existant)";
- case SENSOR_DR_ENTITY:
- return "(dr entity removed)";
- default:
- return "(UNKNOWN)";
- }
-}
-
-/* ****************************************************************** */
-/*
- * Builds a string out of what the sensor said
- */
-
-int ppc_rtas_process_sensor(struct individual_sensor s, int state,
- int error, char * buf)
-{
- /* Defined return vales */
- const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", "Mainenance" };
- const char * enclosure_switch[] = { "Closed", "Open" };
- const char * lid_status[] = { " ", "Open", "Closed" };
- const char * power_source[] = { "AC\t", "Battery", "AC & Battery" };
- const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
- const char * epow_sensor[] = {
- "EPOW Reset", "Cooling warning", "Power warning",
- "System shutdown", "System halt", "EPOW main enclosure",
- "EPOW power off" };
- const char * battery_cyclestate[] = { "None", "In progress", "Requested" };
- const char * battery_charging[] = { "Charging", "Discharching", "No current flow" };
- const char * ibm_drconnector[] = { "Empty", "Present" };
- const char * ibm_intqueue[] = { "Disabled", "Enabled" };
-
- int have_strings = 0;
- int temperature = 0;
- int unknown = 0;
- int n = 0;
-
- /* What kind of sensor do we have here? */
- switch (s.token) {
- case KEY_SWITCH:
- n += sprintf(buf+n, "Key switch:\t");
- n += sprintf(buf+n, "%s\t", key_switch[state]);
- have_strings = 1;
- break;
- case ENCLOSURE_SWITCH:
- n += sprintf(buf+n, "Enclosure switch:\t");
- n += sprintf(buf+n, "%s\t", enclosure_switch[state]);
- have_strings = 1;
- break;
- case THERMAL_SENSOR:
- n += sprintf(buf+n, "Temp. (°C/°F):\t");
- temperature = 1;
- break;
- case LID_STATUS:
- n += sprintf(buf+n, "Lid status:\t");
- n += sprintf(buf+n, "%s\t", lid_status[state]);
- have_strings = 1;
- break;
- case POWER_SOURCE:
- n += sprintf(buf+n, "Power source:\t");
- n += sprintf(buf+n, "%s\t", power_source[state]);
- have_strings = 1;
- break;
- case BATTERY_VOLTAGE:
- n += sprintf(buf+n, "Battery voltage:\t");
- break;
- case BATTERY_REMAINING:
- n += sprintf(buf+n, "Battery remaining:\t");
- n += sprintf(buf+n, "%s\t", battery_remaining[state]);
- have_strings = 1;
- break;
- case BATTERY_PERCENTAGE:
- n += sprintf(buf+n, "Battery percentage:\t");
- break;
- case EPOW_SENSOR:
- n += sprintf(buf+n, "EPOW Sensor:\t");
- n += sprintf(buf+n, "%s\t", epow_sensor[state]);
- have_strings = 1;
- break;
- case BATTERY_CYCLESTATE:
- n += sprintf(buf+n, "Battery cyclestate:\t");
- n += sprintf(buf+n, "%s\t", battery_cyclestate[state]);
- have_strings = 1;
- break;
- case BATTERY_CHARGING:
- n += sprintf(buf+n, "Battery Charging:\t");
- n += sprintf(buf+n, "%s\t", battery_charging[state]);
- have_strings = 1;
- break;
- case IBM_SURVEILLANCE:
- n += sprintf(buf+n, "Surveillance:\t");
- break;
- case IBM_FANRPM:
- n += sprintf(buf+n, "Fan (rpm):\t");
- break;
- case IBM_VOLTAGE:
- n += sprintf(buf+n, "Voltage (mv):\t");
- break;
- case IBM_DRCONNECTOR:
- n += sprintf(buf+n, "DR connector:\t");
- n += sprintf(buf+n, "%s\t", ibm_drconnector[state]);
- have_strings = 1;
- break;
- case IBM_POWERSUPPLY:
- n += sprintf(buf+n, "Powersupply:\t");
- break;
- case IBM_INTQUEUE:
- n += sprintf(buf+n, "Interrupt queue:\t");
- n += sprintf(buf+n, "%s\t", ibm_intqueue[state]);
- have_strings = 1;
- break;
- default:
- n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n",
- s.token);
- unknown = 1;
- have_strings = 1;
- break;
- }
- if (have_strings == 0) {
- if (temperature) {
- n += sprintf(buf+n, "%4d /%4d\t", state, cel_to_fahr(state));
- } else
- n += sprintf(buf+n, "%10d\t", state);
- }
- if (unknown == 0) {
- n += sprintf ( buf+n, "%s\t", ppc_rtas_process_error(error));
- n += get_location_code(s, buf+n);
- }
- return n;
-}
-
-/* ****************************************************************** */
-
-int check_location (char *c, int idx, char * buf)
-{
- int n = 0;
-
- switch (*(c+idx)) {
- case LOC_PLANAR:
- n += sprintf ( buf, "Planar #%c", *(c+idx+1));
- break;
- case LOC_CPU:
- n += sprintf ( buf, "CPU #%c", *(c+idx+1));
- break;
- case LOC_FAN:
- n += sprintf ( buf, "Fan #%c", *(c+idx+1));
- break;
- case LOC_RACKMOUNTED:
- n += sprintf ( buf, "Rack #%c", *(c+idx+1));
- break;
- case LOC_VOLTAGE:
- n += sprintf ( buf, "Voltage #%c", *(c+idx+1));
- break;
- case LOC_LCD:
- n += sprintf ( buf, "LCD #%c", *(c+idx+1));
- break;
- case '.':
- n += sprintf ( buf, "- %c", *(c+idx+1));
- default:
- n += sprintf ( buf, "Unknown location");
- break;
- }
- return n;
-}
-
-
-/* ****************************************************************** */
-/*
- * Format:
- * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
- * the '.' may be an abbrevation
- */
-int check_location_string (char *c, char *buf)
-{
- int n=0,i=0;
-
- while (c[i]) {
- if (isalpha(c[i]) || c[i] == '.') {
- n += check_location(c, i, buf+n);
- }
- else if (c[i] == '/' || c[i] == '-')
- n += sprintf(buf+n, " at ");
- i++;
- }
- return n;
-}
-
-
-/* ****************************************************************** */
-
-int get_location_code(struct individual_sensor s, char * buffer)
-{
- char rstr[512], tmp[10], tmp2[10];
- int n=0, i=0, llen, len;
- /* char *buf = kmalloc(MAX_LINELENGTH, GFP_KERNEL); */
- char *ret;
-
- static int pos = 0; /* remember position where buffer was */
-
- /* construct the sensor number like 0003 */
- /* fill with zeros */
- n = sprintf(tmp, "%d", s.token);
- len = strlen(tmp);
- while (strlen(tmp) < 4)
- n += sprintf (tmp+n, "0");
-
- /* invert the string */
- while (tmp[i]) {
- if (i<len)
- tmp2[4-len+i] = tmp[i];
- else
- tmp2[3-i] = tmp[i];
- i++;
- }
- tmp2[4] = '\0';
-
- sprintf (rstr, SENSOR_PREFIX"%s", tmp2);
-
- ret = (char *) get_property(rtas, rstr, &llen);
-
- n=0;
- if (ret[0] == '\0')
- n += sprintf ( buffer+n, "--- ");/* does not have a location */
- else {
- char t[50];
- ret += pos;
-
- n += check_location_string(ret, buffer + n);
- n += sprintf ( buffer+n, " ");
- /* see how many characters we have printed */
- sprintf ( t, "%s ", ret);
-
- pos += strlen(t);
- if (pos >= llen) pos=0;
- }
- return n;
-}
-/* ****************************************************************** */
-/* INDICATORS - Tone Frequency */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- unsigned long freq;
- char *dest;
- int error;
- freq = simple_strtoul(buf, &dest, 10);
- if (*dest != '\0' && *dest != '\n') {
- printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n");
- return count;
- }
- if (freq < 0) freq = 0;
- rtas_tone_frequency = freq; /* save it for later */
- error = call_rtas("set-indicator", 3, 1, NULL,
- TONE_FREQUENCY, 0, freq);
- if (error != 0)
- printk(KERN_WARNING "error: setting tone frequency returned: %s\n",
- ppc_rtas_process_error(error));
- return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- int n;
- n = sprintf(buf, "%lu\n", rtas_tone_frequency);
-
- if (*ppos >= strlen(buf))
- return 0;
- if (n > strlen(buf) - *ppos)
- n = strlen(buf) - *ppos;
- if (n > count)
- n = count;
- *ppos += n;
- return n;
-}
-/* ****************************************************************** */
-/* INDICATORS - Tone Volume */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- unsigned long volume;
- char *dest;
- int error;
- volume = simple_strtoul(buf, &dest, 10);
- if (*dest != '\0' && *dest != '\n') {
- printk("ppc_rtas_tone_volume_write: Invalid tone volume\n");
- return count;
- }
- if (volume < 0) volume = 0;
- if (volume > 100) volume = 100;
-
- rtas_tone_volume = volume; /* save it for later */
- error = call_rtas("set-indicator", 3, 1, NULL,
- TONE_VOLUME, 0, volume);
- if (error != 0)
- printk(KERN_WARNING "error: setting tone volume returned: %s\n",
- ppc_rtas_process_error(error));
- return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- int n;
- n = sprintf(buf, "%lu\n", rtas_tone_volume);
-
- if (*ppos >= strlen(buf))
- return 0;
- if (n > strlen(buf) - *ppos)
- n = strlen(buf) - *ppos;
- if (n > count)
- n = count;
- *ppos += n;
- return n;
-}
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index eca832613eb8..9a00a0efb999 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.process.c 1.31 10/02/01 09:51:41 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/arch/ppc/kernel/process.c
@@ -34,6 +34,8 @@
#include <linux/user.h>
#include <linux/elf.h>
#include <linux/init.h>
+#include <linux/prctl.h>
+#include <linux/init_task.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -42,20 +44,26 @@
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/prom.h>
+#ifdef CONFIG_PPC_ISERIES
+#include <asm/iSeries/Paca.h>
+#endif
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
extern unsigned long _get_SP(void);
struct task_struct *last_task_used_math = NULL;
struct task_struct *last_task_used_altivec = NULL;
+
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
+
/* this is 16-byte aligned because it has a stack in it */
union task_union __attribute((aligned(16))) init_task_union = {
INIT_TASK(init_task_union.task)
};
+
/* only used to get secondary processor up */
struct task_struct *current_set[NR_CPUS] = {&init_task, };
@@ -260,7 +268,7 @@ void show_regs(struct pt_regs * regs)
printk("\nlast math %p last altivec %p", last_task_used_math,
last_task_used_altivec);
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) && defined(DCRN_PLB0_BEAR)
printk("\nPLB0: bear= 0x%8.8x acr= 0x%8.8x besr= 0x%8.8x\n",
mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_PLB0_ACR),
mfdcr(DCRN_PLB0_BESR));
@@ -336,9 +344,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
/* for kernel thread, set `current' and stackptr in new task */
childregs->gpr[1] = sp + sizeof(struct pt_regs);
childregs->gpr[2] = (unsigned long) p;
- }
+ p->thread.regs = NULL; /* no user register state */
+ } else
+ p->thread.regs = childregs;
childregs->gpr[3] = 0; /* Result from fork() */
- p->thread.regs = childregs;
sp -= STACK_FRAME_OVERHEAD;
childframe = sp;
@@ -355,6 +364,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
sp -= STACK_FRAME_OVERHEAD;
p->thread.ksp = sp;
kregs->nip = (unsigned long)ret_from_fork;
+#ifdef CONFIG_PPC_ISERIES
+ kregs->softEnable = ((struct Paca *)mfspr(SPRG1))->xProcEnabled;
+#endif
/*
* copy fpu info - assume lazy fpu switch now always
@@ -391,7 +403,10 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
{
set_fs(USER_DS);
memset(regs->gpr, 0, sizeof(regs->gpr));
- memset(&regs->ctr, 0, 5 * sizeof(regs->ctr));
+ regs->ctr = 0;
+ regs->link = 0;
+ regs->xer = 0;
+ regs->ccr = 0;
regs->nip = nip;
regs->gpr[1] = sp;
regs->msr = MSR_USER;
@@ -399,8 +414,29 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
last_task_used_math = 0;
if (last_task_used_altivec == current)
last_task_used_altivec = 0;
+ memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
current->thread.fpscr = 0;
+#ifdef CONFIG_ALTIVEC
+ memset(current->thread.vr, 0, sizeof(current->thread.vr));
+ memset(&current->thread.vscr, 0, sizeof(current->thread.vscr));
+ current->thread.vrsave = 0;
+#endif /* CONFIG_ALTIVEC */
+}
+
+#if 0
+int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+
+ if (val > PR_FP_EXC_PRECISE)
+ return -EINVAL;
+ tsk->thread.fpexc_mode = __pack_fe01(val);
+ if (regs != NULL && (regs->msr & MSR_FP) != 0)
+ regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
+ | tsk->thread.fpexc_mode;
+ return 0;
}
+#endif
int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
struct pt_regs *regs)
@@ -465,6 +501,27 @@ print_backtrace(unsigned long *sp)
printk("\n");
}
+void show_trace_task(struct task_struct *tsk)
+{
+ unsigned long stack_top = (unsigned long) tsk + THREAD_SIZE;
+ unsigned long sp, prev_sp;
+ int count = 0;
+
+ if (tsk == NULL)
+ return;
+ sp = (unsigned long) &tsk->thread.ksp;
+ do {
+ prev_sp = sp;
+ sp = *(unsigned long *)sp;
+ if (sp <= prev_sp || sp >= stack_top || (sp & 3) != 0)
+ break;
+ if (count > 0)
+ printk("[%08lx] ", *(unsigned long *)(sp + 4));
+ } while (++count < 16);
+ if (count > 1)
+ printk("\n");
+}
+
#if 0
/*
* Low level print for debugging - Cort
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index f0daf9d5f54a..f9c94da5cd2f 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.prom.c 1.42 09/08/01 15:47:42 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Procedures for interfacing to the Open Firmware PROM on
@@ -19,6 +19,9 @@
#include <linux/version.h>
#include <linux/threads.h>
#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
#include <asm/sections.h>
#include <asm/prom.h>
@@ -34,28 +37,13 @@
#include <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/btext.h>
-#include "open_pic.h"
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
#ifdef CONFIG_FB
#include <asm/linux_logo.h>
#endif
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This way we don't waste space storing
- * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
- * does need to be big enough to ensure that we don't lose things
- * like the interrupt-map property on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH 4096
-
-struct prom_args {
- const char *service;
- int nargs;
- int nret;
- void *args[10];
-};
-
struct pci_address {
unsigned a_hi;
unsigned a_mid;
@@ -68,26 +56,12 @@ struct pci_reg_property {
unsigned size_lo;
};
-struct pci_range {
- struct pci_address addr;
- unsigned phys;
- unsigned size_hi;
- unsigned size_lo;
-};
-
struct isa_reg_property {
unsigned space;
unsigned address;
unsigned size;
};
-struct pci_intr_map {
- struct pci_address addr;
- unsigned dunno;
- phandle int_ctrler;
- unsigned intr;
-};
-
typedef unsigned long interpret_func(struct device_node *, unsigned long,
int, int);
static interpret_func interpret_pci_props;
@@ -96,27 +70,7 @@ static interpret_func interpret_isa_props;
static interpret_func interpret_macio_props;
static interpret_func interpret_root_props;
-#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
-#define FB_MAX 8
-#endif
-char *prom_display_paths[FB_MAX] __initdata = { 0, };
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays __initdata = 0;
-char *of_stdout_device __initdata = 0;
-ihandle prom_disp_node __initdata = 0;
-
-prom_entry prom __initdata = 0;
-ihandle prom_chosen __initdata = 0;
-ihandle prom_stdout __initdata = 0;
-
extern char *klimit;
-char *bootpath;
-char *bootdevice;
-
-unsigned int rtas_data; /* physical pointer */
-unsigned int rtas_entry; /* physical pointer */
-unsigned int rtas_size;
-unsigned int old_rtas;
/* Set for a newworld or CHRP machine */
int use_of_interrupt_tree;
@@ -125,553 +79,30 @@ int num_interrupt_controllers;
int pmac_newworld;
-static struct device_node *allnodes;
+extern unsigned int rtas_entry; /* physical pointer */
+
+extern struct device_node *allnodes;
-static void *call_prom(const char *service, int nargs, int nret, ...);
-static void prom_exit(void);
-static unsigned long copy_device_tree(unsigned long, unsigned long);
-static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
- unsigned long, struct device_node ***);
static unsigned long finish_node(struct device_node *, unsigned long,
interpret_func *, int, int);
static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
-static unsigned long check_display(unsigned long);
-static int prom_next_node(phandle *);
-static void *early_get_property(unsigned long, unsigned long, char *);
static struct device_node *find_phandle(phandle);
-#ifdef CONFIG_BOOTX_TEXT
-static void setup_disp_fake_bi(ihandle dp);
-#endif
-
extern void enter_rtas(void *);
void phys_call_rtas(int, int, int, ...);
extern char cmd_line[512]; /* XXX */
-boot_infos_t *boot_infos;
+extern boot_infos_t *boot_infos;
unsigned long dev_tree_size;
-#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-
-/* Is boot-info compatible ? */
-#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
-#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
-#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
-
-/*
- * Note that prom_init() and anything called from prom_init() must
- * use the RELOC/PTRRELOC macros to access any static data in
- * memory, since the kernel may be running at an address that is
- * different from the address that it was linked at.
- * (Note that strings count as static variables.)
- */
-
-static void __init
-prom_exit()
-{
- struct prom_args args;
- unsigned long offset = reloc_offset();
-
- args.service = "exit";
- args.nargs = 0;
- args.nret = 0;
- RELOC(prom)(&args);
- for (;;) /* should never get here */
- ;
-}
-
-void __init
-prom_enter(void)
-{
- struct prom_args args;
- unsigned long offset = reloc_offset();
-
- args.service = RELOC("enter");
- args.nargs = 0;
- args.nret = 0;
- RELOC(prom)(&args);
-}
-
-static void * __init
-call_prom(const char *service, int nargs, int nret, ...)
-{
- va_list list;
- int i;
- unsigned long offset = reloc_offset();
- struct prom_args prom_args;
-
- prom_args.service = service;
- prom_args.nargs = nargs;
- prom_args.nret = nret;
- va_start(list, nret);
- for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, void *);
- va_end(list);
- for (i = 0; i < nret; ++i)
- prom_args.args[i + nargs] = 0;
- RELOC(prom)(&prom_args);
- return prom_args.args[nargs];
-}
-
-void __init
-prom_print(const char *msg)
-{
- const char *p, *q;
- unsigned long offset = reloc_offset();
-
- if (RELOC(prom_stdout) == 0)
- return;
-
- for (p = msg; *p != 0; p = q) {
- for (q = p; *q != 0 && *q != '\n'; ++q)
- ;
- if (q > p)
- call_prom(RELOC("write"), 3, 1, RELOC(prom_stdout),
- p, q - p);
- if (*q != 0) {
- ++q;
- call_prom(RELOC("write"), 3, 1, RELOC(prom_stdout),
- RELOC("\r\n"), 2);
- }
- }
-}
-
-static void __init
-prom_print_hex(unsigned int v)
-{
- char buf[16];
- int i, c;
-
- for (i = 0; i < 8; ++i) {
- c = (v >> ((7-i)*4)) & 0xf;
- c += (c >= 10)? ('a' - 10): '0';
- buf[i] = c;
- }
- buf[i] = ' ';
- buf[i+1] = 0;
- prom_print(buf);
-}
-
-unsigned long smp_chrp_cpu_nr __initdata = 0;
-
-#ifdef CONFIG_SMP
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of high memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something. We do that by using
- * physical address 0x0. The holding pattern checks that address
- * until its cpu # is there, when it is that cpu jumps to
- * __secondary_start(). smp_boot_cpus() takes care of setting those
- * values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * -- Cort
- */
-static void __init
-prom_hold_cpus(unsigned long mem)
-{
- extern void __secondary_hold(void);
- unsigned long i;
- int cpu;
- phandle node;
- unsigned long offset = reloc_offset();
- char type[16], *path;
- unsigned int reg;
-
- /*
- * XXX: hack to make sure we're chrp, assume that if we're
- * chrp we have a device_type property -- Cort
- */
- node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
- if ( (int)call_prom(RELOC("getprop"), 4, 1, node,
- RELOC("device_type"),type, sizeof(type)) <= 0)
- return;
-
- /* copy the holding pattern code to someplace safe (0) */
- /* the holding pattern is now within the first 0x100
- bytes of the kernel image -- paulus */
- memcpy((void *)0, (void *)(KERNELBASE + offset), 0x100);
- flush_icache_range(0, 0x100);
-
- /* look for cpus */
- *(unsigned long *)(0x0) = 0;
- asm volatile("dcbf 0,%0": : "r" (0) : "memory");
- for (node = 0; prom_next_node(&node); ) {
- type[0] = 0;
- call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
- type, sizeof(type));
- if (strcmp(type, RELOC("cpu")) != 0)
- continue;
- path = (char *) mem;
- memset(path, 0, 256);
- if ((int) call_prom(RELOC("package-to-path"), 3, 1,
- node, path, 255) < 0)
- continue;
- reg = -1;
- call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
- &reg, sizeof(reg));
- cpu = RELOC(smp_chrp_cpu_nr)++;
- RELOC(smp_hw_index)[cpu] = reg;
- /* XXX: hack - don't start cpu 0, this cpu -- Cort */
- if (cpu == 0)
- continue;
- prom_print(RELOC("starting cpu "));
- prom_print(path);
- *(ulong *)(0x4) = 0;
- call_prom(RELOC("start-cpu"), 3, 0, node,
- __pa(__secondary_hold), cpu);
- prom_print(RELOC("..."));
- for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
- ;
- if (*(ulong *)(0x4) == cpu)
- prom_print(RELOC("ok\n"));
- else {
- prom_print(RELOC("failed: "));
- prom_print_hex(*(ulong *)0x4);
- prom_print(RELOC("\n"));
- }
- }
-}
-#endif /* CONFIG_SMP */
-
-void __init
-bootx_init(unsigned long r4, unsigned long phys)
-{
- boot_infos_t *bi = (boot_infos_t *) r4;
- unsigned long space;
- unsigned long ptr, x;
- char *model;
- unsigned long offset = reloc_offset();
-
- RELOC(boot_infos) = PTRUNRELOC(bi);
- if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
- bi->logicalDisplayBase = 0;
-
-#ifdef CONFIG_BOOTX_TEXT
- btext_init(bi);
-
- /*
- * Test if boot-info is compatible. Done only in config
- * CONFIG_BOOTX_TEXT since there is nothing much we can do
- * with an incompatible version, except display a message
- * and eventually hang the processor...
- *
- * I'll try to keep enough of boot-info compatible in the
- * future to always allow display of this message;
- */
- if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
- btext_drawstring(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n"));
- btext_flushscreen();
- }
-#endif /* CONFIG_BOOTX_TEXT */
-
- /* New BootX enters kernel with MMU off, i/os are not allowed
- here. This hack will have been done by the boostrap anyway.
- */
- if (bi->version < 4) {
- /*
- * XXX If this is an iMac, turn off the USB controller.
- */
- model = (char *) early_get_property
- (r4 + bi->deviceTreeOffset, 4, RELOC("model"));
- if (model
- && (strcmp(model, RELOC("iMac,1")) == 0
- || strcmp(model, RELOC("PowerMac1,1")) == 0)) {
- out_le32((unsigned *)0x80880008, 1); /* XXX */
- }
- }
-
- /* Move klimit to enclose device tree, args, ramdisk, etc... */
- if (bi->version < 5) {
- space = bi->deviceTreeOffset + bi->deviceTreeSize;
- if (bi->ramDisk)
- space = bi->ramDisk + bi->ramDiskSize;
- } else
- space = bi->totalParamsSize;
- RELOC(klimit) = PTRUNRELOC((char *) bi + space);
-
- /* New BootX will have flushed all TLBs and enters kernel with
- MMU switched OFF, so this should not be useful anymore.
- */
- if (bi->version < 4) {
- /*
- * Touch each page to make sure the PTEs for them
- * are in the hash table - the aim is to try to avoid
- * getting DSI exceptions while copying the kernel image.
- */
- for (ptr = (KERNELBASE + offset) & PAGE_MASK;
- ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
- x = *(volatile unsigned long *)ptr;
- }
-
-#ifdef CONFIG_BOOTX_TEXT
- /*
- * Note that after we call prepare_disp_BAT, we can't do
- * prom_draw*, flushscreen or clearscreen until we turn the MMU
- * on, since prepare_disp_BAT sets disp_bi->logicalDisplayBase
- * to a virtual address.
- */
- btext_prepare_BAT();
-#endif
-}
-
-#ifdef CONFIG_PPC64BRIDGE
-/*
- * Set up a hash table with a set of entries in it to map the
- * first 64MB of RAM. This is used on 64-bit machines since
- * some of them don't have BATs.
- * We assume the PTE will fit in the primary PTEG.
- */
-
-static inline void make_pte(unsigned long htab, unsigned int hsize,
- unsigned int va, unsigned int pa, int mode)
-{
- unsigned int *pteg;
- unsigned int hash, i, vsid;
-
- vsid = ((va >> 28) * 0x111) << 12;
- hash = ((va ^ vsid) >> 5) & 0x7fff80;
- pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
- for (i = 0; i < 8; ++i, pteg += 4) {
- if ((pteg[1] & 1) == 0) {
- pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
- pteg[3] = pa | mode;
- break;
- }
- }
-}
-
-extern unsigned long _SDR1;
-extern PTE *Hash;
-extern unsigned long Hash_size;
-
-static void __init
-prom_alloc_htab(void)
-{
- unsigned int hsize;
- unsigned long htab;
- unsigned int addr;
- unsigned long offset = reloc_offset();
-
- /*
- * Because of OF bugs we can't use the "claim" client
- * interface to allocate memory for the hash table.
- * This code is only used on 64-bit PPCs, and the only
- * 64-bit PPCs at the moment are RS/6000s, and their
- * OF is based at 0xc00000 (the 12M point), so we just
- * arbitrarily use the 0x800000 - 0xc00000 region for the
- * hash table.
- * -- paulus.
- */
-#ifdef CONFIG_POWER4
- hsize = 4 << 20; /* POWER4 has no BATs */
-#else
- hsize = 2 << 20;
-#endif /* CONFIG_POWER4 */
- htab = (8 << 20);
- RELOC(Hash) = (void *)(htab + KERNELBASE);
- RELOC(Hash_size) = hsize;
- RELOC(_SDR1) = htab + __ilog2(hsize) - 18;
-
- /*
- * Put in PTEs for the first 64MB of RAM
- */
- cacheable_memzero((void *)htab, hsize);
- for (addr = 0; addr < 0x4000000; addr += 0x1000)
- make_pte(htab, hsize, addr + KERNELBASE, addr,
- _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
-}
-#endif /* CONFIG_PPC64BRIDGE */
-
-static void __init
-prom_instantiate_rtas(void)
-{
- ihandle prom_rtas;
- unsigned int i;
- struct prom_args prom_args;
- unsigned long offset = reloc_offset();
-
- prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
- if (prom_rtas == (void *) -1)
- return;
-
- RELOC(rtas_size) = 0;
- call_prom(RELOC("getprop"), 4, 1, prom_rtas,
- RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size));
- prom_print(RELOC("instantiating rtas"));
- if (RELOC(rtas_size) == 0) {
- RELOC(rtas_data) = 0;
- } else {
- /*
- * Ask OF for some space for RTAS.
- * Actually OF has bugs so we just arbitrarily
- * use memory at the 6MB point.
- */
- RELOC(rtas_data) = 6 << 20;
- prom_print(RELOC(" at "));
- prom_print_hex(RELOC(rtas_data));
- }
-
- prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
- prom_print(RELOC("..."));
- prom_args.service = RELOC("call-method");
- prom_args.nargs = 3;
- prom_args.nret = 2;
- prom_args.args[0] = RELOC("instantiate-rtas");
- prom_args.args[1] = prom_rtas;
- prom_args.args[2] = (void *) RELOC(rtas_data);
- RELOC(prom)(&prom_args);
- i = 0;
- if (prom_args.args[3] == 0)
- i = (unsigned int)prom_args.args[4];
- RELOC(rtas_entry) = i;
- if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0))
- prom_print(RELOC(" failed\n"));
- else
- prom_print(RELOC(" done\n"));
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-unsigned long __init
-prom_init(int r3, int r4, prom_entry pp)
-{
- unsigned long mem;
- ihandle prom_mmu;
- unsigned long offset = reloc_offset();
- int l;
- char *p, *d;
- unsigned long phys;
-
- /* Default */
- phys = offset + KERNELBASE;
-
- /* First get a handle for the stdout device */
- RELOC(prom) = pp;
- RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1,
- RELOC("/chosen"));
- if (RELOC(prom_chosen) == (void *)-1)
- prom_exit();
- if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
- RELOC("stdout"), &RELOC(prom_stdout),
- sizeof(prom_stdout)) <= 0)
- prom_exit();
-
- /* Get the full OF pathname of the stdout device */
- mem = (unsigned long) RELOC(klimit) + offset;
- p = (char *) mem;
- memset(p, 0, 256);
- call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255);
- RELOC(of_stdout_device) = PTRUNRELOC(p);
- mem += strlen(p) + 1;
-
- /* Get the boot device and translate it to a full OF pathname. */
- p = (char *) mem;
- l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
- RELOC("bootpath"), p, 1<<20);
- if (l > 0) {
- p[l] = 0; /* should already be null-terminated */
- RELOC(bootpath) = PTRUNRELOC(p);
- mem += l + 1;
- d = (char *) mem;
- *d = 0;
- call_prom(RELOC("canon"), 3, 1, p, d, 1<<20);
- RELOC(bootdevice) = PTRUNRELOC(d);
- mem = ALIGN(mem + strlen(d) + 1);
- }
-
- prom_instantiate_rtas();
-
-#ifdef CONFIG_PPC64BRIDGE
- /*
- * Find out how much memory we have and allocate a
- * suitably-sized hash table.
- */
- prom_alloc_htab();
-#endif
-
- mem = check_display(mem);
-
- prom_print(RELOC("copying OF device tree..."));
- mem = copy_device_tree(mem, mem + (1<<20));
- prom_print(RELOC("done\n"));
-
-#ifdef CONFIG_SMP
- prom_hold_cpus(mem);
-#endif
-
- RELOC(klimit) = (char *) (mem - offset);
-
- /* If we are already running at 0xc0000000, we assume we were loaded by
- * an OF bootloader which did set a BAT for us. This breaks OF translate
- * so we force phys to be 0
- */
- if (offset == 0)
- phys = 0;
- else {
- if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
- RELOC("mmu"), &prom_mmu, sizeof(prom_mmu)) <= 0) {
- prom_print(RELOC(" no MMU found\n"));
- } else {
- int nargs;
- struct prom_args prom_args;
- nargs = 4;
- prom_args.service = RELOC("call-method");
- prom_args.nargs = nargs;
- prom_args.nret = 4;
- prom_args.args[0] = RELOC("translate");
- prom_args.args[1] = prom_mmu;
- prom_args.args[2] = (void *)(offset + KERNELBASE);
- prom_args.args[3] = (void *)1;
- RELOC(prom)(&prom_args);
-
- /* We assume the phys. address size is 3 cells */
- if (prom_args.args[nargs] != 0)
- prom_print(RELOC(" (translate failed)\n"));
- else
- phys = (unsigned long)prom_args.args[nargs+3];
- }
- }
-
-#ifdef CONFIG_BOOTX_TEXT
- if (RELOC(prom_disp_node) != 0)
- setup_disp_fake_bi(RELOC(prom_disp_node));
-#endif
-
- /* Use quiesce call to get OF to shut down any devices it's using */
- prom_print(RELOC("Calling quiesce ...\n"));
- call_prom(RELOC("quiesce"), 0, 0);
-
-#ifdef CONFIG_BOOTX_TEXT
- btext_prepare_BAT();
-#endif
-
- prom_print(RELOC("returning "));
- prom_print_hex(phys);
- prom_print(RELOC(" from prom_init\n"));
- RELOC(prom_stdout) = 0;
-
- return phys;
-}
-
-void phys_call_rtas(int service, int nargs, int nret, ...)
+void __openfirmware
+phys_call_rtas(int service, int nargs, int nret, ...)
{
va_list list;
union {
unsigned long words[16];
double align;
} u;
- unsigned long offset = reloc_offset();
void (*rtas)(void *, unsigned long);
int i;
@@ -683,340 +114,8 @@ void phys_call_rtas(int service, int nargs, int nret, ...)
u.words[i+3] = va_arg(list, unsigned long);
va_end(list);
- rtas = (void (*)(void *, unsigned long)) RELOC(rtas_entry);
- rtas(&u, RELOC(rtas_data));
-}
-
-static int __init
-prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
- struct prom_args prom_args;
- unsigned long offset = reloc_offset();
-
- prom_args.service = RELOC("call-method");
- prom_args.nargs = 6;
- prom_args.nret = 1;
- prom_args.args[0] = RELOC("color!");
- prom_args.args[1] = ih;
- prom_args.args[2] = (void *) i;
- prom_args.args[3] = (void *) b;
- prom_args.args[4] = (void *) g;
- prom_args.args[5] = (void *) r;
- RELOC(prom)(&prom_args);
- return (int) prom_args.args[6];
-}
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later. However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init
-check_display(unsigned long mem)
-{
- phandle node;
- ihandle ih;
- int i;
- unsigned long offset = reloc_offset();
- char type[16], *path;
- static unsigned char default_colors[] = {
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xaa,
- 0x00, 0xaa, 0x00,
- 0x00, 0xaa, 0xaa,
- 0xaa, 0x00, 0x00,
- 0xaa, 0x00, 0xaa,
- 0xaa, 0xaa, 0x00,
- 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55,
- 0x55, 0x55, 0xff,
- 0x55, 0xff, 0x55,
- 0x55, 0xff, 0xff,
- 0xff, 0x55, 0x55,
- 0xff, 0x55, 0xff,
- 0xff, 0xff, 0x55,
- 0xff, 0xff, 0xff
- };
-
- RELOC(prom_disp_node) = 0;
-
- for (node = 0; prom_next_node(&node); ) {
- type[0] = 0;
- call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
- type, sizeof(type));
- if (strcmp(type, RELOC("display")) != 0)
- continue;
- /* It seems OF doesn't null-terminate the path :-( */
- path = (char *) mem;
- memset(path, 0, 256);
- if ((int) call_prom(RELOC("package-to-path"), 3, 1,
- node, path, 255) < 0)
- continue;
-
- /*
- * If this display is the device that OF is using for stdout,
- * move it to the front of the list.
- */
- mem += strlen(path) + 1;
- i = RELOC(prom_num_displays)++;
- if (RELOC(of_stdout_device) != 0 && i > 0
- && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
- for (; i > 0; --i) {
- RELOC(prom_display_paths[i])
- = RELOC(prom_display_paths[i-1]);
- RELOC(prom_display_nodes[i])
- = RELOC(prom_display_nodes[i-1]);
- }
- }
- RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
- RELOC(prom_display_nodes[i]) = node;
- if (i == 0)
- RELOC(prom_disp_node) = node;
- if (RELOC(prom_num_displays) >= FB_MAX)
- break;
- }
-
-try_again:
- /*
- * Open the first display and set its colormap.
- */
- if (RELOC(prom_num_displays) > 0) {
- path = PTRRELOC(RELOC(prom_display_paths[0]));
- prom_print(RELOC("opening display "));
- prom_print(path);
- ih = call_prom(RELOC("open"), 1, 1, path);
- if (ih == 0 || ih == (ihandle) -1) {
- prom_print(RELOC("... failed\n"));
- for (i=1; i<RELOC(prom_num_displays); i++) {
- RELOC(prom_display_paths[i-1]) = RELOC(prom_display_paths[i]);
- RELOC(prom_display_nodes[i-1]) = RELOC(prom_display_nodes[i]);
- }
- if (--RELOC(prom_num_displays) > 0)
- RELOC(prom_disp_node) = RELOC(prom_display_nodes[0]);
- else
- RELOC(prom_disp_node) = NULL;
- goto try_again;
- } else {
- prom_print(RELOC("... ok\n"));
- /*
- * Setup a usable color table when the appropriate
- * method is available.
- * Should update this to use set-colors.
- */
- for (i = 0; i < 32; i++)
- if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
- RELOC(default_colors)[i*3+1],
- RELOC(default_colors)[i*3+2]) != 0)
- break;
-
-#ifdef CONFIG_FB
- for (i = 0; i < LINUX_LOGO_COLORS; i++)
- if (prom_set_color(ih, i + 32,
- RELOC(linux_logo_red)[i],
- RELOC(linux_logo_green)[i],
- RELOC(linux_logo_blue)[i]) != 0)
- break;
-#endif /* CONFIG_FB */
- }
- }
-
- return ALIGN(mem);
-}
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-#ifdef CONFIG_BOOTX_TEXT
-static void __init
-setup_disp_fake_bi(ihandle dp)
-{
- int width = 640, height = 480, depth = 8, pitch;
- unsigned address;
- unsigned long offset = reloc_offset();
- struct pci_reg_property addrs[8];
- int i, naddrs;
- char name[32];
- char *getprop = RELOC("getprop");
-
- prom_print(RELOC("Initializing fake screen: "));
-
- memset(name, 0, sizeof(name));
- call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));
- name[sizeof(name)-1] = 0;
- prom_print(name);
- prom_print(RELOC("\n"));
- call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));
- call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));
- call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));
- pitch = width * ((depth + 7) / 8);
- call_prom(getprop, 4, 1, dp, RELOC("linebytes"),
- &pitch, sizeof(pitch));
- if (pitch == 1)
- pitch = 0x1000; /* for strange IBM display */
- address = 0;
- call_prom(getprop, 4, 1, dp, RELOC("address"),
- &address, sizeof(address));
- if (address == 0) {
- /* look for an assigned address with a size of >= 1MB */
- naddrs = (int) call_prom(getprop, 4, 1, dp,
- RELOC("assigned-addresses"),
- addrs, sizeof(addrs));
- naddrs /= sizeof(struct pci_reg_property);
- for (i = 0; i < naddrs; ++i) {
- if (addrs[i].size_lo >= (1 << 20)) {
- address = addrs[i].addr.a_lo;
- /* use the BE aperture if possible */
- if (addrs[i].size_lo >= (16 << 20))
- address += (8 << 20);
- break;
- }
- }
- if (address == 0) {
- prom_print(RELOC("Failed to get address\n"));
- return;
- }
- }
- /* kludge for valkyrie */
- if (strcmp(name, RELOC("valkyrie")) == 0)
- address += 0x1000;
-
- btext_setup_display(width, height, depth, pitch, address);
-}
-#endif
-
-static int __init
-prom_next_node(phandle *nodep)
-{
- phandle node;
- unsigned long offset = reloc_offset();
-
- if ((node = *nodep) != 0
- && (*nodep = call_prom(RELOC("child"), 1, 1, node)) != 0)
- return 1;
- if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
- return 1;
- for (;;) {
- if ((node = call_prom(RELOC("parent"), 1, 1, node)) == 0)
- return 0;
- if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
- return 1;
- }
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start, unsigned long mem_end)
-{
- phandle root;
- unsigned long new_start;
- struct device_node **allnextp;
- unsigned long offset = reloc_offset();
-
- root = call_prom(RELOC("peer"), 1, 1, (phandle)0);
- if (root == (phandle)0) {
- prom_print(RELOC("couldn't get device tree root\n"));
- prom_exit();
- }
- allnextp = &RELOC(allnodes);
- mem_start = ALIGN(mem_start);
- new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
- *allnextp = 0;
- return new_start;
-}
-
-static unsigned long __init
-inspect_node(phandle node, struct device_node *dad,
- unsigned long mem_start, unsigned long mem_end,
- struct device_node ***allnextpp)
-{
- int l;
- phandle child;
- struct device_node *np;
- struct property *pp, **prev_propp;
- char *prev_name, *namep;
- unsigned char *valp;
- unsigned long offset = reloc_offset();
-
- np = (struct device_node *) mem_start;
- mem_start += sizeof(struct device_node);
- memset(np, 0, sizeof(*np));
- np->node = node;
- **allnextpp = PTRUNRELOC(np);
- *allnextpp = &np->allnext;
- if (dad != 0) {
- np->parent = PTRUNRELOC(dad);
- /* we temporarily use the `next' field as `last_child'. */
- if (dad->next == 0)
- dad->child = PTRUNRELOC(np);
- else
- dad->next->sibling = PTRUNRELOC(np);
- dad->next = np;
- }
-
- /* get and store all properties */
- prev_propp = &np->properties;
- prev_name = RELOC("");
- for (;;) {
- pp = (struct property *) mem_start;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- if ((int) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,
- namep) <= 0)
- break;
- mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
- prev_name = namep;
- valp = (unsigned char *) mem_start;
- pp->value = PTRUNRELOC(valp);
- pp->length = (int)
- call_prom(RELOC("getprop"), 4, 1, node, namep,
- valp, mem_end - mem_start);
- if (pp->length < 0)
- continue;
-#ifdef MAX_PROPERTY_LENGTH
- if (pp->length > MAX_PROPERTY_LENGTH)
- continue; /* ignore this property */
-#endif
- mem_start = ALIGN(mem_start + pp->length);
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- }
- if (np->node != NULL) {
- /* Add a "linux,phandle" property" */
- pp = (struct property *) mem_start;
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- strcpy(namep, RELOC("linux,phandle"));
- mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
- pp->value = (unsigned char *) PTRUNRELOC(&np->node);
- pp->length = sizeof(np->node);
- }
- *prev_propp = NULL;
-
- /* get the node's full name */
- l = (int) call_prom(RELOC("package-to-path"), 3, 1, node,
- (char *) mem_start, mem_end - mem_start);
- if (l >= 0) {
- np->full_name = PTRUNRELOC((char *) mem_start);
- *(char *)(mem_start + l) = 0;
- mem_start = ALIGN(mem_start + l + 1);
- }
-
- /* do all our children */
- child = call_prom(RELOC("child"), 1, 1, node);
- while (child != (void *)0) {
- mem_start = inspect_node(child, np, mem_start, mem_end,
- allnextpp);
- child = call_prom(RELOC("peer"), 1, 1, child);
- }
-
- return mem_start;
+ rtas = (void (*)(void *, unsigned long)) rtas_entry;
+ rtas(&u, rtas_data);
}
/*
@@ -1081,26 +180,6 @@ finish_device_tree(void)
klimit = (char *) mem;
}
-/*
- * early_get_property is used to access the device tree image prepared
- * by BootX very early on, before the pointers in it have been relocated.
- */
-static void * __init
-early_get_property(unsigned long base, unsigned long node, char *prop)
-{
- struct device_node *np = (struct device_node *)(base + node);
- struct property *pp;
-
- for (pp = np->properties; pp != 0; pp = pp->next) {
- pp = (struct property *) (base + (unsigned long)pp);
- if (strcmp((char *)((unsigned long)pp->name + base),
- prop) == 0) {
- return (void *)((unsigned long)pp->value + base);
- }
- }
- return 0;
-}
-
static unsigned long __init
finish_node(struct device_node *np, unsigned long mem_start,
interpret_func *ifunc, int naddrc, int nsizec)
@@ -1111,10 +190,15 @@ finish_node(struct device_node *np, unsigned long mem_start,
np->name = get_property(np, "name", 0);
np->type = get_property(np, "device_type", 0);
+ if (!np->name)
+ np->name = "<NULL>";
+ if (!np->type)
+ np->type = "<NULL>";
+
/* get the device addresses and interrupts */
- if (ifunc != NULL) {
+ if (ifunc != NULL)
mem_start = ifunc(np, mem_start, naddrc, nsizec);
- }
+
if (use_of_interrupt_tree)
mem_start = finish_node_interrupts(np, mem_start);
@@ -1126,12 +210,6 @@ finish_node(struct device_node *np, unsigned long mem_start,
if (ip != NULL)
nsizec = *ip;
- /* the f50 sets the name to 'display' and 'compatible' to what we
- * expect for the name -- Cort
- */
- if (!strcmp(np->name, "display"))
- np->name = get_property(np, "compatible", 0);
-
if (np->parent == NULL)
ifunc = interpret_root_props;
else if (np->type == 0)
@@ -1145,6 +223,8 @@ finish_node(struct device_node *np, unsigned long mem_start,
ifunc = interpret_macio_props;
else if (!strcmp(np->type, "isa"))
ifunc = interpret_isa_props;
+ else if (!strcmp(np->name, "uni-n"))
+ ifunc = interpret_root_props;
else if (!((ifunc == interpret_dbdma_props
|| ifunc == interpret_macio_props)
&& (!strcmp(np->type, "escc")
@@ -1508,7 +588,7 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
i = 0;
adr = (struct address_range *) mem_start;
while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = 0;
+ adr[i].space = 2;
adr[i].address = rp[i].address + base_address;
adr[i].size = rp[i].size;
++i;
@@ -1544,14 +624,13 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start,
struct reg_property *rp;
struct address_range *adr;
unsigned long base_address;
- int i, l, keylargo, *ip;
+ int i, l, *ip;
struct device_node *db;
base_address = 0;
for (db = np->parent; db != NULL; db = db->parent) {
if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
base_address = db->addrs[0].address;
- keylargo = device_is_compatible(db, "Keylargo");
break;
}
}
@@ -1561,7 +640,7 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start,
i = 0;
adr = (struct address_range *) mem_start;
while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = 0;
+ adr[i].space = 2;
adr[i].address = rp[i].address + base_address;
adr[i].size = rp[i].size;
++i;
@@ -1616,7 +695,7 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start,
if (use_of_interrupt_tree)
return mem_start;
-
+
ip = (int *) get_property(np, "interrupts", &l);
if (ip != 0) {
np->intrs = (struct interrupt_info *) mem_start;
@@ -1645,7 +724,7 @@ interpret_root_props(struct device_node *np, unsigned long mem_start,
i = 0;
adr = (struct address_range *) mem_start;
while ((l -= rpsize) >= 0) {
- adr[i].space = (naddrc >= 2? rp[naddrc-2]: 0);
+ adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
adr[i].address = rp[naddrc - 1];
adr[i].size = rp[naddrc + nsizec - 1];
++i;
@@ -1786,7 +865,7 @@ int
machine_is_compatible(const char *compat)
{
struct device_node *root;
-
+
root = find_path_device("/");
if (root == 0)
return 0;
@@ -1870,12 +949,178 @@ prom_add_property(struct device_node* np, struct property* prop)
{
struct property **next = &np->properties;
- prop->next = NULL;
+ prop->next = NULL;
while (*next)
next = &(*next)->next;
*next = prop;
}
+/* I quickly hacked that one, check against spec ! */
+static inline unsigned long __openfirmware
+bus_space_to_resource_flags(unsigned int bus_space)
+{
+ u8 space = (bus_space >> 24) & 0xf;
+ if (space == 0)
+ space = 0x02;
+ if (space == 0x02)
+ return IORESOURCE_MEM;
+ else if (space == 0x01)
+ return IORESOURCE_IO;
+ else {
+ printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
+ bus_space);
+ return 0;
+ }
+}
+
+static struct resource* __openfirmware
+find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
+{
+ unsigned long mask;
+ int i;
+
+ /* Check this one */
+ mask = bus_space_to_resource_flags(range->space);
+ for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
+ if ((pdev->resource[i].flags & mask) == mask &&
+ pdev->resource[i].start <= range->address &&
+ pdev->resource[i].end > range->address) {
+ if ((range->address + range->size - 1) > pdev->resource[i].end) {
+ /* Add better message */
+ printk(KERN_WARNING "PCI/OF resource overlap !\n");
+ return NULL;
+ }
+ break;
+ }
+ }
+ if (i == DEVICE_COUNT_RESOURCE)
+ return NULL;
+ return &pdev->resource[i];
+}
+
+/*
+ * Request an OF device resource. Currently handles child of PCI devices,
+ * or other nodes attached to the root node. Ultimately, put some
+ * link to resources in the OF node.
+ * WARNING: out_resource->name should be initialized before calling this
+ * function.
+ */
+struct resource* __openfirmware
+request_OF_resource(struct device_node* node, int index, const char* name_postfix)
+{
+ struct pci_dev* pcidev;
+ u8 pci_bus, pci_devfn;
+ unsigned long iomask;
+ struct device_node* nd;
+ struct resource* parent;
+ struct resource *res = NULL;
+ int nlen, plen;
+
+ if (index >= node->n_addrs)
+ goto fail;
+
+ /* Sanity check on bus space */
+ iomask = bus_space_to_resource_flags(node->addrs[index].space);
+ if (iomask & IORESOURCE_MEM)
+ parent = &iomem_resource;
+ else if (iomask & IORESOURCE_IO)
+ parent = &ioport_resource;
+ else
+ goto fail;
+
+ /* Find a PCI parent if any */
+ nd = node;
+ pcidev = NULL;
+ while(nd) {
+ if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
+ pcidev = pci_find_slot(pci_bus, pci_devfn);
+ if (pcidev) break;
+ nd = nd->parent;
+ }
+ if (pcidev)
+ parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
+ if (!parent) {
+ printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
+ node->name);
+ goto fail;
+ }
+
+ res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
+ if (!res)
+ goto fail;
+ nlen = strlen(node->name);
+ plen = name_postfix ? strlen(name_postfix) : 0;
+ res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
+ if (res->name) {
+ strcpy((char *)res->name, node->name);
+ if (plen)
+ strcpy((char *)res->name+nlen, name_postfix);
+ }
+ return res;
+fail:
+ return NULL;
+}
+
+int __openfirmware
+release_OF_resource(struct device_node* node, int index)
+{
+ struct pci_dev* pcidev;
+ u8 pci_bus, pci_devfn;
+ unsigned long iomask;
+ struct device_node* nd;
+ struct resource* parent;
+ struct resource *res = NULL;
+
+ if (index >= node->n_addrs)
+ return -EINVAL;
+
+ /* Sanity check on bus space */
+ iomask = bus_space_to_resource_flags(node->addrs[index].space);
+ if (iomask & IORESOURCE_MEM)
+ parent = &iomem_resource;
+ else if (iomask & IORESOURCE_IO)
+ parent = &ioport_resource;
+ else
+ return -EINVAL;
+
+ /* Find a PCI parent if any */
+ nd = node;
+ pcidev = NULL;
+ while(nd) {
+ if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
+ pcidev = pci_find_slot(pci_bus, pci_devfn);
+ if (pcidev) break;
+ nd = nd->parent;
+ }
+ if (pcidev)
+ parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
+ if (!parent) {
+ printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
+ node->name);
+ return -ENODEV;
+ }
+
+ /* Find us in the parent */
+ res = parent->child;
+ while (res) {
+ if (res->start == node->addrs[index].address &&
+ res->end == (res->start + node->addrs[index].size - 1))
+ break;
+ res = res->sibling;
+ }
+ if (!res)
+ return -ENODEV;
+
+ if (res->name) {
+ kfree(res->name);
+ res->name = NULL;
+ }
+ release_resource(res);
+ kfree(res);
+
+ return 0;
+}
+
#if 0
void __openfirmware
print_properties(struct device_node *np)
@@ -1961,11 +1206,11 @@ call_rtas(const char *service, int nargs, int nret,
u.words[i+3] = va_arg(list, unsigned long);
va_end(list);
- /* Shouldn't we enable kernel FP here ? enter_rtas will play
- * with MSR_FE0|MSR_FE1|MSR_FP so I assume rtas might use
- * floating points. If that's the case, then we need to make
- * sure any lazy FP context is backed up
- * --BenH
+ /*
+ * RTAS doesn't use floating point.
+ * Or at least, according to the CHRP spec we enter RTAS
+ * with FP disabled, and it doesn't change the FP registers.
+ * -- paulus.
*/
spin_lock_irqsave(&rtas_lock, s);
enter_rtas((void *)__pa(&u));
@@ -1976,13 +1221,3 @@ call_rtas(const char *service, int nargs, int nret,
outputs[i] = u.words[i+nargs+4];
return u.words[nargs+3];
}
-
-void __init
-abort()
-{
-#ifdef CONFIG_XMON
- xmon(NULL);
-#endif
- for (;;)
- prom_exit();
-}
diff --git a/arch/ppc/kernel/prom_init.c b/arch/ppc/kernel/prom_init.c
new file mode 100644
index 000000000000..fea41427aa29
--- /dev/null
+++ b/arch/ppc/kernel/prom_init.c
@@ -0,0 +1,899 @@
+/*
+ * Note that prom_init() and anything called from prom_init()
+ * may be running at an address that is different from the address
+ * that it was linked at. References to static data items are
+ * handled by compiling this file with -mrelocatable-lib.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/btext.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+
+#ifdef CONFIG_FB
+#include <asm/linux_logo.h>
+#endif
+
+/*
+ * Properties whose value is longer than this get excluded from our
+ * copy of the device tree. This way we don't waste space storing
+ * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
+ * does need to be big enough to ensure that we don't lose things
+ * like the interrupt-map property on a PCI-PCI bridge.
+ */
+#define MAX_PROPERTY_LENGTH 4096
+
+#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
+#define FB_MAX 8
+#endif
+
+#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
+
+struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ void *args[10];
+};
+
+struct pci_address {
+ unsigned a_hi;
+ unsigned a_mid;
+ unsigned a_lo;
+};
+
+struct pci_reg_property {
+ struct pci_address addr;
+ unsigned size_hi;
+ unsigned size_lo;
+};
+
+struct pci_range {
+ struct pci_address addr;
+ unsigned phys;
+ unsigned size_hi;
+ unsigned size_lo;
+};
+
+struct isa_reg_property {
+ unsigned space;
+ unsigned address;
+ unsigned size;
+};
+
+struct pci_intr_map {
+ struct pci_address addr;
+ unsigned dunno;
+ phandle int_ctrler;
+ unsigned intr;
+};
+
+static void prom_exit(void);
+static void *call_prom(const char *service, int nargs, int nret, ...);
+static void *call_prom_ret(const char *service, int nargs, int nret,
+ void **rets, ...);
+static void prom_print_hex(unsigned int v);
+static int prom_set_color(ihandle ih, int i, int r, int g, int b);
+static int prom_next_node(phandle *nodep);
+static unsigned long check_display(unsigned long mem);
+static void setup_disp_fake_bi(ihandle dp);
+static unsigned long copy_device_tree(unsigned long mem_start,
+ unsigned long mem_end);
+static unsigned long inspect_node(phandle node, struct device_node *dad,
+ unsigned long mem_start, unsigned long mem_end,
+ struct device_node ***allnextpp);
+static void prom_hold_cpus(unsigned long mem);
+static void prom_instantiate_rtas(void);
+static void * early_get_property(unsigned long base, unsigned long node,
+ char *prop);
+
+prom_entry prom __initdata = 0;
+ihandle prom_chosen __initdata = 0;
+ihandle prom_stdout __initdata = 0;
+
+char *prom_display_paths[FB_MAX] __initdata = { 0, };
+phandle prom_display_nodes[FB_MAX] __initdata;
+unsigned int prom_num_displays __initdata = 0;
+static char *of_stdout_device __initdata = 0;
+static ihandle prom_disp_node __initdata = 0;
+
+unsigned int rtas_data; /* physical pointer */
+unsigned int rtas_entry; /* physical pointer */
+unsigned int rtas_size;
+unsigned int old_rtas;
+
+boot_infos_t *boot_infos;
+char *bootpath;
+char *bootdevice;
+struct device_node *allnodes;
+
+extern char *klimit;
+extern char _stext;
+
+static void __init
+prom_exit(void)
+{
+ struct prom_args args;
+
+ args.service = "exit";
+ args.nargs = 0;
+ args.nret = 0;
+ prom(&args);
+ for (;;) /* should never get here */
+ ;
+}
+
+static void * __init
+call_prom(const char *service, int nargs, int nret, ...)
+{
+ va_list list;
+ int i;
+ struct prom_args prom_args;
+
+ prom_args.service = service;
+ prom_args.nargs = nargs;
+ prom_args.nret = nret;
+ va_start(list, nret);
+ for (i = 0; i < nargs; ++i)
+ prom_args.args[i] = va_arg(list, void *);
+ va_end(list);
+ for (i = 0; i < nret; ++i)
+ prom_args.args[i + nargs] = 0;
+ prom(&prom_args);
+ return prom_args.args[nargs];
+}
+
+static void * __init
+call_prom_ret(const char *service, int nargs, int nret, void **rets, ...)
+{
+ va_list list;
+ int i;
+ struct prom_args prom_args;
+
+ prom_args.service = service;
+ prom_args.nargs = nargs;
+ prom_args.nret = nret;
+ va_start(list, rets);
+ for (i = 0; i < nargs; ++i)
+ prom_args.args[i] = va_arg(list, void *);
+ va_end(list);
+ for (i = 0; i < nret; ++i)
+ prom_args.args[i + nargs] = 0;
+ prom(&prom_args);
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = prom_args.args[nargs + i];
+ return prom_args.args[nargs];
+}
+
+void __init
+prom_print(const char *msg)
+{
+ const char *p, *q;
+
+ if (prom_stdout == 0)
+ return;
+
+ for (p = msg; *p != 0; p = q) {
+ for (q = p; *q != 0 && *q != '\n'; ++q)
+ ;
+ if (q > p)
+ call_prom("write", 3, 1, prom_stdout, p, q - p);
+ if (*q != 0) {
+ ++q;
+ call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
+ }
+ }
+}
+
+static void __init
+prom_print_hex(unsigned int v)
+{
+ char buf[16];
+ int i, c;
+
+ for (i = 0; i < 8; ++i) {
+ c = (v >> ((7-i)*4)) & 0xf;
+ c += (c >= 10)? ('a' - 10): '0';
+ buf[i] = c;
+ }
+ buf[i] = ' ';
+ buf[i+1] = 0;
+ prom_print(buf);
+}
+
+static int __init
+prom_set_color(ihandle ih, int i, int r, int g, int b)
+{
+ struct prom_args prom_args;
+
+ prom_args.service = "call-method";
+ prom_args.nargs = 6;
+ prom_args.nret = 1;
+ prom_args.args[0] = "color!";
+ prom_args.args[1] = ih;
+ prom_args.args[2] = (void *) i;
+ prom_args.args[3] = (void *) b;
+ prom_args.args[4] = (void *) g;
+ prom_args.args[5] = (void *) r;
+ prom(&prom_args);
+ return (int) prom_args.args[6];
+}
+
+static int __init
+prom_next_node(phandle *nodep)
+{
+ phandle node;
+
+ if ((node = *nodep) != 0
+ && (*nodep = call_prom("child", 1, 1, node)) != 0)
+ return 1;
+ if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+ return 1;
+ for (;;) {
+ if ((node = call_prom("parent", 1, 1, node)) == 0)
+ return 0;
+ if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+ return 1;
+ }
+}
+
+/*
+ * If we have a display that we don't know how to drive,
+ * we will want to try to execute OF's open method for it
+ * later. However, OF will probably fall over if we do that
+ * we've taken over the MMU.
+ * So we check whether we will need to open the display,
+ * and if so, open it now.
+ */
+static unsigned long __init
+check_display(unsigned long mem)
+{
+ phandle node;
+ ihandle ih;
+ int i;
+ char type[16], *path;
+ static unsigned char default_colors[] = {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xaa,
+ 0x00, 0xaa, 0x00,
+ 0x00, 0xaa, 0xaa,
+ 0xaa, 0x00, 0x00,
+ 0xaa, 0x00, 0xaa,
+ 0xaa, 0xaa, 0x00,
+ 0xaa, 0xaa, 0xaa,
+ 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0xff,
+ 0x55, 0xff, 0x55,
+ 0x55, 0xff, 0xff,
+ 0xff, 0x55, 0x55,
+ 0xff, 0x55, 0xff,
+ 0xff, 0xff, 0x55,
+ 0xff, 0xff, 0xff
+ };
+
+ prom_disp_node = 0;
+
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = 0;
+ call_prom("getprop", 4, 1, node, "device_type",
+ type, sizeof(type));
+ if (strcmp(type, "display") != 0)
+ continue;
+ /* It seems OF doesn't null-terminate the path :-( */
+ path = (char *) mem;
+ memset(path, 0, 256);
+ if ((int) call_prom("package-to-path", 3, 1,
+ node, path, 255) < 0)
+ continue;
+
+ /*
+ * If this display is the device that OF is using for stdout,
+ * move it to the front of the list.
+ */
+ mem += strlen(path) + 1;
+ i = prom_num_displays++;
+ if (of_stdout_device != 0 && i > 0
+ && strcmp(of_stdout_device, path) == 0) {
+ for (; i > 0; --i) {
+ prom_display_paths[i]
+ = prom_display_paths[i-1];
+ prom_display_nodes[i]
+ = prom_display_nodes[i-1];
+ }
+ }
+ prom_display_paths[i] = path;
+ prom_display_nodes[i] = node;
+ if (i == 0)
+ prom_disp_node = node;
+ if (prom_num_displays >= FB_MAX)
+ break;
+ }
+
+try_again:
+ /*
+ * Open the first display and set its colormap.
+ */
+ if (prom_num_displays > 0) {
+ path = prom_display_paths[0];
+ prom_print("opening display ");
+ prom_print(path);
+ ih = call_prom("open", 1, 1, path);
+ if (ih == 0 || ih == (ihandle) -1) {
+ prom_print("... failed\n");
+ for (i=1; i<prom_num_displays; i++) {
+ prom_display_paths[i-1] = prom_display_paths[i];
+ prom_display_nodes[i-1] = prom_display_nodes[i];
+ }
+ if (--prom_num_displays > 0)
+ prom_disp_node = prom_display_nodes[0];
+ else
+ prom_disp_node = NULL;
+ goto try_again;
+ } else {
+ prom_print("... ok\n");
+ /*
+ * Setup a usable color table when the appropriate
+ * method is available.
+ * Should update this to use set-colors.
+ */
+ for (i = 0; i < 32; i++)
+ if (prom_set_color(ih, i, default_colors[i*3],
+ default_colors[i*3+1],
+ default_colors[i*3+2]) != 0)
+ break;
+
+#ifdef CONFIG_FB
+ for (i = 0; i < LINUX_LOGO_COLORS; i++)
+ if (prom_set_color(ih, i + 32,
+ linux_logo_red[i],
+ linux_logo_green[i],
+ linux_logo_blue[i]) != 0)
+ break;
+#endif /* CONFIG_FB */
+ }
+ }
+
+ return ALIGN(mem);
+}
+
+/* This function will enable the early boot text when doing OF booting. This
+ * way, xmon output should work too
+ */
+static void __init
+setup_disp_fake_bi(ihandle dp)
+{
+#ifdef CONFIG_BOOTX_TEXT
+ int width = 640, height = 480, depth = 8, pitch;
+ unsigned address;
+ struct pci_reg_property addrs[8];
+ int i, naddrs;
+ char name[32];
+ char *getprop = "getprop";
+
+ prom_print("Initializing fake screen: ");
+
+ memset(name, 0, sizeof(name));
+ call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
+ name[sizeof(name)-1] = 0;
+ prom_print(name);
+ prom_print("\n");
+ call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
+ call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
+ call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
+ pitch = width * ((depth + 7) / 8);
+ call_prom(getprop, 4, 1, dp, "linebytes",
+ &pitch, sizeof(pitch));
+ if (pitch == 1)
+ pitch = 0x1000; /* for strange IBM display */
+ address = 0;
+ call_prom(getprop, 4, 1, dp, "address",
+ &address, sizeof(address));
+ if (address == 0) {
+ /* look for an assigned address with a size of >= 1MB */
+ naddrs = (int) call_prom(getprop, 4, 1, dp,
+ "assigned-addresses",
+ addrs, sizeof(addrs));
+ naddrs /= sizeof(struct pci_reg_property);
+ for (i = 0; i < naddrs; ++i) {
+ if (addrs[i].size_lo >= (1 << 20)) {
+ address = addrs[i].addr.a_lo;
+ /* use the BE aperture if possible */
+ if (addrs[i].size_lo >= (16 << 20))
+ address += (8 << 20);
+ break;
+ }
+ }
+ if (address == 0) {
+ prom_print("Failed to get address\n");
+ return;
+ }
+ }
+ /* kludge for valkyrie */
+ if (strcmp(name, "valkyrie") == 0)
+ address += 0x1000;
+
+ btext_setup_display(width, height, depth, pitch, address);
+
+ btext_prepare_BAT();
+#endif /* CONFIG_BOOTX_TEXT */
+}
+
+/*
+ * Make a copy of the device tree from the PROM.
+ */
+static unsigned long __init
+copy_device_tree(unsigned long mem_start, unsigned long mem_end)
+{
+ phandle root;
+ unsigned long new_start;
+ struct device_node **allnextp;
+
+ root = call_prom("peer", 1, 1, (phandle)0);
+ if (root == (phandle)0) {
+ prom_print("couldn't get device tree root\n");
+ prom_exit();
+ }
+ allnextp = &allnodes;
+ mem_start = ALIGN(mem_start);
+ new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
+ *allnextp = 0;
+ return new_start;
+}
+
+static unsigned long __init
+inspect_node(phandle node, struct device_node *dad,
+ unsigned long mem_start, unsigned long mem_end,
+ struct device_node ***allnextpp)
+{
+ int l;
+ phandle child;
+ struct device_node *np;
+ struct property *pp, **prev_propp;
+ char *prev_name, *namep;
+ unsigned char *valp;
+
+ np = (struct device_node *) mem_start;
+ mem_start += sizeof(struct device_node);
+ memset(np, 0, sizeof(*np));
+ np->node = node;
+ **allnextpp = PTRUNRELOC(np);
+ *allnextpp = &np->allnext;
+ if (dad != 0) {
+ np->parent = PTRUNRELOC(dad);
+ /* we temporarily use the `next' field as `last_child'. */
+ if (dad->next == 0)
+ dad->child = PTRUNRELOC(np);
+ else
+ dad->next->sibling = PTRUNRELOC(np);
+ dad->next = np;
+ }
+
+ /* get and store all properties */
+ prev_propp = &np->properties;
+ prev_name = "";
+ for (;;) {
+ pp = (struct property *) mem_start;
+ namep = (char *) (pp + 1);
+ pp->name = PTRUNRELOC(namep);
+ if ((int) call_prom("nextprop", 3, 1, node, prev_name,
+ namep) <= 0)
+ break;
+ mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
+ prev_name = namep;
+ valp = (unsigned char *) mem_start;
+ pp->value = PTRUNRELOC(valp);
+ pp->length = (int)
+ call_prom("getprop", 4, 1, node, namep,
+ valp, mem_end - mem_start);
+ if (pp->length < 0)
+ continue;
+#ifdef MAX_PROPERTY_LENGTH
+ if (pp->length > MAX_PROPERTY_LENGTH)
+ continue; /* ignore this property */
+#endif
+ mem_start = ALIGN(mem_start + pp->length);
+ *prev_propp = PTRUNRELOC(pp);
+ prev_propp = &pp->next;
+ }
+ if (np->node != NULL) {
+ /* Add a "linux,phandle" property" */
+ pp = (struct property *) mem_start;
+ *prev_propp = PTRUNRELOC(pp);
+ prev_propp = &pp->next;
+ namep = (char *) (pp + 1);
+ pp->name = PTRUNRELOC(namep);
+ strcpy(namep, "linux,phandle");
+ mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
+ pp->value = (unsigned char *) PTRUNRELOC(&np->node);
+ pp->length = sizeof(np->node);
+ }
+ *prev_propp = NULL;
+
+ /* get the node's full name */
+ l = (int) call_prom("package-to-path", 3, 1, node,
+ (char *) mem_start, mem_end - mem_start);
+ if (l >= 0) {
+ np->full_name = PTRUNRELOC((char *) mem_start);
+ *(char *)(mem_start + l) = 0;
+ mem_start = ALIGN(mem_start + l + 1);
+ }
+
+ /* do all our children */
+ child = call_prom("child", 1, 1, node);
+ while (child != (void *)0) {
+ mem_start = inspect_node(child, np, mem_start, mem_end,
+ allnextpp);
+ child = call_prom("peer", 1, 1, child);
+ }
+
+ return mem_start;
+}
+
+unsigned long smp_chrp_cpu_nr __initdata = 0;
+
+/*
+ * With CHRP SMP we need to use the OF to start the other
+ * processors so we can't wait until smp_boot_cpus (the OF is
+ * trashed by then) so we have to put the processors into
+ * a holding pattern controlled by the kernel (not OF) before
+ * we destroy the OF.
+ *
+ * This uses a chunk of high memory, puts some holding pattern
+ * code there and sends the other processors off to there until
+ * smp_boot_cpus tells them to do something. We do that by using
+ * physical address 0x0. The holding pattern checks that address
+ * until its cpu # is there, when it is that cpu jumps to
+ * __secondary_start(). smp_boot_cpus() takes care of setting those
+ * values.
+ *
+ * We also use physical address 0x4 here to tell when a cpu
+ * is in its holding pattern code.
+ *
+ * -- Cort
+ *
+ * Note that we have to do this if we have more than one CPU,
+ * even if this is a UP kernel. Otherwise when we trash OF
+ * the other CPUs will start executing some random instructions
+ * and crash the system. -- paulus
+ */
+static void __init
+prom_hold_cpus(unsigned long mem)
+{
+ extern void __secondary_hold(void);
+ unsigned long i;
+ int cpu;
+ phandle node;
+ char type[16], *path;
+ unsigned int reg;
+
+ /*
+ * XXX: hack to make sure we're chrp, assume that if we're
+ * chrp we have a device_type property -- Cort
+ */
+ node = call_prom("finddevice", 1, 1, "/");
+ if ((int)call_prom("getprop", 4, 1, node,
+ "device_type",type, sizeof(type)) <= 0)
+ return;
+
+ /* copy the holding pattern code to someplace safe (0) */
+ /* the holding pattern is now within the first 0x100
+ bytes of the kernel image -- paulus */
+ memcpy((void *)0, &_stext, 0x100);
+ flush_icache_range(0, 0x100);
+
+ /* look for cpus */
+ *(unsigned long *)(0x0) = 0;
+ asm volatile("dcbf 0,%0": : "r" (0) : "memory");
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = 0;
+ call_prom("getprop", 4, 1, node, "device_type",
+ type, sizeof(type));
+ if (strcmp(type, "cpu") != 0)
+ continue;
+ path = (char *) mem;
+ memset(path, 0, 256);
+ if ((int) call_prom("package-to-path", 3, 1,
+ node, path, 255) < 0)
+ continue;
+ reg = -1;
+ call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));
+ cpu = smp_chrp_cpu_nr++;
+#ifdef CONFIG_SMP
+ smp_hw_index[cpu] = reg;
+#endif /* CONFIG_SMP */
+ /* XXX: hack - don't start cpu 0, this cpu -- Cort */
+ if (cpu == 0)
+ continue;
+ prom_print("starting cpu ");
+ prom_print(path);
+ *(ulong *)(0x4) = 0;
+ call_prom("start-cpu", 3, 0, node,
+ (char *)__secondary_hold - &_stext, cpu);
+ prom_print("...");
+ for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
+ ;
+ if (*(ulong *)(0x4) == cpu)
+ prom_print("ok\n");
+ else {
+ prom_print("failed: ");
+ prom_print_hex(*(ulong *)0x4);
+ prom_print("\n");
+ }
+ }
+}
+
+static void __init
+prom_instantiate_rtas(void)
+{
+ ihandle prom_rtas;
+ unsigned int i;
+ struct prom_args prom_args;
+
+ prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
+ if (prom_rtas == (void *) -1)
+ return;
+
+ rtas_size = 0;
+ call_prom("getprop", 4, 1, prom_rtas,
+ "rtas-size", &rtas_size, sizeof(rtas_size));
+ prom_print("instantiating rtas");
+ if (rtas_size == 0) {
+ rtas_data = 0;
+ } else {
+ /*
+ * Ask OF for some space for RTAS.
+ * Actually OF has bugs so we just arbitrarily
+ * use memory at the 6MB point.
+ */
+ rtas_data = 6 << 20;
+ prom_print(" at ");
+ prom_print_hex(rtas_data);
+ }
+
+ prom_rtas = call_prom("open", 1, 1, "/rtas");
+ prom_print("...");
+ prom_args.service = "call-method";
+ prom_args.nargs = 3;
+ prom_args.nret = 2;
+ prom_args.args[0] = "instantiate-rtas";
+ prom_args.args[1] = prom_rtas;
+ prom_args.args[2] = (void *) rtas_data;
+ prom(&prom_args);
+ i = 0;
+ if (prom_args.args[3] == 0)
+ i = (unsigned int)prom_args.args[4];
+ rtas_entry = i;
+ if ((rtas_entry == -1) || (rtas_entry == 0))
+ prom_print(" failed\n");
+ else
+ prom_print(" done\n");
+}
+
+/*
+ * We enter here early on, when the Open Firmware prom is still
+ * handling exceptions and the MMU hash table for us.
+ */
+unsigned long __init
+prom_init(int r3, int r4, prom_entry pp)
+{
+ unsigned long mem;
+ ihandle prom_mmu;
+ unsigned long offset = reloc_offset();
+ int i, l;
+ char *p, *d;
+ unsigned long phys;
+ void *result[3];
+
+ /* Default */
+ phys = (unsigned long) &_stext;
+
+ /* First get a handle for the stdout device */
+ prom = pp;
+ prom_chosen = call_prom("finddevice", 1, 1,
+ "/chosen");
+ if (prom_chosen == (void *)-1)
+ prom_exit();
+ if ((int) call_prom("getprop", 4, 1, prom_chosen,
+ "stdout", &prom_stdout,
+ sizeof(prom_stdout)) <= 0)
+ prom_exit();
+
+ /* Get the full OF pathname of the stdout device */
+ mem = (unsigned long) klimit + offset;
+ p = (char *) mem;
+ memset(p, 0, 256);
+ call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
+ of_stdout_device = p;
+ mem += strlen(p) + 1;
+
+ /* Get the boot device and translate it to a full OF pathname. */
+ p = (char *) mem;
+ l = (int) call_prom("getprop", 4, 1, prom_chosen,
+ "bootpath", p, 1<<20);
+ if (l > 0) {
+ p[l] = 0; /* should already be null-terminated */
+ bootpath = PTRUNRELOC(p);
+ mem += l + 1;
+ d = (char *) mem;
+ *d = 0;
+ call_prom("canon", 3, 1, p, d, 1<<20);
+ bootdevice = PTRUNRELOC(d);
+ mem = ALIGN(mem + strlen(d) + 1);
+ }
+
+ prom_instantiate_rtas();
+
+ mem = check_display(mem);
+
+ prom_print("copying OF device tree...");
+ mem = copy_device_tree(mem, mem + (1<<20));
+ prom_print("done\n");
+
+ prom_hold_cpus(mem);
+
+ klimit = (char *) (mem - offset);
+
+ /* If we are already running at 0xc0000000, we assume we were
+ * loaded by an OF bootloader which did set a BAT for us.
+ * This breaks OF translate so we force phys to be 0.
+ */
+ if (offset == 0)
+ phys = 0;
+ else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",
+ &prom_mmu, sizeof(prom_mmu)) <= 0) {
+ prom_print(" no MMU found\n");
+ } else if ((int)call_prom_ret("call-method", 4, 4, result, "translate",
+ prom_mmu, &_stext, 1) != 0) {
+ prom_print(" (translate failed)\n");
+ } else {
+ /* We assume the phys. address size is 3 cells */
+ phys = (unsigned long)result[2];
+ }
+
+ if (prom_disp_node != 0)
+ setup_disp_fake_bi(prom_disp_node);
+
+ /* Use quiesce call to get OF to shut down any devices it's using */
+ prom_print("Calling quiesce ...\n");
+ call_prom("quiesce", 0, 0);
+
+ /* Relocate various pointers which will be used once the
+ kernel is running at the address it was linked at. */
+ for (i = 0; i < prom_num_displays; ++i)
+ prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
+
+ prom_print("returning 0x");
+ prom_print_hex(phys);
+ prom_print("from prom_init\n");
+ prom_stdout = 0;
+
+ return phys;
+}
+
+/*
+ * early_get_property is used to access the device tree image prepared
+ * by BootX very early on, before the pointers in it have been relocated.
+ */
+static void * __init
+early_get_property(unsigned long base, unsigned long node, char *prop)
+{
+ struct device_node *np = (struct device_node *)(base + node);
+ struct property *pp;
+
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ pp = (struct property *) (base + (unsigned long)pp);
+ if (strcmp((char *)((unsigned long)pp->name + base),
+ prop) == 0) {
+ return (void *)((unsigned long)pp->value + base);
+ }
+ }
+ return 0;
+}
+
+/* Is boot-info compatible ? */
+#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
+#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
+#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
+
+void __init
+bootx_init(unsigned long r4, unsigned long phys)
+{
+ boot_infos_t *bi = (boot_infos_t *) r4;
+ unsigned long space;
+ unsigned long ptr, x;
+ char *model;
+
+ boot_infos = PTRUNRELOC(bi);
+ if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
+ bi->logicalDisplayBase = 0;
+
+#ifdef CONFIG_BOOTX_TEXT
+ btext_init(bi);
+
+ /*
+ * Test if boot-info is compatible. Done only in config
+ * CONFIG_BOOTX_TEXT since there is nothing much we can do
+ * with an incompatible version, except display a message
+ * and eventually hang the processor...
+ *
+ * I'll try to keep enough of boot-info compatible in the
+ * future to always allow display of this message;
+ */
+ if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
+ btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
+ btext_flushscreen();
+ }
+#endif /* CONFIG_BOOTX_TEXT */
+
+ /* New BootX enters kernel with MMU off, i/os are not allowed
+ here. This hack will have been done by the boostrap anyway.
+ */
+ if (bi->version < 4) {
+ /*
+ * XXX If this is an iMac, turn off the USB controller.
+ */
+ model = (char *) early_get_property
+ (r4 + bi->deviceTreeOffset, 4, "model");
+ if (model
+ && (strcmp(model, "iMac,1") == 0
+ || strcmp(model, "PowerMac1,1") == 0)) {
+ out_le32((unsigned *)0x80880008, 1); /* XXX */
+ }
+ }
+
+ /* Move klimit to enclose device tree, args, ramdisk, etc... */
+ if (bi->version < 5) {
+ space = bi->deviceTreeOffset + bi->deviceTreeSize;
+ if (bi->ramDisk)
+ space = bi->ramDisk + bi->ramDiskSize;
+ } else
+ space = bi->totalParamsSize;
+ klimit = PTRUNRELOC((char *) bi + space);
+
+ /* New BootX will have flushed all TLBs and enters kernel with
+ MMU switched OFF, so this should not be useful anymore.
+ */
+ if (bi->version < 4) {
+ /*
+ * Touch each page to make sure the PTEs for them
+ * are in the hash table - the aim is to try to avoid
+ * getting DSI exceptions while copying the kernel image.
+ */
+ for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
+ ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
+ x = *(volatile unsigned long *)ptr;
+ }
+
+#ifdef CONFIG_BOOTX_TEXT
+ /*
+ * Note that after we call btext_prepare_BAT, we can't do
+ * prom_draw*, flushscreen or clearscreen until we turn the MMU
+ * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
+ * to a virtual address.
+ */
+ btext_prepare_BAT();
+#endif
+}
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
index 993068c91ce2..f806de5d7184 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/ppc/kernel/ptrace.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.ptrace.c 1.8 07/07/01 17:00:08 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/arch/ppc/kernel/ptrace.c
@@ -71,6 +71,64 @@ static inline int put_reg(struct task_struct *task, int regno,
return -EIO;
}
+#ifdef CONFIG_ALTIVEC
+/*
+ * Get contents of AltiVec register state in task TASK
+ */
+static inline int get_vrregs(unsigned long *data, struct task_struct *task)
+{
+ int i, j;
+
+ if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
+ return -EFAULT;
+
+ /* copy AltiVec registers VR[0] .. VR[31] */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 4; j++, data++)
+ if (__put_user(task->thread.vr[i].u[j], data))
+ return -EFAULT;
+
+ /* copy VSCR */
+ for (i = 0; i < 4; i++, data++)
+ if (__put_user(task->thread.vscr.u[i], data))
+ return -EFAULT;
+
+ /* copy VRSAVE */
+ if (__put_user(task->thread.vrsave, data))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Write contents of AltiVec register state into task TASK.
+ */
+static inline int set_vrregs(struct task_struct *task, unsigned long *data)
+{
+ int i, j;
+
+ if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
+ return -EFAULT;
+
+ /* copy AltiVec registers VR[0] .. VR[31] */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 4; j++, data++)
+ if (__get_user(task->thread.vr[i].u[j], data))
+ return -EFAULT;
+
+ /* copy VSCR */
+ for (i = 0; i < 4; i++, data++)
+ if (__get_user(task->thread.vscr.u[i], data))
+ return -EFAULT;
+
+ /* copy VRSAVE */
+ if (__get_user(task->thread.vrsave, data))
+ return -EFAULT;
+
+ return 0;
+}
+#endif
+
static inline void
set_single_step(struct task_struct *task)
{
@@ -132,14 +190,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_attach(child);
goto out_tsk;
}
- ret = -ESRCH;
- if (!(child->ptrace & PT_PTRACED))
- goto out_tsk;
- if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- goto out_tsk;
- }
- if (child->p_pptr != current)
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
goto out_tsk;
switch (request) {
@@ -219,10 +272,17 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
- if (request == PTRACE_SYSCALL)
- child->ptrace |= PT_TRACESYS;
- else
- child->ptrace &= ~PT_TRACESYS;
+ if (request == PTRACE_SYSCALL) {
+ if (!(child->ptrace & PT_SYSCALLTRACE)) {
+ child->ptrace |= PT_SYSCALLTRACE;
+ child->work.syscall_trace++;
+ }
+ } else {
+ if (child->ptrace & PT_SYSCALLTRACE) {
+ child->ptrace &= ~PT_SYSCALLTRACE;
+ child->work.syscall_trace--;
+ }
+ }
child->exit_code = data;
/* make sure the single step bit is not set. */
clear_single_step(child);
@@ -251,7 +311,10 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
- child->ptrace &= ~PT_TRACESYS;
+ if (child->ptrace & PT_SYSCALLTRACE) {
+ child->ptrace &= ~PT_SYSCALLTRACE;
+ child->work.syscall_trace--;
+ }
set_single_step(child);
child->exit_code = data;
/* give it a chance to run. */
@@ -264,6 +327,24 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data);
break;
+#ifdef CONFIG_ALTIVEC
+ case PTRACE_GETVRREGS:
+ /* Get the child altivec register state. */
+ if (child->thread.regs->msr & MSR_VEC)
+ giveup_altivec(child);
+ ret = get_vrregs((unsigned long *)data, child);
+ break;
+
+ case PTRACE_SETVRREGS:
+ /* Set the child altivec register state. */
+ /* this is to clear the MSR_VEC bit to force a reload
+ * of register state from memory */
+ if (child->thread.regs->msr & MSR_VEC)
+ giveup_altivec(child);
+ ret = set_vrregs(child, (unsigned long *)data);
+ break;
+#endif
+
default:
ret = -EIO;
break;
@@ -275,10 +356,10 @@ out:
return ret;
}
-void syscall_trace(void)
+void do_syscall_trace(void)
{
- if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
- != (PT_PTRACED|PT_TRACESYS))
+ if ((current->ptrace & (PT_PTRACED|PT_SYSCALLTRACE))
+ != (PT_PTRACED|PT_SYSCALLTRACE))
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
diff --git a/arch/ppc/kernel/qspan_pci.c b/arch/ppc/kernel/qspan_pci.c
index f5d19ff85a18..49dc9c04586b 100644
--- a/arch/ppc/kernel/qspan_pci.c
+++ b/arch/ppc/kernel/qspan_pci.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.qspan_pci.c 1.5 05/17/01 18:14:22 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* QSpan pci routines.
@@ -29,8 +29,7 @@
#include <asm/mpc8xx.h>
#include <asm/system.h>
#include <asm/machdep.h>
-
-#include "pci.h"
+#include <asm/pci-bridge.h>
/*
diff --git a/arch/ppc/kernel/residual.c b/arch/ppc/kernel/residual.c
deleted file mode 100644
index cae870a305ca..000000000000
--- a/arch/ppc/kernel/residual.c
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * BK Id: SCCS/s.residual.c 1.13 09/11/01 16:54:34 trini
- */
-/*
- * Code to deal with the PReP residual data.
- *
- * Written by: Cort Dougan (cort@cs.nmt.edu)
- * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
- *
- * This file is based on the following documentation:
- *
- * IBM Power Personal Systems Architecture
- * Residual Data
- * Document Number: PPS-AR-FW0001
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/string.h>
-#include <asm/residual.h>
-#include <asm/pnp.h>
-#include <asm/byteorder.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/blk.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#include <asm/sections.h>
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/ide.h>
-
-
-unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
-RESIDUAL *res = (RESIDUAL *)&__res;
-
-char * PnP_BASE_TYPES[] __initdata = {
- "Reserved",
- "MassStorageDevice",
- "NetworkInterfaceController",
- "DisplayController",
- "MultimediaController",
- "MemoryController",
- "BridgeController",
- "CommunicationsDevice",
- "SystemPeripheral",
- "InputDevice",
- "ServiceProcessor"
- };
-
-/* Device Sub Type Codes */
-
-unsigned char * PnP_SUB_TYPES[] __initdata = {
- "\001\000SCSIController",
- "\001\001IDEController",
- "\001\002FloppyController",
- "\001\003IPIController",
- "\001\200OtherMassStorageController",
- "\002\000EthernetController",
- "\002\001TokenRingController",
- "\002\002FDDIController",
- "\002\0x80OtherNetworkController",
- "\003\000VGAController",
- "\003\001SVGAController",
- "\003\002XGAController",
- "\003\200OtherDisplayController",
- "\004\000VideoController",
- "\004\001AudioController",
- "\004\200OtherMultimediaController",
- "\005\000RAM",
- "\005\001FLASH",
- "\005\200OtherMemoryDevice",
- "\006\000HostProcessorBridge",
- "\006\001ISABridge",
- "\006\002EISABridge",
- "\006\003MicroChannelBridge",
- "\006\004PCIBridge",
- "\006\005PCMCIABridge",
- "\006\006VMEBridge",
- "\006\200OtherBridgeDevice",
- "\007\000RS232Device",
- "\007\001ATCompatibleParallelPort",
- "\007\200OtherCommunicationsDevice",
- "\010\000ProgrammableInterruptController",
- "\010\001DMAController",
- "\010\002SystemTimer",
- "\010\003RealTimeClock",
- "\010\004L2Cache",
- "\010\005NVRAM",
- "\010\006PowerManagement",
- "\010\007CMOS",
- "\010\010OperatorPanel",
- "\010\011ServiceProcessorClass1",
- "\010\012ServiceProcessorClass2",
- "\010\013ServiceProcessorClass3",
- "\010\014GraphicAssist",
- "\010\017SystemPlanar",
- "\010\200OtherSystemPeripheral",
- "\011\000KeyboardController",
- "\011\001Digitizer",
- "\011\002MouseController",
- "\011\003TabletController",
- "\011\0x80OtherInputController",
- "\012\000GeneralMemoryController",
- NULL
-};
-
-/* Device Interface Type Codes */
-
-unsigned char * PnP_INTERFACES[] __initdata = {
- "\000\000\000General",
- "\001\000\000GeneralSCSI",
- "\001\001\000GeneralIDE",
- "\001\001\001ATACompatible",
-
- "\001\002\000GeneralFloppy",
- "\001\002\001Compatible765",
- "\001\002\002NS398_Floppy", /* NS Super I/O wired to use index
- register at port 398 and data
- register at port 399 */
- "\001\002\003NS26E_Floppy", /* Ports 26E and 26F */
- "\001\002\004NS15C_Floppy", /* Ports 15C and 15D */
- "\001\002\005NS2E_Floppy", /* Ports 2E and 2F */
- "\001\002\006CHRP_Floppy", /* CHRP Floppy in PR*P system */
-
- "\001\003\000GeneralIPI",
-
- "\002\000\000GeneralEther",
- "\002\001\000GeneralToken",
- "\002\002\000GeneralFDDI",
-
- "\003\000\000GeneralVGA",
- "\003\001\000GeneralSVGA",
- "\003\002\000GeneralXGA",
-
- "\004\000\000GeneralVideo",
- "\004\001\000GeneralAudio",
- "\004\001\001CS4232Audio", /* CS 4232 Plug 'n Play Configured */
-
- "\005\000\000GeneralRAM",
- /* This one is obviously wrong ! */
- "\005\000\000PCIMemoryController", /* PCI Config Method */
- "\005\000\001RS6KMemoryController", /* RS6K Config Method */
- "\005\001\000GeneralFLASH",
-
- "\006\000\000GeneralHostBridge",
- "\006\001\000GeneralISABridge",
- "\006\002\000GeneralEISABridge",
- "\006\003\000GeneralMCABridge",
- /* GeneralPCIBridge = 0, */
- "\006\004\000PCIBridgeDirect",
- "\006\004\001PCIBridgeIndirect",
- "\006\004\002PCIBridgeRS6K",
- "\006\005\000GeneralPCMCIABridge",
- "\006\006\000GeneralVMEBridge",
-
- "\007\000\000GeneralRS232",
- "\007\000\001COMx",
- "\007\000\002Compatible16450",
- "\007\000\003Compatible16550",
- "\007\000\004NS398SerPort", /* NS Super I/O wired to use index
- register at port 398 and data
- register at port 399 */
- "\007\000\005NS26ESerPort", /* Ports 26E and 26F */
- "\007\000\006NS15CSerPort", /* Ports 15C and 15D */
- "\007\000\007NS2ESerPort", /* Ports 2E and 2F */
-
- "\007\001\000GeneralParPort",
- "\007\001\001LPTx",
- "\007\001\002NS398ParPort", /* NS Super I/O wired to use index
- register at port 398 and data
- register at port 399 */
- "\007\001\003NS26EParPort", /* Ports 26E and 26F */
- "\007\001\004NS15CParPort", /* Ports 15C and 15D */
- "\007\001\005NS2EParPort", /* Ports 2E and 2F */
-
- "\010\000\000GeneralPIC",
- "\010\000\001ISA_PIC",
- "\010\000\002EISA_PIC",
- "\010\000\003MPIC",
- "\010\000\004RS6K_PIC",
-
- "\010\001\000GeneralDMA",
- "\010\001\001ISA_DMA",
- "\010\001\002EISA_DMA",
-
- "\010\002\000GeneralTimer",
- "\010\002\001ISA_Timer",
- "\010\002\002EISA_Timer",
- "\010\003\000GeneralRTC",
- "\010\003\001ISA_RTC",
-
- "\010\004\001StoreThruOnly",
- "\010\004\002StoreInEnabled",
- "\010\004\003RS6KL2Cache",
-
- "\010\005\000IndirectNVRAM", /* Indirectly addressed */
- "\010\005\001DirectNVRAM", /* Memory Mapped */
- "\010\005\002IndirectNVRAM24", /* Indirectly addressed - 24 bit */
-
- "\010\006\000GeneralPowerManagement",
- "\010\006\001EPOWPowerManagement",
- "\010\006\002PowerControl", // d1378
-
- "\010\007\000GeneralCMOS",
-
- "\010\010\000GeneralOPPanel",
- "\010\010\001HarddiskLight",
- "\010\010\002CDROMLight",
- "\010\010\003PowerLight",
- "\010\010\004KeyLock",
- "\010\010\005ANDisplay", /* AlphaNumeric Display */
- "\010\010\006SystemStatusLED", /* 3 digit 7 segment LED */
- "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system */
-
- "\010\011\000GeneralServiceProcessor",
- "\010\012\000GeneralServiceProcessor",
- "\010\013\000GeneralServiceProcessor",
-
- "\010\014\001TransferData",
- "\010\014\002IGMC32",
- "\010\014\003IGMC64",
-
- "\010\017\000GeneralSystemPlanar", /* 10/5/95 */
- NULL
- };
-
-static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
- unsigned char SubType) {
- unsigned char ** s=PnP_SUB_TYPES;
- while (*s && !((*s)[0]==BaseType
- && (*s)[1]==SubType)) s++;
- if (*s) return *s+2;
- else return("Unknown !");
-};
-
-static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
- unsigned char SubType,
- unsigned char Interface) {
- unsigned char ** s=PnP_INTERFACES;
- while (*s && !((*s)[0]==BaseType
- && (*s)[1]==SubType
- && (*s)[2]==Interface)) s++;
- if (*s) return *s+3;
- else return NULL;
-};
-
-static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
- int i, c;
- char decomp[4];
-#define p pkt->S14_Pack.S14_Data.S14_PPCPack
- switch(p.Type) {
- case 1:
- /* Decompress first 3 chars */
- c = *(unsigned short *)p.PPCData;
- decomp[0]='A'-1+((c>>10)&0x1F);
- decomp[1]='A'-1+((c>>5)&0x1F);
- decomp[2]='A'-1+(c&0x1F);
- decomp[3]=0;
- printk(" Chip identification: %s%4.4X\n",
- decomp, ld_le16((unsigned short *)(p.PPCData+2)));
- break;
- default:
- printk(" Small vendor item type 0x%2.2x, data (hex): ",
- p.Type);
- for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
- printk("\n");
- break;
- }
-#undef p
-}
-
-static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
- static const unsigned char * intlevel[] = {"high", "low"};
- static const unsigned char * intsense[] = {"edge", "level"};
-
- switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
- case PnPVersion:
- printk(" PnPversion 0x%x.%x\n",
- pkt->S1_Pack.Version[0], /* How to interpret version ? */
- pkt->S1_Pack.Version[1]);
- break;
-// case Logicaldevice:
- break;
-// case CompatibleDevice:
- break;
- case IRQFormat:
-#define p pkt->S4_Pack
- printk(" IRQ Mask 0x%4.4x, %s %s sensitive\n",
- ld_le16((unsigned short *)p.IRQMask),
- intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
- intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
-#undef p
- break;
- case DMAFormat:
-#define p pkt->S5_Pack
- printk(" DMA channel mask 0x%2.2x, info 0x%2.2x\n",
- p.DMAMask, p.DMAInfo);
-#undef p
- break;
- case StartDepFunc:
- printk("Start dependent function:\n");
- break;
- case EndDepFunc:
- printk("End dependent function\n");
- break;
- case IOPort:
-#define p pkt->S8_Pack
- printk(" Variable (%d decoded bits) I/O port\n"
- " from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
- p.IOInfo&ISAAddr16bit?16:10,
- ld_le16((unsigned short *)p.RangeMin),
- ld_le16((unsigned short *)p.RangeMax),
- p.IOAlign, p.IONum);
-#undef p
- break;
- case FixedIOPort:
-#define p pkt->S9_Pack
- printk(" Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
- (p.Range[1]<<8)|p.Range[0],
- ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
-#undef p
- break;
- case Res1:
- case Res2:
- case Res3:
- printk(" Undefined packet type %d!\n",
- tag_small_item_name(pkt->S1_Pack.Tag));
- break;
- case SmallVendorItem:
- printsmallvendor(pkt,size);
- break;
- default:
- printk(" Type 0x2.2x%d, size=%d\n",
- pkt->S1_Pack.Tag, size);
- break;
- }
-}
-
-static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
- static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
- static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
- static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
- static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
- static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
- static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
-
- int i;
- char tmpstr[30], *t;
-#define p pkt->L4_Pack.L4_Data.L4_PPCPack
- switch(p.Type) {
- case 2:
- printk(" %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
- ld_le32((unsigned int *)p.PPCData),
- L2type[p.PPCData[10]-1],
- L2assoc[p.PPCData[4]-1],
- ld_le16((unsigned short *)p.PPCData+3),
- ld_le16((unsigned short *)p.PPCData+4));
- break;
- case 3:
- printk(" PCI Bridge parameters\n"
- " ConfigBaseAddress %0x\n"
- " ConfigBaseData %0x\n"
- " Bus number %d\n",
- ld_le32((unsigned int *)p.PPCData),
- ld_le32((unsigned int *)(p.PPCData+8)),
- p.PPCData[16]);
- for(i=20; i<size-4; i+=12) {
- int j, first;
- if(p.PPCData[i]) printk(" PCI Slot %d", p.PPCData[i]);
- else printk (" Integrated PCI device");
- for(j=0, first=1, t=tmpstr; j<4; j++) {
- int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
- if(line!=0xffff){
- if(first) first=0; else *t++='/';
- *t++='A'+j;
- }
- }
- *t='\0';
- printk(" DevFunc 0x%x interrupt line(s) %s routed to",
- p.PPCData[i+1],tmpstr);
- sprintf(tmpstr,
- inttype[p.PPCData[i+2]-1],
- p.PPCData[i+3]);
- printk(" %s line(s) ",
- tmpstr);
- for(j=0, first=1, t=tmpstr; j<4; j++) {
- int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
- if(line!=0xffff){
- if(first) first=0; else *t++='/';
- t+=sprintf(t,"%d(%c)",
- line&0x7fff,
- line&0x8000?'E':'L');
- }
- }
- printk("%s\n",tmpstr);
- }
- break;
- case 5:
- printk(" Bridge address translation, %s decoding:\n"
- " Processor Bus Size Conversion Translation\n"
- " 0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
- p.PPCData[0]&1 ? "positive" : "subtractive",
- ld_le32((unsigned int *)p.PPCData+1),
- ld_le32((unsigned int *)p.PPCData+3),
- ld_le32((unsigned int *)p.PPCData+5),
- convtype[p.PPCData[2]-1],
- transtype[p.PPCData[1]-1]);
- break;
- case 6:
- printk(" Bus speed %d Hz, %d slot(s)\n",
- ld_le32((unsigned int *)p.PPCData),
- p.PPCData[4]);
- break;
- case 7:
- printk(" SCSI buses: %d, id(s):", p.PPCData[0]);
- for(i=1; i<=p.PPCData[0]; i++)
- printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
- break;
- case 9:
- printk(" %s address (%d bits), at 0x%x size 0x%x bytes\n",
- addrtype[p.PPCData[0]-1],
- p.PPCData[1],
- ld_le32((unsigned int *)(p.PPCData+4)),
- ld_le32((unsigned int *)(p.PPCData+12)));
- break;
- case 10:
- sprintf(tmpstr,
- inttype[p.PPCData[0]-1],
- p.PPCData[1]);
-
- printk(" ISA interrupts routed to %s\n"
- " lines",
- tmpstr);
- for(i=0; i<16; i++) {
- int line=ld_le16((unsigned short *)p.PPCData+i+1);
- if (line!=0xffff) printk(" %d(IRQ%d)", line, i);
- }
- printk("\n");
- break;
- default:
- printk(" Large vendor item type 0x%2.2x\n Data (hex):",
- p.Type);
- for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
- printk("\n");
-#undef p
- }
-}
-
-static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
- switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
- case LargeVendorItem:
- printlargevendor(pkt, size);
- break;
- default:
- printk(" Type 0x2.2x%d, size=%d\n",
- pkt->S1_Pack.Tag, size);
- break;
- }
-}
-static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
- if (pkt->S1_Pack.Tag== END_TAG) {
- printk(" No packets describing %s resources.\n", cat);
- return;
- }
- printk( " Packets describing %s resources:\n",cat);
- do {
- int size;
- if (tag_type(pkt->S1_Pack.Tag)) {
- size= 3 +
- pkt->L1_Pack.Count0 +
- pkt->L1_Pack.Count1*256;
- printlargepacket(pkt, size);
- } else {
- size=tag_small_count(pkt->S1_Pack.Tag)+1;
- printsmallpacket(pkt, size);
- }
- (unsigned char *) pkt+=size;
- } while (pkt->S1_Pack.Tag != END_TAG);
-}
-
-void __init print_residual_device_info(void)
-{
- int i;
- PPC_DEVICE *dev;
-#define did dev->DeviceId
-
- /* make sure we have residual data first */
- if ( res->ResidualLength == 0 )
- return;
-
- printk("Residual: %ld devices\n", res->ActualNumDevices);
- for ( i = 0;
- i < res->ActualNumDevices ;
- i++)
- {
- char decomp[4], sn[20];
- const char * s;
- dev = &res->Devices[i];
- s = PnP_INTERFACE_STR(did.BaseType, did.SubType,
- did.Interface);
- if(!s) {
- sprintf(sn, "interface %d", did.Interface);
- s=sn;
- }
- if ( did.BusId & PCIDEVICE )
- printk("PCI Device, Bus %d, DevFunc 0x%x:",
- dev->BusAccess.PCIAccess.BusNumber,
- dev->BusAccess.PCIAccess.DevFuncNumber);
- if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:");
- if ( did.BusId & ISADEVICE )
- printk("ISA Device, Slot %d, LogicalDev %d:",
- dev->BusAccess.ISAAccess.SlotNumber,
- dev->BusAccess.ISAAccess.LogicalDevNumber);
- if ( did.BusId & EISADEVICE ) printk("EISA Device:");
- if ( did.BusId & PROCESSORDEVICE )
- printk("ProcBus Device, Bus %d, BUID %d: ",
- dev->BusAccess.ProcBusAccess.BusNumber,
- dev->BusAccess.ProcBusAccess.BUID);
- if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA ");
- if ( did.BusId & VMEDEVICE ) printk("VME ");
- if ( did.BusId & MCADEVICE ) printk("MCA ");
- if ( did.BusId & MXDEVICE ) printk("MX ");
- /* Decompress first 3 chars */
- decomp[0]='A'-1+((did.DevId>>26)&0x1F);
- decomp[1]='A'-1+((did.DevId>>21)&0x1F);
- decomp[2]='A'-1+((did.DevId>>16)&0x1F);
- decomp[3]=0;
- printk(" %s%4.4lX, %s, %s, %s\n",
- decomp, did.DevId&0xffff,
- PnP_BASE_TYPES[did.BaseType],
- PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
- s);
- if ( dev->AllocatedOffset )
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->AllocatedOffset],
- "allocated");
- if ( dev->PossibleOffset )
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->PossibleOffset],
- "possible");
- if ( dev->CompatibleOffset )
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->CompatibleOffset],
- "compatible");
- }
-}
-
-
-#if 0
-static void __init printVPD(void) {
-#define vpd res->VitalProductData
- int ps=vpd.PageSize, i, j;
- static const char* Usage[]={
- "FirmwareStack", "FirmwareHeap", "FirmwareCode", "BootImage",
- "Free", "Unpopulated", "ISAAddr", "PCIConfig",
- "IOMemory", "SystemIO", "SystemRegs", "PCIAddr",
- "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other"
- };
- static const unsigned char *FWMan[]={
- "IBM", "Motorola", "FirmWorks", "Bull"
- };
- static const unsigned char *FWFlags[]={
- "Conventional", "OpenFirmware", "Diagnostics", "LowDebug",
- "MultiBoot", "LowClient", "Hex41", "FAT",
- "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path"
- };
- static const unsigned char *ESM[]={
- "Port92", "PCIConfigA8", "FF001030", "????????"
- };
- static const unsigned char *SIOM[]={
- "Port850", "????????", "PCIConfigA8", "????????"
- };
-
- printk("Model: %s\n",vpd.PrintableModel);
- printk("Serial: %s\n", vpd.Serial);
- printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]);
- printk("FirmwareFlags:");
- for(j=0; j<12; j++) {
- if (vpd.FirmwareSupports & (1<<j)) {
- printk(" %s%c", FWFlags[j],
- vpd.FirmwareSupports&(-2<<j) ? ',' : '\n');
- }
- }
- printk("NVRamSize: %ld\n", vpd.NvramSize);
- printk("SIMMslots: %ld\n", vpd.NumSIMMSlots);
- printk("EndianSwitchMethod: %s\n",
- ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]);
- printk("SpreadIOMethod: %s\n",
- SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]);
- printk("Processor/Bus frequencies (Hz): %ld/%ld\n",
- vpd.ProcessorHz, vpd.ProcessorBusHz);
- printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor);
- printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps);
- printk("Cache sector size, Lock granularity: %ld, %ld\n",
- vpd.CoherenceBlockSize, vpd.GranuleSize);
- for (i=0; i<res->ActualNumMemSegs; i++) {
- int mask=res->Segs[i].Usage, first, j;
- printk("%8.8lx-%8.8lx ",
- res->Segs[i].BasePage*ps,
- (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1);
- for(j=15, first=1; j>=0; j--) {
- if (mask&(1<<j)) {
- if (first) first=0;
- else printk(", ");
- printk("%s", Usage[j]);
- }
- }
- printk("\n");
- }
-}
-
-/*
- * Spit out some info about residual data
- */
-void print_residual_device_info(void)
-{
- int i;
- union _PnP_TAG_PACKET *pkt;
- PPC_DEVICE *dev;
-#define did dev->DeviceId
-
- /* make sure we have residual data first */
- if ( res->ResidualLength == 0 )
- return;
- printk("Residual: %ld devices\n", res->ActualNumDevices);
- for ( i = 0;
- i < res->ActualNumDevices ;
- i++)
- {
- dev = &res->Devices[i];
- /*
- * pci devices
- */
- if ( did.BusId & PCIDEVICE )
- {
- printk("PCI Device:");
- /* unknown vendor */
- if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
- printk(" id %08lx types %d/%d", did.DevId,
- did.BaseType, did.SubType);
- /* known vendor */
- else
- printk(" %s %s",
- pci_strvendor(did.DevId>>16),
- pci_strdev(did.DevId>>16,
- did.DevId&0xffff)
- );
-
- if ( did.BusId & PNPISADEVICE )
- {
- printk(" pnp:");
- /* get pnp info on the device */
- pkt = (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->AllocatedOffset];
- for (; pkt->S1_Pack.Tag != DF_END_TAG;
- pkt++ )
- {
- if ( (pkt->S1_Pack.Tag == S4_Packet) ||
- (pkt->S1_Pack.Tag == S4_Packet_flags) )
- printk(" irq %02x%02x",
- pkt->S4_Pack.IRQMask[0],
- pkt->S4_Pack.IRQMask[1]);
- }
- }
- printk("\n");
- continue;
- }
- /*
- * isa devices
- */
- if ( did.BusId & ISADEVICE )
- {
- printk("ISA Device: basetype: %d subtype: %d",
- did.BaseType, did.SubType);
- printk("\n");
- continue;
- }
- /*
- * eisa devices
- */
- if ( did.BusId & EISADEVICE )
- {
- printk("EISA Device: basetype: %d subtype: %d",
- did.BaseType, did.SubType);
- printk("\n");
- continue;
- }
- /*
- * proc bus devices
- */
- if ( did.BusId & PROCESSORDEVICE )
- {
- printk("ProcBus Device: basetype: %d subtype: %d",
- did.BaseType, did.SubType);
- printk("\n");
- continue;
- }
- /*
- * pcmcia devices
- */
- if ( did.BusId & PCMCIADEVICE )
- {
- printk("PCMCIA Device: basetype: %d subtype: %d",
- did.BaseType, did.SubType);
- printk("\n");
- continue;
- }
- printk("Unknown bus access device: busid %lx\n",
- did.BusId);
- }
-}
-#endif
-
-/* Returns the device index in the residual data,
- any of the search items may be set as -1 for wildcard,
- DevID number field (second halfword) is big endian !
-
- Examples:
- - search for the Interrupt controller (8259 type), 2 methods:
- 1) i8259 = residual_find_device(~0,
- NULL,
- SystemPeripheral,
- ProgrammableInterruptController,
- ISA_PIC,
- 0);
- 2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0)
-
- - search for the first two serial devices, whatever their type)
- iserial1 = residual_find_device(~0,NULL,
- CommunicationsDevice,
- RS232Device,
- -1, 0)
- iserial2 = residual_find_device(~0,NULL,
- CommunicationsDevice,
- RS232Device,
- -1, 1)
- - but search for typical COM1 and COM2 is not easy due to the
- fact that the interface may be anything and the name "PNP0500" or
- "PNP0501". Quite bad.
-
-*/
-
-/* devid are easier to uncompress than to compress, so to minimize bloat
-in this rarely used area we unencode and compare */
-
-/* in residual data number is big endian in the device table and
-little endian in the heap, so we use two parameters to avoid writing
-two very similar functions */
-
-static int __init same_DevID(unsigned short vendor,
- unsigned short Number,
- char * str)
-{
- static unsigned const char hexdigit[]="0123456789ABCDEF";
- if (strlen(str)!=7) return 0;
- if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0]) &&
- ( ((vendor>>5)&0x1f)+'A'-1 == str[1]) &&
- ( (vendor&0x1f)+'A'-1 == str[2]) &&
- (hexdigit[(Number>>12)&0x0f] == str[3]) &&
- (hexdigit[(Number>>8)&0x0f] == str[4]) &&
- (hexdigit[(Number>>4)&0x0f] == str[5]) &&
- (hexdigit[Number&0x0f] == str[6]) ) return 1;
- return 0;
-}
-
-PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
- unsigned char * DevID,
- int BaseType,
- int SubType,
- int Interface,
- int n)
-{
- int i;
- if ( !res->ResidualLength ) return NULL;
- for (i=0; i<res->ActualNumDevices; i++) {
-#define Dev res->Devices[i].DeviceId
- if ( (Dev.BusId&BusMask) &&
- (BaseType==-1 || Dev.BaseType==BaseType) &&
- (SubType==-1 || Dev.SubType==SubType) &&
- (Interface==-1 || Dev.Interface==Interface) &&
- (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
- Dev.DevId&0xffff, DevID)) &&
- !(n--) ) return res->Devices+i;
-#undef Dev
- }
- return 0;
-}
-
-PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
- unsigned short DevID,
- int BaseType,
- int SubType,
- int Interface,
- int n)
-{
- int i;
- if ( !res->ResidualLength ) return NULL;
- for (i=0; i<res->ActualNumDevices; i++) {
-#define Dev res->Devices[i].DeviceId
- if ( (Dev.BusId&BusMask) &&
- (BaseType==-1 || Dev.BaseType==BaseType) &&
- (SubType==-1 || Dev.SubType==SubType) &&
- (Interface==-1 || Dev.Interface==Interface) &&
- (DevID==0xffff || (Dev.DevId&0xffff) == DevID) &&
- !(n--) ) return res->Devices+i;
-#undef Dev
- }
- return 0;
-}
-
-PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
- unsigned packet_tag,
- int n)
-{
- unsigned mask, masked_tag, size;
- if(!p) return 0;
- if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
- masked_tag = packet_tag&mask;
- for(; *p != END_TAG; p+=size) {
- if ((*p & mask) == masked_tag && !(n--))
- return (PnP_TAG_PACKET *) p;
- if (tag_type(*p))
- size=ld_le16((unsigned short *)(p+1))+3;
- else
- size=tag_small_count(*p)+1;
- }
- return 0; /* not found */
-}
-
-PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
- unsigned packet_type,
- int n)
-{
- int next=0;
- while (p) {
- p = (unsigned char *) PnP_find_packet(p, 0x70, next);
- if (p && p[1]==packet_type && !(n--))
- return (PnP_TAG_PACKET *) p;
- next = 1;
- };
- return 0; /* not found */
-}
-
-PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
- unsigned packet_type,
- int n)
-{
- int next=0;
- while (p) {
- p = (unsigned char *) PnP_find_packet(p, 0x84, next);
- if (p && p[3]==packet_type && !(n--))
- return (PnP_TAG_PACKET *) p;
- next = 1;
- };
- return 0; /* not found */
-}
diff --git a/arch/ppc/kernel/semaphore.c b/arch/ppc/kernel/semaphore.c
index ac7589238ea2..5eb1ccbe4fae 100644
--- a/arch/ppc/kernel/semaphore.c
+++ b/arch/ppc/kernel/semaphore.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.semaphore.c 1.12 05/17/01 18:14:22 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* PowerPC-specific semaphore code.
@@ -39,6 +39,7 @@ static inline int __sem_update_count(struct semaphore *sem, int incr)
" srawi %1,%0,31\n"
" andc %1,%0,%1\n"
" add %1,%1,%4\n"
+ PPC405_ERR77(0,%3)
" stwcx. %1,0,%3\n"
" bne 1b"
: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index a8765201c99a..da82585918a1 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.setup.c 1.65 11/18/01 20:57:25 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Common prep/pmac/chrp boot and setup code.
@@ -29,35 +29,32 @@
#include <asm/smp.h>
#include <asm/elf.h>
#include <asm/cputable.h>
-#ifdef CONFIG_8xx
-#include <asm/mpc8xx.h>
-#include <asm/8xx_immap.h>
-#endif
-#ifdef CONFIG_8260
-#include <asm/mpc8260.h>
-#include <asm/immap_8260.h>
-#endif
-#ifdef CONFIG_4xx
-#include <asm/ppc4xx.h>
-#endif
#include <asm/bootx.h>
#include <asm/btext.h>
#include <asm/machdep.h>
-#include <asm/feature.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/pmac_feature.h>
+
+#if defined CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
extern void platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
extern void bootx_init(unsigned long r4, unsigned long phys);
-extern unsigned long reloc_offset(void);
extern void identify_cpu(unsigned long offset, unsigned long cpu);
extern void do_cpu_ftr_fixups(unsigned long offset);
+extern void reloc_got2(unsigned long offset);
#ifdef CONFIG_XMON
extern void xmon_map_scc(void);
#endif
+#ifdef CONFIG_KGDB
+extern void kgdb_map_scc(void);
+#endif
+
extern boot_infos_t *boot_infos;
char saved_command_line[256];
unsigned char aux_device_present;
@@ -69,8 +66,6 @@ unsigned long sysmap_size;
size value reported by the boot loader. */
unsigned int boot_mem_size;
-int parse_bootinfo(void);
-
unsigned long ISA_DMA_THRESHOLD;
unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
@@ -103,7 +98,8 @@ int dcache_bsize;
int icache_bsize;
int ucache_bsize;
-#ifdef CONFIG_VGA_CONSOLE
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_FB_VGA16) || \
+ defined(CONFIG_FB_VGA16_MODULE) || defined(CONFIG_FB_VESA)
struct screen_info screen_info = {
0, 25, /* orig-x, orig-y */
0, /* unused */
@@ -115,7 +111,7 @@ struct screen_info screen_info = {
1, /* orig-video-isVGA */
16 /* orig-video-points */
};
-#endif /* CONFIG_VGA_CONSOLE */
+#endif /* CONFIG_VGA_CONSOLE || CONFIG_FB_VGA16 || CONFIG_FB_VESA */
void machine_restart(char *cmd)
{
@@ -291,22 +287,22 @@ early_init(int r3, int r4, int r5)
do_cpu_ftr_fixups(offset);
#if defined(CONFIG_ALL_PPC)
+ reloc_got2(offset);
+
/* If we came here from BootX, clear the screen,
* set up some pointers and return. */
- if ((r3 == 0x426f6f58) && (r5 == 0)) {
+ if ((r3 == 0x426f6f58) && (r5 == 0))
bootx_init(r4, phys);
- return phys;
- }
-
- /* check if we're prep, return if we are */
- if ( *(unsigned long *)(0) == 0xdeadc0de )
- return phys;
- /*
+ /*
+ * don't do anything on prep
* for now, don't use bootinfo because it breaks yaboot 0.5
* and assume that if we didn't find a magic number, we have OF
*/
- phys = prom_init(r3, r4, (prom_entry)r5);
+ else if (*(unsigned long *)(0) != 0xdeadc0de)
+ phys = prom_init(r3, r4, (prom_entry)r5);
+
+ reloc_got2(-offset);
#endif
return phys;
@@ -343,14 +339,14 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
#ifdef CONFIG_BOOTX_TEXT
- extern boot_infos_t *disp_bi;
-
- if (disp_bi) {
+ if (boot_text_mapped) {
btext_clearscreen();
- btext_welcome(disp_bi);
+ btext_welcome();
}
#endif
+ parse_bootinfo(find_bootinfo());
+
/* if we didn't get any bootinfo telling us what we are... */
if (_machine == 0) {
/* prep boot loader tells us if we're prep or not */
@@ -409,15 +405,14 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
char *p;
#ifdef CONFIG_BLK_DEV_INITRD
- if (r3 && r4 && r4 != 0xdeadbeef)
- {
- if (r3 < KERNELBASE)
- r3 += KERNELBASE;
- initrd_start = r3;
- initrd_end = r3 + r4;
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- initrd_below_start_ok = 1;
- }
+ if (r3 && r4 && r4 != 0xdeadbeef) {
+ if (r3 < KERNELBASE)
+ r3 += KERNELBASE;
+ initrd_start = r3;
+ initrd_end = r3 + r4;
+ ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0);
+ initrd_below_start_ok = 1;
+ }
#endif
chosen = find_devices("chosen");
if (chosen != NULL) {
@@ -429,6 +424,12 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
}
}
cmd_line[sizeof(cmd_line) - 1] = 0;
+#ifdef CONFIG_ADB
+ if (strstr(cmd_line, "adb_sync")) {
+ extern int __adb_probe_sync;
+ __adb_probe_sync = 1;
+ }
+#endif /* CONFIG_ADB */
switch (_machine) {
case _MACH_Pmac:
@@ -441,7 +442,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
}
#endif /* CONFIG_ALL_PPC */
-int parse_bootinfo(void)
+struct bi_record *find_bootinfo(void)
{
struct bi_record *rec;
extern char __bss_start[];
@@ -455,11 +456,16 @@ int parse_bootinfo(void)
*/
rec = (struct bi_record *)_ALIGN((ulong)__bss_start+0x10000+(1<<20)-1,(1<<20));
if ( rec->tag != BI_FIRST )
- return -1;
+ return NULL;
}
- for ( ; rec->tag != BI_LAST ;
- rec = (struct bi_record *)((ulong)rec + rec->size) )
- {
+ return rec;
+}
+
+void parse_bootinfo(struct bi_record *rec)
+{
+ if (rec == NULL || rec->tag != BI_FIRST)
+ return;
+ while (rec->tag != BI_LAST) {
ulong *data = rec->data;
switch (rec->tag) {
case BI_CMD_LINE:
@@ -485,9 +491,8 @@ int parse_bootinfo(void)
boot_mem_size = data[0];
break;
}
+ rec = (struct bi_record *)((ulong)rec + rec->size);
}
-
- return 0;
}
/*
@@ -504,8 +509,6 @@ machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, CONFIG_CMDLINE);
#endif /* CONFIG_CMDLINE */
- parse_bootinfo();
-
platform_init(r3, r4, r5, r6, r7);
if (ppc_md.progress)
@@ -525,7 +528,7 @@ int __init ppc_setup_l2cr(char *str)
}
__setup("l2cr=", ppc_setup_l2cr);
-void __init ppc_init(void)
+int __init ppc_init(void)
{
/* clear the progress line */
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
@@ -533,9 +536,10 @@ void __init ppc_init(void)
if (ppc_md.init != NULL) {
ppc_md.init();
}
+ init_crc32();
}
-subsys_initcall(ppc_init);
+arch_initcall(ppc_init);
/* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p)
@@ -549,8 +553,13 @@ void __init setup_arch(char **cmdline_p)
loops_per_jiffy = 500000000 / HZ;
#ifdef CONFIG_ALL_PPC
- feature_init();
-#endif
+ /* This could be called "early setup arch", it must be done
+ * now because xmon need it
+ */
+ if (_machine == _MACH_Pmac)
+ pmac_feature_init(); /* New cool way */
+#endif /* CONFIG_ALL_PPC */
+
#ifdef CONFIG_XMON
xmon_map_scc();
if (strstr(cmd_line, "xmon"))
@@ -561,7 +570,12 @@ void __init setup_arch(char **cmdline_p)
#if defined(CONFIG_KGDB)
kgdb_map_scc();
set_debug_traps();
- breakpoint();
+ if (strstr(cmd_line, "nokgdb"))
+ printk("kgdb default breakpoint deactivated on command line\n");
+ else {
+ printk("kgdb default breakpoint activated\n");
+ breakpoint();
+ }
#endif
/*
@@ -596,24 +610,6 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
-#if defined(CONFIG_PCI) && defined(CONFIG_ALL_PPC)
- /* We create the "pci-OF-bus-map" property now so it appear in the
- * /proc device tree
- */
- if (have_of) {
- struct property* of_prop;
-
- of_prop = (struct property*)alloc_bootmem(sizeof(struct property) + 256);
- if (of_prop && find_path_device("/")) {
- memset(of_prop, -1, sizeof(struct property) + 256);
- of_prop->name = "pci-OF-bus-map";
- of_prop->length = 256;
- of_prop->value = (unsigned char *)&of_prop[1];
- prom_add_property(find_path_device("/"), of_prop);
- }
- }
-#endif /* CONFIG_PCI && CONFIG_ALL_PPC */
-
paging_init();
sort_exception_table();
@@ -621,6 +617,7 @@ void __init setup_arch(char **cmdline_p)
ppc_md.ppc_machine = _machine;
}
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
/* Convert the shorts/longs in hd_driveid from little to big endian;
* chars are endian independant, of course, but strings need to be flipped.
* (Despite what it says in drivers/block/ide.h, they come up as little
@@ -715,3 +712,4 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
id->integrity_word = __le16_to_cpu(id->integrity_word);
}
+#endif
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 58ad86fa0c53..394d8abb05dc 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.signal.c 1.7 05/17/01 18:14:22 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/arch/ppc/kernel/signal.c
@@ -29,6 +29,7 @@
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/elf.h>
+#include <linux/tty.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -180,7 +181,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
siginitset(&new_ka.sa.sa_mask, mask);
}
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+ ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL));
if (!ret && oact) {
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
@@ -254,6 +255,8 @@ int sys_rt_sigreturn(struct pt_regs *regs)
current->blocked = set;
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
rt_sf++; /* Look at next rt_sigframe */
if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) {
@@ -263,8 +266,6 @@ int sys_rt_sigreturn(struct pt_regs *regs)
* see handle_signal()
*/
sr = (struct sigregs *) sigctx.regs;
- if (regs->msr & MSR_FP )
- giveup_fpu(current);
if (copy_from_user(saved_regs, &sr->gp_regs,
sizeof(sr->gp_regs)))
goto badframe;
@@ -298,6 +299,7 @@ int sys_rt_sigreturn(struct pt_regs *regs)
if (get_user(prevsp, &sr->gp_regs[PT_R1])
|| put_user(prevsp, (unsigned long *) regs->gpr[1]))
goto badframe;
+ current->thread.fpscr = 0;
}
return ret;
@@ -328,6 +330,7 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
goto badframe;
flush_icache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[2]);
+ current->thread.fpscr = 0; /* turn off all fp exceptions */
/* Retrieve rt_sigframe from stack and
set up registers for signal handler
@@ -379,13 +382,13 @@ int sys_sigreturn(struct pt_regs *regs)
current->blocked = set;
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);
sc++; /* Look at next sigcontext */
if (sc == (struct sigcontext_struct *)(sigctx.regs)) {
/* Last stacked signal - restore registers */
sr = (struct sigregs *) sigctx.regs;
- if (regs->msr & MSR_FP )
- giveup_fpu(current);
if (copy_from_user(saved_regs, &sr->gp_regs,
sizeof(sr->gp_regs)))
goto badframe;
@@ -413,6 +416,7 @@ int sys_sigreturn(struct pt_regs *regs)
if (get_user(prevsp, &sr->gp_regs[PT_R1])
|| put_user(prevsp, (unsigned long *) regs->gpr[1]))
goto badframe;
+ current->thread.fpscr = 0;
}
return ret;
@@ -431,8 +435,8 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe;
- if (regs->msr & MSR_FP)
- giveup_fpu(current);
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
|| __copy_to_user(&frame->fp_regs, current->thread.fpr,
ELF_NFPREG * sizeof(double))
@@ -441,6 +445,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
goto badframe;
flush_icache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[2]);
+ current->thread.fpscr = 0; /* turn off all fp exceptions */
newsp -= __SIGNAL_FRAMESIZE;
if (put_user(regs->gpr[1], (unsigned long *)newsp)
diff --git a/arch/ppc/kernel/sleep.S b/arch/ppc/kernel/sleep.S
deleted file mode 100644
index 153e358c124a..000000000000
--- a/arch/ppc/kernel/sleep.S
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * BK Id: SCCS/s.sleep.S 1.13 08/19/01 22:23:04 paulus
- */
-/*
- * This file contains sleep low-level functions for PowerBook G3.
- * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
- * and Paul Mackerras (paulus@samba.org).
- *
- * 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.tmpl"
-#include <asm/processor.h>
-#include <asm/page.h>
-
-#define MAGIC 0x4c617273 /* 'Lars' */
-
-/*
- * Structure for storing CPU registers on the stack.
- */
-#define SL_SP 0
-#define SL_PC 4
-#define SL_MSR 8
-#define SL_SDR1 0xc
-#define SL_SPRG0 0x10 /* 4 sprg's */
-#define SL_DBAT0 0x20
-#define SL_IBAT0 0x28
-#define SL_DBAT1 0x30
-#define SL_IBAT1 0x38
-#define SL_DBAT2 0x40
-#define SL_IBAT2 0x48
-#define SL_DBAT3 0x50
-#define SL_IBAT3 0x58
-#define SL_TB 0x60
-#define SL_HID0 0x68
-#define SL_R2 0x6c
-#define SL_R12 0x70 /* r12 to r31 */
-#define SL_SIZE (SL_R12 + 80)
-
-#define tophys(rd,rs) addis rd,rs,-KERNELBASE@h
-#define tovirt(rd,rs) addis rd,rs,KERNELBASE@h
-
- .text
- .align 5
-
-/* This gets called by via-pmu.c late during the sleep process.
- * The PMU was already send the sleep command and will shut us down
- * soon. We need to save all that is needed and setup the wakeup
- * vector that will be called by the ROM on wakeup
- */
-_GLOBAL(low_sleep_handler)
- mflr r0
- stw r0,4(r1)
- stwu r1,-SL_SIZE(r1)
- stw r2,SL_R2(r1)
- stmw r12,SL_R12(r1)
-
- /* Save MSR & SDR1 */
- mfmsr r4
- stw r4,SL_MSR(r1)
- mfsdr1 r4
- stw r4,SL_SDR1(r1)
-
- /* Get a stable timebase and save it */
-1: mftbu r4
- stw r4,SL_TB(r1)
- mftb r5
- stw r5,SL_TB+4(r1)
- mftbu r3
- cmpw r3,r4
- bne 1b
-
- /* Save SPRGs */
- mfsprg r4,0
- stw r4,SL_SPRG0(r1)
- mfsprg r4,1
- stw r4,SL_SPRG0+4(r1)
- mfsprg r4,2
- stw r4,SL_SPRG0+8(r1)
- mfsprg r4,3
- stw r4,SL_SPRG0+12(r1)
-
- /* Save BATs */
- mfdbatu r4,0
- stw r4,SL_DBAT0(r1)
- mfdbatl r4,0
- stw r4,SL_DBAT0+4(r1)
- mfdbatu r4,1
- stw r4,SL_DBAT1(r1)
- mfdbatl r4,1
- stw r4,SL_DBAT1+4(r1)
- mfdbatu r4,2
- stw r4,SL_DBAT2(r1)
- mfdbatl r4,2
- stw r4,SL_DBAT2+4(r1)
- mfdbatu r4,3
- stw r4,SL_DBAT3(r1)
- mfdbatl r4,3
- stw r4,SL_DBAT3+4(r1)
- mfibatu r4,0
- stw r4,SL_IBAT0(r1)
- mfibatl r4,0
- stw r4,SL_IBAT0+4(r1)
- mfibatu r4,1
- stw r4,SL_IBAT1(r1)
- mfibatl r4,1
- stw r4,SL_IBAT1+4(r1)
- mfibatu r4,2
- stw r4,SL_IBAT2(r1)
- mfibatl r4,2
- stw r4,SL_IBAT2+4(r1)
- mfibatu r4,3
- stw r4,SL_IBAT3(r1)
- mfibatl r4,3
- stw r4,SL_IBAT3+4(r1)
-
- /* Save HID0 */
- mfspr r4,HID0
- stw r4,SL_HID0(r1)
-
- /* The ROM can wake us up via 2 different vectors:
- * - On wallstreet & lombard, we must write a magic
- * value 'Lars' at address 4 and a pointer to a
- * memory location containing the PC to resume from
- * at address 0.
- * - On Core99, we must store the wakeup vector at
- * address 0x80 and eventually it's parameters
- * at address 0x84. I've have some trouble with those
- * parameters however and I no longer use them.
- */
- lis r5,grackle_wake_up@ha
- addi r5,r5,grackle_wake_up@l
- tophys(r5,r5)
- stw r5,SL_PC(r1)
- lis r4,KERNELBASE@h
- tophys(r5,r1)
- addi r5,r5,SL_PC
- lis r6,MAGIC@ha
- addi r6,r6,MAGIC@l
- stw r5,0(r4)
- stw r6,4(r4)
- /* Setup stuffs at 0x80-0x84 for Core99 */
- lis r3,core99_wake_up@ha
- addi r3,r3,core99_wake_up@l
- tophys(r3,r3)
- stw r3,0x80(r4)
- stw r5,0x84(r4)
- /* Store a pointer to our backup storage into
- * a kernel global
- */
- lis r3,sleep_storage@ha
- addi r3,r3,sleep_storage@l
- stw r5,0(r3)
-
-
-/*
- * Flush the L1 data cache by reading the first 128kB of RAM
- * and then flushing the same area with the dcbf instruction.
- * The L2 cache has already been disabled.
- */
- li r4,0x1000 /* 128kB / 32B */
- mtctr r4
- lis r4,KERNELBASE@h
-1:
- lwz r0,0(r4)
- addi r4,r4,0x0020 /* Go to start of next cache line */
- bdnz 1b
- sync
-
- li r4,0x1000 /* 128kB / 32B */
- mtctr r4
- lis r4,KERNELBASE@h
-1:
- dcbf r0,r4
- addi r4,r4,0x0020 /* Go to start of next cache line */
- bdnz 1b
- sync
-
-/*
- * Set the HID0 and MSR for sleep.
- */
- mfspr r2,HID0
- rlwinm r2,r2,0,10,7 /* clear doze, nap */
- oris r2,r2,HID0_SLEEP@h
- sync
- mtspr HID0,r2
- sync
-
-/* This loop puts us back to sleep in case we have a spurrious
- * wakeup so that the host bridge properly stays asleep. The
- * CPU will be turned off, either after a known time (about 1
- * second) on wallstreet & lombard, or as soon as the CPU enters
- * SLEEP mode on core99
- */
- mfmsr r2
- oris r2,r2,MSR_POW@h
-1: sync
- mtmsr r2
- isync
- b 1b
-
-/*
- * Here is the resume code.
- */
-
-
-/*
- * Core99 machines resume here
- * r4 has the physical address of SL_PC(sp) (unused)
- */
-_GLOBAL(core99_wake_up)
- /* Make sure HID0 no longer contains any sleep bit */
- mfspr r3,HID0
- rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */
- mtspr HID0,r3
- sync
- isync
-
- /* Won't that cause problems on CPU that doesn't support it ? */
- lis r3, 0
- mtspr SPRN_MMCR0, r3
-
- /* sanitize MSR */
- mfmsr r3
- ori r3,r3,MSR_EE|MSR_IP
- xori r3,r3,MSR_EE|MSR_IP
- sync
- isync
- mtmsr r3
- sync
- isync
-
- /* Recover sleep storage */
- lis r3,sleep_storage@ha
- addi r3,r3,sleep_storage@l
- tophys(r3,r3)
- lwz r1,0(r3)
-
- /* Pass thru to older resume code ... */
-/*
- * Here is the resume code for older machines.
- * r1 has the physical address of SL_PC(sp).
- */
-
-grackle_wake_up:
- /* Enable and then Flash inval the instruction & data cache */
- mfspr r3,HID0
- ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI
- sync
- isync
- mtspr HID0,r3
- xori r3,r3, HID0_ICFI|HID0_DCI
- mtspr HID0,r3
- sync
-
- /* Restore the remaining bits of the HID0 register. */
- subi r1,r1,SL_PC
- lwz r3,SL_HID0(r1)
- sync
- isync
- mtspr HID0,r3
- sync
- isync
-
- /* Restore the kernel's segment registers, the
- BATs, and SDR1. Then we can turn on the MMU. */
- li r0,16 /* load up segment register values */
- mtctr r0 /* for context 0 */
- lis r3,0x2000 /* Ku = 1, VSID = 0 */
- li r4,0
-3: mtsrin r3,r4
- addi r3,r3,0x111 /* increment VSID */
- addis r4,r4,0x1000 /* address of next segment */
- bdnz 3b
-
- lwz r4,SL_SDR1(r1)
- mtsdr1 r4
- lwz r4,SL_SPRG0(r1)
- mtsprg 0,r4
- lwz r4,SL_SPRG0+4(r1)
- mtsprg 1,r4
- lwz r4,SL_SPRG0+8(r1)
- mtsprg 2,r4
- lwz r4,SL_SPRG0+12(r1)
- mtsprg 3,r4
-
- lwz r4,SL_DBAT0(r1)
- mtdbatu 0,r4
- lwz r4,SL_DBAT0+4(r1)
- mtdbatl 0,r4
- lwz r4,SL_DBAT1(r1)
- mtdbatu 1,r4
- lwz r4,SL_DBAT1+4(r1)
- mtdbatl 1,r4
- lwz r4,SL_DBAT2(r1)
- mtdbatu 2,r4
- lwz r4,SL_DBAT2+4(r1)
- mtdbatl 2,r4
- lwz r4,SL_DBAT3(r1)
- mtdbatu 3,r4
- lwz r4,SL_DBAT3+4(r1)
- mtdbatl 3,r4
- lwz r4,SL_IBAT0(r1)
- mtibatu 0,r4
- lwz r4,SL_IBAT0+4(r1)
- mtibatl 0,r4
- lwz r4,SL_IBAT1(r1)
- mtibatu 1,r4
- lwz r4,SL_IBAT1+4(r1)
- mtibatl 1,r4
- lwz r4,SL_IBAT2(r1)
- mtibatu 2,r4
- lwz r4,SL_IBAT2+4(r1)
- mtibatl 2,r4
- lwz r4,SL_IBAT3(r1)
- mtibatu 3,r4
- lwz r4,SL_IBAT3+4(r1)
- mtibatl 3,r4
-
- /* Flush all TLBs */
- lis r4,0x1000
-1: addic. r4,r4,-0x1000
- tlbie r4
- blt 1b
- sync
-
- /* restore the MSR and turn on the MMU */
- lwz r3,SL_MSR(r1)
- bl turn_on_mmu
-
- /* get back the stack pointer */
- tovirt(r1,r1)
-
- /* Restore TB */
- li r3,0
- mttbl r3
- lwz r3,SL_TB(r1)
- lwz r4,SL_TB+4(r1)
- mttbu r3
- mttbl r4
-
- /* Restore the callee-saved registers and return */
- lwz r2,SL_R2(r1)
- lmw r12,SL_R12(r1)
- addi r1,r1,SL_SIZE
- lwz r0,4(r1)
- mtlr r0
- blr
-
-turn_on_mmu:
- mflr r4
- tovirt(r4,r4)
- mtsrr0 r4
- mtsrr1 r3
- sync
- isync
- rfi
-
- .data
- .globl sleep_storage
-sleep_storage:
- .long 0
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e5e3247924d3..221fee33e251 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.smp.c 1.34 10/11/01 12:06:01 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Smp support for ppc.
@@ -38,8 +38,6 @@
#include <asm/residual.h>
#include <asm/time.h>
-#include "open_pic.h"
-
int smp_threads_ready;
volatile int smp_commenced;
int smp_num_cpus = 1;
@@ -69,6 +67,10 @@ extern int cpu_idle(void *unused);
void smp_call_function_interrupt(void);
void smp_message_pass(int target, int msg, unsigned long data, int wait);
+#ifdef CONFIG_PPC_ISERIES
+extern void smp_iSeries_space_timers( unsigned nr );
+#endif
+
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
*
* Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
@@ -290,9 +292,7 @@ void __init smp_boot_cpus(void)
* cpu 0, the master -- Cort
*/
cpu_callin_map[0] = 1;
- current->processor = 0;
-
- init_idle();
+ current->cpu = 0;
for (i = 0; i < NR_CPUS; i++) {
prof_counter[i] = 1;
@@ -320,37 +320,26 @@ void __init smp_boot_cpus(void)
*/
if (cpu_nr > max_cpus)
cpu_nr = max_cpus;
+#ifdef CONFIG_PPC_ISERIES
+ smp_iSeries_space_timers( cpu_nr );
+#endif
for (i = 1; i < cpu_nr; i++) {
int c;
struct pt_regs regs;
/* create a process for the processor */
- /* we don't care about the values in regs since we'll
- never reschedule the forked task. */
- /* We DO care about one bit in the pt_regs we
- pass to do_fork. That is the MSR_FP bit in
- regs.msr. If that bit is on, then do_fork
- (via copy_thread) will call giveup_fpu.
- giveup_fpu will get a pointer to our (current's)
- last register savearea via current->thread.regs
- and using that pointer will turn off the MSR_FP,
- MSR_FE0 and MSR_FE1 bits. At this point, this
- pointer is pointing to some arbitrary point within
- our stack. */
-
+ /* only regs.msr is actually used, and 0 is OK for it */
memset(&regs, 0, sizeof(struct pt_regs));
-
if (do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0) < 0)
panic("failed fork for CPU %d", i);
p = init_task.prev_task;
if (!p)
panic("No idle task for CPU %d", i);
- del_from_runqueue(p);
+ init_idle(p, i);
unhash_process(p);
- init_tasks[i] = p;
- p->processor = i;
- p->cpus_runnable = 1 << i; /* we schedule the first task manually */
+ p->cpu = i;
+ p->cpus_allowed = 1 << i; /* we schedule the first task manually */
current_set[i] = p;
/*
@@ -507,8 +496,6 @@ void __init smp_callin(void)
smp_ops->setup_cpu(cpu);
- init_idle();
-
/*
* This cpu is now "online". Only set them online
* before they enter the loop below since write access
diff --git a/arch/ppc/kernel/softemu8xx.c b/arch/ppc/kernel/softemu8xx.c
index f71da553e183..40a17dc20219 100644
--- a/arch/ppc/kernel/softemu8xx.c
+++ b/arch/ppc/kernel/softemu8xx.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.softemu8xx.c 1.8 05/17/01 18:14:22 cort
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Software emulation of some PPC instructions for the 8xx core.
@@ -35,6 +35,11 @@
#include <asm/io.h>
#include <asm/processor.h>
+extern void
+print_8xx_pte(struct mm_struct *mm, unsigned long addr);
+extern int
+get_8xx_pte(struct mm_struct *mm, unsigned long addr);
+
/* Eventually we may need a look-up table, but this works for now.
*/
#define LFS 48
@@ -117,7 +122,7 @@ Soft_emulate_8xx(struct pt_regs *regs)
default:
retval = 1;
printk("Bad emulation %s/%d\n"
- " NIP: %08x instruction: %08x opcode: %x "
+ " NIP: %08lx instruction: %08x opcode: %x "
"A: %x B: %x C: %x code: %x rc: %x\n",
current->comm,current->pid,
regs->nip,
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 381f1833339c..260345226022 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.time.c 1.26 10/05/01 08:29:42 trini
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* Common time routines among all ppc machines.
@@ -87,6 +87,11 @@ unsigned tb_last_stamp;
extern unsigned long wall_jiffies;
+#ifdef CONFIG_PPC_ISERIES
+extern u64 get_tb64(void);
+extern u64 next_jiffy_update_tb[];
+#endif
+
static long time_offset;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -106,6 +111,8 @@ static inline int tb_delta(unsigned *jiffy_stamp) {
return delta;
}
+#ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_time.c */
+
extern unsigned long prof_cpu_mask;
extern unsigned int * prof_buffer;
extern unsigned long prof_len;
@@ -181,7 +188,7 @@ int timer_interrupt(struct pt_regs * regs)
* We should have an rtc call that only sets the minutes and
* seconds like on Intel to avoid problems with non UTC clocks.
*/
- if ( (time_status & STA_UNSYNC) == 0 &&
+ if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
xtime.tv_sec - last_rtc_update >= 659 &&
abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ &&
jiffies - wall_jiffies == 1) {
@@ -211,6 +218,7 @@ int timer_interrupt(struct pt_regs * regs)
return 1; /* lets ret_from_int know we can do checks */
}
+#endif /* CONFIG_PPC_ISERIES */
/*
* This version of gettimeofday has microsecond resolution.
@@ -223,7 +231,11 @@ void do_gettimeofday(struct timeval *tv)
read_lock_irqsave(&xtime_lock, flags);
sec = xtime.tv_sec;
usec = xtime.tv_usec;
+#ifdef CONFIG_PPC_ISERIES
+ delta = tb_ticks_per_jiffy - ( next_jiffy_update_tb[0] - get_tb64() );
+#else
delta = tb_ticks_since(tb_last_stamp);
+#endif
#ifdef CONFIG_SMP
/* As long as timebases are not in sync, gettimeofday can only
* have jiffy resolution on SMP.
@@ -354,11 +366,10 @@ void __init time_init(void)
}
}
-#define TICK_SIZE tick
-#define FEBRUARY 2
-#define STARTOFTIME 1970
-#define SECDAY 86400L
-#define SECYR (SECDAY * 365)
+#define FEBRUARY 2
+#define STARTOFTIME 1970
+#define SECDAY 86400L
+#define SECYR (SECDAY * 365)
#define leapyear(year) ((year) % 4 == 0)
#define days_in_year(a) (leapyear(a) ? 366 : 365)
#define days_in_month(a) (month_days[(a) - 1])
@@ -367,55 +378,12 @@ static int month_days[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
-/*
- * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
- */
-void GregorianDay(struct rtc_time * tm)
-{
- int leapsToDate;
- int lastYear;
- int day;
- int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-
- lastYear=tm->tm_year-1;
-
- /*
- * Number of leap corrections to apply up to end of last year
- */
- leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
-
- /*
- * This year is a leap year if it is divisible by 4 except when it is
- * divisible by 100 unless it is divisible by 400
- *
- * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
- */
- if((tm->tm_year%4==0) &&
- ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
- (tm->tm_mon>2))
- {
- /*
- * We are past Feb. 29 in a leap year
- */
- day=1;
- }
- else
- {
- day=0;
- }
-
- day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
- tm->tm_mday;
-
- tm->tm_wday=day%7;
-}
-
void to_tm(int tim, struct rtc_time * tm)
{
- register int i;
- register long hms, day;
+ register int i;
+ register long hms, day, gday;
- day = tim / SECDAY;
+ gday = day = tim / SECDAY;
hms = tim % SECDAY;
/* Hours, minutes, seconds are easy */
@@ -440,9 +408,9 @@ void to_tm(int tim, struct rtc_time * tm)
tm->tm_mday = day + 1;
/*
- * Determine the day of week
+ * Determine the day of week. Jan. 1, 1970 was a Thursday.
*/
- GregorianDay(tm);
+ tm->tm_wday = (gday + 4) % 7;
}
/* Auxiliary function to compute scaling factors */
diff --git a/arch/ppc/kernel/todc_time.c b/arch/ppc/kernel/todc_time.c
new file mode 100644
index 000000000000..9591c7ee0eef
--- /dev/null
+++ b/arch/ppc/kernel/todc_time.c
@@ -0,0 +1,456 @@
+/*
+ * arch/ppc/kernel/todc_time.c
+ *
+ * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
+ * Real Time Clocks/Timekeepers.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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 <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/timex.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 mv146818), and set
+ * 'nvram_data' to the address of the 8-bit data register.
+ *
+ * You also need to set 'ppc_md.nvram_read_val' and 'ppc_md.nvram_write_val' to
+ * the proper routines. There are standard ones defined further down in
+ * this file that you can use.
+ *
+ * There is a built in assumption that the RTC and NVRAM are accessed by the
+ * same mechanism (i.e., ppc_md.nvram_read_val, etc works for both).
+ *
+ * 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(todc_info->nvram_data + addr);
+}
+
+void
+todc_direct_write_val(int addr, unsigned char val)
+{
+ writeb(val, 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(addr, todc_info->nvram_as0);
+ return inb(todc_info->nvram_data);
+}
+
+void
+todc_mc146818_write_val(int addr, unsigned char val)
+{
+ outb(addr, todc_info->nvram_as0);
+ outb(val, todc_info->nvram_data);
+ return;
+}
+
+/*
+ * 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)
+{
+ static u_char not_initialized = 1;
+
+ /* Make sure clocks are running */
+ if (not_initialized) {
+ u_char cntl_b;
+
+ cntl_b = ppc_md.nvram_read_val(todc_info->control_b);
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ if ((cntl_b & 0x70) != 0x20) {
+ printk(KERN_INFO "TODC %s %s\n",
+ "real-time-clock was stopped.",
+ "Now starting...");
+ cntl_b &= ~0x70;
+ cntl_b |= 0x20;
+ }
+
+ ppc_md.nvram_write_val(todc_info->control_b, cntl_b);
+ }
+ 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 = ppc_md.nvram_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;
+ ppc_md.nvram_write_val(todc_info->month, month);
+ }
+
+ cntl_b &= ~TODC_DS1501_CNTL_B_TE;
+ ppc_md.nvram_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 = ppc_md.nvram_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 */
+
+ ppc_md.nvram_write_val(todc_info->control_a,
+ cntl_a);
+ ppc_md.nvram_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);
+ ppc_md.nvram_write_val(todc_info->control_a, cntl_a);
+ }
+
+ not_initialized = 0;
+ }
+
+
+ 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.
+ */
+ulong
+todc_get_rtc_time(void)
+{
+ uint year, mon, day, hour, min, sec;
+ uint limit, i;
+ u_char save_control, uip;
+
+ save_control = ppc_md.nvram_read_val(todc_info->control_a);
+
+ if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+ limit = 1;
+
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ break;
+ default:
+ ppc_md.nvram_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 = ppc_md.nvram_read_val(todc_info->RTC_FREQ_SELECT);
+ }
+
+ sec = ppc_md.nvram_read_val(todc_info->seconds) & 0x7f;
+ min = ppc_md.nvram_read_val(todc_info->minutes) & 0x7f;
+ hour = ppc_md.nvram_read_val(todc_info->hours) & 0x3f;
+ day = ppc_md.nvram_read_val(todc_info->day_of_month) & 0x3f;
+ mon = ppc_md.nvram_read_val(todc_info->month) & 0x1f;
+ year = ppc_md.nvram_read_val(todc_info->year) & 0xff;
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ uip |= ppc_md.nvram_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_DS1557:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ break;
+ default:
+ save_control &= ~(todc_info->enable_read);
+ ppc_md.nvram_write_val(todc_info->control_a,
+ save_control);
+ }
+ }
+
+ 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(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
+ year = year + 1900;
+ if (year < 1970) {
+ year += 100;
+ }
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+int
+todc_set_rtc_time(unsigned long nowtime)
+{
+ struct rtc_time tm;
+ u_char save_control, save_freq_select;
+
+ to_tm(nowtime, &tm);
+
+ save_control = ppc_md.nvram_read_val(todc_info->control_a);
+
+ /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
+ ppc_md.nvram_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 =
+ ppc_md.nvram_read_val(todc_info->RTC_FREQ_SELECT);
+ ppc_md.nvram_write_val(todc_info->RTC_FREQ_SELECT,
+ save_freq_select | RTC_DIV_RESET2);
+ }
+
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
+
+ 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);
+ }
+
+ ppc_md.nvram_write_val(todc_info->seconds, tm.tm_sec);
+ ppc_md.nvram_write_val(todc_info->minutes, tm.tm_min);
+ ppc_md.nvram_write_val(todc_info->hours, tm.tm_hour);
+ ppc_md.nvram_write_val(todc_info->month, tm.tm_mon);
+ ppc_md.nvram_write_val(todc_info->day_of_month, tm.tm_mday);
+ ppc_md.nvram_write_val(todc_info->year, tm.tm_year);
+
+ ppc_md.nvram_write_val(todc_info->control_a, save_control);
+
+ if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+ ppc_md.nvram_write_val(todc_info->RTC_FREQ_SELECT,
+ save_freq_select);
+ }
+
+ return 0;
+}
+
+/*
+ * Manipulates read bit to reliably read seconds at a high rate.
+ */
+static unsigned char __init todc_read_timereg(int addr)
+{
+ unsigned char save_control, val;
+
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ case TODC_TYPE_MC146818:
+ break;
+ default:
+ save_control =
+ ppc_md.nvram_read_val(todc_info->control_a);
+ ppc_md.nvram_write_val(todc_info->control_a,
+ (save_control | todc_info->enable_read));
+ }
+ val = ppc_md.nvram_read_val(addr);
+
+ switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1557:
+ case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
+ case TODC_TYPE_DS1747:
+ case TODC_TYPE_MC146818:
+ break;
+ default:
+ save_control &= ~(todc_info->enable_read);
+ ppc_md.nvram_write_val(todc_info->control_a,
+ save_control);
+ }
+
+ return val;
+}
+
+/*
+ * This was taken from prep_setup.c
+ * Use the NVRAM RTC to time a second to calibrate the decrementer.
+ */
+void __init
+todc_calibrate_decr(void)
+{
+ ulong freq;
+ ulong tbl, tbu;
+ long i, loop_count;
+ u_char sec;
+
+ todc_time_init();
+
+ /*
+ * Actually this is bad for precision, we should have a loop in
+ * which we only read the seconds counter. nvram_read_val writes
+ * the address bytes on every call and this takes a lot of time.
+ * Perhaps an nvram_wait_change method returning a time
+ * stamp with a loop count as parameter would be the solution.
+ */
+ /*
+ * Need to make sure the tbl doesn't roll over so if tbu increments
+ * during this test, we need to do it again.
+ */
+ loop_count = 0;
+
+ sec = todc_read_timereg(todc_info->seconds) & 0x7f;
+
+ do {
+ tbu = get_tbu();
+
+ for (i = 0 ; i < 10000000 ; i++) {/* may take up to 1 second */
+ tbl = get_tbl();
+
+ if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) {
+ break;
+ }
+ }
+
+ sec = todc_read_timereg(todc_info->seconds) & 0x7f;
+
+ for (i = 0 ; i < 10000000 ; i++) { /* Should take 1 second */
+ freq = get_tbl();
+
+ if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) {
+ break;
+ }
+ }
+
+ freq -= tbl;
+ } while ((get_tbu() != tbu) && (++loop_count < 2));
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq/1000000, freq%1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ return;
+}
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index fdd5289bebbf..c2265a8afcc8 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.traps.c 1.22 10/11/01 10:33:09 paulus
+ * BK Id: %F% %I% %G% %U% %#%
*/
/*
* linux/arch/ppc/kernel/traps.c
@@ -38,6 +38,9 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
extern int fix_alignment(struct pt_regs *);
extern void bad_page_fault(struct pt_regs *, unsigned long, int sig);
@@ -66,6 +69,13 @@ int (*debugger_sstep)(struct pt_regs *regs);
int (*debugger_iabr_match)(struct pt_regs *regs);
int (*debugger_dabr_match)(struct pt_regs *regs);
void (*debugger_fault_handler)(struct pt_regs *regs);
+#else
+#define debugger(regs) do { } while (0)
+#define debugger_bpt(regs) 0
+#define debugger_sstep(regs) 0
+#define debugger_iabr_match(regs) 0
+#define debugger_dabr_match(regs) 0
+#define debugger_fault_handler ((void (*)(struct pt_regs *))0)
#endif
#endif
@@ -74,15 +84,19 @@ void (*debugger_fault_handler)(struct pt_regs *regs);
*/
-spinlock_t oops_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
void die(const char * str, struct pt_regs * fp, long err)
{
console_verbose();
- spin_lock_irq(&oops_lock);
+ spin_lock_irq(&die_lock);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ set_backlight_enable(1);
+ set_backlight_level(BACKLIGHT_MAX);
+#endif
printk("Oops: %s, sig: %ld\n", str, err);
show_regs(fp);
- spin_unlock_irq(&oops_lock);
+ spin_unlock_irq(&die_lock);
/* do_exit() should take care of panic'ing from an interrupt
* context so we don't handle it here
*/
@@ -94,9 +108,7 @@ _exception(int signr, struct pt_regs *regs)
{
if (!user_mode(regs))
{
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
-#endif
die("Exception in kernel mode", regs, signr);
}
force_sig(signr, current);
@@ -111,7 +123,7 @@ MachineCheckException(struct pt_regs *regs)
unsigned long msr = regs->msr;
if (user_mode(regs)) {
- _exception(SIGSEGV, regs);
+ _exception(SIGSEGV, regs);
return;
}
@@ -120,12 +132,10 @@ MachineCheckException(struct pt_regs *regs)
bad_page_fault(regs, regs->dar, SIGBUS);
return;
#endif
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_fault_handler) {
debugger_fault_handler(regs);
return;
}
-#endif
#ifdef CONFIG_ALL_PPC
/*
@@ -135,7 +145,7 @@ MachineCheckException(struct pt_regs *regs)
* table.
* Note that the 601 only takes a machine check on TEA
* (transfer error ack) signal assertion, and does not
- * set of the top 16 bits of SRR1.
+ * set any of the top 16 bits of SRR1.
* -- paulus.
*/
if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
@@ -169,12 +179,13 @@ MachineCheckException(struct pt_regs *regs)
#endif /* CONFIG_ALL_PPC */
printk("Machine check in kernel mode.\n");
printk("Caused by (from SRR1=%lx): ", msr);
- switch (msr & 0xF0000) {
+ switch (msr & 0x601F0000) {
case 0x80000:
printk("Machine check signal\n");
break;
case 0: /* for 601 */
case 0x40000:
+ case 0x140000: /* 7450 MSS error and TEA */
printk("Transfer error ack signal\n");
break;
case 0x20000:
@@ -183,26 +194,30 @@ MachineCheckException(struct pt_regs *regs)
case 0x10000:
printk("Address parity error signal\n");
break;
+ case 0x20000000:
+ printk("L1 Data Cache error\n");
+ break;
+ case 0x40000000:
+ printk("L1 Instruction Cache error\n");
+ break;
+ case 0x00100000:
+ printk("L2 data cache parity error\n");
+ break;
default:
printk("Unknown values in msr\n");
}
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
-#endif
die("machine check", regs, SIGBUS);
}
void
SMIException(struct pt_regs *regs)
{
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
- {
- debugger(regs);
- return;
- }
-#endif
+ debugger(regs);
+#if !(defined(CONFIG_XMON) || defined(CONFIG_KGDB))
show_regs(regs);
panic("System Management Interrupt");
+#endif
}
void
@@ -210,23 +225,21 @@ UnknownException(struct pt_regs *regs)
{
printk("Bad trap at PC: %lx, SR: %lx, vector=%lx %s\n",
regs->nip, regs->msr, regs->trap, print_tainted());
- _exception(SIGTRAP, regs);
+ _exception(SIGTRAP, regs);
}
void
InstructionBreakpoint(struct pt_regs *regs)
{
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_iabr_match(regs))
return;
-#endif
_exception(SIGTRAP, regs);
}
void
RunModeException(struct pt_regs *regs)
{
- _exception(SIGTRAP, regs);
+ _exception(SIGTRAP, regs);
}
/* Illegal instruction emulation support. Originally written to
@@ -272,51 +285,54 @@ emulate_instruction(struct pt_regs *regs)
void
ProgramCheckException(struct pt_regs *regs)
{
+ int errcode;
+
#if defined(CONFIG_4xx)
unsigned int esr = mfspr(SPRN_ESR);
+ int isbpt = esr & ESR_PTR;
+ extern int do_mathemu(struct pt_regs *regs);
+
+ if (isbpt)
+ mtspr(SPRN_DBSR, DBSR_TIE);
+#ifdef CONFIG_MATH_EMULATION
+ if (!isbpt && do_mathemu(regs) == 0)
+ return;
+#endif /* CONFIG_MATH_EMULATION */
+
+#else /* ! CONFIG_4xx */
+ int isbpt = regs->msr & 0x20000;
- if (esr & ESR_PTR) {
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
- if (debugger_bpt(regs))
- return;
-#endif
- _exception(SIGTRAP, regs);
- } else {
- _exception(SIGILL, regs);
- }
-#else
if (regs->msr & 0x100000) {
/* IEEE FP exception */
_exception(SIGFPE, regs);
- } else if (regs->msr & 0x20000) {
+ return;
+ }
+#endif /* ! CONFIG_4xx */
+
+ if (isbpt) {
/* trap exception */
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_bpt(regs))
return;
-#endif
_exception(SIGTRAP, regs);
- } else {
- /* Try to emulate it if we should. */
- int errcode;
- if ((errcode = emulate_instruction(regs))) {
- if (errcode == -EFAULT)
- _exception(SIGBUS, regs);
- else
- _exception(SIGILL, regs);
- }
+ return;
+ }
+
+ /* Try to emulate it if we should. */
+ if ((errcode = emulate_instruction(regs))) {
+ if (errcode == -EFAULT)
+ _exception(SIGBUS, regs);
+ else
+ _exception(SIGILL, regs);
}
-#endif
}
void
SingleStepException(struct pt_regs *regs)
{
regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_sstep(regs))
return;
-#endif
- _exception(SIGTRAP, regs);
+ _exception(SIGTRAP, regs);
}
void
@@ -337,7 +353,7 @@ AlignmentException(struct pt_regs *regs)
bad_page_fault(regs, regs->dar, SIGSEGV);
return;
}
- _exception(SIGBUS, regs);
+ _exception(SIGBUS, regs);
}
void
@@ -345,9 +361,7 @@ StackOverflow(struct pt_regs *regs)
{
printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
current, regs->gpr[1]);
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
-#endif
show_regs(regs);
panic("kernel stack overflow");
}
@@ -365,20 +379,20 @@ void
SoftwareEmulation(struct pt_regs *regs)
{
extern int do_mathemu(struct pt_regs *);
+ extern int Soft_emulate_8xx(struct pt_regs *);
int errcode;
if (!user_mode(regs)) {
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
-#endif
die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
}
#ifdef CONFIG_MATH_EMULATION
- if ((errcode = do_mathemu(regs))) {
+ errcode = do_mathemu(regs);
#else
- if ((errcode = Soft_emulate_8xx(regs))) {
+ errcode = Soft_emulate_8xx(regs);
#endif
+ if (errcode) {
if (errcode > 0)
_exception(SIGFPE, regs);
else if (errcode == -EFAULT)
@@ -387,7 +401,36 @@ SoftwareEmulation(struct pt_regs *regs)
_exception(SIGILL, regs);
}
}
-#endif
+#endif /* CONFIG_8xx */
+
+#if defined(CONFIG_4xx)
+
+void DebugException(struct pt_regs *regs)
+{
+ unsigned long debug_status;
+
+ debug_status = mfspr(SPRN_DBSR);
+
+ regs->msr &= ~MSR_DE; /* Turn off 'debug' bit */
+ if (debug_status & DBSR_TIE) { /* trap instruction*/
+
+ mtspr(SPRN_DBSR, DBSR_TIE);
+
+ if (!user_mode(regs) && debugger_bpt(regs))
+ return;
+ _exception(SIGTRAP, regs);
+
+ } else if (debug_status & DBSR_IC) { /* instruction completion */
+
+ mtspr(SPRN_DBSR, DBSR_IC);
+ regs->dbcr0 &= ~DBCR0_IC;
+
+ if (!user_mode(regs) && debugger_sstep(regs))
+ return;
+ _exception(SIGTRAP, regs);
+ }
+}
+#endif /* CONFIG_4xx */
#if !defined(CONFIG_TAU_INT)
void
diff --git a/arch/ppc/kernel/walnut_setup.c b/arch/ppc/kernel/walnut_setup.c
deleted file mode 100644
index 99bdcf7a38f1..000000000000
--- a/arch/ppc/kernel/walnut_setup.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * BK Id: SCCS/s.walnut_setup.c 1.10 11/13/01 21:26:07 paulus
- */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-#include <linux/seq_file.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include <asm/time.h>
-#include "walnut_setup.h"
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init walnut_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = walnut_setup_arch;
- ppc_md.show_percpuinfo = walnut_show_percpuinfo;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = walnut_init_IRQ;
- ppc_md.get_irq = walnut_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = walnut_restart;
- ppc_md.power_off = walnut_power_off;
- ppc_md.halt = walnut_halt;
-
- ppc_md.time_init = walnut_time_init;
- ppc_md.set_rtc_time = walnut_set_rtc_time;
- ppc_md.get_rtc_time = walnut_get_rtc_time;
- ppc_md.calibrate_decr = walnut_calibrate_decr;
-
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int walnut_show_percpuinfo()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-walnut_show_percpuinfo(struct seq_file *m)
-{
- bd_t *bp = (bd_t *)__res;
-
- seq_printf(m, "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return 0;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_init_IRQ(void)
-{
- int i;
-
- ppc4xx_pic_init();
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].handler = ppc4xx_pic;
- }
-
- return;
-}
-
-/*
- * Document me.
- */
-int
-walnut_get_irq(struct pt_regs *regs)
-{
- return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-walnut_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-walnut_power_off(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-walnut_halt(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-long __init
-walnut_time_init(void)
-{
- /* XXX - Implement me */
- return 0;
-}
-
-/*
- * Document me.
- */
-int __init
-walnut_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-walnut_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init walnut_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
diff --git a/arch/ppc/kernel/walnut_setup.h b/arch/ppc/kernel/walnut_setup.h
deleted file mode 100644
index 2c142f031ebd..000000000000
--- a/arch/ppc/kernel/walnut_setup.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * BK Id: SCCS/s.walnut_setup.h 1.5 05/17/01 18:14:22 cort
- */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __WALNUT_SETUP_H__
-#define __WALNUT_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void walnut_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void walnut_setup_arch(void);
-extern int walnut_setup_residual(char *buffer);
-extern void walnut_init_IRQ(void);
-extern int walnut_get_irq(struct pt_regs *regs);
-extern void walnut_restart(char *cmd);
-extern void walnut_power_off(void);
-extern void walnut_halt(void);
-extern void walnut_time_init(void);
-extern int walnut_set_rtc_time(unsigned long now);
-extern unsigned long walnut_get_rtc_time(void);
-extern void walnut_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __WALNUT_SETUP_H__ */
diff --git a/arch/ppc/kernel/xics.c b/arch/ppc/kernel/xics.c
deleted file mode 100644
index 7b3f047cccaf..000000000000
--- a/arch/ppc/kernel/xics.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * BK Id: SCCS/s.xics.c 1.5 05/17/01 18:14:22 cort
- */
-/*
- * arch/ppc/kernel/xics.c
- *
- * Copyright 2000 IBM Corporation.
- *
- * 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 <linux/config.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/prom.h>
-#include <asm/io.h>
-#include "i8259.h"
-#include "xics.h"
-
-void xics_enable_irq(u_int irq);
-void xics_disable_irq(u_int irq);
-void xics_mask_and_ack_irq(u_int irq);
-void xics_end_irq(u_int irq);
-
-struct hw_interrupt_type xics_pic = {
- " XICS ",
- NULL,
- NULL,
- xics_enable_irq,
- xics_disable_irq,
- xics_mask_and_ack_irq,
- xics_end_irq
-};
-
-struct hw_interrupt_type xics_8259_pic = {
- " XICS/8259",
- NULL,
- NULL,
- NULL,
- NULL,
- xics_mask_and_ack_irq,
- NULL
-};
-
-#define XICS_IPI 2
-#define XICS_IRQ_8259_CASCADE 0x2c
-#define XICS_IRQ_OFFSET 16
-#define XICS_IRQ_SPURIOUS 0
-
-#define DEFAULT_SERVER 0
-#define DEFAULT_PRIORITY 0
-
-struct xics_ipl {
- union {
- u32 word;
- u8 bytes[4];
- } xirr_poll;
- union {
- u32 word;
- u8 bytes[4];
- } xirr;
- u32 dummy;
- union {
- u32 word;
- u8 bytes[4];
- } qirr;
-};
-
-struct xics_info {
- volatile struct xics_ipl * per_cpu[NR_CPUS];
-};
-
-struct xics_info xics_info;
-
-#define xirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.word)
-#define cppr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.bytes[0])
-#define poll_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr_poll.word)
-#define qirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->qirr.bytes[0])
-
-void
-xics_enable_irq(
- u_int irq
- )
-{
- int status;
- int call_status;
-
- irq -= XICS_IRQ_OFFSET;
- if (irq == XICS_IPI)
- return;
- call_status = call_rtas("ibm,set-xive", 3, 1, (ulong*)&status,
- irq, DEFAULT_SERVER, DEFAULT_PRIORITY);
- if( call_status != 0 ) {
- printk("xics_enable_irq: irq=%x: call_rtas failed; retn=%x, status=%x\n",
- irq, call_status, status);
- return;
- }
-}
-
-void
-xics_disable_irq(
- u_int irq
- )
-{
- int status;
- int call_status;
-
- irq -= XICS_IRQ_OFFSET;
- call_status = call_rtas("ibm,int-off", 1, 1, (ulong*)&status, irq);
- if( call_status != 0 ) {
- printk("xics_disable_irq: irq=%x: call_rtas failed, retn=%x\n",
- irq, call_status);
- return;
- }
-}
-
-void
-xics_end_irq(
- u_int irq
- )
-{
- int cpu = smp_processor_id();
-
- cppr_info(cpu) = 0; /* actually the value overwritten by ack */
- xirr_info(cpu) = (0xff<<24) | (irq-XICS_IRQ_OFFSET);
-}
-
-void
-xics_mask_and_ack_irq(
- u_int irq
- )
-{
- int cpu = smp_processor_id();
-
- if( irq < XICS_IRQ_OFFSET ) {
- i8259_pic.ack(irq);
- xirr_info(cpu) = (0xff<<24) | XICS_IRQ_8259_CASCADE;
- }
- else {
- cppr_info(cpu) = 0xff;
- }
-}
-
-int
-xics_get_irq(struct pt_regs *regs)
-{
- u_int cpu = smp_processor_id();
- u_int vec;
- int irq;
-
- vec = xirr_info(cpu);
- /* (vec >> 24) == old priority */
- vec &= 0x00ffffff;
- /* for sanity, this had better be < NR_IRQS - 16 */
- if( vec == XICS_IRQ_8259_CASCADE )
- irq = i8259_irq(cpu);
- else if( vec == XICS_IRQ_SPURIOUS )
- irq = -1;
- else
- irq = vec + XICS_IRQ_OFFSET;
- return irq;
-}
-
-#ifdef CONFIG_SMP
-void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
-{
- qirr_info(smp_processor_id()) = 0xff;
- smp_message_recv(MSG_RESCHEDULE, regs);
-}
-
-void xics_cause_IPI(int cpu)
-{
- qirr_info(cpu) = 0;
-}
-
-void xics_setup_cpu(void)
-{
- int cpu = smp_processor_id();
-
- cppr_info(cpu) = 0xff;
-}
-#endif /* CONFIG_SMP */
-
-void
-xics_init_IRQ( void )
-{
- int i;
- extern unsigned long smp_chrp_cpu_nr;
-
-#ifdef CONFIG_SMP
- for (i = 0; i < smp_chrp_cpu_nr; ++i)
- xics_info.per_cpu[i] =
- ioremap(0xfe000000 + smp_hw_index[i] * 0x1000, 0x20);
-#else
- xics_info.per_cpu[0] = ioremap(0xfe000000, 0x20);
-#endif /* CONFIG_SMP */
- xics_8259_pic.enable = i8259_pic.enable;
- xics_8259_pic.disable = i8259_pic.disable;
- for (i = 0; i < 16; ++i)
- irq_desc[i].handler = &xics_8259_pic;
- for (; i < NR_IRQS; ++i)
- irq_desc[i].handler = &xics_pic;
-
- cppr_info(0) = 0xff;
- if (request_irq(XICS_IRQ_8259_CASCADE + XICS_IRQ_OFFSET, no_action,
- 0, "8259 cascade", 0))
- printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
- i8259_init();
-
-#ifdef CONFIG_SMP
- request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
-#endif
-}
diff --git a/arch/ppc/kernel/xics.h b/arch/ppc/kernel/xics.h
deleted file mode 100644
index dd0a591b834f..000000000000
--- a/arch/ppc/kernel/xics.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * BK Id: SCCS/s.xics.h 1.5 05/17/01 18:14:22 cort
- */
-/*
- * arch/ppc/kernel/xics.h
- *
- * Copyright 2000 IBM Corporation.
- *
- * 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.
- */
-
-#ifndef _PPC_KERNEL_XICS_H
-#define _PPC_KERNEL_XICS_H
-
-#include "local_irq.h"
-
-extern struct hw_interrupt_type xics_pic;
-extern struct hw_interrupt_type xics_8259_pic;
-
-void xics_init_IRQ(void);
-int xics_get_irq(struct pt_regs *);
-
-#endif /* _PPC_KERNEL_XICS_H */