diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
commit | ba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch) | |
tree | 78670a0139bf4d5ace617b29b7eba82bbc74d602 /arch/ppc/kernel | |
parent | b77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff) |
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'arch/ppc/kernel')
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 *)®s->nip, ptr, 4); + *ptr++ = ';'; + *ptr++ = hexchars[SP_REGNUM >> 4]; + *ptr++ = hexchars[SP_REGNUM & 0xf]; + *ptr++ = ':'; + ptr = mem2hex(((char *)®s) + 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); |