summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-05-12 21:05:59 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-05-12 21:05:59 +0000
commitba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch)
tree78670a0139bf4d5ace617b29b7eba82bbc74d602 /arch/ppc/kernel
parentb77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff)
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile9
-rw-r--r--arch/ppc/kernel/align.c25
-rw-r--r--arch/ppc/kernel/feature.c69
-rw-r--r--arch/ppc/kernel/gemini_pci.c175
-rw-r--r--arch/ppc/kernel/gemini_setup.c223
-rw-r--r--arch/ppc/kernel/head.S25
-rw-r--r--arch/ppc/kernel/head_8xx.S176
-rw-r--r--arch/ppc/kernel/irq.c10
-rw-r--r--arch/ppc/kernel/m8260_setup.c303
-rw-r--r--arch/ppc/kernel/m8xx_setup.c1
-rw-r--r--arch/ppc/kernel/misc.S18
-rw-r--r--arch/ppc/kernel/pmac_nvram.c274
-rw-r--r--arch/ppc/kernel/pmac_pci.c23
-rw-r--r--arch/ppc/kernel/pmac_pic.c16
-rw-r--r--arch/ppc/kernel/pmac_setup.c11
-rw-r--r--arch/ppc/kernel/ppc-stub.c60
-rw-r--r--arch/ppc/kernel/ppc8260_pic.c111
-rw-r--r--arch/ppc/kernel/ppc8260_pic.h15
-rw-r--r--arch/ppc/kernel/ppc8xx_pic.c22
-rw-r--r--arch/ppc/kernel/ppc_htab.c2
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c35
-rw-r--r--arch/ppc/kernel/process.c4
-rw-r--r--arch/ppc/kernel/prom.c27
-rw-r--r--arch/ppc/kernel/qspan_pci.c2
-rw-r--r--arch/ppc/kernel/setup.c46
-rw-r--r--arch/ppc/kernel/totalmp.c109
-rw-r--r--arch/ppc/kernel/traps.c2
27 files changed, 1216 insertions, 577 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 73db2269e..ed16da557 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -31,7 +31,7 @@ CONFIG_CHRP=y
endif
O_OBJS := entry.o traps.o irq.o idle.o time.o process.o signal.o syscalls.o \
- misc.o bitops.o ptrace.o align.o ppc_htab.o semaphore.o
+ misc.o ptrace.o align.o ppc_htab.o semaphore.o bitops.o
ifndef CONFIG_8xx
O_OBJS += hashtable.o
@@ -45,10 +45,6 @@ ifdef CONFIG_KGDB
O_OBJS += ppc-stub.o
endif
-ifdef CONFIG_TOTALMP
-O_OBJS += totalmp.o
-endif
-
ifdef CONFIG_PMAC_PBOOK
O_OBJS += sleep.o
endif
@@ -100,6 +96,9 @@ endif
ifeq ($(CONFIG_GEMINI),y)
O_OBJS += gemini_prom.o gemini_pci.o gemini_setup.o open_pic.o
endif
+ifeq ($(CONFIG_8260),y)
+ O_OBJS += m8260_setup.o ppc8260_pic.o
+endif
all: $(KHEAD) kernel.o
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 7f6340261..5b7366adc 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/cache.h>
struct aligninfo {
unsigned char len;
@@ -38,6 +39,8 @@ struct aligninfo {
#define S 0x40 /* single-precision fp, or byte-swap value */
#define HARD 0x80 /* string, stwcx. */
+#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
+
/*
* The PowerPC stores certain bits of the instruction that caused the
* alignment exception in the DSISR register. This array maps those
@@ -220,9 +223,27 @@ fix_alignment(struct pt_regs *regs)
areg = regs->dsisr & 0x1f; /* register to update */
instr = (regs->dsisr >> 10) & 0x7f;
#endif
+
nb = aligninfo[instr].len;
- if (nb == 0)
- return 0; /* too hard or invalid instruction bits */
+ if (nb == 0) {
+ long *p;
+ int i;
+
+ if (instr != DCBZ)
+ return 0; /* too hard or invalid instruction */
+ /*
+ * The dcbz (data cache block zero) instruction
+ * gives an alignment fault if used on non-cacheable
+ * memory. We handle the fault mainly for the
+ * case when we are running with the cache disabled
+ * for debugging.
+ */
+ p = (long *) (regs->dar & -L1_CACHE_BYTES);
+ for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+ p[i] = 0;
+ return 1;
+ }
+
flags = aligninfo[instr].flags;
/* For the 4xx-family processors, the 'dar' field of the
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
index d5baa3747..e47befdd3 100644
--- a/arch/ppc/kernel/feature.c
+++ b/arch/ppc/kernel/feature.c
@@ -57,8 +57,8 @@ static fbit feature_bits_ohare_pbook[] = {
{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_Mediabay_IDE_enable */
- {0x38,1,OH_IDE1_RESET_N}, /* FEATURE_Mediabay_IDE_reset */
+ {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 */
@@ -68,6 +68,8 @@ static fbit feature_bits_ohare_pbook[] = {
{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 */
};
/* Those bits are from a PowerBook. It's possible that desktop machines
@@ -87,8 +89,8 @@ static fbit feature_bits_heathrow[] = {
{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_Mediabay_IDE_enable */
- {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_Mediabay_IDE_reset */
+ {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 */
@@ -98,9 +100,44 @@ static fbit feature_bits_heathrow[] = {
{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 */
};
-/* Those bits are from an iBook.
+/*
+ * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
+ * Mostly the same as the heathrow.
+ */
+static fbit feature_bits_paddington[] = {
+ {0x38,0,0}, /* FEATURE_null */
+ {0x38,0,0}, /* 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 */
+};
+
+/* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
*/
static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_null */
@@ -110,14 +147,14 @@ static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_Serial_IO_B */
{0x38,0,0}, /* FEATURE_SWIM3_enable */
{0x38,0,0}, /* FEATURE_MESH_enable */
- {0x38,0,0}, /* FEATURE_IDE0_enable */
- {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
+ {0x3c,0,0}, /* FEATURE_IDE0_enable */
+ {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
{0x38,0,0}, /* FEATURE_IOBUS_enable */
- {0x38,0,0}, /* FEATURE_Mediabay_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_power */
+ {0x34,1,0x00000200}, /* FEATURE_Mediabay_reset */
+ {0x34,1,0x00000400}, /* FEATURE_Mediabay_power */
{0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_enable */
- {0x3c,1,0x08000000}, /* FEATURE_Mediabay_IDE_reset */
+ {0x3c,0,0x0}, /* FEATURE_IDE1_enable */
+ {0x3c,1,0x08000000}, /* FEATURE_IDE1_reset */
{0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,0}, /* FEATURE_BMac_reset */
{0x38,0,0}, /* FEATURE_BMac_IO_enable */
@@ -127,6 +164,8 @@ static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x3c,1,0x40000000}, /* FEATURE_IDE2_reset */
+ {0x34,0,0x00001000}, /* FEATURE_Mediabay_IDE_switch */
+ {0x34,0,0x00000100}, /* FEATURE_Mediabay_content */
};
/* definition of a feature controller object */
@@ -164,6 +203,8 @@ feature_init(void)
*/
if (device_is_compatible(np, "Keylargo")) {
feature_add_controller(np, feature_bits_keylargo);
+ } else if (device_is_compatible(np, "paddington")) {
+ feature_add_controller(np, feature_bits_paddington);
} else {
feature_add_controller(np, feature_bits_heathrow);
}
@@ -268,6 +309,8 @@ feature_set(struct device_node* device, enum system_feature f)
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",
@@ -299,6 +342,8 @@ feature_clear(struct device_node* device, enum system_feature f)
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",
@@ -329,6 +374,8 @@ feature_test(struct device_node* device, enum system_feature f)
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",
diff --git a/arch/ppc/kernel/gemini_pci.c b/arch/ppc/kernel/gemini_pci.c
index fb80dc493..1ac83d1c8 100644
--- a/arch/ppc/kernel/gemini_pci.c
+++ b/arch/ppc/kernel/gemini_pci.c
@@ -77,178 +77,19 @@ gemini_pcibios_write_config_dword(unsigned char bus, unsigned char dev,
return PCIBIOS_SUCCESSFUL;
}
-struct gemini_device {
- unsigned short vendor, device;
- unsigned char irq;
- unsigned short cmd;
- unsigned char cache_line, latency;
- void (*init)(struct pci_dev *dev);
-};
-
-static struct gemini_device gemini_map[] = {
- { PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885, 11, 0x15, 32, 248, NULL },
- { PCI_VENDOR_ID_NCR, 0x701, 10, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 3, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_MPIC, 0xff, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_670, 0xff, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, 0xff, 0, 0, 0, NULL },
-};
-
-static int gemini_map_count = (sizeof( gemini_map ) /
- sizeof( gemini_map[0] ));
-
-
-
-/* This just sets up the known devices on the board. */
-static void __init mapin_device( struct pci_dev *dev )
-{
- struct gemini_device *p;
- unsigned short cmd;
- int i;
-
-
- for( i=0; i < gemini_map_count; i++ ) {
- p = &(gemini_map[i]);
-
- if ( p->vendor == dev->vendor &&
- p->device == dev->device ) {
-
- if (p->irq != 0xff) {
- pci_write_config_byte( dev, PCI_INTERRUPT_LINE, p->irq );
- dev->irq = p->irq;
- }
-
- if (p->cmd) {
- pci_read_config_word( dev, PCI_COMMAND, &cmd );
- pci_write_config_word( dev, PCI_COMMAND, (p->cmd|cmd));
- }
-
- if (p->cache_line)
- pci_write_config_byte( dev, PCI_CACHE_LINE_SIZE, p->cache_line );
-
- if (p->latency)
- pci_write_config_byte( dev, PCI_LATENCY_TIMER, p->latency );
- }
- }
-}
-
-#define KB 1024
-#define MB (KB*KB)
-
-#define ALIGN(val,align) (((val) + ((align) -1))&(~((align) -1)))
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-
-#define FIRST_IO_ADDR 0x10000
-#define FIRST_MEM_ADDR 0x02000000
-
-#define GEMINI_PCI_MEM_BASE (0xf0000000)
-#define GEMINI_PCI_IO_BASE (0xfe800000)
-
-static unsigned long pci_mem_base = GEMINI_PCI_MEM_BASE;
-static unsigned long pci_io_base = GEMINI_PCI_IO_BASE;
-
-static unsigned int io_base = FIRST_IO_ADDR;
-static unsigned int mem_base = FIRST_MEM_ADDR;
-
-
-
-__init void layout_dev( struct pci_dev *dev )
+void __init gemini_pcibios_fixup(void)
{
int i;
- struct pci_bus *bus;
- unsigned short cmd;
- unsigned int reg, base, mask, size, alignto, type;
-
- bus = dev->bus;
-
- /* make any known settings happen */
- mapin_device( dev );
-
- gemini_pcibios_read_config_word( bus->number, dev->devfn, PCI_COMMAND, &cmd );
-
- for( reg = PCI_BASE_ADDRESS_0, i=0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++ ) {
-
- /* MPIC already done */
- if (dev->vendor == PCI_VENDOR_ID_IBM &&
- dev->device == PCI_DEVICE_ID_IBM_MPIC)
- return;
-
- gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 0xffffffff );
- gemini_pcibios_read_config_dword( bus->number, dev->devfn, reg, &base );
- if (!base) {
- dev->resource[i].start = 0;
- continue;
- }
-
- if (base & PCI_BASE_ADDRESS_SPACE_IO) {
- cmd |= PCI_COMMAND_IO;
- base &= PCI_BASE_ADDRESS_IO_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- alignto = MAX(0x400, size);
- base = ALIGN(io_base, alignto);
- io_base = base + size;
- gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg,
- ((pci_io_base + base) & 0x00ffffff) | 0x1);
- dev->resource[i].start = (pci_io_base + base) | 0x1;
- }
-
- else {
- cmd |= PCI_COMMAND_MEMORY;
- type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- switch( type ) {
-
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- printk("Warning: Ignoring 64-bit device; slot %d, function %d.\n",
- PCI_SLOT( dev->devfn ), PCI_FUNC( dev->devfn ));
- reg += 4;
- continue;
+ 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);
}
-
- alignto = MAX(0x1000, size);
- base = ALIGN(mem_base, alignto);
- mem_base = base + size;
- gemini_pcibios_write_config_dword( bus->number, dev->devfn,
- reg, (pci_mem_base + base));
- dev->resource[i].start = pci_mem_base + base;
}
}
-
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- cmd |= PCI_COMMAND_IO;
-
- gemini_pcibios_write_config_word( bus->number, dev->devfn, PCI_COMMAND,
- (cmd|PCI_COMMAND_MASTER));
-}
-
-__init void layout_bus( struct pci_bus *bus )
-{
- struct pci_dev *dev;
-
- io_base = ALIGN(io_base, 4*KB);
- mem_base = ALIGN(mem_base, 4*KB);
-
- pci_for_each_dev(dev)
- {
- if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
- ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
- layout_dev( dev );
- }
-}
-
-void __init gemini_pcibios_fixup(void)
-{
- unsigned long orig_mem_base, orig_io_base;
-
- orig_mem_base = pci_mem_base;
- orig_io_base = pci_io_base;
-
- pci_mem_base = orig_mem_base;
- pci_io_base = orig_io_base;
}
decl_config_access_method(gemini);
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
index ae9a0bd5c..e069baf5b 100644
--- a/arch/ppc/kernel/gemini_setup.c
+++ b/arch/ppc/kernel/gemini_setup.c
@@ -35,15 +35,14 @@
#include "open_pic.h"
void gemini_setup_pci_ptrs(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
-static unsigned char gemini_switch_map = 0;
static char *gemini_board_families[] = {
- "VGM", "VSS", "KGM", "VGR", "KSS"
-};
-
-static char *gemini_memtypes[] = {
- "EDO DRAM, 60nS", "SDRAM, 15nS, CL=2", "SDRAM, 15nS, CL=2 with ECC"
+ "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
@@ -66,14 +65,14 @@ static inline unsigned long _get_HID1(void)
int
gemini_get_cpuinfo(char *buffer)
{
- int i, len;
+ int len;
unsigned char reg, rev;
char *family;
unsigned int type;
reg = readb(GEMINI_FEAT);
family = gemini_board_families[((reg>>4) & 0xf)];
- if (((reg>>4) & 0xf) > 2)
+ if (((reg>>4) & 0xf) > gemini_board_count)
printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
reg = readb(GEMINI_BREV);
@@ -85,18 +84,17 @@ gemini_get_cpuinfo(char *buffer)
len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
family, type, (rev + 'A'), (reg & 0xf));
- len += sprintf( buffer+len, "vendor\t\t: %s\n",
- (_get_PVR() & (1<<15)) ? "IBM" : "Motorola");
+ len = sprintf(buffer, "board\t\t: Gemini %s", family);
+ if (type > 9)
+ len += sprintf(buffer+len, "%c", (type - 10) + 'A');
+ else
+ len += sprintf(buffer+len, "%d", type);
- reg = readb(GEMINI_MEMCFG);
- len += sprintf( buffer+len, "memory type\t: %s\n",
- gemini_memtypes[(reg & 0xc0)>>6]);
- len += sprintf( buffer+len, "switches on\t: ");
- for( i=0; i < 8; i++ ) {
- if ( gemini_switch_map & (1<<i))
- len += sprintf(buffer+len, "%d ", i);
- }
- len += sprintf(buffer+len, "\n");
+ len += sprintf(buffer+len, ", rev %c, eco %d\n",
+ (rev + 'A'), (reg & 0xf));
+
+ len += sprintf(buffer+len, "clock\t\t: %dMhz\n",
+ gemini_get_clock_speed());
return len;
}
@@ -116,11 +114,16 @@ static u_char gemini_openpic_initsenses[] = {
void __init gemini_openpic_init(void)
{
+
+ OpenPIC = (volatile struct OpenPIC *)
+ grackle_read(0x80005800 + 0x10);
+#if 0
grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0,
GEMINI_MPIC_ADDR);
grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY);
OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR;
+#endif
OpenPIC_InitSenses = gemini_openpic_initsenses;
OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
@@ -148,7 +151,6 @@ gemini_heartbeat(void)
void __init gemini_setup_arch(void)
{
- unsigned int cpu;
extern char cmd_line[];
@@ -165,29 +167,8 @@ void __init gemini_setup_arch(void)
/* nothing but serial consoles... */
sprintf(cmd_line, "%s console=ttyS0", cmd_line);
-
- /* The user switches on the front panel can be used as follows:
-
- Switch 0 - adds "debug" to the command line for verbose boot info,
- Switch 7 - boots in single-user mode
-
- */
-
- gemini_switch_map = readb( GEMINI_USWITCH );
-
- if ( gemini_switch_map & (1<<GEMINI_SWITCH_VERBOSE))
- sprintf(cmd_line, "%s debug", cmd_line);
-
- if ( gemini_switch_map & (1<<GEMINI_SWITCH_SINGLE_USER))
- sprintf(cmd_line, "%s single", cmd_line);
-
printk("Boot arguments: %s\n", cmd_line);
- /* mutter some kind words about who made the CPU */
- cpu = _get_PVR();
- printk("CPU manufacturer: %s [rev=%04x]\n", (cpu & (1<<15)) ? "IBM" :
- "Motorola", (cpu & 0xffff));
-
ppc_md.heartbeat = gemini_heartbeat;
ppc_md.heartbeat_reset = HZ/8;
ppc_md.heartbeat_count = 1;
@@ -202,19 +183,17 @@ void __init gemini_setup_arch(void)
int
gemini_get_clock_speed(void)
{
- unsigned long hid1;
+ unsigned long hid1, pvr = _get_PVR();
int clock;
- unsigned char reg;
-
- hid1 = _get_HID1();
- if ((_get_PVR()>>16) == 8)
+
+ hid1 = (_get_HID1() >> 28) & 0xf;
+ if (PVR_VER(pvr) == 8 ||
+ PVR_VER(pvr) == 12)
hid1 = cpu_7xx[hid1];
else
hid1 = cpu_6xx[hid1];
- reg = readb(GEMINI_BSTAT) & 0xc0;
-
- switch( reg >> 2 ) {
+ switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
case 0:
default:
@@ -226,7 +205,7 @@ gemini_get_clock_speed(void)
break;
case 2:
- clock = (hid1*50)/3;
+ clock = (hid1*50);
break;
}
@@ -242,83 +221,72 @@ gemini_get_clock_speed(void)
void __init gemini_init_l2(void)
{
- unsigned char reg;
- unsigned long cache;
- int speed;
-
- reg = readb(GEMINI_L2CFG);
-
- /* 750's L2 initializes differently from a 604's. Also note that a Grackle
- bug will hang a dual-604 board, so make sure that doesn't happen by not
- turning on the L2 */
- if ( _get_PVR() >> 16 != 8 ) {
-
- /* check for dual cpus and cry sadly about the loss of an L2... */
- if ((( readb(GEMINI_CPUSTAT) & 0x0c ) >> 2) != 1)
- printk("Sorry. Your dual-604 does not allow the L2 to be enabled due "
- "to a Grackle bug.\n");
- else if ( reg & GEMINI_L2_SIZE_MASK ) {
- printk("Enabling 604 L2 cache: %dKb\n",
- (128<<((reg & GEMINI_L2_SIZE_MASK)>>6)));
- writeb( 1, GEMINI_L2CFG );
- }
- }
+ unsigned char reg, brev, fam, creg;
+ unsigned long cache;
+ unsigned long pvr = _get_PVR();
+
+ reg = readb(GEMINI_L2CFG);
+ brev = readb(GEMINI_BREV);
+ fam = readb(GEMINI_FEAT);
+
+ switch(PVR_VER(pvr)) {
+
+ case 8:
+ if (reg & 0xc0)
+ cache = (((reg >> 6) & 0x3) << 28);
+ else
+ cache = 0x3 << 28;
- /* do a 750 */
- else {
- /* Synergy's first round of 750 boards had the L2 size stuff into the
- board register above. If it's there, it's used; if not, the
- standard default is 1Mb. The L2 type, I'm told, is "most likely
- probably always going to be late-write". --Dan */
-
- if (reg & 0xc0) {
- printk("Enabling 750 L2 cache: %dKb\n",
- (128 << ((reg & 0xc0)>>6)));
- /* take the size given */
- cache = (((reg>>6) & 0x3)<<28);
- }
- else
- {
- printk("Enabling 750 L2 cache: 1M\n");
- /* default of 1Mb */
- cache = 0x3<<28;
- }
-
- reg &= 0x3;
-
- /* a cache ratio of 1:1 and CPU clock speeds in excess of 300Mhz are bad
- things. If found, tune it down to 1:1.5. -- Dan */
- if (!reg) {
-
-printk("3\n");
- speed = gemini_get_clock_speed();
-
- if (speed >= 300) {
- printk("Warning: L2 ratio is 1:1 on a %dMhz processor. Dropping to 1:1.5.\n",
- speed );
- printk("Contact Synergy Microsystems for an ECO to fix this problem\n");
- reg = 0x1;
- }
- }
-
- /* standard stuff */
- cache |= ((1<<reg)<<25);
#ifdef CONFIG_SMP
- /* A couple errata for the 750's (both IBM and Motorola silicon)
- note that you can get missed cache lines on MP implementations.
- The workaround - if you call it that - is to make the L2
- write-through. This is fixed in IBM's 3.1 rev (I'm told), but
- for now, always make 2.x versions use L2 write-through. --Dan */
- if (((_get_PVR()>>8) & 0xf) <= 2)
- {
- cache |= L2CR_L2WT;
- printk("L2 cache: Enabling Write-Through due to 750 Errata.\n");
- }
-#endif
- cache |= L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE;
- _set_L2CR(0);
- _set_L2CR(cache|L2CR_L2I|L2CR_L2E);
+ /* 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_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE);
+ _set_L2CR(0);
+ _set_L2CR(cache | L2CR_L2I | L2CR_L2E);
+
}
void
@@ -540,8 +508,11 @@ void gemini_post_irq(struct pt_regs* regs, int irq)
void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+ int i;
int chrp_get_irq( struct pt_regs * );
- void layout_bus( struct pci_bus * );
+
+ for(i = 0; i < GEMINI_LEDS; i++)
+ gemini_led_off(i);
gemini_setup_pci_ptrs();
@@ -585,5 +556,5 @@ void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.ppc_kbd_sysrq_xlate = NULL;
#endif
- ppc_md.pcibios_fixup_bus = layout_bus;
+ ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
}
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 218bb4ebb..6700806bd 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1274,6 +1274,7 @@ __secondary_start:
ori r3,r3,start_secondary@l
mtspr SRR0,r3
mtspr SRR1,r4
+ SYNC
rfi
#endif /* CONFIG_SMP */
@@ -1436,7 +1437,7 @@ start_here:
tlbsync /* ... on all CPUs */
sync
#endif
-
+
bl load_up_mmu
/* Set up for using our exception vectors */
@@ -1544,6 +1545,28 @@ setup_screen_bat:
mtspr IBAT1U,r3
blr
#endif
+
+#ifdef CONFIG_8260
+/* Jump into the system reset for the rom.
+ * We first disable the MMU, and then jump to the ROM reset address.
+ *
+ * r3 is the board info structure, r4 is the location for starting.
+ * I use this for building a small kernel that can load other kernels,
+ * rather than trying to write or rely on a rom monitor that can tftp load.
+ */
+ .globl m8260_gorom
+m8260_gorom:
+ li r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ lis r6,2f@h
+ addis r6,r6,-KERNELBASE@h
+ ori r6,r6,2f@l
+ mtspr SRR0,r6
+ mtspr SRR1,r5
+ rfi
+2:
+ mtlr r4
+ blr
+#endif
/*
* We put a few things here that have to be page-aligned.
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 83f276585..59b8a49c6 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -136,7 +136,7 @@ __start:
mtspr DC_CST, r8
lis r8, IDC_ENABLE@h
mtspr IC_CST, r8
-#if 0
+#ifdef CONFIG_8xx_COPYBACK
mtspr DC_CST, r8
#else
/* For a debug option, I left this here to easily enable
@@ -356,15 +356,26 @@ SystemCall:
* only perform the attribute functions.
*/
InstructionTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, SRR0 /* Get effective address of fault */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3780
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_EPN, r20 /* Have to use MD_EPN for walk, MI_EPN can't */
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load the MI_TWC with the attributes
@@ -372,88 +383,131 @@ InstructionTLBMiss:
*/
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_TWC, r21 /* Set page attributes */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
+#if 0
+ ori r20, r20, _PAGE_ACCESSED
+ stw r20, 0(r21)
+#endif
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MI_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b InstructionAccess
. = 0x1200
DataStoreTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
- mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ mfspr r20, MD_TWC /* ....and get the pte address */
+ lwz r20, 0(r20) /* Get the pte */
+
+ /* Insert the Guarded flag into the TWC from the Linux PTE.
+ * It is bit 27 of both the Linux PTE and the TWC (at least
+ * I got that right :-). It will be better when we can put
+ * this into the Linux pgd/pmd and load it in the operation
+ * above.
+ */
+ rlwimi r21, r20, 0, 27, 27
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
+ mtspr MD_TWC, r21
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+#if 0
+ ori r20, r20, 0x00f0
+#else
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#endif
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
/* This is an instruction TLB error on the MPC8xx. This could be due
@@ -474,6 +528,12 @@ InstructionTLBError:
*/
. = 0x1400
DataTLBError:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
@@ -487,52 +547,59 @@ DataTLBError:
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, bail */
/* We have a pte table, so fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
- andi. r20, r21, _PAGE_RW /* Is it writeable? */
+ andi. r21, r20, _PAGE_RW /* Is it writeable? */
beq 2f /* Bail out if not */
- ori r21, r21, _PAGE_DIRTY /* Update changed bit */
- mfspr r20, MD_TWC /* Get pte address again */
- stw r21, 0(r20) /* and update pte in table */
+ /* Update 'changed', among others.
+ */
+ ori r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
+ mfspr r21, MD_TWC /* Get pte address again */
+ stw r20, 0(r21) /* and update pte in table */
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2:
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
STD_EXCEPTION(0x1500, Trap_15, UnknownException)
@@ -542,6 +609,7 @@ DataTLBError:
STD_EXCEPTION(0x1900, Trap_19, UnknownException)
STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+
/* On the MPC8xx, these next four traps are used for development
* support of breakpoints and such. Someday I will get around to
* using them.
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index c0cc492ad..28be8bf46 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -117,9 +117,9 @@ void irq_kfree(void *ptr)
kfree(ptr);
}
-#ifdef CONFIG_8xx
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
/* Name change so we can catch standard drivers that potentially mess up
- * the internal interrupt controller on 8xx and 82xx. Just bear with me,
+ * the internal interrupt controller on 8xx and 8260. Just bear with me,
* I don't like this either and I am searching a better solution. For
* now, this is what I need. -- Dan
*/
@@ -194,10 +194,10 @@ void sys_free_irq(unsigned int irq, void *dev_id)
#else
void free_irq(unsigned int irq, void *dev_id)
{
-#ifndef CONFIG_8xx
- request_irq(irq, NULL, 0, NULL, dev_id);
-#else
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
request_8xxirq(irq, NULL, 0, NULL, dev_id);
+#else
+ request_irq(irq, NULL, 0, NULL, dev_id);
#endif
}
#endif
diff --git a/arch/ppc/kernel/m8260_setup.c b/arch/ppc/kernel/m8260_setup.c
new file mode 100644
index 000000000..65ea973d8
--- /dev/null
+++ b/arch/ppc/kernel/m8260_setup.c
@@ -0,0 +1,303 @@
+/*
+ * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
+ *
+ * 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)
+ * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
+ * Further modified for generic 8xx and 8260 by Dan.
+ */
+
+/*
+ * 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/malloc.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/ide.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/ide.h>
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#include <asm/machdep.h>
+
+#include "time.h"
+#include "ppc8260_pic.h"
+
+static int m8260_set_rtc_time(unsigned long time);
+unsigned long m8260_get_rtc_time(void);
+void m8260_calibrate_decr(void);
+
+#if 0
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+#endif
+
+extern unsigned long loops_per_sec;
+
+unsigned char __res[sizeof(bd_t)];
+unsigned long empty_zero_page[1024];
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+#endif
+
+extern char saved_command_line[256];
+
+extern unsigned long find_available_memory(void);
+extern void m8260_cpm_reset(void);
+
+void __init adbdev_init(void)
+{
+}
+
+void __init
+m8260_setup_arch(void)
+{
+ extern char cmd_line[];
+
+ printk("Boot arguments: %s\n", cmd_line);
+
+ /* Reset the Communication Processor Module.
+ */
+ m8260_cpm_reset();
+}
+
+void
+abort(void)
+{
+#ifdef CONFIG_XMON
+ extern void xmon(void *);
+ xmon(0);
+#endif
+ machine_restart(NULL);
+}
+
+/* The decrementer counts at the system (internal) clock frequency
+ * divided by four.
+ */
+void __init m8260_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *)__res;
+ int freq, divisor;
+
+ freq = (binfo->bi_intfreq * 1000000);
+ divisor = 16;
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+/* The 8260 has an internal 1-second timer update register that
+ * we should use for this purpose.
+ */
+static uint rtc_time;
+static int
+m8260_set_rtc_time(unsigned long time)
+{
+ rtc_time = time;
+ return(0);
+}
+
+unsigned long __init
+m8260_get_rtc_time(void)
+{
+
+ /* Get time from the RTC.
+ */
+ return((unsigned long)rtc_time);
+}
+
+void
+m8260_restart(char *cmd)
+{
+ extern void m8260_gorom(bd_t *bi, uint addr);
+
+ m8260_gorom(NULL, 0xff000100);
+}
+
+void
+m8260_power_off(void)
+{
+ m8260_restart(NULL);
+}
+
+void
+m8260_halt(void)
+{
+ m8260_restart(NULL);
+}
+
+
+int m8260_setup_residual(char *buffer)
+{
+ int len = 0;
+ bd_t *bp;
+
+ bp = (bd_t *)__res;
+
+ len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
+ bp->bi_intfreq /*/ 1000000*/,
+ bp->bi_busfreq /*/ 1000000*/);
+
+ return len;
+}
+
+/* Initialize the internal interrupt controller. The number of
+ * interrupts supported can vary with the processor type, and the
+ * 8260 family can have up to 64.
+ * External interrupts can be either edge or level triggered, and
+ * need to be initialized by the appropriate driver.
+ */
+void __init
+m8260_init_IRQ(void)
+{
+ int i;
+ void cpm_interrupt_init(void);
+
+#if 0
+ ppc8260_pic.irq_offset = 0;
+#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.
+ */
+ immr->im_intctl.ic_sicr = 0;
+ immr->im_intctl.ic_siprr = 0x05309770;
+ immr->im_intctl.ic_scprrh = 0x05309770;
+ immr->im_intctl.ic_scprrl = 0x05309770;
+
+}
+
+
+void __init
+m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+
+ 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 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+ /* take care of cmd line */
+ if ( r6 )
+ {
+
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = m8260_setup_arch;
+ ppc_md.setup_residual = m8260_setup_residual;
+ ppc_md.get_cpuinfo = NULL;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = m8260_init_IRQ;
+ ppc_md.get_irq = m8260_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = m8260_restart;
+ ppc_md.power_off = m8260_power_off;
+ ppc_md.halt = m8260_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = m8260_set_rtc_time;
+ ppc_md.get_rtc_time = m8260_get_rtc_time;
+ ppc_md.calibrate_decr = m8260_calibrate_decr;
+
+#if 0
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_pretranslate = pckbd_pretranslate;
+ 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.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+#else
+ 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;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = NULL;
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = m8xx_ide_insw;
+ ppc_ide_md.outsw = m8xx_ide_outsw;
+ ppc_ide_md.default_irq = m8xx_ide_default_irq;
+ ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
+ ppc_ide_md.check_region = m8xx_ide_check_region;
+ ppc_ide_md.request_region = m8xx_ide_request_region;
+ ppc_ide_md.release_region = m8xx_ide_release_region;
+ ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
+ ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
+}
+
+void
+prom_init(uint r3, uint r4, uint r5, uint r6)
+{
+ /* Nothing to do now, but we are called immediatedly upon
+ * kernel start up with MMU disabled, so if there is
+ * anything we need to do......
+ */
+}
+
+/* Mainly for ksyms.
+*/
+int
+request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flag, const char *naem, void *dev)
+{
+ panic("request IRQ\n");
+}
diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c
index a417bed2e..9f0a517e3 100644
--- a/arch/ppc/kernel/m8xx_setup.c
+++ b/arch/ppc/kernel/m8xx_setup.c
@@ -130,7 +130,6 @@ void
abort(void)
{
#ifdef CONFIG_XMON
- extern void xmon(void *);
xmon(0);
#endif
machine_restart(NULL);
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index e4fbefbc3..96adb96cd 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -18,6 +18,7 @@
#include <asm/errno.h>
#include <asm/processor.h>
#include <asm/page.h>
+#include <asm/cache.h>
#include "ppc_asm.h"
#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
@@ -165,6 +166,11 @@ _GLOBAL(_tlbie)
* This is a no-op on the 601.
*/
_GLOBAL(flush_instruction_cache)
+#ifdef CONFIG_8xx
+ isync
+ lis r5, IDC_INVALL@h
+ mtspr IC_CST, r5
+#else
mfspr r3,PVR
rlwinm r3,r3,16,16,31
cmpi 0,r3,1
@@ -173,6 +179,7 @@ _GLOBAL(flush_instruction_cache)
mfspr r3,HID0
ori r3,r3,HID0_ICFI
mtspr HID0,r3
+#endif /* CONFIG_8xx */
SYNC
blr
@@ -241,8 +248,7 @@ _GLOBAL(__flush_page_to_ram)
rlwinm r5,r5,16,16,31
cmpi 0,r5,1
beqlr /* for 601, do nothing */
- li r4,0x0FFF
- andc r3,r3,r4 /* Get page base address */
+ rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
mtctr r4
mr r6,r3
@@ -373,6 +379,7 @@ _GLOBAL(__spin_trylock)
* void atomic_clear_mask(atomic_t mask, atomic_t *addr)
* void atomic_set_mask(atomic_t mask, atomic_t *addr);
*/
+#if 0 /* now inline - paulus */
_GLOBAL(atomic_add)
10: lwarx r5,0,r4 /* Fetch old value & reserve */
add r5,r5,r3 /* Perform 'add' operation */
@@ -423,11 +430,10 @@ _GLOBAL(atomic_dec_and_test)
subi r5,r5,1 /* Perform 'add' operation */
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
- cmpi 0,r5,0 /* Return 'true' IFF 0 */
- li r3,1
- beqlr
- li r3,0
+ cntlzw r3,r5
+ srwi r3,r3,5
blr
+#endif /* 0 */
_GLOBAL(atomic_clear_mask)
10: lwarx r5,0,r4
andc r5,r5,r3
diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c
index a3a9bae70..db0632238 100644
--- a/arch/ppc/kernel/pmac_nvram.c
+++ b/arch/ppc/kernel/pmac_nvram.c
@@ -7,14 +7,18 @@
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <asm/init.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
+
/*
* Read and write the non-volatile RAM on PowerMacs and CHRP machines.
*/
@@ -23,9 +27,191 @@ static volatile unsigned char *nvram_addr;
static volatile unsigned char *nvram_data;
static int nvram_mult, is_core_99;
static char* nvram_image;
+static int core99_bank = 0;
+
+extern int pmac_newworld;
#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];
+};
+
+static int nvram_partitions[3];
+
+static u8
+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
+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
+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
+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
+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
+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;
+ 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
+}
+
__init
void pmac_nvram_init(void)
{
@@ -40,17 +226,32 @@ void pmac_nvram_init(void)
}
nvram_naddrs = dp->n_addrs;
is_core_99 = device_is_compatible(dp, "nvram,flash");
- if (is_core_99)
- {
+ if (is_core_99) {
int i;
- if (nvram_naddrs < 1)
+ u32 gen_bank0, gen_bank1;
+
+ if (nvram_naddrs < 1) {
+ printk(KERN_ERR "nvram: no address\n");
return;
- nvram_image = kmalloc(dp->addrs[0].size, GFP_KERNEL);
- if (!nvram_image)
+ }
+ nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
+ if (!nvram_image) {
+ printk(KERN_ERR "nvram: can't allocate image\n");
return;
- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- for (i=0; i<dp->addrs[0].size; i++)
- nvram_image[i] = in_8(nvram_data + i);
+ }
+ 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, dp->addrs[0].size);
nvram_mult = 1;
@@ -68,6 +269,33 @@ void pmac_nvram_init(void)
}
}
+void
+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);
+}
+
__openfirmware
unsigned char nvram_read_byte(int addr)
{
@@ -125,3 +353,33 @@ void nvram_write_byte(unsigned char val, int addr)
}
eieio();
}
+
+int
+pmac_get_partition(int partition)
+{
+ return nvram_partitions[partition];
+}
+
+u8
+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_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
index b57d5aa28..ee54ba37d 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -525,7 +525,8 @@ static void __init init_bandit(struct bridge_data *bp)
bp->io_base);
}
-#define GRACKLE_STG_ENABLE 0x00000040
+#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. */
@@ -535,11 +536,25 @@ static inline void grackle_set_stg(struct bridge_data *bp, int enable)
out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
val = in_le32((volatile unsigned int *)bp->cfg_data);
- val = enable? (val | GRACKLE_STG_ENABLE): (val & ~GRACKLE_STG_ENABLE);
+ 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);
}
+static inline void grackle_set_loop_snoop(struct bridge_data *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 __init pmac_find_bridges(void)
{
int bus;
@@ -620,7 +635,9 @@ static void __init add_bridges(struct device_node *dev)
bp->cfg_data = (volatile unsigned char *)
ioremap(0xfee00000, 0x1000);
bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
-#if 0 /* Disabled for now, HW problems */
+ if (machine_is_compatible("AAPL,PowerBook1998"))
+ grackle_set_loop_snoop(bp, 1);
+#if 0 /* Disabled for now, HW problems ??? */
grackle_set_stg(bp, 1);
#endif
} else {
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
index b58d69fc9..ab2fdbc15 100644
--- a/arch/ppc/kernel/pmac_pic.c
+++ b/arch/ppc/kernel/pmac_pic.c
@@ -158,13 +158,13 @@ static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
{
int irq, bits;
- for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ 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 -= cntlzw(bits);
+ irq += __ilog2(bits);
break;
}
/* The previous version of this code allowed for this case, we
@@ -213,13 +213,13 @@ pmac_get_irq(struct pt_regs *regs)
}
else
{
- for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ 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 -= cntlzw(bits);
+ irq += __ilog2(bits);
break;
}
}
@@ -489,11 +489,9 @@ sleep_save_intrs(int viaint)
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);
- do {
- /* make sure mask gets to controller before we
- return to user */
- mb();
- } while(in_le32(&pmac_irq_hw[0]->enable) != ppc_cached_irq_mask[0]);
+ /* make sure mask gets to controller before we return to caller */
+ mb();
+ (void)in_le32(&pmac_irq_hw[0]->enable);
}
void
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index c2c4cbbf4..35aa7a76d 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -100,6 +100,8 @@ int has_l2cache = 0;
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);
@@ -198,6 +200,11 @@ pmac_get_cpuinfo(char *buffer)
}
}
+ /* Indicate newworld/oldworld */
+ len += sprintf(buffer+len, "pmac-generation\t: %s\n",
+ pmac_newworld ? "NewWorld" : "OldWorld");
+
+
return len;
}
@@ -499,6 +506,8 @@ pmac_restart(char *cmd)
struct adb_request req;
#endif /* CONFIG_ADB_CUDA */
+ pmac_nvram_update();
+
switch (sys_ctrler) {
#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
@@ -524,6 +533,8 @@ pmac_power_off(void)
struct adb_request req;
#endif /* CONFIG_ADB_CUDA */
+ pmac_nvram_update();
+
switch (sys_ctrler) {
#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
index 42ca7eadc..7a673fb70 100644
--- a/arch/ppc/kernel/ppc-stub.c
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -99,6 +99,7 @@
*
****************************************************************************/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mm.h>
@@ -123,6 +124,7 @@ static char remcomOutBuffer[BUFMAX];
static int initialized = 0;
static int kgdb_active = 0;
+static int kgdb_started = 0;
static u_int fault_jmp_buf[100];
static int kdebug;
@@ -342,7 +344,7 @@ static void kgdb_flush_cache_all(void)
flush_instruction_cache();
}
-static inline int get_msr()
+static inline int get_msr(void)
{
int msr;
asm volatile("mfmsr %0" : "=r" (msr):);
@@ -460,6 +462,9 @@ static int computeSignal(unsigned int tt)
return SIGHUP; /* default for things we don't know about */
}
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
/*
* This function does all command processing for interfacing to gdb.
*/
@@ -481,6 +486,7 @@ handle_exception (struct pt_regs *regs)
return;
}
kgdb_active = 1;
+ kgdb_started = 1;
#ifdef KGDB_DEBUG
printk("kgdb: entering handle_exception; trap [0x%x]\n",
@@ -501,9 +507,25 @@ handle_exception (struct pt_regs *regs)
sigval = computeSignal(regs->trap);
ptr = remcomOutBuffer;
+#if 0
*ptr++ = 'S';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
+#else
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+ *ptr++ = hexchars[PC_REGNUM >> 4];
+ *ptr++ = hexchars[PC_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&regs->nip, ptr, 4);
+ *ptr++ = ';';
+ *ptr++ = hexchars[SP_REGNUM >> 4];
+ *ptr++ = hexchars[SP_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(((char *)&regs) + SP_REGNUM*4, ptr, 4);
+ *ptr++ = ';';
+#endif
*ptr++ = 0;
@@ -639,6 +661,7 @@ handle_exception (struct pt_regs *regs)
} else {
strcpy(remcomOutBuffer, "E03");
}
+ flush_icache_range(addr, addr+length);
} else {
strcpy(remcomOutBuffer, "E02");
}
@@ -668,7 +691,9 @@ handle_exception (struct pt_regs *regs)
case 's':
kgdb_flush_cache_all();
regs->msr |= MSR_SE;
+#if 0
set_msr(msr | MSR_SE);
+#endif
unlock_kernel();
kgdb_active = 0;
return;
@@ -700,6 +725,37 @@ breakpoint(void)
}
asm(" .globl breakinst
- breakinst: trap
+ breakinst: .long 0x7d821008
");
}
+
+/* Output string in GDB O-packet format if GDB has connected. If nothing
+ output, returns 0 (caller must then handle output). */
+int
+kgdb_output_string (const char* s, unsigned int count)
+{
+ char buffer[512];
+
+ if (!kgdb_started)
+ return 0;
+
+ count = (count <= (sizeof(buffer) / 2 - 2))
+ ? count : (sizeof(buffer) / 2 - 2);
+
+ buffer[0] = 'O';
+ mem2hex (s, &buffer[1], count);
+ putpacket(buffer);
+
+ return 1;
+ }
+
+#ifndef CONFIG_8xx
+
+/* 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
+ */
+void
+kgdb_map_scc(void)
+{
+}
+#endif
diff --git a/arch/ppc/kernel/ppc8260_pic.c b/arch/ppc/kernel/ppc8260_pic.c
new file mode 100644
index 000000000..21cfde0f7
--- /dev/null
+++ b/arch/ppc/kernel/ppc8260_pic.c
@@ -0,0 +1,111 @@
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/irq.h>
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#include "ppc8260_pic.h"
+
+/* The 8260 internal interrupt controller. It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static u_char irq_to_siureg[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static u_char irq_to_siubit[] = {
+ 31, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 29, 30, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 31,
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static void m8260_mask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ 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];
+}
+
+static void m8260_unmask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ 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];
+}
+
+static void m8260_mask_and_ack(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr, *sipnr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ sipnr = &(immr->im_intctl.ic_sipnrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+ sipnr[word] = 1 << bit;
+}
+
+struct hw_interrupt_type ppc8260_pic = {
+ " 8260 SIU ",
+ NULL,
+ NULL,
+ m8260_unmask_irq,
+ m8260_mask_irq,
+ m8260_mask_and_ack,
+ 0
+};
+
+
+int
+m8260_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits;
+
+ /* For MPC8260, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = immr->im_intctl.ic_sivec;
+ irq = bits >> 26;
+#if 0
+ irq += ppc8260_pic.irq_offset;
+#endif
+ return irq;
+}
+
diff --git a/arch/ppc/kernel/ppc8260_pic.h b/arch/ppc/kernel/ppc8260_pic.h
new file mode 100644
index 000000000..b073dbe6b
--- /dev/null
+++ b/arch/ppc/kernel/ppc8260_pic.h
@@ -0,0 +1,15 @@
+
+#ifndef _PPC_KERNEL_PPC8260_H
+#define _PPC_KERNEL_PPC8260_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type ppc8260_pic;
+
+void m8260_pic_init(void);
+void m8260_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake);
+int m8260_get_irq(struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_PPC8260_H */
diff --git a/arch/ppc/kernel/ppc8xx_pic.c b/arch/ppc/kernel/ppc8xx_pic.c
index afcda088b..e2db1e34d 100644
--- a/arch/ppc/kernel/ppc8xx_pic.c
+++ b/arch/ppc/kernel/ppc8xx_pic.c
@@ -8,7 +8,7 @@
#include <asm/mpc8xx.h>
#include "ppc8xx_pic.h"
-/* The 8xx or 82xx internal interrupt controller. It is usually
+/* The 8xx internal interrupt controller. It is usually
* the only interrupt controller. Some boards, like the MBX and
* Sandpoint have the 8259 as a secondary controller. Depending
* upon the processor type, the internal controller can have as
@@ -25,13 +25,8 @@ static void m8xx_mask_irq(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
-#endif
}
static void m8xx_unmask_irq(unsigned int irq_nr)
@@ -42,13 +37,8 @@ static void m8xx_unmask_irq(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] |= (1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
-#endif
}
static void m8xx_mask_and_ack(unsigned int irq_nr)
@@ -59,15 +49,9 @@ static void m8xx_mask_and_ack(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend[word] = 1 << (31-bit);
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
-#endif
}
struct hw_interrupt_type ppc8xx_pic = {
@@ -129,7 +113,7 @@ m8xx_get_irq(struct pt_regs *regs)
/* The MBX is the only 8xx board that uses the 8259.
*/
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
{
int bits, irq;
@@ -165,7 +149,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
unsigned long irqflags, const char * devname, void *dev_id)
{
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
irq += i8259_pic.irq_offset;
return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
#else
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 441310e68..655eb4390 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -502,7 +502,7 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
#define TMPBUFLEN 256
char buf[TMPBUFLEN], *p;
static const char *sizestrings[4] = {
- "unknown size", "256KB", "512KB", "1MB"
+ "2MB", "256KB", "512KB", "1MB"
};
static const char *clockstrings[8] = {
"clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 7d4c038ec..9b7d2be31 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -54,9 +54,10 @@ extern int sys_sigreturn(struct pt_regs *regs);
extern void do_lost_interrupts(unsigned long);
extern int do_signal(sigset_t *, struct pt_regs *);
-asmlinkage long long __ashrdi3(long long, int);
-asmlinkage long long __lshrdi3(long long, int);
-asmlinkage int abs(int);
+long long __ashrdi3(long long, int);
+long long __ashldi3(long long, int);
+long long __lshrdi3(long long, int);
+int abs(int);
EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_signal);
@@ -95,25 +96,12 @@ EXPORT_SYMBOL(ucSystemType);
#endif
#endif
-EXPORT_SYMBOL(atomic_add);
-EXPORT_SYMBOL(atomic_sub);
-EXPORT_SYMBOL(atomic_inc);
-EXPORT_SYMBOL(atomic_inc_return);
-EXPORT_SYMBOL(atomic_dec);
-EXPORT_SYMBOL(atomic_dec_return);
-EXPORT_SYMBOL(atomic_dec_and_test);
-
EXPORT_SYMBOL(set_bit);
EXPORT_SYMBOL(clear_bit);
EXPORT_SYMBOL(change_bit);
EXPORT_SYMBOL(test_and_set_bit);
EXPORT_SYMBOL(test_and_clear_bit);
EXPORT_SYMBOL(test_and_change_bit);
-#if 0
-EXPORT_SYMBOL(ffz);
-EXPORT_SYMBOL(find_first_zero_bit);
-EXPORT_SYMBOL(find_next_zero_bit);
-#endif
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
@@ -254,6 +242,7 @@ EXPORT_SYMBOL(nvram_write_byte);
#endif /* CONFIG_NVRAM */
EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
@@ -281,3 +270,17 @@ EXPORT_SYMBOL(console_drivers);
EXPORT_SYMBOL(xmon);
#endif
EXPORT_SYMBOL(down_read_failed);
+
+extern void (*debugger)(struct pt_regs *regs);
+extern int (*debugger_bpt)(struct pt_regs *regs);
+extern int (*debugger_sstep)(struct pt_regs *regs);
+extern int (*debugger_iabr_match)(struct pt_regs *regs);
+extern int (*debugger_dabr_match)(struct pt_regs *regs);
+extern void (*debugger_fault_handler)(struct pt_regs *regs);
+
+EXPORT_SYMBOL(debugger);
+EXPORT_SYMBOL(debugger_bpt);
+EXPORT_SYMBOL(debugger_sstep);
+EXPORT_SYMBOL(debugger_iabr_match);
+EXPORT_SYMBOL(debugger_dabr_match);
+EXPORT_SYMBOL(debugger_fault_handler);
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index ce8e039c0..e1f1b4983 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -489,7 +489,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
{
int error;
char * filename;
- lock_kernel();
+
filename = getname((char *) a0);
error = PTR_ERR(filename);
if (IS_ERR(filename))
@@ -503,8 +503,6 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
- unlock_kernel();
-
return error;
}
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index a987b8fd6..31fc85068 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -106,7 +106,10 @@ unsigned int rtas_entry = 0; /* physical pointer */
unsigned int rtas_size = 0;
unsigned int old_rtas = 0;
+/* Set for a newworld machine */
int use_of_interrupt_tree = 0;
+int pmac_newworld = 0;
+
static struct device_node *allnodes = 0;
#ifdef CONFIG_BOOTX_TEXT
@@ -802,7 +805,6 @@ __init
static void
setup_disp_fake_bi(ihandle dp)
{
- unsigned int len;
int width = 640, height = 480, depth = 8, pitch;
unsigned address;
boot_infos_t* bi;
@@ -982,15 +984,17 @@ void
finish_device_tree(void)
{
unsigned long mem = (unsigned long) klimit;
- char* model;
-
- /* Here, we decide if we'll use the interrupt-tree (new Core99 code) or not.
- * This code was only tested with Core99 machines so far, but should be easily
- * adapted to older newworld machines (iMac, B&W G3, Lombard).
- */
- model = get_property(allnodes, "model", 0);
- if ((boot_infos == 0) && model && (strcmp(model, "PowerBook2,1") == 0
- || strcmp(model, "PowerMac2,1") == 0 || strcmp(model, "PowerMac3,1") == 0))
+
+ /* All newworld machines now use the interrupt tree */
+ struct device_node *np = allnodes;
+ while(np) {
+ if (get_property(np, "interrupt-parent", 0)) {
+ pmac_newworld = 1;
+ break;
+ }
+ np = np->allnext;
+ }
+ if (boot_infos == 0 && pmac_newworld)
use_of_interrupt_tree = 1;
mem = finish_node(allnodes, mem, NULL);
@@ -1827,7 +1831,8 @@ abort()
#ifdef CONFIG_XMON
xmon(NULL);
#endif
- prom_exit();
+ for (;;)
+ prom_exit();
}
#ifdef CONFIG_BOOTX_TEXT
diff --git a/arch/ppc/kernel/qspan_pci.c b/arch/ppc/kernel/qspan_pci.c
index 860f4f0cc..c31dd9399 100644
--- a/arch/ppc/kernel/qspan_pci.c
+++ b/arch/ppc/kernel/qspan_pci.c
@@ -84,7 +84,7 @@
" .align 2\n" \
" .long 1b,3b\n" \
".text" \
- : "=r"(x) : "r"(addr))
+ : "=r"(x) : "r"(addr) : " %0")
#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500))
#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504))
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 2b771ef14..49a8da139 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -27,6 +27,10 @@
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#endif
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/feature.h>
@@ -109,8 +113,10 @@ struct machdep_calls ppc_md;
* on pmac as well so we don't need the ifdef's.
* Until we get multiple-console support in here
* that is. -- Cort
+ * Maybe tie it to serial consoles, since this is really what
+ * these processors use on existing boards. -- Dan
*/
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
struct screen_info screen_info = {
0, 25, /* orig-x, orig-y */
0, /* unused */
@@ -283,10 +289,10 @@ int get_cpuinfo(char *buffer)
}
break;
case 0x0050:
- len += sprintf(len+buffer, "821\n");
+ len += sprintf(len+buffer, "8xx\n");
break;
case 0x0081:
- len += sprintf(len+buffer, "8240\n");
+ len += sprintf(len+buffer, "82xx\n");
break;
case 0x4011:
len += sprintf(len+buffer, "405GP\n");
@@ -300,7 +306,7 @@ int get_cpuinfo(char *buffer)
* Assume here that all clock rates are the same in a
* smp system. -- Cort
*/
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
if ( have_of )
{
struct device_node *cpu_node;
@@ -418,10 +424,10 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
parse_bootinfo();
-
+
if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
#ifndef CONFIG_MACH_SPECIFIC
/* if we didn't get any bootinfo telling us what we are... */
if ( _machine == 0 )
@@ -540,6 +546,8 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
oak_init(r3, r4, r5, r6, r7);
#elif defined(CONFIG_8xx)
m8xx_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_8260)
+ m8260_init(r3, r4, r5, r6, r7);
#else
#error "No board type has been defined for identify_machine()!"
#endif /* CONFIG_4xx */
@@ -659,13 +667,19 @@ void __init setup_arch(char **cmdline_p)
map_bootx_text();
#endif
+#ifdef CONFIG_ALL_PPC
+ feature_init();
+#endif
+
#ifdef CONFIG_XMON
xmon_map_scc();
if (strstr(cmd_line, "xmon"))
xmon(0);
#endif /* CONFIG_XMON */
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
+
#if defined(CONFIG_KGDB)
+ kgdb_map_scc();
set_debug_traps();
breakpoint();
#endif
@@ -688,6 +702,7 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
+
paging_init();
}
@@ -696,7 +711,6 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
int i;
unsigned short *stringcast;
-
id->config = __le16_to_cpu(id->config);
id->cyls = __le16_to_cpu(id->cyls);
id->reserved2 = __le16_to_cpu(id->reserved2);
@@ -708,16 +722,16 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->vendor1 = __le16_to_cpu(id->vendor1);
id->vendor2 = __le16_to_cpu(id->vendor2);
stringcast = (unsigned short *)&id->serial_no[0];
- for (i=0; i<(20/2); i++)
+ for (i = 0; i < (20/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->buf_type = __le16_to_cpu(id->buf_type);
id->buf_size = __le16_to_cpu(id->buf_size);
id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
stringcast = (unsigned short *)&id->fw_rev[0];
- for (i=0; i<(8/2); i++)
+ for (i = 0; i < (8/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
stringcast = (unsigned short *)&id->model[0];
- for (i=0; i<(40/2); i++)
+ for (i = 0; i < (40/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->dword_io = __le16_to_cpu(id->dword_io);
id->reserved50 = __le16_to_cpu(id->reserved50);
@@ -735,12 +749,12 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
id->eide_pio = __le16_to_cpu(id->eide_pio);
id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
- for (i=0; i<2; i++)
+ for (i = 0; i < 2; i++)
id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
- for (i=0; i<4; i++)
+ for (i = 0; i < 4; i++)
id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
id->queue_depth = __le16_to_cpu(id->queue_depth);
- for (i=0; i<4; i++)
+ for (i = 0; i < 4; i++)
id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
id->major_rev_num = __le16_to_cpu(id->major_rev_num);
id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
@@ -756,14 +770,14 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
id->word92 = __le16_to_cpu(id->word92);
id->hw_config = __le16_to_cpu(id->hw_config);
- for (i=0; i<32; i++)
+ for (i = 0; i < 32; i++)
id->words94_125[i] = __le16_to_cpu(id->words94_125[i]);
id->last_lun = __le16_to_cpu(id->last_lun);
id->word127 = __le16_to_cpu(id->word127);
id->dlf = __le16_to_cpu(id->dlf);
id->csfo = __le16_to_cpu(id->csfo);
- for (i=0; i<31; i++)
+ for (i = 0; i < 30; i++)
id->words130_159[i] = __le16_to_cpu(id->words130_159[i]);
- for (i=0; i<97; i++)
+ for (i = 0; i < 96; i++)
id->words160_255[i] = __le16_to_cpu(id->words160_255[i]);
}
diff --git a/arch/ppc/kernel/totalmp.c b/arch/ppc/kernel/totalmp.c
deleted file mode 100644
index ecbc04b57..000000000
--- a/arch/ppc/kernel/totalmp.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * $Id: totalmp.c,v 1.6 1999/08/31 06:54:10 davem Exp $
- *
- * Support for Total Impact's TotalMP PowerPC accelerator board.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu)
- *
- * 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/pci.h>
-#include <linux/init.h>
-#include <linux/openpic.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-
-extern void totalmp_init(void);
-
-extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
- u_int field);
-void __init totalmp_init(void)
-{
- struct pci_dev *dev;
- u32 val;
- unsigned long ctl_area, ctl_area_phys;
-
- /* it's a pci card */
- if ( !pci_present() ) return;
-
- /* search for a MPIC. For now, we assume
- * only one TotalMP card installed. -- Cort
- */
- for(dev=pci_devices; dev; dev=dev->next)
- {
- if ( (dev->vendor == PCI_VENDOR_ID_IBM)
- && ((dev->device == PCI_DEVICE_ID_IBM_MPIC)
- || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) )
- {
- break;
- }
- }
-
- if ( !dev ) return;
-
- OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]);
-#if 0
- if ( (ulong)OpenPIC > 0x10000000 )
- {
- printk("TotalMP: relocating base %lx -> %lx\n",
- (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
- OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC);
- }*/
-#endif
- OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE);
-
- openpic_init(0);
-
- /* put openpic in 8259-cascade mode */
- openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000);
- /* set ipi to highest priority */
- openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000);
-
- /* allocate and remap the control area to be no-cache */
- ctl_area = __get_free_pages(GFP_ATOMIC, 3);
- ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area);
- ctl_area = (unsigned long)ioremap(ctl_area, 0x8000);
-
- /* soft reset cpu 0 */
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
- openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1);
-
- /* wait for base address reg to change, signaling that cpu 0 is done */
-#define wait_for(where) { \
- udelay(100); \
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); \
- if ( val != 0x77700000 ) \
- { \
- printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \
- /*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \
- return; \
- } }
-
- /* tell cpu0 where the control area is */
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16);
- wait_for(0);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0xff000000)>>20);
- wait_for(1);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x00ff0000)>>12);
- wait_for(2);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x0000ff00)>>4);
- wait_for(3);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x000000ff)<<4);
- wait_for(4);
-#undef wait_for
- /* wait for cpu0 to "sign-on" */
-}
-
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index ac7f47602..28a5a5035 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -119,10 +119,10 @@ MachineCheckException(struct pt_regs *regs)
printk("Unknown values in msr\n");
}
show_regs(regs);
- print_backtrace((unsigned long *)regs->gpr[1]);
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
#endif
+ print_backtrace((unsigned long *)regs->gpr[1]);
panic("machine check");
}
_exception(SIGSEGV, regs);